Skip to content

Commit

Permalink
oss changes (hashicorp#15487)
Browse files Browse the repository at this point in the history
* oss changes

* add changelog
  • Loading branch information
pmmukh authored and Gabrielopesantos committed Jun 6, 2022
1 parent 52f651a commit d64063f
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 28 deletions.
2 changes: 2 additions & 0 deletions audit/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()),
},
Expand Down Expand Up @@ -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"`
Expand Down
3 changes: 3 additions & 0 deletions changelog/15487.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
audit: added entity_created boolean to audit log, set when login operations create an entity
```
3 changes: 3 additions & 0 deletions sdk/logical/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion vault/core_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
29 changes: 16 additions & 13 deletions vault/identity_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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.
Expand Down
16 changes: 8 additions & 8 deletions vault/identity_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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)
}
Expand Down
10 changes: 7 additions & 3 deletions vault/request_handling.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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 {
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions vault/request_handling_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion vault/token_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit d64063f

Please sign in to comment.