Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent brute forcing : telemetry oss changes #18718

Merged
merged 3 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/18718.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
core: Add vault.core.locked_users telemetry metric to emit information about total number of locked users.
akshya96 marked this conversation as resolved.
Show resolved Hide resolved
```
27 changes: 18 additions & 9 deletions vault/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -3425,6 +3425,7 @@ func (c *Core) runLockedUserEntryUpdates(ctx context.Context) error {
return err
}

totalLockedUsersCount := 0
for _, nsID := range nsIDs {
// get the list of mount accessors of locked users for each namespace
mountAccessors, err := c.barrier.List(ctx, coreLockedUsersPath+nsID)
Expand All @@ -3439,18 +3440,23 @@ func (c *Core) runLockedUserEntryUpdates(ctx context.Context) error {
// if incorrect, update the entry in userFailedLoginInfo map
for _, mountAccessorPath := range mountAccessors {
mountAccessor := strings.TrimSuffix(mountAccessorPath, "/")
if err := c.runLockedUserEntryUpdatesForMountAccessor(ctx, mountAccessor, coreLockedUsersPath+nsID+mountAccessorPath); err != nil {
lockedAliasesCount, err := c.runLockedUserEntryUpdatesForMountAccessor(ctx, mountAccessor, coreLockedUsersPath+nsID+mountAccessorPath)
if err != nil {
return err
}
totalLockedUsersCount = totalLockedUsersCount + lockedAliasesCount
}
}

// emit locked user count metrics
metrics.SetGaugeWithLabels([]string{"core", "locked_users"}, float32(totalLockedUsersCount), nil)
return nil
}

// runLockedUserEntryUpdatesForMountAccessor updates the storage entry for each locked user (alias name)
// if the entry is stale, it removes it from storage and userFailedLoginInfo map if present
// if the entry is not stale, it updates the userFailedLoginInfo map with correct values for entry if incorrect
func (c *Core) runLockedUserEntryUpdatesForMountAccessor(ctx context.Context, mountAccessor string, path string) error {
func (c *Core) runLockedUserEntryUpdatesForMountAccessor(ctx context.Context, mountAccessor string, path string) (int, error) {
// get mount entry for mountAccessor
mountEntry := c.router.MatchingMountByAccessor(mountAccessor)
if mountEntry == nil {
Expand All @@ -3462,9 +3468,11 @@ func (c *Core) runLockedUserEntryUpdatesForMountAccessor(ctx context.Context, mo
// get the list of aliases for mount accessor
aliases, err := c.barrier.List(ctx, path)
if err != nil {
return err
return 0, err
}

lockedAliasesCount := len(aliases)

// check storage entry for each alias to update
for _, alias := range aliases {
loginUserInfoKey := FailedLoginUser{
Expand All @@ -3474,7 +3482,7 @@ func (c *Core) runLockedUserEntryUpdatesForMountAccessor(ctx context.Context, mo

existingEntry, err := c.barrier.Get(ctx, path+alias)
if err != nil {
return err
return 0, err
}

if existingEntry == nil {
Expand All @@ -3484,7 +3492,7 @@ func (c *Core) runLockedUserEntryUpdatesForMountAccessor(ctx context.Context, mo
var lastLoginTime int
err = jsonutil.DecodeJSON(existingEntry.Value, &lastLoginTime)
if err != nil {
return err
return 0, err
}

lastFailedLoginTimeFromStorageEntry := time.Unix(int64(lastLoginTime), 0)
Expand All @@ -3497,15 +3505,16 @@ func (c *Core) runLockedUserEntryUpdatesForMountAccessor(ctx context.Context, mo
if time.Now().After(lastFailedLoginTimeFromStorageEntry.Add(lockoutDurationFromConfiguration)) {
// stale entry, remove from storage
if err := c.barrier.Delete(ctx, path+alias); err != nil {
return err
return 0, err
}

// remove entry for this user from userFailedLoginInfo map if present as the user is not locked
if failedLoginInfoFromMap != nil {
if err = c.UpdateUserFailedLoginInfo(ctx, loginUserInfoKey, nil, true); err != nil {
return err
return 0, err
}
}
lockedAliasesCount -= 1
continue
}

Expand All @@ -3519,11 +3528,11 @@ func (c *Core) runLockedUserEntryUpdatesForMountAccessor(ctx context.Context, mo
if failedLoginInfoFromMap != &actualFailedLoginInfo {
// entry is invalid, updating the entry in userFailedLoginMap with correct information
if err = c.UpdateUserFailedLoginInfo(ctx, loginUserInfoKey, &actualFailedLoginInfo, false); err != nil {
return err
return 0, err
}
}
}
return nil
return lockedAliasesCount, nil
}

// PopMFAResponseAuthByID pops an item from the mfaResponseAuthQueue by ID
Expand Down