The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/pkg/services/user/password.go

80 lines
2.3 KiB

package user
import (
"unicode"
"github.com/grafana/grafana/pkg/apimachinery/errutil"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
var (
ErrPasswordTooShort = errutil.BadRequest("password.password-policy-too-short", errutil.WithPublicMessage("New password is too short"))
ErrPasswordPolicyInfringe = errutil.BadRequest("password.password-policy-infringe", errutil.WithPublicMessage("New password doesn't comply with the password policy"))
MinPasswordLength = 12
)
type Password string
func NewPassword(newPassword string, config *setting.Cfg) (Password, error) {
if err := ValidatePassword(newPassword, config); err != nil {
return "", err
}
return Password(newPassword), nil
}
func (p Password) Validate(config *setting.Cfg) error {
return ValidatePassword(string(p), config)
}
func (p Password) Hash(salt string) (Password, error) {
hashed, err := util.EncodePassword(string(p), salt)
if err != nil {
return "", err
}
return Password(hashed), nil
}
// ValidatePassword checks if a new password meets the required criteria based on the given configuration.
// If BasicAuthStrongPasswordPolicy is disabled, it only checks for password length.
// Otherwise, it ensures the password meets the minimum length requirement and contains at least one uppercase letter,
// one lowercase letter, one number, and one symbol.
func ValidatePassword(newPassword string, config *setting.Cfg) error {
if !config.BasicAuthStrongPasswordPolicy {
if len(newPassword) < 4 {
return ErrPasswordTooShort.Errorf("new password is too short")
}
return nil
}
if len(newPassword) < MinPasswordLength {
return ErrPasswordPolicyInfringe.Errorf("new password is too short for the strong password policy")
}
hasUpperCase := false
hasLowerCase := false
hasNumber := false
hasSymbol := false
for _, r := range newPassword {
if !hasLowerCase && unicode.IsLower(r) {
hasLowerCase = true
}
if !hasUpperCase && unicode.IsUpper(r) {
hasUpperCase = true
}
if !hasNumber && unicode.IsNumber(r) {
hasNumber = true
}
if !hasSymbol && !unicode.IsLetter(r) && !unicode.IsNumber(r) {
hasSymbol = true
}
if hasUpperCase && hasLowerCase && hasNumber && hasSymbol {
return nil
}
}
return ErrPasswordPolicyInfringe.Errorf("new password doesn't comply with the password policy")
}