Skip to content

Commit

Permalink
backport of commit 35a5fbf
Browse files Browse the repository at this point in the history
  • Loading branch information
maxb authored Aug 21, 2023
1 parent 8e68410 commit ac23c49
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 20 deletions.
3 changes: 3 additions & 0 deletions changelog/18809.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
activity (enterprise): Fix misattribution of entities to no or child namespace auth methods
```
28 changes: 17 additions & 11 deletions vault/activity_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,6 @@ type segmentInfo struct {
tokenCount *activity.TokenCount
}

type clients struct {
distinctEntities uint64
distinctNonEntities uint64
}

// ActivityLog tracks unique entity counts and non-entity token counts.
// It handles assembling log fragments (and sending them to the active
// node), writing log segments, and precomputing queries.
Expand Down Expand Up @@ -1867,39 +1862,50 @@ func (a *ActivityLog) loadConfigOrDefault(ctx context.Context) (activityConfig,

// HandleTokenUsage adds the TokenEntry to the current fragment of the activity log
// This currently occurs on token usage only.
func (a *ActivityLog) HandleTokenUsage(ctx context.Context, entry *logical.TokenEntry, clientID string, isTWE bool) {
func (a *ActivityLog) HandleTokenUsage(ctx context.Context, entry *logical.TokenEntry, clientID string, isTWE bool) error {
// First, check if a is enabled, so as to avoid the cost of creating an ID for
// tokens without entities in the case where it not.
a.fragmentLock.RLock()
if !a.enabled {
a.fragmentLock.RUnlock()
return
return nil
}
a.fragmentLock.RUnlock()

// Do not count wrapping tokens in client count
if IsWrappingToken(entry) {
return
return nil
}

// Do not count root tokens in client count.
if entry.IsRoot() {
return
return nil
}

// Tokens created for the purpose of Link should bypass counting for billing purposes
if entry.InternalMeta != nil && entry.InternalMeta[IgnoreForBilling] == "true" {
return
return nil
}

// Look up the mount accessor of the auth method that issued the token, taking care to resolve the token path
// against the token namespace, which may not be the same as the request namespace!
tokenNS, err := NamespaceByID(ctx, entry.NamespaceID, a.core)
if err != nil {
return err
}
if tokenNS == nil {
return namespace.ErrNoNamespace
}
tokenCtx := namespace.ContextWithNamespace(ctx, tokenNS)
mountAccessor := ""
mountEntry := a.core.router.MatchingMountEntry(ctx, entry.Path)
mountEntry := a.core.router.MatchingMountEntry(tokenCtx, entry.Path)
if mountEntry != nil {
mountAccessor = mountEntry.Accessor
}

// Parse an entry's client ID and add it to the activity log
a.AddClientToFragment(clientID, entry.NamespaceID, entry.CreationTime, isTWE, mountAccessor)
return nil
}

func (a *ActivityLog) namespaceToLabel(ctx context.Context, nsID string) string {
Expand Down
24 changes: 18 additions & 6 deletions vault/activity_log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ func TestActivityLog_Creation_WrappingTokens(t *testing.T) {
}

id, isTWE := te.CreateClientID()
a.HandleTokenUsage(context.Background(), te, id, isTWE)
err := a.HandleTokenUsage(context.Background(), te, id, isTWE)
if err != nil {
t.Fatal(err)
}

a.fragmentLock.Lock()
if a.fragment != nil {
Expand All @@ -150,7 +153,10 @@ func TestActivityLog_Creation_WrappingTokens(t *testing.T) {
}

id, isTWE = teNew.CreateClientID()
a.HandleTokenUsage(context.Background(), teNew, id, isTWE)
err = a.HandleTokenUsage(context.Background(), teNew, id, isTWE)
if err != nil {
t.Fatal(err)
}

a.fragmentLock.Lock()
if a.fragment != nil {
Expand Down Expand Up @@ -377,18 +383,24 @@ func TestActivityLog_SaveTokensToStorageDoesNotUpdateTokenCount(t *testing.T) {
tokenPath := fmt.Sprintf("%sdirecttokens/%d/0", ActivityLogPrefix, a.GetStartTimestamp())
clientPath := fmt.Sprintf("sys/counters/activity/log/entity/%d/0", a.GetStartTimestamp())
// Create some entries without entityIDs
tokenEntryOne := logical.TokenEntry{NamespaceID: "ns1_id", Policies: []string{"hi"}}
entityEntry := logical.TokenEntry{EntityID: "foo", NamespaceID: "ns1_id", Policies: []string{"hi"}}
tokenEntryOne := logical.TokenEntry{NamespaceID: namespace.RootNamespaceID, Policies: []string{"hi"}}
entityEntry := logical.TokenEntry{EntityID: "foo", NamespaceID: namespace.RootNamespaceID, Policies: []string{"hi"}}

idNonEntity, isTWE := tokenEntryOne.CreateClientID()

for i := 0; i < 3; i++ {
a.HandleTokenUsage(ctx, &tokenEntryOne, idNonEntity, isTWE)
err := a.HandleTokenUsage(ctx, &tokenEntryOne, idNonEntity, isTWE)
if err != nil {
t.Fatal(err)
}
}

idEntity, isTWE := entityEntry.CreateClientID()
for i := 0; i < 2; i++ {
a.HandleTokenUsage(ctx, &entityEntry, idEntity, isTWE)
err := a.HandleTokenUsage(ctx, &entityEntry, idEntity, isTWE)
if err != nil {
t.Fatal(err)
}
}
err := a.saveCurrentSegmentToStorage(ctx, false)
if err != nil {
Expand Down
9 changes: 6 additions & 3 deletions vault/request_handling.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,12 @@ func (c *Core) CheckToken(ctx context.Context, req *logical.Request, unauth bool
var te *logical.TokenEntry
var entity *identity.Entity
var identityPolicies map[string][]string
var err error

// Even if unauth, if a token is provided, there's little reason not to
// gather as much info as possible for the audit log and to e.g. control
// trace mode for EGPs.
if !unauth || (unauth && req.ClientToken != "") {
var err error
acl, te, entity, identityPolicies, err = c.fetchACLTokenEntryAndEntity(ctx, req)
// In the unauth case we don't want to fail the command, since it's
// unauth, we just have no information to attach to the request, so
Expand Down Expand Up @@ -435,9 +435,12 @@ func (c *Core) CheckToken(ctx context.Context, req *logical.Request, unauth bool
c.activityLogLock.RLock()
activityLog := c.activityLog
c.activityLogLock.RUnlock()
// If it is an authenticated ( i.e with vault token ) request, increment client count
// If it is an authenticated ( i.e. with vault token ) request, increment client count
if !unauth && activityLog != nil {
activityLog.HandleTokenUsage(ctx, te, clientID, isTWE)
err := c.activityLog.HandleTokenUsage(ctx, te, clientID, isTWE)
if err != nil {
return auth, te, err
}
}
return auth, te, nil
}
Expand Down

0 comments on commit ac23c49

Please sign in to comment.