LoginAttempt: Add setting to control max number of attempts before user login gets locked (#97091)

* Add setting to adjust number of login attempts before user login gets locked

* Ensure at least one attempt can be made

* Update documentation with new setting

* Update docs/sources/setup-grafana/configure-grafana/_index.md

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>
This commit is contained in:
Karl Persson 2024-11-28 14:33:18 +01:00 committed by GitHub
parent f2b96593ea
commit b2626a2d65
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 37 additions and 18 deletions

View File

@ -351,6 +351,9 @@ data_source_proxy_whitelist =
# disable protection against brute force login attempts
disable_brute_force_login_protection = false
# max number of failed login attempts before user gets locked
brute_force_login_protection_max_attempts = 5
# set to true if you host Grafana behind HTTPS. default is false.
cookie_secure = false

View File

@ -350,6 +350,9 @@
# disable protection against brute force login attempts
;disable_brute_force_login_protection = false
# max number of failed login attempts before user gets locked
;brute_force_login_protection_max_attempts = 5
# set to true if you host Grafana behind HTTPS. default is false.
;cookie_secure = false

View File

@ -630,7 +630,11 @@ Define a whitelist of allowed IP addresses or domains, with ports, to be used in
### disable_brute_force_login_protection
Set to `true` to disable [brute force login protection](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html#account-lockout). Default is `false`. An existing user's account will be locked after 5 attempts in 5 minutes.
Set to `true` to disable [brute force login protection](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html#account-lockout). Default is `false`. An existing user's account will be unable to login for 5 minutes if all login attempts are spent within a 5 minute window.
### brute_force_login_protection_max_attempts
Configure how many login attempts a user have within a 5 minute window before the account will be locked. Default is `5`.
### cookie_secure

View File

@ -11,10 +11,7 @@ import (
"github.com/grafana/grafana/pkg/setting"
)
const (
maxInvalidLoginAttempts int64 = 5
loginAttemptsWindow = time.Minute * 5
)
const loginAttemptsWindow = time.Minute * 5
func ProvideService(db db.DB, cfg *setting.Cfg, lock *serverlock.ServerLockService) *Service {
return &Service{
@ -80,7 +77,7 @@ func (s *Service) Validate(ctx context.Context, username string) (bool, error) {
return false, err
}
if count >= maxInvalidLoginAttempts {
if count >= s.cfg.BruteForceLoginProtectionMaxAttempts {
return false, nil
}

View File

@ -12,6 +12,8 @@ import (
)
func TestService_Validate(t *testing.T) {
const maxInvalidLoginAttempts = 5
testCases := []struct {
name string
loginAttempts int64
@ -64,6 +66,7 @@ func TestService_Validate(t *testing.T) {
for _, tt := range testCases {
t.Run(tt.name, func(t *testing.T) {
cfg := setting.NewCfg()
cfg.BruteForceLoginProtectionMaxAttempts = maxInvalidLoginAttempts
cfg.DisableBruteForceLoginProtection = tt.disabled
service := &Service{
store: fakeStore{
@ -84,6 +87,7 @@ func TestLoginAttempts(t *testing.T) {
ctx := context.Background()
cfg := setting.NewCfg()
cfg.DisableBruteForceLoginProtection = false
cfg.BruteForceLoginProtectionMaxAttempts = 5
db := db.InitTestDB(t)
service := ProvideService(db, cfg, nil)

View File

@ -154,18 +154,19 @@ type Cfg struct {
RendererDefaultImageScale float64
// Security
DisableInitAdminCreation bool
DisableBruteForceLoginProtection bool
CookieSecure bool
CookieSameSiteDisabled bool
CookieSameSiteMode http.SameSite
AllowEmbedding bool
XSSProtectionHeader bool
ContentTypeProtectionHeader bool
StrictTransportSecurity bool
StrictTransportSecurityMaxAge int
StrictTransportSecurityPreload bool
StrictTransportSecuritySubDomains bool
DisableInitAdminCreation bool
DisableBruteForceLoginProtection bool
BruteForceLoginProtectionMaxAttempts int64
CookieSecure bool
CookieSameSiteDisabled bool
CookieSameSiteMode http.SameSite
AllowEmbedding bool
XSSProtectionHeader bool
ContentTypeProtectionHeader bool
StrictTransportSecurity bool
StrictTransportSecurityMaxAge int
StrictTransportSecurityPreload bool
StrictTransportSecuritySubDomains bool
// CSPEnabled toggles Content Security Policy support.
CSPEnabled bool
// CSPTemplate contains the Content Security Policy template.
@ -1498,7 +1499,14 @@ func readSecuritySettings(iniFile *ini.File, cfg *Cfg) error {
security := iniFile.Section("security")
cfg.SecretKey = valueAsString(security, "secret_key", "")
cfg.DisableGravatar = security.Key("disable_gravatar").MustBool(true)
cfg.DisableBruteForceLoginProtection = security.Key("disable_brute_force_login_protection").MustBool(false)
cfg.BruteForceLoginProtectionMaxAttempts = security.Key("brute_force_login_protection_max_attempts").MustInt64(5)
// Ensure at least one login attempt can be performed.
if cfg.BruteForceLoginProtectionMaxAttempts <= 0 {
cfg.BruteForceLoginProtectionMaxAttempts = 1
}
CookieSecure = security.Key("cookie_secure").MustBool(false)
cfg.CookieSecure = CookieSecure