Files
computer-playbook/cli/administration/deploy/development/deploy/rotate.py
T
kevinveenbirkenbachandClaude Opus 5 905a5fb2d9 feat(deploy): rotate credentials between the two passes
PASS 2 read the exact values PASS 1 wrote, so no deploy ever had to propagate a secret that moved. Every role that only writes a credential at creation time therefore stayed green without the update path being exercised once.

Both orchestrators now call `inventory credentials reset` after the recover drill and before the async pass: compose through the container in the new .rotate module, swarm through the matrix orchestrator with --mirror, because its inventory keeps one host_vars copy per node. --backup keeps the pre-rotation file for the post-mortem, since after a rotation nothing records what PASS 1 deployed with. `administrator` stays exempt in both: its password is ansible_become_password, and rotating it would lock the deploy out of its own host.

Expect roles that never re-apply a changed secret to fail PASS 2 from here on; that is the gate working. Both database engines already converge their root password on every run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 23:17:06 +02:00

51 lines
1.5 KiB
Python

"""Credential rotation between PASS 1 and PASS 2 of a matrix-deploy round."""
from __future__ import annotations
import json
import os
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from cli.administration.deploy.development.compose import Compose
ROTATION_EXEMPT = ("administrator",)
def _rotate_credentials(
compose: Compose, *, inventory_dir: str, round_variants: dict[str, int]
) -> None:
"""Regenerate the round's inventory credentials before the async pass.
Args:
compose: the development stack the inventory lives in.
inventory_dir: the round's inventory directory.
round_variants: variant index per app, as baked by `init`.
PASS 2 otherwise reads the exact values PASS 1 wrote, so nothing in the
deploy ever has to propagate a changed secret. `administrator` stays
exempt: its password is `ansible_become_password`, and rotating it would
lock the deploy out of its own host.
"""
print("=== matrix-deploy: rotating credentials between passes ===")
compose.exec(
[
"infinito",
"administration",
"inventory",
"credentials",
"reset",
"--inventory-dir",
inventory_dir,
"--schema",
"--users",
"--app-variants",
json.dumps(round_variants, sort_keys=True),
"--backup",
"--except",
*ROTATION_EXEMPT,
],
check=True,
workdir=os.environ["INFINITO_SRC_DIR"],
)