fix(apiserver): bcrypt passwords and default-credential warnings in config-file auth (bug-1947)
Cause: ConfigFileProvider.Authenticate compared the stored plaintext password with != (timing side channel, passwords readable from the file), and config/auth.yaml shipped admin/admin, user1/user1 etc. as plaintext with nothing reporting that a default credential was active. Fix: auth.yaml passwords may be bcrypt hashes (golang.org/x/crypto/bcrypt, v0.23.0 as already pinned in go.mod, now vendored); plaintext entries are still accepted but compared in constant time (SHA-256 + subtle), and an unknown user costs the same bcrypt work. The provider reports startup warnings (SecurityWarner, logged by main) for every plaintext entry and for every shipped default credential still active. The shipped auth.yaml and auth.yaml.example now store bcrypt hashes of the same dev passwords, so tests/regression/run.sh (admin/admin) keeps working. tools/encrypt gains -action=hash to generate entries. Tests: TestConfigFileProvider_BcryptPassword, TestConfigFileProvider_SecurityWarnings, TestShippedAuthConfig_HashedDefaults. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d3ce298232
commit
f91642dbc0
14 changed files with 1037 additions and 16 deletions
|
|
@ -14,6 +14,7 @@ import (
|
|||
"os"
|
||||
|
||||
survey "github.com/AlecAivazis/survey/v2" // survey package
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// admin need set env: ENCRYPTION_KEY
|
||||
|
|
@ -24,21 +25,21 @@ func main() {
|
|||
// command usage
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, `
|
||||
Usage: crypter -action=<enc|dec> [options]
|
||||
Usage: crypter -action=<enc|dec|hash> [options]
|
||||
|
||||
Options:
|
||||
-action enc|dec
|
||||
-action enc|dec|hash (hash: bcrypt hash for a password: entry in auth.yaml)
|
||||
-password password (if empty, will be prompted)
|
||||
`)
|
||||
}
|
||||
|
||||
action := flag.String("action", "", "action to perform: enc or dec")
|
||||
action := flag.String("action", "", "action to perform: enc, dec or hash")
|
||||
password := flag.String("password", "", "password")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if *action != "enc" && *action != "dec" {
|
||||
fmt.Println("Invalid action. Use -action=enc or -action=dec")
|
||||
if *action != "enc" && *action != "dec" && *action != "hash" {
|
||||
fmt.Println("Invalid action. Use -action=enc, -action=dec or -action=hash")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +59,14 @@ func main() {
|
|||
fmt.Println(encryptedPassword)
|
||||
}
|
||||
|
||||
if *action == "hash" {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(inputPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to hash password: %v", err)
|
||||
}
|
||||
fmt.Println(string(hash))
|
||||
}
|
||||
|
||||
if *action == "dec" {
|
||||
realPassword, err := Decrypt(inputPassword, "")
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue