Supply Chain

Assess Ansible Playbook Security with cnspec

Scan Ansible playbooks for security misconfigurations using cnspec.

Validate Ansible playbooks against security policies before they run against your infrastructure. cnspec parses playbook YAML and exposes tasks, roles, and configuration as queryable MQL resources, so you can check for insecure module options, missing privilege escalation controls, and other configuration issues in code review and CI before a single play executes.

Prerequisites

To scan Ansible playbooks with cnspec, you must have:

Scan an Ansible playbook

Scan a playbook file:

cnspec scan ansible playbook.yml

Scan a directory containing playbook files:

cnspec scan ansible /path/to/playbooks/

Scan options

OptionDescription
--asset-nameOverride the asset name
--annotationAdd an annotation to the asset (key=value)
--incognitoRun in incognito mode (do not report results to Mondoo Platform)
-o, --outputSet the output format (compact, full, json, junit, summary, yaml)
-f, --policy-bundlePath to a policy file (local path, s3:// URI, or http(s):// URL)
--policySpecify policies to execute (requires --policy-bundle)
--risk-thresholdExit with status 1 if any risk meets or exceeds this value (0-100)

Explore Ansible playbooks

Run cnspec shell ansible playbook.yml to open the interactive shell and explore your playbooks.

List all plays

cnspec> ansible.plays
ansible.plays: [
  0: ansible.play name="Configure web servers"
  1: ansible.play name="Configure database servers"
  ...
]

Retrieve play details

Get hosts, roles, and privilege escalation settings for each play:

cnspec> ansible.plays { name hosts roles become becomeUser strategy }
ansible.plays: [
  0: {
    name: "Configure web servers"
    hosts: "webservers"
    roles: ["nginx", "certbot"]
    become: 1
    becomeUser: "root"
    strategy: "linear"
  }
  ...
]

Retrieve play variables

cnspec> ansible.plays { name vars }
ansible.plays: [
  0: {
    name: "Configure web servers"
    vars: {
      http_port: "80"
      max_clients: "200"
    }
  }
  ...
]

List tasks within each play

cnspec> ansible.plays { name tasks }
ansible.plays: [
  0: {
    name: "Configure web servers"
    tasks: [
      0: ansible.task name="Install nginx"
      1: ansible.task name="Copy nginx config"
      2: ansible.task name="Start nginx service"
    ]
  }
  ...
]

Retrieve task details

Get the action and conditions for each task:

cnspec> ansible.plays { tasks { name action when notify } }
ansible.plays: [
  0: {
    tasks: [
      0: {
        name: "Install nginx"
        action: {
          module: "apt"
          args: {
            name: "nginx"
            state: "present"
          }
        }
        when: ""
        notify: ["restart nginx"]
      }
      ...
    ]
  }
  ...
]

Find tasks with conditional execution

cnspec> ansible.plays { tasks.where(when != "") { name when } }
ansible.plays: [
  0: {
    tasks.where: [
      0: {
        name: "Install nginx"
        when: "ansible_os_family == 'Debian'"
      }
    ]
  }
]

Retrieve block and rescue tasks

cnspec> ansible.plays { tasks { name block rescue } }
ansible.plays: [
  0: {
    tasks: [
      0: {
        name: "Deploy application"
        block: [
          0: ansible.task name="Pull latest code"
          1: ansible.task name="Run migrations"
        ]
        rescue: [
          0: ansible.task name="Rollback deployment"
        ]
      }
    ]
  }
  ...
]

List handlers

cnspec> ansible.plays { name handlers }
ansible.plays: [
  0: {
    name: "Configure web servers"
    handlers: [
      0: ansible.handler name="restart nginx"
      1: ansible.handler name="reload nginx"
    ]
  }
  ...
]

Retrieve handler actions

cnspec> ansible.plays { handlers { name action } }
ansible.plays: [
  0: {
    handlers: [
      0: {
        name: "restart nginx"
        action: {
          module: "service"
          args: {
            name: "nginx"
            state: "restarted"
          }
        }
      }
      ...
    ]
  }
  ...
]

Get full details for all plays

cnspec> ansible.plays { * }

Example security checks

Ensure yum tasks validate certificates

A common misconfiguration is disabling certificate validation when installing packages. Check that no ansible.builtin.yum tasks have validate_certs set to false:

ansible.plays.all(
  tasks.where(action["ansible.builtin.yum"] != empty).all(
    action["ansible.builtin.yum"]["validate_certs"] != false
  )
)

Ensure no plays run as root

ansible.plays.all(remoteUser != "root")

Check that privilege escalation uses a specific method

ansible.plays.where(become == true).all(
  becomeMethod == "sudo"
)

Learn more

On this page