#12591·prowler

Add AWS check mappings to the Cyber Essentials 3.3 compliance framework

Author: pedroootCreated Aug 28, 2026Updated Sep 16, 2026
Labelsfeature-requestprovider/awsgood first issuecompliance

Summary

Prowler ships the NCSC Cyber Essentials 3.3 compliance framework, currently mapped for Azure only (added in #11588). This issue tracks extending it to AWS.

Cyber Essentials is the UK government-backed baseline certification and a prerequisite for many UK public sector contracts, so broader provider coverage is directly useful to users doing self-assessment prep.

Why this is a good first issue

The framework uses Prowler's universal compliance schema, which means this task is JSON only — no Python, no UI, no new output formatters.

The provider list is derived automatically from the keys of each requirement's checks dict (ComplianceFramework.get_providers() in prowler/lib/check/compliance_models.py). The UI renderer is already wired up and provider-agnostic. Add your provider key and aws support appears in the CLI table, CSV, OCSF output and the Prowler App.

What to change

One file: prowler/compliance/cyber_essentials_3.3.json

It has 28 requirements across the five official Cyber Essentials themes (Firewalls, Secure Configuration, Security Update Management, User Access Control, Malware Protection). For each one, add a "aws" key to the existing checks dict:

json
{
  "id": "CE-FW-01",
  "name": "Boundary firewall on every in-scope device",
  "attributes": { "...": "unchanged" },
  "checks": {
    "azure": [
      "network_rdp_internet_access_restricted",
      "network_ssh_internet_access_restricted"
    ],
    "aws": [
      "<your check IDs here>"
    ]
  }
}

Rules of thumb:

  • Do not touch the azure lists or anything under attributes — see the note below.
  • An empty list is a valid, correct answer. 13 of the 28 requirements are device-level or process controls with no cloud control-plane equivalent. If AWS genuinely cannot evidence a requirement, use "aws": []. Honest gaps are far better than padding a requirement with a tangentially related check.
  • The check's own title should literally describe what the requirement demands. "Related to the same theme" is not a mapping.

Verify your check IDs — this is the easy way to get it wrong

Nothing validates check IDs at load time. A typo does not raise an error: it silently produces a requirement that never matches any finding. Please run this before opening the PR:

python
import json
from pathlib import Path

PROVIDER = "aws"
real = {p.name.replace(".metadata.json", "")
        for p in Path(f"prowler/providers/{PROVIDER}/services").rglob("*.metadata.json")}
data = json.load(open("prowler/compliance/cyber_essentials_3.3.json"))
refs = {c for r in data["requirements"] for c in r.get("checks", {}).get(PROVIDER, [])}
missing = refs - real
assert not missing, f"{PROVIDER} missing: {missing}"
print(f"OK: {len(refs)} check IDs, all exist")

And a CLI smoke test:

bash
uv run python prowler-cli.py aws --list-compliance          # cyber_essentials_3.3 appears?
uv run python prowler-cli.py aws --compliance cyber_essentials_3.3 --log-level ERROR

Where to start looking

AWS currently has ~645 checks across 90 services. The ones most likely to be relevant:

ec2/vpc (security groups, NACLs), iam, s3, kms, ssm (patch compliance), guardduty, inspector2, securityhub, organizations

AWS has the deepest check inventory in Prowler, so most of the five themes should map without any new checks. Security Update Management is the one to look at carefully — ssm patch-compliance checks are the closest fit.

A note on shared attributes

Each requirement has a single flat attributes dict shared by all providers — including AssessmentStatus (Automated/Manual) and CloudApplicability (full/partial/non-applicable).

If you find a requirement currently marked Manual / non-applicable (because Azure cannot evidence it) that AWS genuinely can automate, that's a valuable finding — but changing it affects the Azure mapping too. Please comment on this issue rather than changing it unilaterally, and we'll agree on the right value together.

Using the Claude Code skill

This repo ships a skill covering this exact workflow end-to-end: skills/prowler-compliance/SKILL.md.

It documents the universal vs legacy schemas, the attributes_metadata validation rules, how checks keys map to providers, and how to audit your own check-to-requirement mappings as a cloud auditor before opening the PR. If you use Claude Code it will pick the skill up automatically once you start working on a compliance framework. If you don't, read it as plain Markdown — it's written to be useful either way.

The authoritative contributor doc is docs/developer-guide/security-compliance-framework.mdx.

Need a check that doesn't exist yet?

Quite likely for some requirements — especially in Security Update Management and Malware Protection.

Comment on this issue with the requirement ID and what you'd need the check to assert, and we'll guide you through creating it (metadata JSON, check class, unit tests with a mocked service). You do not need to figure that out alone, and a PR that maps what exists today and leaves the rest empty is a perfectly good contribution on its own.

Checklist

  • Add "aws" keys to the checks dict of all 28 requirements (empty lists where not applicable)
  • Run the check-existence script above — no missing IDs
  • Do not modify the azure mappings or the attributes values
  • Add a changelog entry in prowler/changelog.d/ (see cyber-essentials-3.3.added.md for the format)
  • uv run pytest tests/lib/check/universal_compliance_models_test.py passes

References

  • Azure implementation PR: #11588
  • Original framework request: #11579
  • Framework file: prowler/compliance/cyber_essentials_3.3.json
  • NCSC Cyber Essentials: Requirements for IT Infrastructure v3.3 (April 2026)