Add early checks for user hashes.
parent
1ee442e86f
commit
716e017521
|
@ -35,8 +35,15 @@ func NewFileUserProvider(filepath string) *FileUserProvider {
|
||||||
database, err := readDatabase(filepath)
|
database, err := readDatabase(filepath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Panic since the file does not exist when Authelia is starting.
|
// Panic since the file does not exist when Authelia is starting.
|
||||||
panic(err)
|
panic(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Early check whether hashed passwords are correct for all users
|
||||||
|
err = checkPasswordHashes(database)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
return &FileUserProvider{
|
return &FileUserProvider{
|
||||||
path: &filepath,
|
path: &filepath,
|
||||||
database: database,
|
database: database,
|
||||||
|
@ -44,24 +51,34 @@ func NewFileUserProvider(filepath string) *FileUserProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkPasswordHashes(database *DatabaseModel) error {
|
||||||
|
for u, v := range database.Users {
|
||||||
|
_, err := ParseHash(v.HashedPassword)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to parse hash of user %s: %s", u, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func readDatabase(path string) (*DatabaseModel, error) {
|
func readDatabase(path string) (*DatabaseModel, error) {
|
||||||
content, err := ioutil.ReadFile(path)
|
content, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("Unable to read database from file %s: %s", path, err)
|
||||||
}
|
}
|
||||||
db := DatabaseModel{}
|
db := DatabaseModel{}
|
||||||
err = yaml.Unmarshal(content, &db)
|
err = yaml.Unmarshal(content, &db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("Unable to parse database: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, err := govalidator.ValidateStruct(db)
|
ok, err := govalidator.ValidateStruct(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("Invalid schema of database: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("The database format is invalid: %s", err.Error())
|
return nil, fmt.Errorf("The database format is invalid: %s", err)
|
||||||
}
|
}
|
||||||
return &db, nil
|
return &db, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ func TestShouldUpdatePassword(t *testing.T) {
|
||||||
|
|
||||||
func TestShouldRaiseWhenLoadingMalformedDatabaseForFirstTime(t *testing.T) {
|
func TestShouldRaiseWhenLoadingMalformedDatabaseForFirstTime(t *testing.T) {
|
||||||
WithDatabase(MalformedUserDatabaseContent, func(path string) {
|
WithDatabase(MalformedUserDatabaseContent, func(path string) {
|
||||||
assert.Panics(t, func() {
|
assert.PanicsWithValue(t, "Unable to parse database: yaml: line 4: mapping values are not allowed in this context", func() {
|
||||||
NewFileUserProvider(path)
|
NewFileUserProvider(path)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -92,7 +92,15 @@ func TestShouldRaiseWhenLoadingMalformedDatabaseForFirstTime(t *testing.T) {
|
||||||
|
|
||||||
func TestShouldRaiseWhenLoadingDatabaseWithBadSchemaForFirstTime(t *testing.T) {
|
func TestShouldRaiseWhenLoadingDatabaseWithBadSchemaForFirstTime(t *testing.T) {
|
||||||
WithDatabase(BadSchemaUserDatabaseContent, func(path string) {
|
WithDatabase(BadSchemaUserDatabaseContent, func(path string) {
|
||||||
assert.Panics(t, func() {
|
assert.PanicsWithValue(t, "Invalid schema of database: Users: non zero value required", func() {
|
||||||
|
NewFileUserProvider(path)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShouldRaiseWhenLoadingDatabaseWithBadHashesForTheFirstTime(t *testing.T) {
|
||||||
|
WithDatabase(BadHashContent, func(path string) {
|
||||||
|
assert.PanicsWithValue(t, "Unable to parse hash of user john: Cannot match pattern 'rounds=<int>' to find the number of rounds", func() {
|
||||||
NewFileUserProvider(path)
|
NewFileUserProvider(path)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -165,3 +173,16 @@ users:
|
||||||
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
email: james.dean@authelia.com
|
email: james.dean@authelia.com
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
var BadHashContent = []byte(`
|
||||||
|
users:
|
||||||
|
john:
|
||||||
|
password: "$6$rounds00000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: john.doe@authelia.com
|
||||||
|
groups:
|
||||||
|
- admins
|
||||||
|
- dev
|
||||||
|
james:
|
||||||
|
password: "$6$rounds=500000$jgiCMRyGXzoqpxS3$w2pJeZnnH8bwW3zzvoMWtTRfQYsHbWbD/hquuQ5vUeIyl9gdwBIt6RWk2S6afBA0DPakbeWgD/4SZPiS0hYtU/"
|
||||||
|
email: james.dean@authelia.com
|
||||||
|
`)
|
||||||
|
|
Loading…
Reference in New Issue