summaryrefslogtreecommitdiff
path: root/pkg/database
diff options
context:
space:
mode:
authorJulien Dessaux2024-11-16 00:36:17 +0100
committerJulien Dessaux2024-11-16 00:36:17 +0100
commit5b6da560896970c610c691dff6ed052a57ed5a1d (patch)
tree7ec12f39943513230659d3068d59e8687770f053 /pkg/database
parentfix(tfstated): return 403 Forbidden on non existent account (diff)
downloadtfstated-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.go38
-rw-r--r--pkg/database/sql/000_init.sql3
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()),