Skip to main content
RunBook Academy

← All checklists in Ansible

QuarterlySecurity

Checklist: Automation security review

21 items ·15 critical ·5 warn ·1 info

Run this quarterly, and additionally after any change to the automation account, the branch protection rules, the pipeline, or the set of people who can trigger a production run.

It overlaps the secrets review deliberately but asks a different question. The secrets review asks what credentials exist and who can read them. This one asks what the automation is allowed to do, who can make it do something, and whether you would find out if somebody did.

What a failure means

Every critical item describes a way somebody could cause a change to the fleet without the estate noticing, or a way a compromise of one thing becomes a compromise of everything. Ansible is a lateral-movement tool with a friendly interface, and the difference between that being a benefit and a liability is this list.

Findings here are usually not urgent in the sense of an outage, and are usually expensive to fix, which is why they need a named owner and a date rather than a resolution before the review closes.

Access this needs

The host-side items go through the command module and read: sudo -l, sshd -T, cat authorized_keys, grep. They need become on the targets. The repository items are static reads. Nothing here writes.

Two items - branch protection and trigger access - are checked in the version control and CI systems, not from a shell, and two more - the network path and the detection - are attested by a person.

Where the evidence goes

Record the findings, the owner and the agreed date for each, in whatever register your organisation uses for security findings rather than in the repository. The items with no command - branch protection, trigger access, network path, detection, decommissioned trust - need the name of the person who confirmed them, because those are the five that an auditor will ask about and the five that a command cannot answer.

Sign-off

  • Reviewer: ________________ Date: ___________
  • Platform owner: ___________ Date: ___________
  • Security owner: ___________ Date: ___________

Critical15 items

  1. ansible-inventory -i inventories/production --list | jq -r '._meta.hostvars | to_entries[] | "\(.key) \(.value.ansible_user // "unset")"' | sort -u -k2
  2. ansible -i inventories/production web -m ansible.builtin.command -a 'sudo -l -U ansible' --one-line
  3. grep -rn 'sudoers' roles/ playbooks/
  4. ansible -i inventories/production web -m ansible.builtin.command -a 'sshd -T' --one-line | grep -o 'passwordauthentication [a-z]*'
  5. ansible -i inventories/production web -m ansible.builtin.command -a 'cat /home/ansible/.ssh/authorized_keys' --one-line
  6. ansible-config dump | awk '/^HOST_KEY_CHECKING/ && !/= True/ {print "FINDING: " $0}'
  7. grep -nE '^(roles_path|library|collections_path|collections_paths|action_plugins|callback_plugins|connection_plugins|filter_plugins|lookup_plugins|inventory_plugins|strategy_plugins|test_plugins|vars_plugins)[[:space:]]*=' ansible.cfg
  8. ls -la library/ plugins/ filter_plugins/ action_plugins/ lookup_plugins/ callback_plugins/ 2>/dev/null
  9. cat requirements.yml; ansible-config dump | grep -E '^GALAXY_SERVER'
  10. systemctl list-timers --all --no-pager | grep -i ansible; crontab -l 2>/dev/null | grep -i ansible

Warning5 items

  1. ansible -i inventories/production web -m ansible.builtin.command -a 'grep -c from= /home/ansible/.ssh/authorized_keys' --one-line
  2. ansible-config dump --only-changed | grep '^CONFIG_FILE'
  3. grep -rnE '\{\{[^}]*ansible_(hostname|fqdn|nodename|distribution_version|env)' playbooks/ roles/*/templates/
  4. grep -rn 'become_user\|become_method' playbooks/ roles/ ansible.cfg

Info1 item