Skip to content

Prove the audit bind refuses to create its source during the migration window #960

Description

@sehkone

Prove the audit bind refuses to create its source during the migration window

Context

The audit bind is declared create_host_path: false so Docker refuses to manufacture the bind source when the reserve mount is not there. The migration window is where that guarantee matters most: after the aside rename the underlying store is empty, the reserve may be mounted but still carries no openbao/, and a Compose bring-up in that state must fail rather than create the directory on the mounted reserve. A created openbao/ there would be a bind source the migration did not put there, standing on the destination side of a copy that has not run.

Rust coverage proves bootroot infra up refuses bring-up under migration incomplete (src/commands/audit_store.rs:3240). That is a different assertion: it proves bootroot declines to start containers, not that Docker itself refuses the bind when something else brings the stack up. The migration E2E scenario never attempts a Compose bring-up inside the window, so the create_host_path: false guarantee is asserted nowhere against the state the window actually produces.

What was withdrawn from this issue, and why it is not to be re-added. An earlier revision also asked that every mount-absent open-migration report render the outstanding activation commands, including under the migration-set refusals. That reading came from an acceptance criterion in #926 that had not been narrowed the way its capacity-figures bullet was; #926 has since been amended, and the withholding is deliberate. A rollback is rendered for the mount state its run observed, so one rendered with the mount absent carries no umount; rendering an activation beside it would let an operator run the activation, take the rollback, and meet rmdir against a live mount point, stopping under sh -e before the restoring rename. Nothing in this issue changes what is rendered.

Scope

Add an E2E scenario that exercises the migration window and proves the bind guard holds inside it. The scenario reaches an activated but still empty reserve — .pre-mount present, the mount active, <audit_store_dir>/openbao absent — attempts the normal Compose bring-up, and proves the OpenBao container fails to start with no entry created beneath the mounted store.

The scenario runs through the same registrar-internal-init lifecycle harness the existing migration coverage uses, and starts from an existing audit store so the aside rename and the full window are exercised rather than simulated. It leaves both writers stopped until the normal closing path.

Acceptance criteria

  • The E2E suite attempts docker compose up while .pre-mount exists, the reserve mount is active, and <audit_store_dir>/openbao is absent.
  • It proves the OpenBao container fails to start and that no entry is created beneath the mounted store.
  • The fixture starts with an existing audit store, so the aside rename and the full migration window are exercised, and it leaves both writers stopped until the normal closing path.
  • The scenario runs through the existing registrar-internal-init lifecycle harness rather than a new one.
  • The existing infra up refusal coverage is kept and unchanged.
  • No change weakens create_host_path: false, changes the audit-store layout, or lets bootroot perform a host-changing migration step.
  • No rendering behaviour changes: the commands any outcome renders, and the outcomes themselves, are exactly what they are today.

Constraints

  • Keep the test operator-faithful: it must use the rendered or normal Compose surface, and must not simulate Docker's result by creating or removing paths directly.
  • Do not create, copy, rename, delete, mount, or unmount a store from bootroot.
  • Do not change withholds_activation, the migration-set refusals, holding-directory precedence, or any rendered command list.
  • Do not add a second activation renderer or a new outcome vocabulary.
  • Do not use a recursive delete or a pipeline in anything the scenario renders or runs.

Out of scope

  • Rendering the activation for mount-absent reports under a migration-set refusal. Withdrawn deliberately, for the reason in Context; Move audit records onto the reserve, at activation and when the reserve changes #926's acceptance criteria now state the withholding.
  • Choosing a rollback procedure for collision states where the reverse rename target already exists or a foreign filesystem occupies the store.
  • Changing the migration copy, capacity, manifest, or reserve-replacement contracts.
  • Altering daemon-side registrar-verb behavior.

Test plan

  • Extend assert_the_rendered_steps_migrate_an_existing_store, or add a focused sibling, in scripts/impl/run-registrar-internal-init-e2e.sh with the mid-window Compose attempt and the assertion that no bind source appears on the mounted reserve.
  • Assert the OpenBao container's failure by its own exit rather than by the absence of a side effect alone, so a bring-up that silently does nothing cannot pass.
  • Run the registrar-internal-init E2E job, plus cargo clippy --all-targets -- -D warnings, cargo fmt -- --config group_imports=StdExternalCrate --check, and ./scripts/check-docs.sh.
  • Assert the existing infra up refusal test still passes unchanged.

Dependencies

Part of #926. This follow-up has no follow-up issue dependency and is filed under umbrella #773.

Pointers

  • src/commands/audit_store.rs:3240 — existing infra up refusal coverage, which this issue keeps and does not duplicate.
  • scripts/impl/run-registrar-internal-init-e2e.sh:773 — existing bind-guard boundary test.
  • scripts/impl/run-registrar-internal-init-e2e.sh:1223 — the migration E2E function that lacks the mid-window Compose attempt.
  • src/commands/audit_store/migration.rs:264withholds_activation, whose behaviour this issue leaves untouched; its doc comment records why the mount-absent refusal states withhold.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions