← All posts
How-To

Continuous Compliance: Scoring Your Network Against CIS Benchmarks

Compliance is a moving number, not a once-a-year PDF.

NAPT Team10 min read
Continuous compliance loopScan devicesScore vs CISL1 / L2 controlsRemediateweekly cron closes the loop — score trends up over time
Scan, score, remediate — then schedule it so the score trends up instead of decaying.

An annual audit tells you how compliant you were on one day. Continuous compliance tells you how compliant you are right now — and which direction the number is moving. The difference is automation.

The scoring model

The CIS Benchmarks split controls into Level 1 (baseline hardening that should never break a service) and Level 2 (stricter, defence-in-depth). Score each as a weighted pass rate.

python
CONTROLS = [
    {"id": "1.1", "level": 1, "weight": 2, "check": "no_telnet"},
    {"id": "1.2", "level": 1, "weight": 2, "check": "ssh_v2_only"},
    {"id": "2.1", "level": 1, "weight": 1, "check": "exec_timeout"},
    {"id": "3.4", "level": 2, "weight": 3, "check": "aaa_new_model"},
]

def score(results):
    earned = sum(c["weight"] for c in CONTROLS if results[c["id"]])
    total  = sum(c["weight"] for c in CONTROLS)
    return round(100 * earned / total, 1)

Run the checks against config

python
from netmiko import ConnectHandler

def audit(host):
    conn = ConnectHandler(device_type="cisco_ios", host=host,
                          username="ro", password="••••")
    cfg = conn.send_command("show running-config")
    return {
        "1.1": "transport input telnet" not in cfg,
        "1.2": "ip ssh version 2" in cfg,
        "2.1": "exec-timeout" in cfg,
        "3.4": "aaa new-model" in cfg,
    }

results = audit("10.0.0.11")
print(f"Compliance score: {score(results)}%")

Surface the failing controls, not just the number

python
failing = [c["id"] for c in CONTROLS if not results[c["id"]]]
for cid in failing:
    ctrl = next(c for c in CONTROLS if c["id"] == cid)
    print(f"FAIL  {cid}  L{ctrl['level']}  {ctrl['check']}")
Warning: Never auto-remediate Level 2 controls on the same run that discovers them. Open them for approval first — a stricter AAA or logging change can lock you out if the supporting infrastructure is not ready.

Close the loop on a schedule

The point of continuous compliance is the trend line. Run the audit weekly, store each score, and chart it. A drifting score is an early warning long before an auditor arrives.

bash
# weekly cron — Monday 02:00
0 2 * * 1  napt run compliance-audit --inventory fleet.yaml --store

In the platform, each audit emits findings keyed compliance/cis-1.1/core-sw-1; the Compliance panel renders the score trend and routes failed Level 1 controls into the remediation workflow automatically.

#compliance#cis#how-to

Was this helpful?

Generate scripts for the task covered in this post

Describe what you need and NAPT writes production-ready automation in Netmiko, NAPALM, or Nornir.

Open Script Generator →
New to NAPT? Start with the Setup Guide

Related posts