diff options
author | Julien Dessaux | 2024-11-16 00:36:17 +0100 |
---|---|---|
committer | Julien Dessaux | 2024-11-16 00:36:17 +0100 |
commit | 5b6da560896970c610c691dff6ed052a57ed5a1d (patch) | |
tree | 7ec12f39943513230659d3068d59e8687770f053 /pkg/database | |
parent | fix(tfstated): return 403 Forbidden on non existent account (diff) | |
download | tfstated-5b6da560896970c610c691dff6ed052a57ed5a1d.tar.gz tfstated-5b6da560896970c610c691dff6ed052a57ed5a1d.tar.bz2 tfstated-5b6da560896970c610c691dff6ed052a57ed5a1d.zip |
fix(tfstated): hash passwords instead of relying on the database encryption key
Diffstat (limited to 'pkg/database')
-rw-r--r-- | pkg/database/accounts.go | 38 | ||||
-rw-r--r-- | pkg/database/sql/000_init.sql | 3 |
2 files changed, 20 insertions, 21 deletions
diff --git a/pkg/database/accounts.go b/pkg/database/accounts.go index 3919709..6400d5a 100644 --- a/pkg/database/accounts.go +++ b/pkg/database/accounts.go @@ -11,22 +11,27 @@ import ( "go.n16f.net/uuid" ) +// Overriden by tests +var AdvertiseAdminPassword = func(password string) { + slog.Info("Generated an initial admin password, please change it or delete the admin account after your first login", "password", password) +} + func (db *DB) LoadAccountByUsername(username string) (*model.Account, error) { account := model.Account{ Username: username, } var ( - encryptedPassword []byte - created int64 - lastLogin int64 + created int64 + lastLogin int64 ) err := db.QueryRow( - `SELECT id, password, is_admin, created, last_login, settings + `SELECT id, salt, password_hash, is_admin, created, last_login, settings FROM accounts WHERE username = ?;`, username, ).Scan(&account.Id, - &encryptedPassword, + &account.Salt, + &account.PasswordHash, &account.IsAdmin, &created, &lastLogin, @@ -38,11 +43,6 @@ func (db *DB) LoadAccountByUsername(username string) (*model.Account, error) { } return nil, err } - password, err := db.dataEncryptionKey.DecryptAES256(encryptedPassword) - if err != nil { - return nil, err - } - account.Password = string(password) account.Created = time.Unix(created, 0) account.LastLogin = time.Unix(lastLogin, 0) return &account, nil @@ -69,23 +69,21 @@ func (db *DB) InitAdminAccount() error { if err = password.Generate(uuid.V4); err != nil { return fmt.Errorf("failed to generate initial admin password: %w", err) } - var encryptedPassword []byte - encryptedPassword, err = db.dataEncryptionKey.EncryptAES256([]byte(password.String())) - if err != nil { - return fmt.Errorf("failed to encrypt initial admin password: %w", err) - } + salt := model.GenerateSalt() + hash := model.HashPassword(password.String(), salt) if _, err = tx.ExecContext(db.ctx, - `INSERT INTO accounts(username, password, is_admin) - VALUES ("admin", :password, TRUE) - ON CONFLICT DO UPDATE SET password = :password + `INSERT INTO accounts(username, salt, password_hash, is_admin) + VALUES ("admin", :salt, :hash, TRUE) + ON CONFLICT DO UPDATE SET password_hash = :hash WHERE username = "admin";`, - sql.Named("password", encryptedPassword), + sql.Named("salt", salt), + sql.Named("hash", hash), ); err != nil { return fmt.Errorf("failed to set initial admin password: %w", err) } err = tx.Commit() if err == nil { - slog.Info("Generated an initial admin password, please change it or delete the admin account after your first login", "password", password.String()) + AdvertiseAdminPassword(password.String()) } } return err diff --git a/pkg/database/sql/000_init.sql b/pkg/database/sql/000_init.sql index c56473f..b635442 100644 --- a/pkg/database/sql/000_init.sql +++ b/pkg/database/sql/000_init.sql @@ -5,7 +5,8 @@ CREATE TABLE schema_version ( CREATE TABLE accounts ( id INTEGER PRIMARY KEY, username TEXT NOT NULL, - password BLOB NOT NULL, + salt BLOB NOT NULL, + password_hash BLOB NOT NULL, is_admin INTEGER NOT NULL DEFAULT FALSE, created INTEGER NOT NULL DEFAULT (unixepoch()), last_login INTEGER NOT NULL DEFAULT (unixepoch()), |