Close RAIL-HO-WP-0009 declared-state gaps; leave live 6443 prune gated
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:
parent
434121be99
commit
4d9e77c968
29 changed files with 793 additions and 99 deletions
53
Makefile
53
Makefile
|
|
@ -131,21 +131,21 @@ backup: ## Backup S1 OS config to /opt/backup/railiance/infra/ (age-encrypted, r
|
|||
|
||||
# ---- Ansible ----
|
||||
ansible-bootstrap: ## Run base bootstrap play (users, ssh, ufw, sops-agent, custodian-agent)
|
||||
cd ansible && ansible-playbook playbooks/bootstrap.yaml -u admin
|
||||
cd ansible && ansible-playbook playbooks/bootstrap.yaml $(ANSIBLE_USER_FLAG)
|
||||
|
||||
provision-custodian-agent: ## Deploy custodian agent SSH key to all managed hosts
|
||||
@python3 -c "import yaml; d=yaml.safe_load(open('ansible/inventory/group_vars/all.yaml')); k=d.get('custodian_agent_pubkey',''); exit(0 if k else 1)" \
|
||||
|| (echo "ERROR: custodian_agent_pubkey is empty. Run: cd ~/the-custodian && make custodian-keygen"; exit 1)
|
||||
cd ansible && ansible-playbook playbooks/custodian-agent.yaml -u $(SSH_USER)
|
||||
cd ansible && ansible-playbook playbooks/custodian-agent.yaml $(ANSIBLE_USER_FLAG)
|
||||
|
||||
provision-custodian-agent-host: ## Deploy custodian agent key to one host: make provision-custodian-agent-host HOST=Railiance01
|
||||
@test -n "$(HOST)" || (echo "Usage: make provision-custodian-agent-host HOST=Railiance01"; exit 1)
|
||||
cd ansible && ansible-playbook playbooks/custodian-agent.yaml -u $(SSH_USER) \
|
||||
cd ansible && ansible-playbook playbooks/custodian-agent.yaml $(ANSIBLE_USER_FLAG) \
|
||||
--limit "$(HOST)"
|
||||
|
||||
bootstrap-ssh-ca: ## Deploy OpenBao SSH CA trust + auth_principals: make bootstrap-ssh-ca SSH_CA_PUBKEY=/path/to/ca_user.pub
|
||||
@test -n "$(SSH_CA_PUBKEY)" || (echo "Usage: make bootstrap-ssh-ca SSH_CA_PUBKEY=/path/to/ca_user.pub [HOST=Railiance01]"; exit 1)
|
||||
cd ansible && ansible-playbook playbooks/bootstrap-ssh-ca.yaml -u $(SSH_USER) \
|
||||
cd ansible && ansible-playbook playbooks/bootstrap-ssh-ca.yaml $(ANSIBLE_USER_FLAG) \
|
||||
-e ssh_ca_pubkey_path="$(SSH_CA_PUBKEY)" \
|
||||
$(if $(HOST),--limit "$(HOST)",)
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ deploy-stack: ## Print the full S1→S5 ordered deploy sequence (operator follow
|
|||
@echo "PRE-CONDITIONS"
|
||||
@echo " [ ] SSH key: ~/.ssh/id_ops"
|
||||
@echo " [ ] SOPS key: ~/.config/sops/age/keys.txt (or SOPS_AGE_KEY)"
|
||||
@echo " [ ] ops-bridge: bridge up state-hub-coulombcore k3s-api-coulombcore"
|
||||
@echo " [ ] ops-bridge: bridge up state-hub-coulombcore k3s-api-coulombcore k3s-api-railiance01"
|
||||
@echo ""
|
||||
@echo "S1 — Infrastructure Substrate (this repo)"
|
||||
@echo " make tf-plan && make tf-apply # provision server (skip if exists)"
|
||||
|
|
@ -222,7 +222,10 @@ remote-set: ## Set origin to your Gitea repo (GITEA/OWNER/REPO vars)
|
|||
ANS_DIR := ansible
|
||||
INV_SCRIPT := $(ANS_DIR)/inventory_from_yaml.py
|
||||
PLAY := $(ANS_DIR)/playbooks/bootstrap.yaml
|
||||
SSH_USER ?= admin
|
||||
# Inventory servers.yaml sets ansible_user. Override only when needed:
|
||||
# make converge SSH_USER=tegwick
|
||||
SSH_USER ?=
|
||||
ANSIBLE_USER_FLAG := $(if $(SSH_USER),-u $(SSH_USER),)
|
||||
|
||||
# Load your SOPS key for decryption when running playbooks (optional if you use keys.txt)
|
||||
export SOPS_AGE_KEY := $(shell cat ~/.config/sops/age/keys.txt 2>/dev/null)
|
||||
|
|
@ -234,50 +237,66 @@ ansible-help: ## Show common Ansible commands
|
|||
@echo " make converge # run baseline convergence on all hosts"
|
||||
@echo " make converge-host HOST=web-01# run on a single host"
|
||||
@echo " make converge-tags TAGS=base # run only tagged tasks"
|
||||
@echo " make converge-firewall HOST=Railiance01 # UFW only (RAIL-HO-WP-0009)"
|
||||
@echo " make converge-check # dry-run (check mode)"
|
||||
@echo " make converge-diff # show config diffs"
|
||||
@echo " make verify-host HOST=Railiance01"
|
||||
@echo " make goss-status # last on-host timer result"
|
||||
|
||||
ansible-inventory: ## Print the dynamic inventory Ansible will use
|
||||
cd $(ANS_DIR) && ansible-inventory --list | head -200
|
||||
|
||||
ansible-ping: ## Quick connectivity check (SSH + Python availability)
|
||||
cd $(ANS_DIR) && ansible all -u $(SSH_USER) -m ping
|
||||
cd $(ANS_DIR) && ansible all $(ANSIBLE_USER_FLAG) -m ping
|
||||
|
||||
status: ## Show live security state of all hosts (UFW, fail2ban, SSH hardening)
|
||||
@echo "=== Connectivity ==="
|
||||
cd $(ANS_DIR) && ansible all -u $(SSH_USER) -m ping
|
||||
cd $(ANS_DIR) && ansible all $(ANSIBLE_USER_FLAG) -m ping
|
||||
@echo "=== UFW ==="
|
||||
cd $(ANS_DIR) && ansible all -u $(SSH_USER) -m shell -a "ufw status" --become
|
||||
cd $(ANS_DIR) && ansible all $(ANSIBLE_USER_FLAG) -m shell -a "ufw status" --become
|
||||
@echo "=== fail2ban ==="
|
||||
cd $(ANS_DIR) && ansible all -u $(SSH_USER) -m shell -a "systemctl is-active fail2ban"
|
||||
cd $(ANS_DIR) && ansible all $(ANSIBLE_USER_FLAG) -m shell -a "systemctl is-active fail2ban"
|
||||
@echo "=== SSH hardening ==="
|
||||
cd $(ANS_DIR) && ansible all -u $(SSH_USER) -m shell -a "grep -iE '^(PermitRootLogin|PasswordAuthentication)' /etc/ssh/sshd_config" --become
|
||||
cd $(ANS_DIR) && ansible all $(ANSIBLE_USER_FLAG) -m shell -a "grep -iE '^(PermitRootLogin|PasswordAuthentication)' /etc/ssh/sshd_config" --become
|
||||
@echo ""
|
||||
@echo "--- Hint: run 'make verify' for a structured pass/fail report ---"
|
||||
|
||||
verify: ## Run Goss test suite against all hosts, commit TAP reports — exits non-zero on failure
|
||||
@echo "Running Goss baseline assertions..."
|
||||
@cd $(ANS_DIR) && ansible-playbook playbooks/verify.yaml -u $(SSH_USER) || \
|
||||
@cd $(ANS_DIR) && ansible-playbook playbooks/verify.yaml $(ANSIBLE_USER_FLAG) || \
|
||||
(echo "One or more assertions FAILED — see reports/ for TAP output." && exit 1)
|
||||
@echo "All assertions passed."
|
||||
@git add reports/ && \
|
||||
git diff --cached --quiet && echo "No new reports to commit." || \
|
||||
git commit -m "chore: Goss verification reports $$(date -u +%Y-%m-%dT%H%M%SZ)"
|
||||
|
||||
verify-host: ## Run Goss against one host: make verify-host HOST=Railiance01
|
||||
@test -n "$(HOST)" || (echo "Usage: make verify-host HOST=Railiance01"; exit 1)
|
||||
@echo "Running Goss baseline assertions on $(HOST)..."
|
||||
@cd $(ANS_DIR) && ansible-playbook playbooks/verify.yaml $(ANSIBLE_USER_FLAG) -l $(HOST) || \
|
||||
(echo "One or more assertions FAILED — see reports/ for TAP output." && exit 1)
|
||||
|
||||
goss-status: ## Fetch last on-host Goss timer result (fails if FAILED flag present)
|
||||
cd $(ANS_DIR) && ansible-playbook playbooks/goss-status.yaml $(ANSIBLE_USER_FLAG)
|
||||
|
||||
converge: ## Converge all hosts to the baseline (idempotent)
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) -u $(SSH_USER)
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) $(ANSIBLE_USER_FLAG)
|
||||
|
||||
converge-host: ## Converge a single host: make converge-host HOST=core-01
|
||||
@test -n "$(HOST)" || (echo "Usage: make converge-host HOST=<name>"; exit 1)
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) -u $(SSH_USER) -l $(HOST)
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) $(ANSIBLE_USER_FLAG) -l $(HOST)
|
||||
|
||||
converge-tags: ## Run only certain tags: make converge-tags TAGS="base,ufw"
|
||||
@test -n "$(TAGS)" || (echo "Usage: make converge-tags TAGS=tag1,tag2"; exit 1)
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) -u $(SSH_USER) --tags "$(TAGS)"
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) $(ANSIBLE_USER_FLAG) --tags "$(TAGS)"
|
||||
|
||||
converge-firewall: ## Apply only UFW tasks: make converge-firewall HOST=Railiance01
|
||||
@test -n "$(HOST)" || (echo "Usage: make converge-firewall HOST=Railiance01"; exit 1)
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) $(ANSIBLE_USER_FLAG) -l $(HOST) --tags firewall
|
||||
|
||||
converge-check: ## Dry-run (no changes), great for previews
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) -u $(SSH_USER) --check
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) $(ANSIBLE_USER_FLAG) --check
|
||||
|
||||
converge-diff: ## Show file/templating diffs while applying changes
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) -u $(SSH_USER) --diff
|
||||
cd $(ANS_DIR) && ansible-playbook $(PLAY) $(ANSIBLE_USER_FLAG) --diff
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue