oss changes (#15487)

* oss changes

* add changelog
This commit is contained in:
Pratyoy Mukhopadhyay 2022-05-18 09:16:13 -07:00 committed by GitHub
parent 561d8d45f8
commit 62c09bc2be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 43 additions and 28 deletions

View File

@ -283,6 +283,7 @@ func (f *AuditFormatter) FormatResponse(ctx context.Context, w io.Writer, config
Metadata: auth.Metadata, Metadata: auth.Metadata,
RemainingUses: req.ClientTokenRemainingUses, RemainingUses: req.ClientTokenRemainingUses,
EntityID: auth.EntityID, EntityID: auth.EntityID,
EntityCreated: auth.EntityCreated,
TokenType: auth.TokenType.String(), TokenType: auth.TokenType.String(),
TokenTTL: int64(auth.TTL.Seconds()), TokenTTL: int64(auth.TTL.Seconds()),
}, },
@ -415,6 +416,7 @@ type AuditAuth struct {
NumUses int `json:"num_uses,omitempty"` NumUses int `json:"num_uses,omitempty"`
RemainingUses int `json:"remaining_uses,omitempty"` RemainingUses int `json:"remaining_uses,omitempty"`
EntityID string `json:"entity_id,omitempty"` EntityID string `json:"entity_id,omitempty"`
EntityCreated bool `json:"entity_created,omitempty"`
TokenType string `json:"token_type,omitempty"` TokenType string `json:"token_type,omitempty"`
TokenTTL int64 `json:"token_ttl,omitempty"` TokenTTL int64 `json:"token_ttl,omitempty"`
TokenIssueTime string `json:"token_issue_time,omitempty"` TokenIssueTime string `json:"token_issue_time,omitempty"`

3
changelog/15487.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:improvement
audit: added entity_created boolean to audit log, set when login operations create an entity
```

View File

@ -108,6 +108,9 @@ type Auth struct {
// MFARequirement // MFARequirement
MFARequirement *MFARequirement `json:"mfa_requirement"` 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 { func (a *Auth) GoString() string {

View File

@ -269,7 +269,7 @@ func TestCoreMetrics_EntityGauges(t *testing.T) {
Name: "githubuser", Name: "githubuser",
} }
entity, err := is.CreateOrFetchEntity(ctx, alias1) entity, _, err := is.CreateOrFetchEntity(ctx, alias1)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -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 // CreateOrFetchEntity creates a new entity. This is used by core to
// associate each login attempt by an alias to a unified entity in Vault. // 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()) defer metrics.MeasureSince([]string{"identity", "create_or_fetch_entity"}, time.Now())
var entity *identity.Entity var entity *identity.Entity
var err error var err error
var update bool var update bool
var entityCreated bool
if alias == nil { if alias == nil {
return nil, fmt.Errorf("alias is nil") return nil, false, fmt.Errorf("alias is nil")
} }
if alias.Name == "" { if alias.Name == "" {
return nil, fmt.Errorf("empty alias name") return nil, false, fmt.Errorf("empty alias name")
} }
mountValidationResp := i.router.ValidateMountByAccessor(alias.MountAccessor) mountValidationResp := i.router.ValidateMountByAccessor(alias.MountAccessor)
if mountValidationResp == nil { 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 { 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 // Check if an entity already exists for the given alias
entity, err = i.entityByAliasFactors(alias.MountAccessor, alias.Name, true) entity, err = i.entityByAliasFactors(alias.MountAccessor, alias.Name, true)
if err != nil { if err != nil {
return nil, err return nil, false, err
} }
if entity != nil && changedAliasIndex(entity, alias) == -1 { if entity != nil && changedAliasIndex(entity, alias) == -1 {
return entity, nil return entity, false, nil
} }
i.lock.Lock() 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 // Check if an entity was created before acquiring the lock
entity, err = i.entityByAliasFactorsInTxn(txn, alias.MountAccessor, alias.Name, true) entity, err = i.entityByAliasFactorsInTxn(txn, alias.MountAccessor, alias.Name, true)
if err != nil { if err != nil {
return nil, err return nil, false, err
} }
if entity != nil { if entity != nil {
idx := changedAliasIndex(entity, alias) idx := changedAliasIndex(entity, alias)
if idx == -1 { if idx == -1 {
return entity, nil return entity, false, nil
} }
a := entity.Aliases[idx] a := entity.Aliases[idx]
a.Metadata = alias.Metadata a.Metadata = alias.Metadata
@ -1160,7 +1161,7 @@ func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.
entity = new(identity.Entity) entity = new(identity.Entity)
err = i.sanitizeEntity(ctx, entity) err = i.sanitizeEntity(ctx, entity)
if err != nil { if err != nil {
return nil, err return nil, false, err
} }
// Create a new alias // Create a new alias
@ -1176,7 +1177,7 @@ func (i *IdentityStore) CreateOrFetchEntity(ctx context.Context, alias *logical.
err = i.sanitizeAlias(ctx, newAlias) err = i.sanitizeAlias(ctx, newAlias)
if err != nil { if err != nil {
return nil, err return nil, false, err
} }
i.logger.Debug("creating a new entity", "alias", newAlias) 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}, {"auth_method", newAlias.MountType},
{"mount_point", newAlias.MountPath}, {"mount_point", newAlias.MountPath},
}) })
entityCreated = true
} }
// Update MemDB and persist entity object // Update MemDB and persist entity object
err = i.upsertEntityInTxn(ctx, txn, entity, nil, true) err = i.upsertEntityInTxn(ctx, txn, entity, nil, true)
if err != nil { if err != nil {
return nil, err return nil, false, err
} }
txn.Commit() txn.Commit()
return entity.Clone() clonedEntity, err := entity.Clone()
return clonedEntity, entityCreated, err
} }
// changedAliasIndex searches an entity for changed alias metadata. // changedAliasIndex searches an entity for changed alias metadata.

View File

@ -182,7 +182,7 @@ func TestIdentityStore_EntityIDPassthrough(t *testing.T) {
} }
// Create an entity with GitHub alias // Create an entity with GitHub alias
entity, err := is.CreateOrFetchEntity(ctx, alias) entity, _, err := is.CreateOrFetchEntity(ctx, alias)
if err != nil { if err != nil {
t.Fatal(err) 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 { if err != nil {
t.Fatal(err) 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) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -309,7 +309,7 @@ func TestIdentityStore_CreateOrFetchEntity(t *testing.T) {
t.Fatalf("err:%v resp:%#v", err, resp) t.Fatalf("err:%v resp:%#v", err, resp)
} }
entity, err = is.CreateOrFetchEntity(ctx, alias) entity, _, err = is.CreateOrFetchEntity(ctx, alias)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -335,7 +335,7 @@ func TestIdentityStore_CreateOrFetchEntity(t *testing.T) {
"foo": "zzzz", "foo": "zzzz",
} }
entity, err = is.CreateOrFetchEntity(ctx, alias) entity, _, err = is.CreateOrFetchEntity(ctx, alias)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -599,7 +599,7 @@ func TestIdentityStore_MergeConflictingAliases(t *testing.T) {
t.Fatal(err) 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, MountAccessor: meGH.Accessor,
MountType: "github", MountType: "github",
Name: "githubuser", 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
expectSingleCount(t, sink, "identity.entity.creation") expectSingleCount(t, sink, "identity.entity.creation")
_, err = is.CreateOrFetchEntity(ctx, alias) _, _, err = is.CreateOrFetchEntity(ctx, alias)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -488,7 +488,6 @@ func (c *Core) handleCancelableRequest(ctx context.Context, req *logical.Request
req.Operation == logical.PatchOperation) { req.Operation == logical.PatchOperation) {
return logical.ErrorResponse("cannot write to a path ending in '/'"), nil return logical.ErrorResponse("cannot write to a path ending in '/'"), nil
} }
waitGroup, err := waitForReplicationState(ctx, c, req) waitGroup, err := waitForReplicationState(ctx, c, req)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1437,7 +1436,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
var err error var err error
// Fetch the entity for the alias, or create an entity if one // Fetch the entity for the alias, or create an entity if one
// doesn't exist. // doesn't exist.
entity, err = c.identityStore.CreateOrFetchEntity(ctx, auth.Alias) entity, entityCreated, err := c.identityStore.CreateOrFetchEntity(ctx, auth.Alias)
if err != nil { if err != nil {
switch auth.Alias.Local { switch auth.Alias.Local {
case true: 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") 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 goto CREATE_TOKEN
} }
// If the entity creation via forwarding was successful, update the bool flag
if entity != nil && err == nil {
entityCreated = true
}
default: default:
entity, err = possiblyForwardAliasCreation(ctx, c, err, auth, entity) entity, entityCreated, err = possiblyForwardAliasCreation(ctx, c, err, auth, entity)
} }
} }
if err != nil { if err != nil {
@ -1462,6 +1465,7 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
} }
auth.EntityID = entity.ID auth.EntityID = entity.ID
auth.EntityCreated = entityCreated
validAliases, err := c.identityStore.refreshExternalGroupMembershipsByEntityID(ctx, auth.EntityID, auth.GroupAliases, req.MountAccessor) validAliases, err := c.identityStore.refreshExternalGroupMembershipsByEntityID(ctx, auth.EntityID, auth.GroupAliases, req.MountAccessor)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err

View File

@ -50,8 +50,8 @@ func getAuthRegisterFunc(c *Core) (RegisterAuthFunc, error) {
return c.RegisterAuth, nil return c.RegisterAuth, nil
} }
func possiblyForwardAliasCreation(ctx context.Context, c *Core, inErr error, auth *logical.Auth, entity *identity.Entity) (*identity.Entity, error) { func possiblyForwardAliasCreation(ctx context.Context, c *Core, inErr error, auth *logical.Auth, entity *identity.Entity) (*identity.Entity, bool, error) {
return entity, inErr return entity, false, inErr
} }
var errCreateEntityUnimplemented = "create entity unimplemented in the server" var errCreateEntityUnimplemented = "create entity unimplemented in the server"

View File

@ -2591,7 +2591,7 @@ func (ts *TokenStore) handleCreateCommon(ctx context.Context, req *logical.Reque
} }
// Create or fetch entity from entity alias // 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 { if err != nil {
return nil, err return nil, err
} }