Upgrade to v1.77.1¶
v1.77.1 removes storage layout v4 and its tools (ADR 0072), signs the recovery account in by SRP instead of a password (ADR 0076) and sends HSTS. History is in the CHANGELOG.
Before you start¶
The installation must run layout v5 on v1.77.0 or earlier (v1.77 if older). v1.77.1 neither reads layout v4 nor migrates from it. Upgrade the service and the Pulumi library together: the service reads a verifier the library writes. Stop any script that sends the recovery password to <console>/login/recovery: the service answers it with 400 without reading it.
| Check | Expected |
|---|---|
secrets with source: ssm |
layout: v5 |
ports.dynamodb or adapters.state.settings |
tables, one per module; no table |
| DynamoDB | the module tables only; the v4 table is retired |
| SSM | nothing under <root>/internal/credentials/; no layout v4 name of a moved secret (below) |
| the Pulumi program | Layout: LayoutV5 and no Compat other than RetireLegacyTable |
A layout v4 installation moves with v1.77.0 first: v1.75, v1.76, sluis migrate v5 prune.
v1.77.1 reads none of these layout v4 names:
Layout v4 name below <root>/ |
Layout v5 name |
|---|---|
internal/credentials/... |
internal/<module>/... |
internal/config/issuer/state-secret |
internal/oidc/state-secret |
internal/config/recovery/password |
internal/oidc/recovery-password |
internal/config/providers/google/<p>/client-id, client-secret |
internal/oidc/signin/<p>/... |
internal/config/clients/<id>/secret |
internal/oidc/clients/<id> |
Delete them with sluis migrate v5 prune of v1.77.0, or by name. The ssm source still reads other names under internal/config/, such as valkey/password.
aws ssm describe-parameters --query 'Parameters[].Name' --output text \
--parameter-filters "Key=Name,Option=BeginsWith,Values=/sluis/<instance>/internal/credentials/"
What was removed¶
| Removed | Use instead |
|---|---|
secrets.layout: v4, and an ssm section without layout |
layout: v5 |
ports.dynamodb.table, adapters.state.settings.table, the installation's aws.table |
tables, one per module |
sluis migrate v5 |
v1.77.0 |
sluis migrate --skip directory |
--skip google |
sluis serve |
sluis issuer |
Pulumi Layout, LayoutV4, LayoutV5, LayoutV4V5 on LambdaArgs, RoleArgs, KeyPolicyArgs |
nothing |
Pulumi CompatArgs; Compat on LambdaArgs and StatesArgs |
nothing |
Pulumi StatesArgs.Legacy, LegacyStateArgs, States.Legacy, States.LegacyBackupArn, LegacyBackupArnOutput, LegacyBackupRetentionDays |
nothing |
Pulumi NewState, StateArgs, State, StateType, StateGrant.TableArn, PortsArgs.TableName |
NewStates, States.Grant() |
Pulumi LambdaArgs.MigrationRoleArn |
nothing |
Pulumi StateSecretParameterName, RecoveryPasswordParameterName, ConfigParameterPrefix |
the ...V5 names |
A document that names a removed key does not load.
1. Update the Pulumi program¶
args := &sluispulumi.LambdaArgs{
- Layout: sluispulumi.LayoutV5,
}
roles := sluispulumi.RoleArgs{
- Layout: sluispulumi.LayoutV5,
}
-state := &sluispulumi.StateGrant{Tables: tables, TableArn: legacy}
+state := &sluispulumi.StateGrant{Tables: tables}
Delete any constant built from ConfigParameterPrefix or StateSecretParameterName. A layout v5 installation's preview then shows no change.
2. Update documents and command lines¶
| Where | Change |
|---|---|
secrets: {source: ssm} |
add layout: v5 |
| a single table | name the module tables in tables |
sluis serve |
sluis issuer |
--skip directory |
--skip google |
3. Kubernetes with another secrets store¶
With the openbao or memory Secrets adapter, copy each credential sluis writes to its layout v5 address, keeping the <ref>, before the new version starts. One not copied reads as absent, so make its connection again.
| Credential | Before | v1.77.1 |
|---|---|---|
| Google Workspace key | credentials/directory/google/<id>/<ref> |
credentials/google/workspace/<id>/<ref> |
| organisation | credentials/github-org/<org>/<ref> |
credentials/github/org/<org>/<ref> |
| link App | credentials/github-app/link/<ref> |
credentials/github/app/link/<ref> |
| catalogue App | credentials/github-app/<id>/<ref> |
credentials/github/app/<id>/<ref> |
| runner App | credentials/github-runner-app/<tier>/<org>/<ref> |
credentials/github/app/runner-<tier>-<org>/<ref> |
| GitHub link | credentials/github-link/<account>/<ref> |
credentials/github/link/<account>/<ref> |
| Slack workspace | credentials/slack-workspace/<team>/<ref> |
credentials/slack/workspace/<team>/<ref> |
| Slack App | credentials/slack-app/<id>/<ref> |
credentials/slack/app/<id>/<ref> |
| console session key | credentials/console/session-key |
credentials/oidc/console/session-key |
| generated client | credentials/oidc-client/<id>/secret |
unchanged |
4. Update the policy¶
The issuer's password sign-in signs in as system:serviceaccount:<namespace>:<recovery.serviceAccount>, or sluis:recovery where none is set. Place it in the group the console client requires, as a cluster already does.
all:sluis:operator:
matchers:
- service_account: {namespace: sluis, name: recovery}
5. Apply¶
The library writes the recovery verifier and denies the issuer's role the password.
pulumi preview --diff
pulumi up
| Resource | Effect |
|---|---|
internal/oidc/recovery-verifier |
created |
internal/oidc/recovery-password, conformance-password |
the issuer's role loses read |
recovery.verifierSecret: recovery/verifier |
rendered in place of recovery.passwordSecret |
Without Pulumi, derive the credential and store it where recovery.verifierSecret names.
sluisctl recovery password --instance <instance> | sluisctl recovery verifier
6. Check the behaviour changes¶
| Change | Who notices |
|---|---|
| The sign-in page proves the password with SRP-6a and never sends it | operators who recover |
The issuer and the console send Strict-Transport-Security on https |
a host that cannot answer https |
Refusal log lines carry method, path, client_id and user_agent |
log alerts that match refusals |
sluis secrets rekey compares keys by resolved ARN |
operators who rekey |
Audit database URLs need sslmode=verify-full, a CA file and a password file (upgrade audit) |
installations that run audit with Postgres |
hsts.maxAge and hsts.includeSubDomains tune the header (endpoints).
7. Roll¶
Roll the service, the modules and the library together.
Verify¶
Sign in at https://<issuer host>/console/login with Recovery sign-in, then turn recovery off (turn off recovery).
Roll back¶
Roll back to v1.77.0 with the same documents. With another secrets store, copy the credentials back first.