Implement reproducible S1 handoff contracts
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a02994-7685-7940-bf34-3555b8256018
This commit is contained in:
parent
c8cb1c8edf
commit
b93af8cc78
44 changed files with 2035 additions and 342 deletions
|
|
@ -6,8 +6,9 @@ a reproducible, CI-friendly pass/fail verdict.
|
|||
|
||||
## The spec
|
||||
|
||||
`spec/server-baseline.yaml` is the single source of truth for the target state
|
||||
of every managed node. It covers:
|
||||
`spec/server-baseline.yaml` is executable through
|
||||
`scripts/baseline_contract.py`. The dynamic inventory resolves its selected
|
||||
profile into the variables consumed by both Ansible and Goss. It covers:
|
||||
|
||||
- **Firewall** — UFW active, default deny inbound, required ports allowed
|
||||
(SSH 22/tcp; HostEurope Nydus 2224/tcp). The k3s API (6443/tcp) is
|
||||
|
|
@ -15,16 +16,18 @@ of every managed node. It covers:
|
|||
`k3s_api_revoked_sources` is pruned on a firewall-tagged converge. Flannel
|
||||
VXLAN (8472/udp) is omitted while the cluster is single-node; peer
|
||||
addresses go in `flannel_vxlan_allowed_sources` when a second node appears.
|
||||
Hosts with `ufw_manage: false` (CoulombCore) are not rewritten. A host with
|
||||
an empty 6443 allowlist is recoverable over SSH.
|
||||
`CoulombCore` selects an explicit external-firewall profile and verifies its
|
||||
replacement INPUT default-drop control without rewriting it. A host with an
|
||||
empty 6443 allowlist is recoverable over SSH.
|
||||
- **SSH daemon** — root login disabled, password auth disabled, pubkey auth enabled
|
||||
- **Services** — ufw, fail2ban, ssh.socket enabled and running
|
||||
- **Packages** — ufw, fail2ban, git, curl, vim, htop (age and sops installed as binaries)
|
||||
- **Users** — admin user with bash shell and passwordless sudo
|
||||
- **Security** — fail2ban sshd jail active, HISTCONTROL=ignorespace in /etc/profile.d/
|
||||
|
||||
When you change the desired state of a node, update this file first. Then
|
||||
update the Ansible role **and** the Goss tests to match.
|
||||
When you change governed desired state, update this file. The consumers use the
|
||||
same resolved variables; `make validate-baseline` fails if either consumer is
|
||||
disconnected from the contract.
|
||||
|
||||
## Running verification
|
||||
|
||||
|
|
@ -74,10 +77,11 @@ that converge UFW. The mapping is:
|
|||
|
||||
## Adding new assertions
|
||||
|
||||
1. Add the desired state to `spec/server-baseline.yaml`
|
||||
2. Add the Ansible task to `ansible/roles/base/tasks/main.yml`
|
||||
3. Add the Goss assertion to `goss/baseline.yaml.j2`
|
||||
4. Run `make converge-firewall` and `make verify-host HOST=…` to confirm
|
||||
1. Add the desired state to `spec/server-baseline.yaml`.
|
||||
2. If it introduces a new control kind, teach both consumers that kind.
|
||||
3. Run `make validate-baseline` and the unit tests.
|
||||
4. Run `make converge-firewall` and `make verify-host HOST=…` only in the
|
||||
appropriate reviewed live-change sequence.
|
||||
|
||||
An hourly on-host timer (`railiance-goss-baseline.timer`) reruns the last
|
||||
rendered baseline. See `docs/conformance-loop.md`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue