Secure Cisco ACI with cnspec
Scan a Cisco ACI fabric through its APIC controller cluster against security and compliance best practices with cnspec.
Scan your Cisco Application Centric Infrastructure (ACI) fabric to find security risks before they become incidents. cnspec connects to the Cisco Application Policy Infrastructure Controller (APIC) cluster through the APIC REST API and evaluates the controllers, the fabric switches, fabric-wide settings, certificates, AAA with its local users, roles, security domains, and RADIUS, TACACS+, and LDAP servers, management access over HTTPS, HTTP, SSH, and Telnet, and the faults the fabric reports.
Cisco APIC is one of the network devices cnspec can assess. For the full list of supported devices, see the network device scanning overview. New to cnspec? Start with the quickstart.
The Cisco APIC resources are experimental. Field names and behavior can change in a future cnspec release.
What cnspec scans
cnspec connects to one controller and reads the configuration of the whole APIC cluster and the ACI fabric it manages. The scan produces one asset for the fabric, named after its fabric domain, with the platform cisco-apic. The asset reports the APIC software version in Cisco's notation, such as 6.0(5h), which is the form Cisco security advisories use.
The fabric's leaf and spine switches appear as cisco.apic.fabricNode resources you can query, but cnspec doesn't create a separate asset for each switch. To assess a switch's own configuration, scan it directly with the Cisco network devices provider.
The scan doesn't cover tenants, application profiles, endpoint groups, contracts, pod policies, or fabric access policies.
Prerequisites
To scan a Cisco ACI fabric with cnspec, you must have:
- cnspec installed on your workstation
- Network access to the APIC REST API (default port 443) on any controller in the cluster
- An APIC account with the
read-allrole in theallsecurity domain
Give cnspec access to your fabric
cnspec reads from the APIC and never changes its configuration. It removes secret values as soon as it receives them, so user passwords, one-time password seeds, RADIUS, TACACS+, and LDAP keys, key ring private keys, and other secrets never reach a check or a scan report. SNMP community names are also redacted because the name is the community string.
Create a read-only account
Create a dedicated local account with the read-all role in the all security domain. From the APIC CLI, run:
apic1# configure
apic1(config)# username mondoo
apic1(config-username)# domain all
apic1(config-username-domain)# role read-all privilege readAn account in a narrower security domain can't see the objects outside that domain. If the account isn't allowed to read an object, cnspec reports an access denied error for it. It never treats the object as empty, so a check can't mistake missing evidence for an unconfigured feature.
Choose an authentication method
cnspec supports two ways to authenticate to the APIC:
- Password: cnspec logs in once per scan, refreshes the session token as needed, and logs out when the scan ends, including when it fails.
- Certificate signature: cnspec signs every request with the private key of an X.509 certificate attached to the user. No session is opened, so there is no token to refresh and no login rate limit. We recommend this method for scheduled, unattended scans.
To set up certificate signature authentication, create a key pair and a self-signed certificate:
openssl req -new -newkey rsa:2048 -days 365 -nodes -x509 -keyout mondoo.key -out mondoo.crt -subj '/CN=mondoo'Then, in the APIC GUI, go to Admin > AAA > Users, open the mondoo user, and add the contents of mondoo.crt as a user certificate. The name you give the certificate is the value of the --certificate-name option. Keep mondoo.key on the machine that runs cnspec.
Test your connection
Before running a full scan, verify that cnspec can connect by opening a cnspec shell. For APIC_HOST, substitute the hostname or IP address of any controller in the cluster:
cnspec shell apic --hostname APIC_HOST --username mondoo --ask-passTo authenticate with a certificate instead of a password:
cnspec shell apic --hostname APIC_HOST --username mondoo --certificate-name mondoo -i ./mondoo.keyIf the account authenticates against a remote AAA server such as LDAP, RADIUS, or TACACS+, pass the APIC login domain:
cnspec shell apic --hostname APIC_HOST --username mondoo --login-domain LOGIN_DOMAIN --ask-passControllers ship with a self-signed certificate. To skip TLS certificate verification for a controller that still uses it, add --insecure.
If cnspec connects successfully and shows a prompt, you're ready to scan.
Connection options
| Option | Description |
|---|---|
--hostname | Hostname or IP address of any controller in the APIC cluster (required) |
--port | REST API port (default: 443) |
--username | Username for authentication (default: admin) |
--password, -p | Password for authentication |
--ask-pass | Prompt for the password |
--identity-file, -i | RSA private key for certificate signature authentication (requires --certificate-name) |
--certificate-name | Name of the certificate attached to the user, for certificate signature authentication |
--login-domain | APIC login domain of a user who authenticates against a remote AAA server |
--insecure, -k | Skip TLS certificate verification (for the factory self-signed certificate) |
Scanning more than one ACI fabric? Use an inventory file to define every APIC
cluster and its credentials in one place, then scan them all with a single cnspec scan --inventory-file command.
Scan a Cisco ACI fabric
To scan a fabric, use the cnspec scan command:
cnspec scan apic --hostname APIC_HOST --username mondoo --ask-passWhen the scan completes, cnspec prints a pass or fail result for each check and an overall risk score. To output results in other formats such as JSON, JUnit, or SARIF, read Report Results.
You can write your own policies to check your ACI fabrics against the controls that matter to your organization.
Example checks
You can interactively explore and test checks using the cnspec shell. To open a shell connected to your APIC cluster:
cnspec shell apic --hostname APIC_HOST --username mondoo --ask-passBelow are some example queries and checks you can run from the shell.
List the controllers in the cluster
cnspec> cisco.apic.controllers { name version health }Find fabric switches that aren't active
cnspec> cisco.apic.fabric.nodes.where(role != "controller" && fabricState != "active") { name serialNumber }Ensure the password policy requires at least 12 characters
cnspec> cisco.apic.aaa.passwordPolicy { strengthCheckEnabled == true minimumLength >= 12 historyCount >= 5 }Ensure account lockout is enabled
cnspec> cisco.apic.aaa.lockoutPolicy.enabled == trueFind enabled local users whose password never expires
cnspec> cisco.apic.aaa.users.where(enabled && passwordLifetimeDays == 0) { name }Ensure LDAP servers use TLS with strict certificate validation
cnspec> cisco.apic.aaa.ldapServers.all(sslEnabled == true && sslValidationLevel == "strict")Show the default authentication realm
cnspec> cisco.apic.aaa.defaultAuthentication { realm providerGroup.name fallbackCheck }Ensure Telnet is disabled in every management access policy
cnspec> cisco.apic.management.accessPolicies.all(telnet == null || telnet.enabled == false)Ensure HTTP is disabled or redirects to HTTPS
cnspec> cisco.apic.management.accessPolicies.all(httpServer.enabled == false || httpServer.redirectToHttps == true)Ensure TLS 1.0 and 1.1 are disabled
cnspec> cisco.apic.management.accessPolicies.all(httpsServer.tlsVersions.none(_ == "TLSv1" || _ == "TLSv1.1"))Ensure SSH doesn't offer SHA-1 key exchange
cnspec> cisco.apic.management.sshServer.kexAlgorithms.none(_ == /sha1/)Ensure the web UI idle timeout is 15 minutes or less
cnspec> cisco.apic.management.session.uiIdleTimeoutSeconds <= 900Ensure the HTTPS certificate doesn't expire in the next 30 days
cnspec> cisco.apic.management.httpsServer.certificate.certificate.notAfter > time.now + 30 * time.dayReview fabric-wide security settings
cnspec> cisco.apic.fabric.settings { enforceSubnetCheck coopStrictMode rogueEndpointControlEnabled mcpEnabled }List unacknowledged critical faults
cnspec> cisco.apic.faults.where(severity == "critical" && acknowledged == false) { code description node.name }Learn more
-
To scan multiple fabrics at once instead of one at a time, read Remote Scanning with Inventory Files.
-
To learn about all the Cisco APIC resources and properties you can query, read the Cisco APIC Resource Pack Reference.
-
To learn more about how the MQL query language works, read Write Effective MQL.
-
For more information about the APIC REST API, see the Cisco APIC REST API Configuration Guide.