mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
<!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## Summary When `zitadel init` runs on every Helm upgrade/re-deploy, `VerifyUser` always executed `CREATE USER ... WITH PASSWORD '...'`. If the role already existed, PostgreSQL returned `42710` and logged the full statement—including the plaintext password—even though ZITADEL swallowed that error. This mirrors the existing `VerifyDatabase` catalog check: query `pg_roles` first and skip creation when the role exists. Also stops mutating the package-level `createUserStmt` when appending `WITH PASSWORD`. Fixes #12178 ## Changes - `cmd/initialise/verify_user.go`: check `SELECT EXISTS(... FROM pg_roles ...)` before `CREATE USER`; build password clause on a local statement copy - `cmd/initialise/verify_user_test.go`: cover catalog skip, catalog-check failure, and create paths with the new query ## Test plan - [x] `go test ./cmd/initialise/...` (passed) - [ ] Re-run init against an existing role and confirm Postgres logs no longer contain `CREATE USER ... WITH PASSWORD` <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-bc514793-d275-4d91-a71b-1b7566668b65?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-bc514793-d275-4d91-a71b-1b7566668b65&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> Co-authored-by: Cursor Agent <[email protected]> Co-authored-by: Silvan <[email protected]>
150 lines
4.1 KiB
Go
150 lines
4.1 KiB
Go
package initialise
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"database/sql/driver"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
func Test_verifyUser(t *testing.T) {
|
|
err := ReadStmts()
|
|
if err != nil {
|
|
t.Errorf("unable to read stmts: %v", err)
|
|
t.FailNow()
|
|
}
|
|
|
|
type args struct {
|
|
db db
|
|
username string
|
|
password string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
targetErr error
|
|
}{
|
|
{
|
|
name: "doesn't exists, create fails",
|
|
args: args{
|
|
db: prepareDB(t,
|
|
expectQuery("SELECT current_user", nil, []string{"current_user"}, [][]driver.Value{
|
|
{"postgres"},
|
|
}),
|
|
expectQuery("SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", nil, []string{"exists"}, [][]driver.Value{
|
|
{false},
|
|
}, "zitadel-user"),
|
|
expectExec("-- replace zitadel-user with the name of the user\nCREATE USER \"zitadel-user\"", sql.ErrTxDone),
|
|
),
|
|
username: "zitadel-user",
|
|
password: "",
|
|
},
|
|
targetErr: sql.ErrTxDone,
|
|
},
|
|
{
|
|
name: "correct without password",
|
|
args: args{
|
|
db: prepareDB(t,
|
|
expectQuery("SELECT current_user", nil, []string{"current_user"}, [][]driver.Value{
|
|
{"postgres"},
|
|
}),
|
|
expectQuery("SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", nil, []string{"exists"}, [][]driver.Value{
|
|
{false},
|
|
}, "zitadel-user"),
|
|
expectExec("-- replace zitadel-user with the name of the user\nCREATE USER \"zitadel-user\"", nil),
|
|
),
|
|
username: "zitadel-user",
|
|
password: "",
|
|
},
|
|
targetErr: nil,
|
|
},
|
|
{
|
|
name: "correct with password",
|
|
args: args{
|
|
db: prepareDB(t,
|
|
expectQuery("SELECT current_user", nil, []string{"current_user"}, [][]driver.Value{
|
|
{"postgres"},
|
|
}),
|
|
expectQuery("SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", nil, []string{"exists"}, [][]driver.Value{
|
|
{false},
|
|
}, "zitadel-user"),
|
|
expectExec("-- replace zitadel-user with the name of the user\nCREATE USER \"zitadel-user\" WITH PASSWORD 'password'", nil),
|
|
),
|
|
username: "zitadel-user",
|
|
password: "password",
|
|
},
|
|
targetErr: nil,
|
|
},
|
|
{
|
|
name: "correct with password containing percent and quote",
|
|
args: args{
|
|
db: prepareDB(t,
|
|
expectQuery("SELECT current_user", nil, []string{"current_user"}, [][]driver.Value{
|
|
{"postgres"},
|
|
}),
|
|
expectQuery("SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", nil, []string{"exists"}, [][]driver.Value{
|
|
{false},
|
|
}, "zitadel-user"),
|
|
expectExec("-- replace zitadel-user with the name of the user\nCREATE USER \"zitadel-user\" WITH PASSWORD 'p%''ass'", nil),
|
|
),
|
|
username: "zitadel-user",
|
|
password: "p%'ass",
|
|
},
|
|
targetErr: nil,
|
|
},
|
|
{
|
|
name: "already exists in catalog, skip creation",
|
|
args: args{
|
|
db: prepareDB(t,
|
|
expectQuery("SELECT current_user", nil, []string{"current_user"}, [][]driver.Value{
|
|
{"postgres"},
|
|
}),
|
|
expectQuery("SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", nil, []string{"exists"}, [][]driver.Value{
|
|
{true},
|
|
}, "zitadel-user"),
|
|
),
|
|
username: "zitadel-user",
|
|
password: "password",
|
|
},
|
|
targetErr: nil,
|
|
},
|
|
{
|
|
name: "catalog check fails",
|
|
args: args{
|
|
db: prepareDB(t,
|
|
expectQuery("SELECT current_user", nil, []string{"current_user"}, [][]driver.Value{
|
|
{"postgres"},
|
|
}),
|
|
expectQuery("SELECT EXISTS(SELECT 1 FROM pg_roles WHERE rolname = $1)", sql.ErrConnDone, []string{"exists"}, [][]driver.Value{}, "zitadel-user"),
|
|
),
|
|
username: "zitadel-user",
|
|
password: "password",
|
|
},
|
|
targetErr: sql.ErrConnDone,
|
|
},
|
|
{
|
|
name: "same user, skip create",
|
|
args: args{
|
|
db: prepareDB(t,
|
|
expectQuery("SELECT current_user", nil, []string{"current_user"}, [][]driver.Value{
|
|
{"zitadel-user"},
|
|
}),
|
|
),
|
|
username: "zitadel-user",
|
|
},
|
|
targetErr: nil,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if err := VerifyUser(tt.args.username, tt.args.password)(context.Background(), tt.args.db.db); !errors.Is(err, tt.targetErr) {
|
|
t.Errorf("VerifyUser() error = %v, want: %v", err, tt.targetErr)
|
|
}
|
|
if err := tt.args.db.mock.ExpectationsWereMet(); err != nil {
|
|
t.Error(err)
|
|
}
|
|
})
|
|
}
|
|
}
|