parent
561d8d45f8
commit
62c09bc2be
|
@ -283,6 +283,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
|
|||
Metadata: auth.Metadata,
|
||||
RemainingUses: req.ClientTokenRemainingUses,
|
||||
EntityID: auth.EntityID,
|
||||
EntityCreated: auth.EntityCreated,
|
||||
TokenType: auth.TokenType.String(),
|
||||
TokenTTL: int64(auth.TTL.Seconds()),
|
||||
},
|
||||
|
@ -415,6 +416,7 @@ type AuditAuth struct {
|
|||
NumUses int `json:"num_uses,omitempty"`
|
||||
RemainingUses int `json:"remaining_uses,omitempty"`
|
||||
EntityID string `json:"entity_id,omitempty"`
|
||||
EntityCreated bool `json:"entity_created,omitempty"`
|
||||
TokenType string `json:"token_type,omitempty"`
|
||||
TokenTTL int64 `json:"token_ttl,omitempty"`
|
||||
TokenIssueTime string `json:"token_issue_time,omitempty"`
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
audit: added entity_created boolean to audit log, set when login operations create an entity
|
||||
```
|
|
@ -108,6 +108,9 @@ type Auth struct {
|
|||
|
||||
// MFARequirement
|
||||
MFARequirement *MFARequirement `json:"mfa_requirement"`
|
||||
|
||||
// EntityCreated is set to true if an entity is created as part of a login request
|
||||
EntityCreated bool `json:"entity_created"`
|
||||
}
|
||||
|
||||
func (a *Auth) GoString() string {
|
||||
|
|
|
@ -269,7 +269,7 @@ func TestCoreMetrics_EntityGauges(t *testing.T) {
|
|||
Name: "githubuser",
|
||||
}
|
||||
|
||||
entity, err := is.CreateOrFetchEntity(ctx, alias1)
|
||||
entity, _, err := is.CreateOrFetchEntity(ctx, alias1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -1099,37 +1099,38 @@ func (i *IdentityStore) CreateEntity(ctx context.Context) (*identity.Entity, err
|
|||
|
||||
// CreateOrFetchEntity creates a new entity. This is used by core to
|
||||
// associate each login attempt by an alias to a unified entity in Vault.
|
||||
func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.Alias) (*identity.Entity, error) {
|
||||
func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.Alias) (*identity.Entity, bool, error) {
|
||||
defer metrics.MeasureSince([]string{"identity", "create_or_fetch_entity"}, time.Now())
|
||||
|
||||
var entity *identity.Entity
|
||||
var err error
|
||||
var update bool
|
||||
var entityCreated bool
|
||||
|
||||
if alias == nil {
|
||||
return nil, fmt.Errorf("alias is nil")
|
||||
return nil, false, fmt.Errorf("alias is nil")
|
||||
}
|
||||
|
||||
if alias.Name == "" {
|
||||
return nil, fmt.Errorf("empty alias name")
|
||||
return nil, false, fmt.Errorf("empty alias name")
|
||||
}
|
||||
|
||||
mountValidationResp := i.router.ValidateMountByAccessor(alias.MountAccessor)
|
||||
if mountValidationResp == nil {
|
||||
return nil, fmt.Errorf("invalid mount accessor %q", alias.MountAccessor)
|
||||
return nil, false, fmt.Errorf("invalid mount accessor %q", alias.MountAccessor)
|
||||
}
|
||||
|
||||
if mountValidationResp.MountType != alias.MountType {
|
||||
return nil, fmt.Errorf("mount accessor %q is not a mount of type %q", alias.MountAccessor, alias.MountType)
|
||||
return nil, false, fmt.Errorf("mount accessor %q is not a mount of type %q", alias.MountAccessor, alias.MountType)
|
||||
}
|
||||
|
||||
// Check if an entity already exists for the given alias
|
||||
entity, err = i.entityByAliasFactors(alias.MountAccessor, alias.Name, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
if entity != nil && changedAliasIndex(entity, alias) == -1 {
|
||||
return entity, nil
|
||||
return entity, false, nil
|
||||
}
|
||||
|
||||
i.lock.Lock()
|
||||
|
@ -1142,12 +1143,12 @@ func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.
|
|||
// Check if an entity was created before acquiring the lock
|
||||
entity, err = i.entityByAliasFactorsInTxn(txn, alias.MountAccessor, alias.Name, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
if entity != nil {
|
||||
idx := changedAliasIndex(entity, alias)
|
||||
if idx == -1 {
|
||||
return entity, nil
|
||||
return entity, false, nil
|
||||
}
|
||||
a := entity.Aliases[idx]
|
||||
a.Metadata = alias.Metadata
|
||||
|
@ -1160,7 +1161,7 @@ func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.
|
|||
entity = new(identity.Entity)
|
||||
err = i.sanitizeEntity(ctx, entity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Create a new alias
|
||||
|
@ -1176,7 +1177,7 @@ func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.
|
|||
|
||||
err = i.sanitizeAlias(ctx, newAlias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
i.logger.Debug("creating a new entity", "alias", newAlias)
|
||||
|
@ -1202,16 +1203,18 @@ func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.
|
|||
{"auth_method", newAlias.MountType},
|
||||
{"mount_point", newAlias.MountPath},
|
||||
})
|
||||
entityCreated = true
|
||||
}
|
||||
|
||||
// Update MemDB and persist entity object
|
||||
err = i.upsertEntityInTxn(ctx, txn, entity, nil, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
txn.Commit()
|
||||
return entity.Clone()
|
||||
clonedEntity, err := entity.Clone()
|
||||
return clonedEntity, entityCreated, err
|
||||
}
|
||||
|
||||
// changedAliasIndex searches an entity for changed alias metadata.
|
||||
|
|
|
@ -182,7 +182,7 @@ func TestIdentityStore_EntityIDPassthrough(t *testing.T) {
|
|||
}
|
||||
|
||||
// Create an entity with GitHub alias
|
||||
entity, err := is.CreateOrFetchEntity(ctx, alias)
|
||||
entity, _, err := is.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ func TestIdentityStore_CreateOrFetchEntity(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
entity, err := is.CreateOrFetchEntity(ctx, alias)
|
||||
entity, _, err := is.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ func TestIdentityStore_CreateOrFetchEntity(t *testing.T) {
|
|||
t.Fatalf("bad: alias name; expected: %q, actual: %q", alias.Name, entity.Aliases[0].Name)
|
||||
}
|
||||
|
||||
entity, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
entity, _, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ func TestIdentityStore_CreateOrFetchEntity(t *testing.T) {
|
|||
t.Fatalf("err:%v resp:%#v", err, resp)
|
||||
}
|
||||
|
||||
entity, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
entity, _, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ func TestIdentityStore_CreateOrFetchEntity(t *testing.T) {
|
|||
"foo": "zzzz",
|
||||
}
|
||||
|
||||
entity, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
entity, _, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -599,7 +599,7 @@ func TestIdentityStore_MergeConflictingAliases(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
newEntity, err := c.identityStore.CreateOrFetchEntity(namespace.RootContext(nil), &logical.Alias{
|
||||
newEntity, _, err := c.identityStore.CreateOrFetchEntity(namespace.RootContext(nil), &logical.Alias{
|
||||
MountAccessor: meGH.Accessor,
|
||||
MountType: "github",
|
||||
Name: "githubuser",
|
||||
|
@ -792,14 +792,14 @@ func TestIdentityStore_NewEntityCounter(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
_, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
_, _, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expectSingleCount(t, sink, "identity.entity.creation")
|
||||
|
||||
_, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
_, _, err = is.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -488,7 +488,6 @@ func (c *Core) handleCancelableRequest(ctx context.Context, req *logical.Request
|
|||
req.Operation == logical.PatchOperation) {
|
||||
return logical.ErrorResponse("cannot write to a path ending in '/'"), nil
|
||||
}
|
||||
|
||||
waitGroup, err := waitForReplicationState(ctx, c, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1437,7 +1436,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
|
|||
var err error
|
||||
// Fetch the entity for the alias, or create an entity if one
|
||||
// doesn't exist.
|
||||
entity, err = c.identityStore.CreateOrFetchEntity(ctx, auth.Alias)
|
||||
entity, entityCreated, err := c.identityStore.CreateOrFetchEntity(ctx, auth.Alias)
|
||||
if err != nil {
|
||||
switch auth.Alias.Local {
|
||||
case true:
|
||||
|
@ -1446,8 +1445,12 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
|
|||
resp.AddWarning("primary cluster doesn't yet issue entities for local auth mounts; falling back to not issuing entities for local auth mounts")
|
||||
goto CREATE_TOKEN
|
||||
}
|
||||
// If the entity creation via forwarding was successful, update the bool flag
|
||||
if entity != nil && err == nil {
|
||||
entityCreated = true
|
||||
}
|
||||
default:
|
||||
entity, err = possiblyForwardAliasCreation(ctx, c, err, auth, entity)
|
||||
entity, entityCreated, err = possiblyForwardAliasCreation(ctx, c, err, auth, entity)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -1462,6 +1465,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
|
|||
}
|
||||
|
||||
auth.EntityID = entity.ID
|
||||
auth.EntityCreated = entityCreated
|
||||
validAliases, err := c.identityStore.refreshExternalGroupMembershipsByEntityID(ctx, auth.EntityID, auth.GroupAliases, req.MountAccessor)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
|
@ -50,8 +50,8 @@ func getAuthRegisterFunc(c *Core) (RegisterAuthFunc, error) {
|
|||
return c.RegisterAuth, nil
|
||||
}
|
||||
|
||||
func possiblyForwardAliasCreation(ctx context.Context, c *Core, inErr error, auth *logical.Auth, entity *identity.Entity) (*identity.Entity, error) {
|
||||
return entity, inErr
|
||||
func possiblyForwardAliasCreation(ctx context.Context, c *Core, inErr error, auth *logical.Auth, entity *identity.Entity) (*identity.Entity, bool, error) {
|
||||
return entity, false, inErr
|
||||
}
|
||||
|
||||
var errCreateEntityUnimplemented = "create entity unimplemented in the server"
|
||||
|
|
|
@ -2591,7 +2591,7 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
|
|||
}
|
||||
|
||||
// Create or fetch entity from entity alias
|
||||
entity, err := ts.core.identityStore.CreateOrFetchEntity(ctx, alias)
|
||||
entity, _, err := ts.core.identityStore.CreateOrFetchEntity(ctx, alias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue