From 6e04e4ede186f87cb8e68116d518448d8e05db75 Mon Sep 17 00:00:00 2001 From: akshya96 <87045294+akshya96@users.noreply.github.com> Date: Tue, 17 Jan 2023 15:10:50 -0800 Subject: [PATCH] Prevent brute forcing : telemetry oss changes (#18718) * Prevent brute forcing : telemetry oss changes * adding changelog --- changelog/18718.txt | 3 +++ vault/core.go | 27 ++++++++++++++++++--------- 2 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 changelog/18718.txt diff --git a/changelog/18718.txt b/changelog/18718.txt new file mode 100644 index 000000000..a5b9b1334 --- /dev/null +++ b/changelog/18718.txt @@ -0,0 +1,3 @@ +```release-note:improvement +core: Add vault.core.locked_users telemetry metric to emit information about total number of locked users. +``` \ No newline at end of file diff --git a/vault/core.go b/vault/core.go index 89ed93434..3dd2f7b93 100644 --- a/vault/core.go +++ b/vault/core.go @@ -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) @@ -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 { @@ -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{ @@ -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 { @@ -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) @@ -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 } @@ -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