Skip to content

Apply cve.yml from CI too - #24

Merged
TakGN merged 1 commit into
mainfrom
cve-2026-98432-ci
Oct 30, 2026
Merged

TakGN merged 1 commit into
mainfrom
cve-2026-98432-ci

Conversation

@TakGN

@TakGN TakGN commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

What

cve.yml (the CVE-2026-98432 filter on sf and sf2, from #21) now applies from CI like site.yml and platform.yml:

  • On a pull request: a dry run.
  • On merge: a dry run, then the apply, once a required reviewer approves it in production.

It runs on its own, in its own concurrency group cve-main. It needs nothing from the other two playbooks, and they never touch these boxes.

  • cve.yml now creates and keeps CI's own account on sf/sf2, ipni-ci:
    • It signs in only with CI's existing key (keys/github-actions.pub), installed exclusively.
    • Its password is locked, and its sudo needs no password.
    • It touches no other account, user included.
  • group_vars/infra_boxes/main.yml: adds infra_ci_user: ipni-ci and infra_ci_pubkey_file. Operators still sign in as user with -K.
  • scripts/ci-playbook.sh accepts cve and signs in as infra_ci_user, read from group_vars and passed as an extra var so it outranks the operators' ansible_user. No new secret.
  • inventory/known_hosts: sf's and sf2's host keys in ssh's [ip]:5222 form. For each box, the scanned key, the key file on the box and an operator's known_hosts agreed.
  • Workflow:
    • cve is added to the manual run's playbook choice and to the changes job.
    • New cve-dry-run and cve-apply jobs, the apply in production.
    • The cve jobs run when cve.yml, the hardening role's CVE tasks, templates or defaults, host_vars/sf*/, CI's public key, or the shared paths change.
  • README ("Running playbooks from CI", the CVE section) and AGENTS.md are updated.

Why

So what runs on sf/sf2 is what's on main, reviewed and approved like every other box, instead of whatever an operator last ran from their machine.

Reviewer notes

  • This gives CI root on ipni/infra's indexers. Ansible needs passwordless sudo, and it can't be narrowed to the nft commands. ipni/infra should know before the first run.
    • To revoke: remove the account's tasks from cve.yml, then on each box run sudo userdel -r ipni-ci and sudo rm /etc/sudoers.d/90-ipni-ci.
  • This PR's cve-dry-run will fail to connect at first. ipni-ci doesn't exist yet, and CI can't create it. The first run on each box is an operator's, from this branch:
    ansible-playbook cve.yml -K --check --diff -l sf
    ansible-playbook cve.yml -K -l sf
    # then the same for sf2
    That also installs the count-mode filter, which sf doesn't have yet. After that, re-run cve-dry-run: it should connect as ipni-ci and report no changes.
  • Not verified yet: whether GitHub's runners can reach port 5222 through sf/sf2's MikroTik gateway. ipni/infra's docs say SSH on 5222 gets through; the re-run above is the first real test.
  • site.yml and platform.yml dry runs will also run. This PR touches the workflow, inventory/ and group_vars/, which both treat as shared. Neither should change anything.
  • Checked locally:
    • All 7 playbooks pass --syntax-check.
    • The wrapper's extra vars come out as {"ansible_user": "ipni-ci"} for cve and unchanged for site.
    • The workflow parses, and the cve path pattern matches the intended files and not others (e.g. not roles/hardening/tasks/main.yml, host_vars/sing-1/, keys/takgn.pub).
    • bash -n and shellcheck are clean, and yamllint is clean.
    • ansible-lint gives the same findings as main.
    • cve.yml --check --diff -l sf as user with sudo off: no failures.

🤖 Generated with Claude Code

cve.yml puts the CVE-2026-98432 filter on sf and sf2, ipni/infra's
indexers. It joins site.yml and platform.yml in CI: a dry run on pull
requests, and on merge a dry run then the apply, once a required
reviewer approves it in `production`. It runs on its own, in cve-main,
since it needs nothing from the other two and they never touch these
boxes.

CI cannot sign in there as `ipni` (those boxes do not have it) or as
the operators' shared `user`, whose sudo wants a password. So cve.yml
now creates and keeps an account of its own for CI, ipni-ci: key only,
with CI's existing key and nothing else, password locked, passwordless
sudo. ci-playbook.sh makes CI sign in as it, reading the name from
group_vars/infra_boxes. No new secret.

CI only connects to pinned host keys, so sf's and sf2's go into
inventory/known_hosts in ssh's [ip]:5222 form; the scanned key, the key
file on each box and an operator's known_hosts agreed.

CI cannot create its own account, so the first run on each box is an
operator's, with -K. Until then cve.yml's CI dry runs fail to connect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@TakGN
TakGN merged commit b5a7d98 into main Oct 30, 2026
21 of 22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant