Skip to content

feat(aws): draw the database password with a generator - #9

Open
JeroenSoeters wants to merge 3 commits into
mainfrom
feat/generator-db-password
Open

feat(aws): draw the database password with a generator#9
JeroenSoeters wants to merge 3 commits into
mainfrom
feat/generator-db-password

Conversation

@JeroenSoeters

Copy link
Copy Markdown
Contributor

Summary

Converts the AWS bootstrap example's database master password from eval-time random.password(...).opaque.setOnce to a formae PasswordGenerator with no rotation block: a one-time agent-side draw, like-for-like with the setOnce behavior it replaces. Besides being the 0.89.0 feature showcase, this removes the eval-time-randomness footgun (the random.password read URI is cached per evaluation, so identically-parameterized secrets silently share one value; a generator draws per generator).

The generator is gated on --database=new exactly like the secret it feeds; alb, tailnet, and --database byo modes all evaluate cleanly (byo emits no generator). Version pins move together: formae schema 0.88.0 to 0.89.0, agent image formae:0.87.0 to formae:0.89.0, aws schema 0.1.13 to 0.1.17 (whose secretString accepts a generator output; this also retires the stale schema-pin TODO).

DO NOT MERGE until formae 0.89.0 stable ships

ghcr.io/platform-engineering-labs/formae:0.89.0 does not exist yet; this is customer-facing example code and must not pin a dev tag. Merge with (or right after) the 0.89.0 release.

The database master password was minted at evaluation time with
random.password and pinned with setOnce. That shape cannot rotate, and
eval-time randomness carries a footgun: the random.password read URI is
cached per PKL evaluation, so two secrets with identical parameters
silently share one value. A generator draws per generator and per
binding, so the hazard disappears instead of being designed around.

The secret now binds a PasswordGenerator with no rotation block: a
one-time draw, like-for-like with the setOnce behavior it replaces, and
the same 24-character alphanumeric shape. The generator only exists when
--database=new, exactly like the secret it feeds.

Generators need the formae 0.89.0 schema and a 0.89.0 agent, so the
formae schema pin and the bundled agent image move up together; the aws
schema pin moves to 0.1.17, which accepts a generator output where the
0.1.13 secretString type did not.
@JeroenSoeters
JeroenSoeters force-pushed the feat/generator-db-password branch from e2abb50 to ca8b490 Compare September 6, 2026 06:11
…ssword

A setOnce field keeps the value it was created with, so formae refuses
to route a generator through it: re-applying this version over an
installation bootstrapped on the eval-time password is rejected at plan
time. Document the two-apply migration (drop setOnce, then adopt the
generator) and the agent restart it ends with, since the deployed agent
receives FORMAE_DB_PASSWORD at task start and keeps the old value until
its task is replaced.
The shipped version removes the random module import, so the documented
transitional shape must restore it or the step-1 apply fails at
evaluation. The transitional file was verified to evaluate.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant