This reverts commit 92fcfda8ad30a539be67b7fb7abff539bf93a098. Co-authored-by: davidadeleon <56207066+davidadeleon@users.noreply.github.com>
This commit is contained in:
parent
5605b59746
commit
9c14ea8114
|
@ -1,3 +0,0 @@
|
||||||
```release-note:improvement
|
|
||||||
core: emit logs when user(s) are locked out and when all lockouts have been cleared
|
|
||||||
```
|
|
|
@ -2829,7 +2829,6 @@ func createCoreConfig(c *ServerCommand, config *server.Config, backend physical.
|
||||||
DisableSSCTokens: config.DisableSSCTokens,
|
DisableSSCTokens: config.DisableSSCTokens,
|
||||||
Experiments: config.Experiments,
|
Experiments: config.Experiments,
|
||||||
AdministrativeNamespacePath: config.AdministrativeNamespacePath,
|
AdministrativeNamespacePath: config.AdministrativeNamespacePath,
|
||||||
UserLockoutLogInterval: config.UserLockoutLogInterval,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.flagDev {
|
if c.flagDev {
|
||||||
|
|
|
@ -776,7 +776,6 @@ func testConfig_Sanitized(t *testing.T) {
|
||||||
"enable_response_header_hostname": false,
|
"enable_response_header_hostname": false,
|
||||||
"enable_response_header_raft_node_id": false,
|
"enable_response_header_raft_node_id": false,
|
||||||
"log_requests_level": "basic",
|
"log_requests_level": "basic",
|
||||||
"user_lockout_log_interval": 0 * time.Second,
|
|
||||||
"ha_storage": map[string]interface{}{
|
"ha_storage": map[string]interface{}{
|
||||||
"cluster_addr": "top_level_cluster_addr",
|
"cluster_addr": "top_level_cluster_addr",
|
||||||
"disable_clustering": true,
|
"disable_clustering": true,
|
||||||
|
|
|
@ -167,7 +167,6 @@ func TestSysConfigState_Sanitized(t *testing.T) {
|
||||||
"enable_response_header_hostname": false,
|
"enable_response_header_hostname": false,
|
||||||
"enable_response_header_raft_node_id": false,
|
"enable_response_header_raft_node_id": false,
|
||||||
"log_requests_level": "",
|
"log_requests_level": "",
|
||||||
"user_lockout_log_interval": json.Number("0"),
|
|
||||||
"listeners": []interface{}{
|
"listeners": []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"config": nil,
|
"config": nil,
|
||||||
|
|
|
@ -23,9 +23,7 @@ type SharedConfig struct {
|
||||||
|
|
||||||
Listeners []*Listener `hcl:"-"`
|
Listeners []*Listener `hcl:"-"`
|
||||||
|
|
||||||
UserLockouts []*UserLockout `hcl:"-"`
|
UserLockouts []*UserLockout `hcl:"-"`
|
||||||
UserLockoutLogInterval time.Duration `hcl:"-"`
|
|
||||||
UserLockoutLogIntervalRaw interface{} `hcl:"user_lockout_log_interval"`
|
|
||||||
|
|
||||||
Seals []*KMS `hcl:"-"`
|
Seals []*KMS `hcl:"-"`
|
||||||
Entropy *Entropy `hcl:"-"`
|
Entropy *Entropy `hcl:"-"`
|
||||||
|
@ -89,14 +87,6 @@ func ParseConfig(d string) (*SharedConfig, error) {
|
||||||
result.DisableMlockRaw = nil
|
result.DisableMlockRaw = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.UserLockoutLogIntervalRaw != nil {
|
|
||||||
if result.UserLockoutLogInterval, err = parseutil.ParseDurationSecond(result.UserLockoutLogIntervalRaw); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result.FoundKeys = append(result.FoundKeys, "UserLockoutLogInterval")
|
|
||||||
result.UserLockoutLogIntervalRaw = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
list, ok := obj.Node.(*ast.ObjectList)
|
list, ok := obj.Node.(*ast.ObjectList)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("error parsing: file doesn't contain a root object")
|
return nil, fmt.Errorf("error parsing: file doesn't contain a root object")
|
||||||
|
@ -186,7 +176,6 @@ func (c *SharedConfig) Sanitized() map[string]interface{} {
|
||||||
"pid_file": c.PidFile,
|
"pid_file": c.PidFile,
|
||||||
"cluster_name": c.ClusterName,
|
"cluster_name": c.ClusterName,
|
||||||
"administrative_namespace_path": c.AdministrativeNamespacePath,
|
"administrative_namespace_path": c.AdministrativeNamespacePath,
|
||||||
"user_lockout_log_interval": c.UserLockoutLogInterval,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional log related settings
|
// Optional log related settings
|
||||||
|
|
|
@ -56,11 +56,6 @@ func (c *SharedConfig) Merge(c2 *SharedConfig) *SharedConfig {
|
||||||
result.DefaultMaxRequestDuration = c2.DefaultMaxRequestDuration
|
result.DefaultMaxRequestDuration = c2.DefaultMaxRequestDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
result.UserLockoutLogInterval = c.UserLockoutLogInterval
|
|
||||||
if c2.UserLockoutLogInterval > result.UserLockoutLogInterval {
|
|
||||||
result.UserLockoutLogInterval = c2.UserLockoutLogInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
result.LogLevel = c.LogLevel
|
result.LogLevel = c.LogLevel
|
||||||
if c2.LogLevel != "" {
|
if c2.LogLevel != "" {
|
||||||
result.LogLevel = c2.LogLevel
|
result.LogLevel = c2.LogLevel
|
||||||
|
|
|
@ -104,11 +104,6 @@ const (
|
||||||
// MfaAuthResponse when the value is not specified in the server config
|
// MfaAuthResponse when the value is not specified in the server config
|
||||||
defaultMFAAuthResponseTTL = 300 * time.Second
|
defaultMFAAuthResponseTTL = 300 * time.Second
|
||||||
|
|
||||||
// defaultUserLockoutLogInterval is the default duration that Vault will
|
|
||||||
// emit a log informing that a user lockout is in effect when the value
|
|
||||||
// is not specified in the server config
|
|
||||||
defaultUserLockoutLogInterval = 1 * time.Minute
|
|
||||||
|
|
||||||
// defaultMaxTOTPValidateAttempts is the default value for the number
|
// defaultMaxTOTPValidateAttempts is the default value for the number
|
||||||
// of failed attempts to validate a request subject to TOTP MFA. If the
|
// of failed attempts to validate a request subject to TOTP MFA. If the
|
||||||
// number of failed totp passcode validations exceeds this max value, the
|
// number of failed totp passcode validations exceeds this max value, the
|
||||||
|
@ -663,9 +658,6 @@ type Core struct {
|
||||||
|
|
||||||
updateLockedUserEntriesCancel context.CancelFunc
|
updateLockedUserEntriesCancel context.CancelFunc
|
||||||
|
|
||||||
lockoutLoggerCancel context.CancelFunc
|
|
||||||
userLockoutLogInterval time.Duration
|
|
||||||
|
|
||||||
// number of workers to use for lease revocation in the expiration manager
|
// number of workers to use for lease revocation in the expiration manager
|
||||||
numExpirationWorkers int
|
numExpirationWorkers int
|
||||||
|
|
||||||
|
@ -879,8 +871,6 @@ type CoreConfig struct {
|
||||||
// only accessible in the root namespace, currently sys/audit-hash and sys/monitor.
|
// only accessible in the root namespace, currently sys/audit-hash and sys/monitor.
|
||||||
AdministrativeNamespacePath string
|
AdministrativeNamespacePath string
|
||||||
|
|
||||||
UserLockoutLogInterval time.Duration
|
|
||||||
|
|
||||||
NumRollbackWorkers int
|
NumRollbackWorkers int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -929,10 +919,6 @@ func CreateCore(conf *CoreConfig) (*Core, error) {
|
||||||
return nil, fmt.Errorf("cannot have DefaultLeaseTTL larger than MaxLeaseTTL")
|
return nil, fmt.Errorf("cannot have DefaultLeaseTTL larger than MaxLeaseTTL")
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.UserLockoutLogInterval == 0 {
|
|
||||||
conf.UserLockoutLogInterval = defaultUserLockoutLogInterval
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the advertise addr if its given to us
|
// Validate the advertise addr if its given to us
|
||||||
if conf.RedirectAddr != "" {
|
if conf.RedirectAddr != "" {
|
||||||
u, err := url.Parse(conf.RedirectAddr)
|
u, err := url.Parse(conf.RedirectAddr)
|
||||||
|
@ -1057,7 +1043,6 @@ func CreateCore(conf *CoreConfig) (*Core, error) {
|
||||||
disableSSCTokens: conf.DisableSSCTokens,
|
disableSSCTokens: conf.DisableSSCTokens,
|
||||||
effectiveSDKVersion: effectiveSDKVersion,
|
effectiveSDKVersion: effectiveSDKVersion,
|
||||||
userFailedLoginInfo: make(map[FailedLoginUser]*FailedLoginInfo),
|
userFailedLoginInfo: make(map[FailedLoginUser]*FailedLoginInfo),
|
||||||
userLockoutLogInterval: conf.UserLockoutLogInterval,
|
|
||||||
experiments: conf.Experiments,
|
experiments: conf.Experiments,
|
||||||
pendingRemovalMountsAllowed: conf.PendingRemovalMountsAllowed,
|
pendingRemovalMountsAllowed: conf.PendingRemovalMountsAllowed,
|
||||||
expirationRevokeRetryBase: conf.ExpirationRevokeRetryBase,
|
expirationRevokeRetryBase: conf.ExpirationRevokeRetryBase,
|
||||||
|
@ -3537,51 +3522,6 @@ func (c *Core) setupCachedMFAResponseAuth() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Core) startLockoutLogger() {
|
|
||||||
// Are we already running a logger
|
|
||||||
if c.lockoutLoggerCancel != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithCancel(c.activeContext)
|
|
||||||
c.lockoutLoggerCancel = cancelFunc
|
|
||||||
|
|
||||||
// Perform first check for lockout entries
|
|
||||||
lockedUserCount := c.getUserFailedLoginCount(ctx)
|
|
||||||
|
|
||||||
if lockedUserCount > 0 {
|
|
||||||
c.Logger().Warn("user lockout(s) in effect")
|
|
||||||
} else {
|
|
||||||
// We shouldn't end up here
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start lockout watcher
|
|
||||||
go func() {
|
|
||||||
ticker := time.NewTicker(c.userLockoutLogInterval)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
// Check for lockout entries
|
|
||||||
lockedUserCount := c.getUserFailedLoginCount(ctx)
|
|
||||||
|
|
||||||
if lockedUserCount > 0 {
|
|
||||||
c.Logger().Warn("user lockout(s) in effect")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
c.Logger().Info("user lockout(s) cleared")
|
|
||||||
ticker.Stop()
|
|
||||||
c.lockoutLoggerCancel = nil
|
|
||||||
return
|
|
||||||
case <-ctx.Done():
|
|
||||||
ticker.Stop()
|
|
||||||
c.lockoutLoggerCancel = nil
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateLockedUserEntries runs every 15 mins to remove stale user entries from storage
|
// updateLockedUserEntries runs every 15 mins to remove stale user entries from storage
|
||||||
// it also updates the userFailedLoginInfo map with correct information for locked users if incorrect
|
// it also updates the userFailedLoginInfo map with correct information for locked users if incorrect
|
||||||
func (c *Core) updateLockedUserEntries() {
|
func (c *Core) updateLockedUserEntries() {
|
||||||
|
@ -3610,13 +3550,7 @@ func (c *Core) updateLockedUserEntries() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
return
|
||||||
|
|
||||||
func (c *Core) getUserFailedLoginCount(ctx context.Context) int {
|
|
||||||
c.userFailedLoginInfoLock.Lock()
|
|
||||||
defer c.userFailedLoginInfoLock.Unlock()
|
|
||||||
|
|
||||||
return len(c.userFailedLoginInfo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// runLockedUserEntryUpdates runs updates for locked user storage entries and userFailedLoginInfo map
|
// runLockedUserEntryUpdates runs updates for locked user storage entries and userFailedLoginInfo map
|
||||||
|
|
|
@ -51,18 +51,6 @@ func unlockUser(ctx context.Context, core *Core, mountAccessor string, aliasName
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if core.lockoutLoggerCancel != nil {
|
|
||||||
// Check if we have no more locked users and cancel any running lockout logger
|
|
||||||
core.userFailedLoginInfoLock.RLock()
|
|
||||||
numLockedUsers := len(core.userFailedLoginInfo)
|
|
||||||
core.userFailedLoginInfoLock.RUnlock()
|
|
||||||
|
|
||||||
if numLockedUsers == 0 {
|
|
||||||
core.Logger().Info("user lockout(s) cleared")
|
|
||||||
core.lockoutLoggerCancel()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1464,7 +1464,6 @@ func (c *Core) handleLoginRequest(ctx context.Context, req *logical.Request) (re
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if isloginUserLocked {
|
if isloginUserLocked {
|
||||||
c.startLockoutLogger()
|
|
||||||
return nil, nil, logical.ErrPermissionDenied
|
return nil, nil, logical.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2280,8 +2279,6 @@ func (c *Core) LocalGetUserFailedLoginInfo(ctx context.Context, userKey FailedLo
|
||||||
// LocalUpdateUserFailedLoginInfo updates the failed login information for a user based on alias name and mountAccessor
|
// LocalUpdateUserFailedLoginInfo updates the failed login information for a user based on alias name and mountAccessor
|
||||||
func (c *Core) LocalUpdateUserFailedLoginInfo(ctx context.Context, userKey FailedLoginUser, failedLoginInfo *FailedLoginInfo, deleteEntry bool) error {
|
func (c *Core) LocalUpdateUserFailedLoginInfo(ctx context.Context, userKey FailedLoginUser, failedLoginInfo *FailedLoginInfo, deleteEntry bool) error {
|
||||||
c.userFailedLoginInfoLock.Lock()
|
c.userFailedLoginInfoLock.Lock()
|
||||||
defer c.userFailedLoginInfoLock.Unlock()
|
|
||||||
|
|
||||||
switch deleteEntry {
|
switch deleteEntry {
|
||||||
case false:
|
case false:
|
||||||
// update entry in the map
|
// update entry in the map
|
||||||
|
@ -2324,6 +2321,7 @@ func (c *Core) LocalUpdateUserFailedLoginInfo(ctx context.Context, userKey Faile
|
||||||
// delete the entry from the map, if no key exists it is no-op
|
// delete the entry from the map, if no key exists it is no-op
|
||||||
delete(c.userFailedLoginInfo, userKey)
|
delete(c.userFailedLoginInfo, userKey)
|
||||||
}
|
}
|
||||||
|
c.userFailedLoginInfoLock.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue