Close RAIL-HO-WP-0009 declared-state gaps; leave live 6443 prune gated
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Make the k3s API tunnel-only (ADR-005), stop declaring Flannel VXLAN
open to Anywhere, tag the base role so firewall can be scoped, and
schedule the Goss declared-vs-live check. CoulombCore sets ufw_manage
false so a converge cannot enable UFW there. T02 still needs operator
approval for make converge-firewall HOST=Railiance01.
This commit is contained in:
codex 2026-08-15 15:41:59 +02:00
parent 434121be99
commit 4d9e77c968
29 changed files with 793 additions and 99 deletions

View file

@ -4,9 +4,10 @@
#
# THIS IS A TEMPLATE. It is rendered per host from inventory variables, so the
# firewall assertions below are generated from the SAME declaration that
# converges the host (k3s_api_allowed_sources in group_vars/all.yaml). That is
# deliberate: a hand-written assertion drifts from the declaration it is meant
# to check, which is exactly how RAIL-HO-WP-0009 happened.
# converges the host (k3s_api_allowed_sources, flannel_vxlan_allowed_sources,
# ufw_extra_allowed in group_vars). That is deliberate: a hand-written
# assertion drifts from the declaration it is meant to check, which is exactly
# how RAIL-HO-WP-0009 happened.
package:
ufw:
@ -60,16 +61,33 @@ command:
{% for src in k3s_api_allowed_sources | default([]) %}
- '/6443\/tcp\s+ALLOW\s+{{ src.address | regex_escape }}/'
{% endfor %}
- /8472\/udp.*ALLOW/
{% for src in flannel_vxlan_allowed_sources | default([]) %}
- '/8472\/udp\s+ALLOW\s+{{ src.address | regex_escape }}/'
{% endfor %}
{% for rule in ufw_extra_allowed | default([]) %}
- '/{{ rule.port }}\/{{ rule.proto | default("tcp") }}\s+ALLOW/'
{% endfor %}
# The k3s API must never be reachable from Anywhere. The previous assertion
# matched /6443\/tcp.*ALLOW/, which passes identically whether the API is
# restricted to one operator address or open to the entire internet — it
# asserted that the port was allowed, not from whom.
# Exact allowlist size: extra hand grants must fail, not only missing ones.
# The previous assertion matched /6443\/tcp.*ALLOW/, which passes identically
# whether the API is restricted to one operator address or open to the entire
# internet — it asserted that the port was allowed, not from whom.
"ufw status | grep -Ec '6443/tcp[[:space:]]+ALLOW[[:space:]]+Anywhere' || true":
exit-status: 0
stdout:
- "0"
"ufw status | grep -E '6443/tcp[[:space:]]+ALLOW' | grep -vc 'Anywhere' || true":
exit-status: 0
stdout:
- "{{ k3s_api_allowed_sources | default([]) | length }}"
"ufw status | grep -Ec '8472/udp[[:space:]]+ALLOW[[:space:]]+Anywhere' || true":
exit-status: 0
stdout:
- "0"
"ufw status | grep -E '8472/udp[[:space:]]+ALLOW' | grep -vc 'Anywhere' || true":
exit-status: 0
stdout:
- "{{ flannel_vxlan_allowed_sources | default([]) | length }}"
{% for src in k3s_api_revoked_sources | default([]) %}
# Revoked operator source must not retain access: {{ src.comment | default('') }}