diff --git a/http/handler.go b/http/handler.go index f7d6437bb2..a9be673cb6 100644 --- a/http/handler.go +++ b/http/handler.go @@ -474,6 +474,7 @@ func requestAuth(core *vault.Core, r *http.Request, req *logical.Request) *logic if err == nil && te != nil { req.ClientTokenAccessor = te.Accessor req.ClientTokenRemainingUses = te.NumUses + req.SetTokenEntry(te) } } diff --git a/logical/request.go b/logical/request.go index 7bff6f0804..4c395370d6 100644 --- a/logical/request.go +++ b/logical/request.go @@ -141,6 +141,14 @@ type Request struct { // accessible. Unauthenticated bool `json:"unauthenticated" structs:"unauthenticated" mapstructure:"unauthenticated"` + // Cached token entry. This avoids another lookup in request handling when + // we've already looked it up at http handling time. Note that this token + // has not been "used", as in it will not properly take into account use + // count limitations. As a result this field should only ever be used for + // transport to a function that would otherwise do a lookup and then + // properly use the token. + tokenEntry *TokenEntry + // For replication, contains the last WAL on the remote side after handling // the request, used for best-effort avoidance of stale read-after-write lastRemoteWAL uint64 @@ -199,6 +207,14 @@ func (r *Request) SetLastRemoteWAL(last uint64) { r.lastRemoteWAL = last } +func (r *Request) TokenEntry() *TokenEntry { + return r.tokenEntry +} + +func (r *Request) SetTokenEntry(te *TokenEntry) { + r.tokenEntry = te +} + // RenewRequest creates the structure of the renew request. func RenewRequest(path string, secret *Secret, data map[string]interface{}) *Request { return &Request{ diff --git a/logical/token.go b/logical/token.go new file mode 100644 index 0000000000..337791e486 --- /dev/null +++ b/logical/token.go @@ -0,0 +1,119 @@ +package logical + +import ( + "time" + + sockaddr "github.com/hashicorp/go-sockaddr" +) + +// TokenEntry is used to represent a given token +type TokenEntry struct { + // ID of this entry, generally a random UUID + ID string `json:"id" mapstructure:"id" structs:"id" sentinel:""` + + // Accessor for this token, a random UUID + Accessor string `json:"accessor" mapstructure:"accessor" structs:"accessor" sentinel:""` + + // Parent token, used for revocation trees + Parent string `json:"parent" mapstructure:"parent" structs:"parent" sentinel:""` + + // Which named policies should be used + Policies []string `json:"policies" mapstructure:"policies" structs:"policies"` + + // Used for audit trails, this is something like "auth/user/login" + Path string `json:"path" mapstructure:"path" structs:"path"` + + // Used for auditing. This could include things like "source", "user", "ip" + Meta map[string]string `json:"meta" mapstructure:"meta" structs:"meta" sentinel:"meta"` + + // Used for operators to be able to associate with the source + DisplayName string `json:"display_name" mapstructure:"display_name" structs:"display_name"` + + // Used to restrict the number of uses (zero is unlimited). This is to + // support one-time-tokens (generalized). There are a few special values: + // if it's -1 it has run through its use counts and is executing its final + // use; if it's -2 it is tainted, which means revocation is currently + // running on it; and if it's -3 it's also tainted but revocation + // previously ran and failed, so this hints the tidy function to try it + // again. + NumUses int `json:"num_uses" mapstructure:"num_uses" structs:"num_uses"` + + // Time of token creation + CreationTime int64 `json:"creation_time" mapstructure:"creation_time" structs:"creation_time" sentinel:""` + + // Duration set when token was created + TTL time.Duration `json:"ttl" mapstructure:"ttl" structs:"ttl" sentinel:""` + + // Explicit maximum TTL on the token + ExplicitMaxTTL time.Duration `json:"explicit_max_ttl" mapstructure:"explicit_max_ttl" structs:"explicit_max_ttl" sentinel:""` + + // If set, the role that was used for parameters at creation time + Role string `json:"role" mapstructure:"role" structs:"role"` + + // If set, the period of the token. This is only used when created directly + // through the create endpoint; periods managed by roles or other auth + // backends are subject to those renewal rules. + Period time.Duration `json:"period" mapstructure:"period" structs:"period" sentinel:""` + + // These are the deprecated fields + DisplayNameDeprecated string `json:"DisplayName" mapstructure:"DisplayName" structs:"DisplayName" sentinel:""` + NumUsesDeprecated int `json:"NumUses" mapstructure:"NumUses" structs:"NumUses" sentinel:""` + CreationTimeDeprecated int64 `json:"CreationTime" mapstructure:"CreationTime" structs:"CreationTime" sentinel:""` + ExplicitMaxTTLDeprecated time.Duration `json:"ExplicitMaxTTL" mapstructure:"ExplicitMaxTTL" structs:"ExplicitMaxTTL" sentinel:""` + + EntityID string `json:"entity_id" mapstructure:"entity_id" structs:"entity_id"` + + // The set of CIDRs that this token can be used with + BoundCIDRs []*sockaddr.SockAddrMarshaler `json:"bound_cidrs"` +} + +func (te *TokenEntry) SentinelGet(key string) (interface{}, error) { + if te == nil { + return nil, nil + } + switch key { + case "period": + return te.Period, nil + + case "period_seconds": + return int64(te.Period.Seconds()), nil + + case "explicit_max_ttl": + return te.ExplicitMaxTTL, nil + + case "explicit_max_ttl_seconds": + return int64(te.ExplicitMaxTTL.Seconds()), nil + + case "creation_ttl": + return te.TTL, nil + + case "creation_ttl_seconds": + return int64(te.TTL.Seconds()), nil + + case "creation_time": + return time.Unix(te.CreationTime, 0).Format(time.RFC3339Nano), nil + + case "creation_time_unix": + return time.Unix(te.CreationTime, 0), nil + + case "meta", "metadata": + return te.Meta, nil + } + + return nil, nil +} + +func (te *TokenEntry) SentinelKeys() []string { + return []string{ + "period", + "period_seconds", + "explicit_max_ttl", + "explicit_max_ttl_seconds", + "creation_ttl", + "creation_ttl_seconds", + "creation_time", + "creation_time_unix", + "meta", + "metadata", + } +} diff --git a/vault/acl.go b/vault/acl.go index e86e79e35f..bc79205224 100644 --- a/vault/acl.go +++ b/vault/acl.go @@ -406,7 +406,7 @@ CHECK: ret.Allowed = true return } -func (c *Core) performPolicyChecks(ctx context.Context, acl *ACL, te *TokenEntry, req *logical.Request, inEntity *identity.Entity, opts *PolicyCheckOpts) (ret *AuthResults) { +func (c *Core) performPolicyChecks(ctx context.Context, acl *ACL, te *logical.TokenEntry, req *logical.Request, inEntity *identity.Entity, opts *PolicyCheckOpts) (ret *AuthResults) { ret = new(AuthResults) // First, perform normal ACL checks if requested. The only time no ACL diff --git a/vault/capabilities_test.go b/vault/capabilities_test.go index 40111af0a2..3684788383 100644 --- a/vault/capabilities_test.go +++ b/vault/capabilities_test.go @@ -69,7 +69,7 @@ path "secret/sample" { entityID := resp.Data["id"].(string) // Create a token for the entity and assign policy2 on the token - ent := &TokenEntry{ + ent := &logical.TokenEntry{ ID: "capabilitiestoken", Path: "secret/sample", Policies: []string{"policy2"}, @@ -135,7 +135,7 @@ func TestCapabilities(t *testing.T) { } // Create a token for the policy - ent := &TokenEntry{ + ent := &logical.TokenEntry{ ID: "capabilitiestoken", Path: "testpath", Policies: []string{"dev"}, diff --git a/vault/core_test.go b/vault/core_test.go index efb37cb4d6..ff28434745 100644 --- a/vault/core_test.go +++ b/vault/core_test.go @@ -276,7 +276,7 @@ func TestCore_Seal_BadToken(t *testing.T) { // GH-3497 func TestCore_Seal_SingleUse(t *testing.T) { c, keys, _ := TestCoreUnsealed(t) - c.tokenStore.create(context.Background(), &TokenEntry{ + c.tokenStore.create(context.Background(), &logical.TokenEntry{ ID: "foo", NumUses: 1, Policies: []string{"root"}, @@ -719,7 +719,7 @@ func TestCore_HandleLogin_Token(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - expect := &TokenEntry{ + expect := &logical.TokenEntry{ ID: clientToken, Accessor: te.Accessor, Parent: "", @@ -1022,7 +1022,7 @@ func TestCore_HandleRequest_CreateToken_Lease(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - expect := &TokenEntry{ + expect := &logical.TokenEntry{ ID: clientToken, Accessor: te.Accessor, Parent: root, @@ -1067,7 +1067,7 @@ func TestCore_HandleRequest_CreateToken_NoDefaultPolicy(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - expect := &TokenEntry{ + expect := &logical.TokenEntry{ ID: clientToken, Accessor: te.Accessor, Parent: root, diff --git a/vault/expiration.go b/vault/expiration.go index 66b069d477..6c38fc79a3 100644 --- a/vault/expiration.go +++ b/vault/expiration.go @@ -557,7 +557,7 @@ func (m *ExpirationManager) RevokePrefix(prefix string) error { // This is done by using the secondary index. It also removes the lease entry // for the token itself. As a result it should *ONLY* ever be called from the // token store's revokeSalted function. -func (m *ExpirationManager) RevokeByToken(te *TokenEntry) error { +func (m *ExpirationManager) RevokeByToken(te *logical.TokenEntry) error { defer metrics.MeasureSince([]string{"expire", "revoke-by-token"}, time.Now()) // Lookup the leases @@ -1227,7 +1227,7 @@ func (m *ExpirationManager) removeIndexByToken(token, leaseID string) error { // CreateOrFetchRevocationLeaseByToken is used to create or fetch the matching // leaseID for a particular token. The lease is set to expire immediately after // it's created. -func (m *ExpirationManager) CreateOrFetchRevocationLeaseByToken(te *TokenEntry) (string, error) { +func (m *ExpirationManager) CreateOrFetchRevocationLeaseByToken(te *logical.TokenEntry) (string, error) { // Fetch the saltedID of the token and construct the leaseID saltedID, err := m.tokenStore.SaltID(m.quitContext, te.ID) if err != nil { diff --git a/vault/expiration_test.go b/vault/expiration_test.go index e0650f17de..e0b93ec43b 100644 --- a/vault/expiration_test.go +++ b/vault/expiration_test.go @@ -736,7 +736,7 @@ func TestExpiration_RevokeByToken(t *testing.T) { } // Should nuke all the keys - te := &TokenEntry{ + te := &logical.TokenEntry{ ID: "foobarbaz", } if err := exp.RevokeByToken(te); err != nil { @@ -823,7 +823,7 @@ func TestExpiration_RevokeByToken_Blocking(t *testing.T) { } // Should nuke all the keys - te := &TokenEntry{ + te := &logical.TokenEntry{ ID: "foobarbaz", } if err := exp.RevokeByToken(te); err != nil { @@ -899,7 +899,7 @@ func TestExpiration_RenewToken(t *testing.T) { func TestExpiration_RenewToken_period(t *testing.T) { exp := mockExpiration(t) - root := &TokenEntry{ + root := &logical.TokenEntry{ Policies: []string{"root"}, Path: "auth/token/root", DisplayName: "root", diff --git a/vault/identity_store_test.go b/vault/identity_store_test.go index 8cae25f55e..ae44ae02f5 100644 --- a/vault/identity_store_test.go +++ b/vault/identity_store_test.go @@ -29,7 +29,7 @@ func TestIdentityStore_EntityIDPassthrough(t *testing.T) { } // Create a token with the above created entity set on it - ent := &TokenEntry{ + ent := &logical.TokenEntry{ ID: "testtokenid", Path: "test", Policies: []string{"root"}, @@ -221,7 +221,7 @@ func TestIdentityStore_WrapInfoInheritance(t *testing.T) { // Create a token which has EntityID set and has update permissions to // sys/wrapping/wrap - te := &TokenEntry{ + te := &logical.TokenEntry{ Path: "test", Policies: []string{"default", responseWrappingPolicyName}, EntityID: entityID, @@ -260,7 +260,7 @@ func TestIdentityStore_TokenEntityInheritance(t *testing.T) { ts := c.tokenStore // Create a token which has EntityID set - te := &TokenEntry{ + te := &logical.TokenEntry{ Path: "test", Policies: []string{"dev", "prod"}, EntityID: "testentityid", diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index 6b203f0294..cdf61e2d27 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -1283,7 +1283,7 @@ func TestSystemBackend_revokePrefixAuth_newUrl(t *testing.T) { exp := ts.expiration - te := &TokenEntry{ + te := &logical.TokenEntry{ ID: "foo", Path: "auth/github/login/bar", TTL: time.Hour, @@ -1346,7 +1346,7 @@ func TestSystemBackend_revokePrefixAuth_origUrl(t *testing.T) { exp := ts.expiration - te := &TokenEntry{ + te := &logical.TokenEntry{ ID: "foo", Path: "auth/github/login/bar", TTL: time.Hour, diff --git a/vault/request_handling.go b/vault/request_handling.go index cfde6f4858..df22ab727a 100644 --- a/vault/request_handling.go +++ b/vault/request_handling.go @@ -77,7 +77,7 @@ func (c *Core) fetchEntityAndDerivedPolicies(entityID string) (*identity.Entity, return entity, policies, err } -func (c *Core) fetchACLTokenEntryAndEntity(req *logical.Request) (*ACL, *TokenEntry, *identity.Entity, error) { +func (c *Core) fetchACLTokenEntryAndEntity(req *logical.Request) (*ACL, *logical.TokenEntry, *identity.Entity, error) { defer metrics.MeasureSince([]string{"core", "fetch_acl_and_token"}, time.Now()) // Ensure there is a client token @@ -91,10 +91,17 @@ func (c *Core) fetchACLTokenEntryAndEntity(req *logical.Request) (*ACL, *TokenEn } // Resolve the token policy - te, err := c.tokenStore.Lookup(c.activeContext, req.ClientToken) - if err != nil { - c.logger.Error("failed to lookup token", "error", err) - return nil, nil, nil, ErrInternalError + var te *logical.TokenEntry + switch req.TokenEntry() { + case nil: + var err error + te, err = c.tokenStore.Lookup(c.activeContext, req.ClientToken) + if err != nil { + c.logger.Error("failed to lookup token", "error", err) + return nil, nil, nil, ErrInternalError + } + default: + te = req.TokenEntry() } // Ensure the token is valid @@ -142,11 +149,11 @@ func (c *Core) fetchACLTokenEntryAndEntity(req *logical.Request) (*ACL, *TokenEn return acl, te, entity, nil } -func (c *Core) checkToken(ctx context.Context, req *logical.Request, unauth bool) (*logical.Auth, *TokenEntry, error) { +func (c *Core) checkToken(ctx context.Context, req *logical.Request, unauth bool) (*logical.Auth, *logical.TokenEntry, error) { defer metrics.MeasureSince([]string{"core", "check_token"}, time.Now()) var acl *ACL - var te *TokenEntry + var te *logical.TokenEntry var entity *identity.Entity var err error @@ -783,7 +790,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re } // Generate a token - te := TokenEntry{ + te := logical.TokenEntry{ Path: req.Path, Policies: auth.Policies, Meta: auth.Metadata, diff --git a/vault/token_store.go b/vault/token_store.go index 349a8696d1..4d50c31b7e 100644 --- a/vault/token_store.go +++ b/vault/token_store.go @@ -79,7 +79,7 @@ var ( // is particularly useful to fetch the accessor of the client token and get it // populated in the logical request along with the client token. The accessor // of the client token can get audit logged. -func (c *Core) LookupToken(token string) (*TokenEntry, error) { +func (c *Core) LookupToken(token string) (*logical.TokenEntry, error) { if token == "" { return nil, fmt.Errorf("missing client token") } @@ -551,118 +551,6 @@ func (ts *TokenStore) Salt(ctx context.Context) (*salt.Salt, error) { return salt, nil } -// TokenEntry is used to represent a given token -type TokenEntry struct { - // ID of this entry, generally a random UUID - ID string `json:"id" mapstructure:"id" structs:"id" sentinel:""` - - // Accessor for this token, a random UUID - Accessor string `json:"accessor" mapstructure:"accessor" structs:"accessor" sentinel:""` - - // Parent token, used for revocation trees - Parent string `json:"parent" mapstructure:"parent" structs:"parent" sentinel:""` - - // Which named policies should be used - Policies []string `json:"policies" mapstructure:"policies" structs:"policies"` - - // Used for audit trails, this is something like "auth/user/login" - Path string `json:"path" mapstructure:"path" structs:"path"` - - // Used for auditing. This could include things like "source", "user", "ip" - Meta map[string]string `json:"meta" mapstructure:"meta" structs:"meta" sentinel:"meta"` - - // Used for operators to be able to associate with the source - DisplayName string `json:"display_name" mapstructure:"display_name" structs:"display_name"` - - // Used to restrict the number of uses (zero is unlimited). This is to - // support one-time-tokens (generalized). There are a few special values: - // if it's -1 it has run through its use counts and is executing its final - // use; if it's -2 it is tainted, which means revocation is currently - // running on it; and if it's -3 it's also tainted but revocation - // previously ran and failed, so this hints the tidy function to try it - // again. - NumUses int `json:"num_uses" mapstructure:"num_uses" structs:"num_uses"` - - // Time of token creation - CreationTime int64 `json:"creation_time" mapstructure:"creation_time" structs:"creation_time" sentinel:""` - - // Duration set when token was created - TTL time.Duration `json:"ttl" mapstructure:"ttl" structs:"ttl" sentinel:""` - - // Explicit maximum TTL on the token - ExplicitMaxTTL time.Duration `json:"explicit_max_ttl" mapstructure:"explicit_max_ttl" structs:"explicit_max_ttl" sentinel:""` - - // If set, the role that was used for parameters at creation time - Role string `json:"role" mapstructure:"role" structs:"role"` - - // If set, the period of the token. This is only used when created directly - // through the create endpoint; periods managed by roles or other auth - // backends are subject to those renewal rules. - Period time.Duration `json:"period" mapstructure:"period" structs:"period" sentinel:""` - - // These are the deprecated fields - DisplayNameDeprecated string `json:"DisplayName" mapstructure:"DisplayName" structs:"DisplayName" sentinel:""` - NumUsesDeprecated int `json:"NumUses" mapstructure:"NumUses" structs:"NumUses" sentinel:""` - CreationTimeDeprecated int64 `json:"CreationTime" mapstructure:"CreationTime" structs:"CreationTime" sentinel:""` - ExplicitMaxTTLDeprecated time.Duration `json:"ExplicitMaxTTL" mapstructure:"ExplicitMaxTTL" structs:"ExplicitMaxTTL" sentinel:""` - - EntityID string `json:"entity_id" mapstructure:"entity_id" structs:"entity_id"` - - // The set of CIDRs that this token can be used with - BoundCIDRs []*sockaddr.SockAddrMarshaler `json:"bound_cidrs"` -} - -func (te *TokenEntry) SentinelGet(key string) (interface{}, error) { - if te == nil { - return nil, nil - } - switch key { - case "period": - return te.Period, nil - - case "period_seconds": - return int64(te.Period.Seconds()), nil - - case "explicit_max_ttl": - return te.ExplicitMaxTTL, nil - - case "explicit_max_ttl_seconds": - return int64(te.ExplicitMaxTTL.Seconds()), nil - - case "creation_ttl": - return te.TTL, nil - - case "creation_ttl_seconds": - return int64(te.TTL.Seconds()), nil - - case "creation_time": - return time.Unix(te.CreationTime, 0).Format(time.RFC3339Nano), nil - - case "creation_time_unix": - return time.Unix(te.CreationTime, 0), nil - - case "meta", "metadata": - return te.Meta, nil - } - - return nil, nil -} - -func (te *TokenEntry) SentinelKeys() []string { - return []string{ - "period", - "period_seconds", - "explicit_max_ttl", - "explicit_max_ttl_seconds", - "creation_ttl", - "creation_ttl_seconds", - "creation_time", - "creation_time_unix", - "meta", - "metadata", - } -} - // tsRoleEntry contains token store role information type tsRoleEntry struct { // The name of the role. Embedded so it can be used for pathing @@ -720,8 +608,8 @@ func (ts *TokenStore) SaltID(ctx context.Context, id string) (string, error) { } // RootToken is used to generate a new token with root privileges and no parent -func (ts *TokenStore) rootToken(ctx context.Context) (*TokenEntry, error) { - te := &TokenEntry{ +func (ts *TokenStore) rootToken(ctx context.Context) (*logical.TokenEntry, error) { + te := &logical.TokenEntry{ Policies: []string{"root"}, Path: "auth/token/root", DisplayName: "root", @@ -763,7 +651,7 @@ func (ts *TokenStore) tokenStoreAccessorList(ctx context.Context, req *logical.R // createAccessor is used to create an identifier for the token ID. // A storage index, mapping the accessor to the token ID is also created. -func (ts *TokenStore) createAccessor(ctx context.Context, entry *TokenEntry) error { +func (ts *TokenStore) createAccessor(ctx context.Context, entry *logical.TokenEntry) error { defer metrics.MeasureSince([]string{"token", "createAccessor"}, time.Now()) // Create a random accessor @@ -798,7 +686,7 @@ func (ts *TokenStore) createAccessor(ctx context.Context, entry *TokenEntry) err // Create is used to create a new token entry. The entry is assigned // a newly generated ID if not provided. -func (ts *TokenStore) create(ctx context.Context, entry *TokenEntry) error { +func (ts *TokenStore) create(ctx context.Context, entry *logical.TokenEntry) error { defer metrics.MeasureSince([]string{"token", "create"}, time.Now()) // Generate an ID if necessary if entry.ID == "" { @@ -830,14 +718,14 @@ func (ts *TokenStore) create(ctx context.Context, entry *TokenEntry) error { // Store is used to store an updated token entry without writing the // secondary index. -func (ts *TokenStore) store(ctx context.Context, entry *TokenEntry) error { +func (ts *TokenStore) store(ctx context.Context, entry *logical.TokenEntry) error { defer metrics.MeasureSince([]string{"token", "store"}, time.Now()) return ts.storeCommon(ctx, entry, false) } // storeCommon handles the actual storage of an entry, possibly generating // secondary indexes -func (ts *TokenStore) storeCommon(ctx context.Context, entry *TokenEntry, writeSecondary bool) error { +func (ts *TokenStore) storeCommon(ctx context.Context, entry *logical.TokenEntry, writeSecondary bool) error { saltedID, err := ts.SaltID(ctx, entry.ID) if err != nil { return err @@ -895,7 +783,7 @@ func (ts *TokenStore) storeCommon(ctx context.Context, entry *TokenEntry, writeS // locking here isn't perfect, as other parts of the code may update an entry, // but usually none after the entry is already created...so this is pretty // good. -func (ts *TokenStore) UseToken(ctx context.Context, te *TokenEntry) (*TokenEntry, error) { +func (ts *TokenStore) UseToken(ctx context.Context, te *logical.TokenEntry) (*logical.TokenEntry, error) { if te == nil { return nil, fmt.Errorf("invalid token entry provided for use count decrementing") } @@ -955,7 +843,7 @@ func (ts *TokenStore) UseToken(ctx context.Context, te *TokenEntry) (*TokenEntry return te, nil } -func (ts *TokenStore) UseTokenByID(ctx context.Context, id string) (*TokenEntry, error) { +func (ts *TokenStore) UseTokenByID(ctx context.Context, id string) (*logical.TokenEntry, error) { te, err := ts.Lookup(ctx, id) if err != nil { return te, err @@ -965,7 +853,7 @@ func (ts *TokenStore) UseTokenByID(ctx context.Context, id string) (*TokenEntry, } // Lookup is used to find a token given its ID. It acquires a read lock, then calls lookupSalted. -func (ts *TokenStore) Lookup(ctx context.Context, id string) (*TokenEntry, error) { +func (ts *TokenStore) Lookup(ctx context.Context, id string) (*logical.TokenEntry, error) { defer metrics.MeasureSince([]string{"token", "lookup"}, time.Now()) if id == "" { return nil, fmt.Errorf("cannot lookup blank token") @@ -984,7 +872,7 @@ func (ts *TokenStore) Lookup(ctx context.Context, id string) (*TokenEntry, error // lookupTainted is used to find a token that may or maynot be tainted given its // ID. It acquires a read lock, then calls lookupSalted. -func (ts *TokenStore) lookupTainted(ctx context.Context, id string) (*TokenEntry, error) { +func (ts *TokenStore) lookupTainted(ctx context.Context, id string) (*logical.TokenEntry, error) { defer metrics.MeasureSince([]string{"token", "lookup"}, time.Now()) if id == "" { return nil, fmt.Errorf("cannot lookup blank token") @@ -1004,7 +892,7 @@ func (ts *TokenStore) lookupTainted(ctx context.Context, id string) (*TokenEntry // lookupSalted is used to find a token given its salted ID. If tainted is // true, entries that are in some revocation state (currently, indicated by num // uses < 0), the entry will be returned anyways -func (ts *TokenStore) lookupSalted(ctx context.Context, saltedID string, tainted bool) (*TokenEntry, error) { +func (ts *TokenStore) lookupSalted(ctx context.Context, saltedID string, tainted bool) (*logical.TokenEntry, error) { // Lookup token path := lookupPrefix + saltedID raw, err := ts.view.Get(ctx, path) @@ -1018,7 +906,7 @@ func (ts *TokenStore) lookupSalted(ctx context.Context, saltedID string, tainted } // Unmarshal the token - entry := new(TokenEntry) + entry := new(logical.TokenEntry) if err := jsonutil.DecodeJSON(raw.Value, entry); err != nil { return nil, errwrap.Wrapf("failed to decode entry: {{err}}", err) } @@ -1075,7 +963,7 @@ func (ts *TokenStore) lookupSalted(ctx context.Context, saltedID string, tainted return nil, errwrap.Wrapf("failed to fetch lease times: {{err}}", err) } - var ret *TokenEntry + var ret *logical.TokenEntry switch { // It's a root token with unlimited creation TTL (so never had an @@ -1551,10 +1439,10 @@ func (ts *TokenStore) handleTidy(ctx context.Context, req *logical.Request, data if te == nil { ts.logger.Info("deleting token with nil entry", "salted_token", saltedID) - // RevokeByToken expects a '*TokenEntry'. For the + // RevokeByToken expects a '*logical.TokenEntry'. For the // purposes of tidying, it is sufficient if the token // entry only has ID set. - tokenEntry := &TokenEntry{ + tokenEntry := &logical.TokenEntry{ ID: accessorEntry.TokenID, } @@ -1754,7 +1642,7 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque } // Setup the token entry - te := TokenEntry{ + te := logical.TokenEntry{ Parent: req.ClientToken, // The mount point is always the same since we have only one token diff --git a/vault/token_store_test.go b/vault/token_store_test.go index 21b188fbfd..abb494675c 100644 --- a/vault/token_store_test.go +++ b/vault/token_store_test.go @@ -108,7 +108,7 @@ func TestTokenStore_TokenEntryUpgrade(t *testing.T) { } // Test the default case to ensure there are no regressions - ent := &TokenEntry{ + ent := &logical.TokenEntry{ DisplayName: "test-display-name", Path: "test", Policies: []string{"dev", "ops"}, @@ -152,7 +152,7 @@ func TestTokenStore_TokenEntryUpgrade(t *testing.T) { } // Fill in the deprecated fields and read out from proper fields - ent = &TokenEntry{ + ent = &logical.TokenEntry{ Path: "test", Policies: []string{"dev", "ops"}, DisplayNameDeprecated: "test-display-name", @@ -196,7 +196,7 @@ func TestTokenStore_TokenEntryUpgrade(t *testing.T) { } // Check if NumUses picks up a lower value - ent = &TokenEntry{ + ent = &logical.TokenEntry{ Path: "test", NumUses: 5, NumUsesDeprecated: 10, @@ -229,7 +229,7 @@ func TestTokenStore_TokenEntryUpgrade(t *testing.T) { // Switch the values from deprecated and proper field and check if the // lower value is still getting picked up - ent = &TokenEntry{ + ent = &logical.TokenEntry{ Path: "test", NumUses: 10, NumUsesDeprecated: 5, @@ -301,7 +301,7 @@ func testMakeTokenViaRequest(t testing.TB, ts *TokenStore, req *logical.Request) return resp } -func testMakeTokenDirectly(t testing.TB, ts *TokenStore, te *TokenEntry) { +func testMakeTokenDirectly(t testing.TB, ts *TokenStore, te *logical.TokenEntry) { if err := ts.create(context.Background(), te); err != nil { t.Fatal(err) } @@ -346,7 +346,7 @@ func TestTokenStore_AccessorIndex(t *testing.T) { c, _, _ := TestCoreUnsealed(t) ts := c.tokenStore - ent := &TokenEntry{ + ent := &logical.TokenEntry{ Path: "test", Policies: []string{"dev", "ops"}, TTL: time.Hour, @@ -603,7 +603,7 @@ func TestTokenStore_CreateLookup(t *testing.T) { c, _, _ := TestCoreUnsealed(t) ts := c.tokenStore - ent := &TokenEntry{ + ent := &logical.TokenEntry{ Path: "test", Policies: []string{"dev", "ops"}, TTL: time.Hour, @@ -642,7 +642,7 @@ func TestTokenStore_CreateLookup_ProvidedID(t *testing.T) { c, _, _ := TestCoreUnsealed(t) ts := c.tokenStore - ent := &TokenEntry{ + ent := &logical.TokenEntry{ ID: "foobarbaz", Path: "test", Policies: []string{"dev", "ops"}, @@ -685,7 +685,7 @@ func TestTokenStore_CreateLookup_ExpirationInRestoreMode(t *testing.T) { c, _, _ := TestCoreUnsealed(t) ts := c.tokenStore - ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}} + ent := &logical.TokenEntry{Path: "test", Policies: []string{"dev", "ops"}} if err := ts.create(context.Background(), ent); err != nil { t.Fatalf("err: %v", err) } @@ -778,7 +778,7 @@ func TestTokenStore_UseToken(t *testing.T) { } // Create a restricted token - ent = &TokenEntry{ + ent = &logical.TokenEntry{ Path: "test", Policies: []string{"dev", "ops"}, NumUses: 2, @@ -835,7 +835,7 @@ func TestTokenStore_Revoke(t *testing.T) { c, _, _ := TestCoreUnsealed(t) ts := c.tokenStore - ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}} + ent := &logical.TokenEntry{Path: "test", Policies: []string{"dev", "ops"}} if err := ts.create(context.Background(), ent); err != nil { t.Fatalf("err: %v", err) } @@ -871,7 +871,7 @@ func TestTokenStore_Revoke_Leases(t *testing.T) { t.Fatal(err) } - ent := &TokenEntry{Path: "test", Policies: []string{"dev", "ops"}} + ent := &logical.TokenEntry{Path: "test", Policies: []string{"dev", "ops"}} if err := ts.create(context.Background(), ent); err != nil { t.Fatalf("err: %v", err) } @@ -920,14 +920,14 @@ func TestTokenStore_Revoke_Orphan(t *testing.T) { c, _, _ := TestCoreUnsealed(t) ts := c.tokenStore - ent := &TokenEntry{ + ent := &logical.TokenEntry{ Path: "test", Policies: []string{"dev", "ops"}, TTL: time.Hour, } testMakeTokenDirectly(t, ts, ent) - ent2 := &TokenEntry{ + ent2 := &logical.TokenEntry{ Parent: ent.ID, TTL: time.Hour, } @@ -1006,24 +1006,24 @@ func BenchmarkTokenStore_RevokeTree(b *testing.B) { // Builds a TokenTree of a specified depth, so that // we may run revoke tests on it. -func buildTokenTree(t testing.TB, ts *TokenStore, depth uint64) (root *TokenEntry, children []*TokenEntry) { - root = &TokenEntry{ +func buildTokenTree(t testing.TB, ts *TokenStore, depth uint64) (root *logical.TokenEntry, children []*logical.TokenEntry) { + root = &logical.TokenEntry{ TTL: time.Hour, } testMakeTokenDirectly(t, ts, root) - frontier := []*TokenEntry{root} + frontier := []*logical.TokenEntry{root} current := uint64(0) for current < depth { - next := make([]*TokenEntry, 0, 2*len(frontier)) + next := make([]*logical.TokenEntry, 0, 2*len(frontier)) for _, node := range frontier { - left := &TokenEntry{ + left := &logical.TokenEntry{ Parent: node.ID, TTL: time.Hour, } testMakeTokenDirectly(t, ts, left) - right := &TokenEntry{ + right := &logical.TokenEntry{ Parent: node.ID, TTL: time.Hour, } @@ -1043,24 +1043,24 @@ func TestTokenStore_RevokeSelf(t *testing.T) { exp := mockExpiration(t) ts := exp.tokenStore - ent1 := &TokenEntry{ + ent1 := &logical.TokenEntry{ TTL: time.Hour, } testMakeTokenDirectly(t, ts, ent1) - ent2 := &TokenEntry{ + ent2 := &logical.TokenEntry{ Parent: ent1.ID, TTL: time.Hour, } testMakeTokenDirectly(t, ts, ent2) - ent3 := &TokenEntry{ + ent3 := &logical.TokenEntry{ Parent: ent2.ID, TTL: time.Hour, } testMakeTokenDirectly(t, ts, ent3) - ent4 := &TokenEntry{ + ent4 := &logical.TokenEntry{ Parent: ent2.ID, TTL: time.Hour, } @@ -1075,7 +1075,7 @@ func TestTokenStore_RevokeSelf(t *testing.T) { } lookup := []string{ent1.ID, ent2.ID, ent3.ID, ent4.ID} - var out *TokenEntry + var out *logical.TokenEntry for _, id := range lookup { var found bool for i := 0; i < 10; i++ { @@ -1135,7 +1135,7 @@ func TestTokenStore_HandleRequest_CreateToken_DisplayName(t *testing.T) { t.Fatalf("err: %v\nresp: %#v", err, resp) } - expected := &TokenEntry{ + expected := &logical.TokenEntry{ ID: resp.Auth.ClientToken, Accessor: resp.Auth.Accessor, Parent: root, @@ -1167,7 +1167,7 @@ func TestTokenStore_HandleRequest_CreateToken_NumUses(t *testing.T) { t.Fatalf("err: %v\nresp: %#v", err, resp) } - expected := &TokenEntry{ + expected := &logical.TokenEntry{ ID: resp.Auth.ClientToken, Accessor: resp.Auth.Accessor, Parent: root, @@ -1234,7 +1234,7 @@ func TestTokenStore_HandleRequest_CreateToken_NoPolicy(t *testing.T) { t.Fatalf("err: %v\nresp: %#v", err, resp) } - expected := &TokenEntry{ + expected := &logical.TokenEntry{ ID: resp.Auth.ClientToken, Accessor: resp.Auth.Accessor, Parent: root, diff --git a/vault/wrapping.go b/vault/wrapping.go index 6c43613707..5f2b59d5c5 100644 --- a/vault/wrapping.go +++ b/vault/wrapping.go @@ -109,7 +109,7 @@ DONELISTHANDLING: // wrapping token ID in the audit logs, so that it can be determined from // the audit logs whether the token was ever actually used. creationTime := time.Now() - te := TokenEntry{ + te := logical.TokenEntry{ Path: req.Path, Policies: []string{"response-wrapping"}, CreationTime: creationTime.Unix(),