kaizen-agentic/roles/host-operator/protocols/ufw-admin-allowlist.md
tegwick 06037b0486
Some checks failed
CI Smoke / host-smoke (push) Successful in 1s
ci / test (push) Failing after 9s
CI Smoke / container-smoke (push) Successful in 4s
docs: UFW k3s API admin allowlist procedure for host-operator
Add reusable protocol, wire it in ROLE.yaml, and document the current
railiance01 allowlist plus quick commands in the pilot access-plan.
2026-07-16 14:04:44 +02:00

3.1 KiB

agent slug title version last_updated
host-operator ufw-admin-allowlist UFW k3s API admin allowlist 0.1.0 2026-07-16

UFW admin allowlist (k3s API / port 6443)

Purpose

After world-open 6443/tcp is removed, remote kubectl / k3s API access works only from explicitly allowlisted public IPs. This procedure adds, lists, and removes admin IPs safely.

Access class: firewall_change — requires recorded human approval on production.

When to use

  • New admin laptop / office / mobile network needs direct API access to the node
  • Admin public IP changed (ISP / travel)
  • CI or jump host must hit public :6443 (prefer SSH tunnel when possible)

When not needed

  • SSH into the host and run sudo k3s kubectl … locally
  • Access only via SSH tunnel / ops-bridge (SSH already open)
  • IP is already listed in ufw status

Preconditions

  • SSH access to the host as an operator with passwordless or approved sudo
  • Approver recorded for firewall_change on production hosts
  • Target public IP known (see Discover IP)

Discover IP (from the admin machine)

curl -4 -s ifconfig.me; echo
# or
curl -4 -s https://api.ipify.org; echo

Use the public IPv4, not a private LAN address (unless that is how the host sees you).

List current rules

ssh <host> 'sudo ufw status numbered verbose'

Note OpenSSH should remain Anywhere (or your org policy). k3s API lines look like:

6443/tcp    ALLOW IN    <ip>    # k3s-api-admin-<label>

Add an admin IP

ssh <host> "sudo ufw allow from <PUBLIC_IP> to any port 6443 proto tcp comment 'k3s-api-admin-<label>'"
ssh <host> 'sudo ufw status numbered'

Example:

ssh railiance01 "sudo ufw allow from 203.0.113.50 to any port 6443 proto tcp comment 'k3s-api-admin-home'"

Verify

From the admin machine (with kubeconfig pointing at the public API):

kubectl get node
# or
curl -sk --max-time 5 https://<host-ip>:6443/version

Remove a stale admin IP

ssh <host> 'sudo ufw status numbered'
# identify rule number N for the stale IP
ssh <host> 'sudo ufw delete N'   # confirm when prompted, or: echo y | sudo ufw delete N

Prefer deleting by number to avoid removing the wrong rule.

Rollback (emergency: restore world-open API — last resort)

Only if lockout of all admins is worse than temporary exposure:

ssh <host> 'sudo ufw allow 6443/tcp comment temporary-world-open-k3s-api'
# re-establish allowlist, then:
ssh <host> 'sudo ufw delete allow 6443/tcp'

Prefer fixing allowlist IPs over world-open.

Optional: IPv6

If admins use IPv6 to the host:

sudo ufw allow from <PUBLIC_IPV6> to any port 6443 proto tcp comment 'k3s-api-admin-<label>-v6'

Engagement bookkeeping

After changes:

  1. Update access-plan.md allowlist table (IP, label, date, who)
  2. Append session log / close-session summary (no secrets)
  3. Note in vault Watch Points if IPs are dynamic
  • host-operator privilege gate (firewall_change)
  • Pilot reference: engagements/pilots/eng-coulomb-railiance01-ho-001/access-plan.md