Add Secrets Manager resolution to probod-bootstrap

Introduce a Resolver that owns env lookup and typed parsing for
probod-bootstrap. Env values prefixed with aws://<secret-id> are
fetched from AWS Secrets Manager (plaintext SecretString); each
secret ID is cached per run. Builder now takes a Resolver only.

Prefix every probod-bootstrap input with PROBOD_ so bootstrap config
does not collide with unrelated process environment (for example
AWS_* used by other tooling). Secrets Manager authentication uses
the standard AWS SDK default chain (AWS_REGION, IAM role, profile);
PROBOD_AWS_* vars configure S3 in the generated config only.

Update Helm deployment env names, GNUmakefile dev-config, Lima
provision, e2e testutil, compose.prod.yaml, and docs.

Deployments must rename bootstrap env vars to PROBOD_* (e.g.
AUTH_COOKIE_SECRET → PROBOD_AUTH_COOKIE_SECRET).

BREAKING CHANGE: all env vars are now prefixed by `PROBOD_`.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
This commit is contained in:
Ludovic Vielle
2026-06-24 11:06:49 +02:00
parent 612e9cbc22
commit 2b8f6f5b3b
18 changed files with 1152 additions and 732 deletions

View File

@@ -256,68 +256,68 @@ func generateConfig() (string, error) {
env := map[string]string{
// Required.
"PROBOD_ENCRYPTION_KEY": "thisisnotasecretAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"AUTH_COOKIE_SECRET": "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes",
"AUTH_PASSWORD_PEPPER": "this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes",
"OAUTH2_SERVER_SIGNING_KEY": oauth2SigningKey,
"PROBOD_ENCRYPTION_KEY": "thisisnotasecretAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"PROBOD_AUTH_COOKIE_SECRET": "this-is-a-secure-secret-for-cookie-signing-at-least-32-bytes",
"PROBOD_AUTH_PASSWORD_PEPPER": "this-is-a-secure-pepper-for-password-hashing-at-least-32-bytes",
"PROBOD_OAUTH2_SERVER_SIGNING_KEY": oauth2SigningKey,
// Unit.
"METRICS_ADDR": "localhost:19081",
"TRACING_ADDR": "localhost:14317",
"PROBOD_METRICS_ADDR": "localhost:19081",
"PROBOD_TRACING_ADDR": "localhost:14317",
// Probod base.
"PROBOD_BASE_URL": "http://localhost:18080",
// API.
"API_ADDR": "localhost:18080",
"API_CORS_ALLOWED_ORIGINS": "http://localhost:18080",
"PROBOD_API_ADDR": "localhost:18080",
"PROBOD_API_CORS_ALLOWED_ORIGINS": "http://localhost:18080",
// PG.
"PG_DATABASE": "probod_test",
"PG_POOL_SIZE": "10",
"PG_MIN_POOL_SIZE": "1",
"PROBOD_PG_DATABASE": "probod_test",
"PROBOD_PG_POOL_SIZE": "10",
"PROBOD_PG_MIN_POOL_SIZE": "1",
// Auth.
"AUTH_COOKIE_SECURE": "false",
"AUTH_PASSWORD_ITERATIONS": "600000",
"PROBOD_AUTH_COOKIE_SECURE": "false",
"PROBOD_AUTH_PASSWORD_ITERATIONS": "600000",
// OAuth2 server durations kept small for faster e2e flows.
"OAUTH2_SERVER_ACCESS_TOKEN_DURATION": "10",
"OAUTH2_SERVER_REFRESH_TOKEN_DURATION": "10",
"OAUTH2_SERVER_AUTHORIZATION_CODE_DURATION": "5",
"OAUTH2_SERVER_DEVICE_CODE_DURATION": "15",
"PROBOD_OAUTH2_SERVER_ACCESS_TOKEN_DURATION": "10",
"PROBOD_OAUTH2_SERVER_REFRESH_TOKEN_DURATION": "10",
"PROBOD_OAUTH2_SERVER_AUTHORIZATION_CODE_DURATION": "5",
"PROBOD_OAUTH2_SERVER_DEVICE_CODE_DURATION": "15",
// Trust center.
"TRUST_CENTER_HTTP_ADDR": ":10080",
"TRUST_CENTER_HTTPS_ADDR": ":10443",
"PROBOD_TRUST_CENTER_HTTP_ADDR": ":10080",
"PROBOD_TRUST_CENTER_HTTPS_ADDR": ":10443",
// AWS / S3 (SeaweedFS).
"AWS_BUCKET": "probod-test",
"AWS_ACCESS_KEY_ID": "probod",
"AWS_SECRET_ACCESS_KEY": "thisisnotasecret",
"AWS_ENDPOINT": "http://127.0.0.1:8333",
"PROBOD_AWS_BUCKET": "probod-test",
"PROBOD_AWS_ACCESS_KEY_ID": "probod",
"PROBOD_AWS_SECRET_ACCESS_KEY": "thisisnotasecret",
"PROBOD_AWS_ENDPOINT": "http://127.0.0.1:8333",
// Mailer.
"MAILER_SENDER_NAME": "Probo Test",
"MAILER_SENDER_EMAIL": "no-reply@test.getprobo.com",
"MAILER_INTERVAL": "1",
"PROBOD_MAILER_SENDER_NAME": "Probo Test",
"PROBOD_MAILER_SENDER_EMAIL": "no-reply@test.getprobo.com",
"PROBOD_MAILER_INTERVAL": "1",
// LLM.
"OPENAI_API_KEY": "thisisnotasecret",
"PROBOD_OPENAI_API_KEY": "thisisnotasecret",
// Custom domains.
"CUSTOM_DOMAINS_CNAME_TARGET": "custom.test.getprobo.com",
"ACME_DIRECTORY": "https://localhost:14000/dir",
"ACME_EMAIL": "admin@test.getprobo.com",
"PROBOD_CUSTOM_DOMAINS_CNAME_TARGET": "custom.test.getprobo.com",
"PROBOD_ACME_DIRECTORY": "https://localhost:14000/dir",
"PROBOD_ACME_EMAIL": "admin@test.getprobo.com",
}
builder := bootstrap.NewBuilder(func(key string) string {
builder := bootstrap.NewBuilder(bootstrap.NewResolver(func(key string) string {
if v, ok := env[key]; ok {
return v
}
return os.Getenv(key)
})
}))
cfg, err := builder.Build()
if err != nil {