Tools Used in DevSecOps · Prowler

Prowler

Prowler is an open-source security-assessment CLI that connects to a live cloud account with read-only credentials, runs hundreds of individual checks against it, and tells you exactly where that account's actual configuration diverges from the CIS Benchmarks and a dozen other published standards — in minutes, from a laptop or a pipeline job, with no agent to install and nothing to enable in the account beforehand. It started as a single Bash script auditing one AWS account against one benchmark and has grown into a Python engine covering AWS, Azure, GCP, and Kubernetes from one command, one check library, and one compliance-mapping layer. By the end of this page you should know how a Prowler scan actually executes against an account, how to read a compliance-framework report rather than just a flat findings list, and precisely what it adds on top of — rather than instead of — AWS's own Security Hub.

☺ Explain it like I'm 10

Imagine a home inspector who shows up with one clipboard that has the fire code, the electrical code, and the building code all cross-referenced on it already. They walk through your house once, and for every outlet without a cover plate they can tell you it fails the electrical code and the insurance code and the city rental code, all from the same one observation — because their clipboard already knows how those three rulebooks overlap. Prowler is that inspector for a cloud account: it looks at your actual settings once, and tells you every rulebook that one bad setting breaks, instead of making you hire a separate inspector per rulebook.

🦥Your host for this topic: Sol the Sloth — Prowler is Sol's own instrument. A full-account audit means walking every bucket, every role, every security group slowly and completely, and a CLI that checks a thousand things in one pass is exactly the tool that pace deserves.

What Prowler is, and the problem it solves

☺ Like you're 10: It began as one person's script for checking a single AWS rulebook, and grew into a proper multi-cloud tool that checks a dozen rulebooks at once.

Prowler was created by Toni de la Fuente and first released in 2015 as an AWS-focused command-line script built specifically to automate the CIS Amazon Web Services Foundations Benchmark — a from-scratch, checklist-by-checklist reimplementation of what had previously been a manual, spreadsheet-driven audit. It's since been rewritten from the ground up in Python (Prowler v3, then v4) as a proper multi-provider engine, and it now scans AWS, Azure, GCP, and Kubernetes from the same CLI, with each provider's checks organized the same way and reported through the same output pipeline. The project is open source under the Apache-2.0 license, hosted on GitHub under the prowler-cloud organization, and remains free to install and run with no account, license key, or network callback required for the CLI itself — a company built around the project (also named Prowler) additionally offers a hosted dashboard and a self-hostable web application layered on the same open-source scanning engine, the same open-core shape as several other tools on this course's tool shelf, but nothing in this page requires either.

The problem Prowler solves is running a genuinely comprehensive account audit without either writing the checks yourself or buying a platform to get them. A cloud account accumulates hundreds of independently-configurable resources — IAM roles, S3 buckets, security groups, KMS keys, CloudTrail trails, RDS instances — and a "does this look safe" review done by a person reading the console one page at a time is both slow and structurally incomplete, because nobody remembers to check all of it, every time, the same way. Prowler answers that by encoding the CIS Benchmark (and everything layered on top of it) as executable checks: point it at an account and every check runs against that account's live state, every time, identically.

◆ Key idea

Prowler's checks are read-only by design — every check is implemented as a handful of describe/list/get API calls against the provider, never a write or a remediation action. That's what makes a full-account audit safe to run against production without a change window: nothing Prowler does can modify the resources it's inspecting. (A separate, opt-in remediation layer exists in some of the project's tooling, but the audit itself never touches state.)

Architecture: read-only API calls, checks-as-code, one report

☺ Like you're 10: Prowler asks the cloud provider a big list of "what is currently true" questions, checks each answer against a rule, and tags every answer with every rulebook that rule belongs to.

A Prowler scan has no server-side component and touches nothing but the provider's own read APIs. Given credentials — an AWS profile or assumed role, an Azure service principal, a GCP service account key, or a kubeconfig context — the engine authenticates once, then dispatches each check as a small, self-contained unit: a Python class that knows which read-only API calls it needs (for example, iam:GetAccountPasswordPolicy or s3:GetBucketPolicyStatus), what a passing configuration looks like, and which compliance frameworks that specific control belongs to. Checks run multi-threaded and are grouped by service, so a scan of a mid-sized account typically finishes in single-digit minutes rather than the hour a fully serial pass would take — thread count is tunable, which matters more than it sounds like the moment a large account starts tripping API rate limits.

Live account AWS (+ Organizations) Azure subscription GCP project Kubernetes cluster read-only API calls only prowler — one Python engine Authenticate once assumed role · service principal · SA key · kubeconfig Checks-as-code one Python class per control, grouped by service, multi-threaded (iam_* · s3_* · ec2_* …) Compliance metadata each check tagged to CIS · PCI-DSS · HIPAA SOC 2 · GDPR · ISO 27001 NIST 800-53 · more Mutelist filter --mutelist-file: account + check + region + resource One report CLI table · HTML CSV · JSON-OCSF grouped by framework AWS Security Hub --security-hub findings as ASFF Same engine, four providers, one compliance-mapping layer, one report format.

The detail worth carrying forward from this diagram: compliance mapping isn't a separate reporting step bolted on after the scan — it's metadata attached to each check before it ever runs. A single check's metadata.json declares which frameworks and which specific requirement within each framework it satisfies, so the same PASS or FAIL result rolls up into as many framework reports as apply, computed once. That's the mechanism the next two sections build on directly.

Running a full-account audit from the CLI

☺ Like you're 10: One command scans a whole account by default; a handful of flags narrow it to specific checks, specific regions, or a whole organization's worth of accounts at once.

Prowler installs from PyPI (pip install prowler) or runs as a container image, which is the friendlier default for a CI job that shouldn't have to manage a Python environment — the image's namespace on Docker Hub has moved as the project changed hands, so confirm the current one against the project's own README rather than trusting an old blog post. Either way, the CLI authenticates using each provider's normal credential chain: for AWS, that's the same environment variables, shared credentials file, or instance/task role Prowler would find without any special configuration; for Azure and GCP, the equivalent service-principal or service-account patterns.

# install
$ pip install prowler
$ prowler --version

# the default: scan the whole AWS account reachable from your current credentials,
# every enabled region, every check, human-readable output plus a report file on disk
$ prowler aws

# other providers — same engine, same flag shapes
$ prowler azure --az-cli-auth
$ prowler gcp --credentials-file sa-key.json
$ prowler kubernetes --kubeconfig-file ~/.kube/config

# narrow a run: specific checks, specific services, specific regions
$ prowler aws --check s3_bucket_level_public_access_block,iam_root_hardware_mfa_enabled
$ prowler aws --service iam s3 ec2
$ prowler aws --region us-east-1 eu-west-1

# see what a given install actually knows before trusting a table on a page like this one
$ prowler aws --list-checks
$ prowler aws --list-services
$ prowler aws --list-compliance

A single account is the easy case. A real organization audit means every member account, which Prowler handles by assuming a role into each one rather than running once per account by hand:

# assume a role in one target account from a management or audit account
$ prowler aws --role arn:aws:iam::222233334444:role/ProwlerAudit \
    --role-session-name prowler-audit

# a common real-world wrapper: pull every active account ID from AWS Organizations,
# then loop the assumed-role scan across all of them into one combined output directory
$ for acct in $(aws organizations list-accounts \
      --query "Accounts[?Status=='ACTIVE'].Id" --output text); do
    prowler aws --role "arn:aws:iam::${acct}:role/ProwlerAudit" \
      --output-directory "reports/${acct}"
  done

The identity running Prowler needs read access across the account, not just the resource types you expect to matter — a check you didn't anticipate still needs to see the resource it's checking. AWS publishes exactly this pairing for the purpose: attach the SecurityAudit managed policy for the bulk of read access Prowler's checks need, plus ViewOnlyAccess to cover the handful of additional read calls SecurityAudit alone doesn't grant. Both are read-only by AWS's own definition, but "read access to nearly everything in the account" is still a credential worth protecting — assume it through a role with a short session duration rather than handing out a long-lived access key with that policy attached.

Not every finding should stay actionable forever. A bucket that's intentionally public because it hosts a static site, a legacy security group mid-decommission, a check that structurally can't apply to a workload your team doesn't run — Prowler's mutelist suppresses exactly these, scoped as precisely as you want:

# mutelist.yaml
Accounts:
  "111122223333":
    Checks:
      s3_bucket_level_public_access_block:
        Regions: ["us-east-1"]
        Resources: ["acme-marketing-site"]
        Tags: []
        Reason: "Static site behind CloudFront with an OAI — see runbook RB-114"
$ prowler aws --mutelist-file mutelist.yaml

Treat a mutelist entry with no Reason the same way Checkov's inline skip comments get treated in code review: technically allowed, practically worthless. A muted finding with a real reason and a runbook link is an accepted risk on record; a muted finding with none is a scanner someone quietly turned off for one resource, with no trace of why.

Reading compliance-framework-mapped output

☺ Like you're 10: Instead of one long list of "this is wrong," you can ask Prowler to sort the exact same findings by which rulebook they break — and one broken setting usually shows up under several rulebooks at once.

The flat findings list — every check, every resource, PASS or FAIL — is the ground truth, but it's rarely what a compliance conversation actually needs. The --compliance flag re-groups that same run's results around a specific published framework instead, mapping each requirement in that framework to the underlying checks that satisfy it:

# run the full scan, but report it through the lens of one specific framework
$ prowler aws --compliance cis_2.0_aws
$ prowler aws --compliance pci_4.0_aws
$ prowler aws --compliance hipaa_aws
$ prowler aws --compliance soc2_aws

# every framework identifier a given install ships — treat the list above as illustrative;
# exact identifiers shift release to release, this is the authoritative source
$ prowler aws --list-compliance

A compliance-mode report reads by requirement, not by check: CIS Benchmark section 1.5 ("ensure hardware MFA is enabled for the root user") shows as PASS or FAIL, backed by whichever underlying check(s) evaluate it, and a requirement can legitimately come back MANUAL rather than PASS or FAIL — some controls (an organizational policy document existing, a process being followed) simply can't be verified by an API call, and Prowler is explicit about that distinction rather than silently marking everything it can't check as passing. The CIS Benchmarks themselves are published in two profile levels worth knowing by name — Level 1 is a baseline every account should clear with minimal operational friction; Level 2 is stricter and assumes a security-conscious environment willing to accept the operational trade-offs — and Prowler's CIS-mode reports carry that level distinction through into the output.

Check IDWhat it catchesShows up under
iam_root_hardware_mfa_enabledRoot account not protected by a hardware or virtual MFA deviceCIS 1.5 · PCI-DSS · SOC 2
iam_avoid_root_usageRoot credentials used for day-to-day API calls instead of being locked awayCIS 1.7 · ISO 27001
s3_bucket_level_public_access_blockA bucket, or the account default, missing S3 Block Public AccessCIS 2.1 · SOC 2 · HIPAA
ec2_securitygroup_allow_ingress_from_internet_to_port_22A security group allowing SSH from 0.0.0.0/0CIS 5.2 · PCI-DSS
cloudtrail_multi_region_enabledNo multi-region CloudTrail trail capturing management eventsCIS 3.1 · HIPAA · SOC 2
rds_instance_storage_encryptedAn RDS instance created without storage encryption at restPCI-DSS · HIPAA · GDPR

Treat these IDs and mappings as illustrative rather than a table to memorize — Prowler ships new checks and adjusts framework mappings every release, and check IDs plus their exact requirement mappings for your installed version are always one command away via --list-checks and --list-compliance. What's stable is the mechanism, not the specific list: metadata attached once, reported many ways.

◆ Key idea — one check, several audiences

The same finding that fails s3_bucket_level_public_access_block in a flat scan is simultaneously a CIS Benchmark gap, a SOC 2 control failure, and HIPAA-relevant evidence of a missing safeguard — computed once, because the check's own metadata already declares all three mappings. That's exactly the "one control, mapped many ways" idea compliance & governance makes as a general principle; Prowler is a concrete implementation of it for cloud configuration specifically, and compliance as code at scale covers how that mapped evidence gets collected continuously rather than gathered by hand once a year.

Prowler and AWS Security Hub: complements, not competitors

☺ Like you're 10: One is a very thorough inspector you call in for a deep walkthrough; the other is a permanent night-watchman who's always on duty but trusts fewer rulebooks by default. You generally want both, and you can point the inspector's report straight at the watchman's desk.

AWS Security Hub is AWS's own native aggregation service: it ingests findings continuously from AWS's other detection services — GuardDuty, Inspector, Macie, IAM Access Analyzer — plus its own configuration checks against a handful of built-in standards (the AWS Foundational Security Best Practices standard, and an AWS-maintained CIS Benchmark implementation among them), and gives an account or an entire AWS Organization one correlated console and one finding format (ASFF, the AWS Security Finding Format) that every contributing service writes into. Its defining property is that it's always running, wired directly into CloudTrail and Config change events, so drift shows up close to real time rather than at the next scheduled scan.

Prowler is not a replacement for that — it's a second, independent source of findings written in the same format, and the two are designed to interoperate directly:

# push this run's findings straight into Security Hub as ASFF,
# on top of whatever CLI/HTML/CSV/JSON-OCSF output you also asked for
$ prowler aws --security-hub

# only send failing findings — keep passes out of the Security Hub finding count entirely
$ prowler aws --security-hub --send-sh-only-fails

What Prowler adds on top of Security Hub's own checks is depth and portability, not a competing console. Security Hub's built-in CIS coverage is real but narrower than Prowler's dedicated CIS implementation, which tracks the full published benchmark — including checks Security Hub's own standard doesn't implement — and Prowler additionally covers a stack of other frameworks (PCI-DSS, HIPAA, GDPR, SOC 2, ISO 27001, NIST 800-53, and more) that Security Hub has no native standard for at all. Prowler also runs anywhere: from a laptop, a CI job, an air-gapped environment, or an account where Security Hub was never enabled in the first place, and identically across AWS, Azure, GCP, and Kubernetes — Security Hub, by contrast, is an AWS-only service that has to be explicitly enabled (and paid for, per finding ingested and evaluated) before it does anything.

The honest framing: Security Hub is the natural single pane of glass for continuous, native, cross-service AWS monitoring once your other AWS security services are already running — GuardDuty's threat detection, Inspector's vulnerability findings, Macie's data-classification findings all land there automatically, and Prowler's ASFF push means its own findings can join them in that same queue rather than living in a separate report nobody checks. Prowler is the deeper, portable, scheduled or on-demand audit layer — the tool you'd point at a brand-new account on day one before Security Hub is even configured, run from a pipeline gate that has to work identically across three cloud providers, or reach for when an auditor asks specifically for CIS or PCI-DSS coverage that Security Hub's own standards don't provide. Most mature AWS environments run both: Security Hub as the always-on aggregation point, Prowler as a deeper, portable, and multi-cloud audit that feeds into it rather than sitting beside it unread.

🦥 Sol's view

"I don't reach for Prowler because Security Hub is missing. I reach for it because Security Hub only tells me what its own built-in standards decided to check — and my job this week is proving PCI-DSS coverage to an auditor who doesn't care what Security Hub's default standard implements. Same account, same findings underneath, a completely different rulebook laid on top. That's not redundant work. That's the whole reason 'complements' is the right word and 'replaces' isn't."

Gotchas and failure modes

☺ Like you're 10: Most surprises come from the inspector not being let into every room, being let into too many rooms without a good enough safety chain on the door, or a report that looks scary until you realize what "not enabled" actually means.

Alternatives and when to reach for something else

☺ Like you're 10: Other tools ask the cloud provider similar questions — they just hand you the answers in a different shape, or bundle in a lot more than just "is this configured safely."

OptionModelBest whenCosts you
ProwlerOpen-source CLI, checks-as-code, read-only, multi-cloud, CIS-plus-a-dozen-frameworks mapping built inA deep, portable, scheduled or on-demand audit that has to run identically across providers, or prove coverage against a specific compliance frameworkA point-in-time snapshot each run, not a continuously watching service; large accounts need thread tuning and region-scope discipline
ScoutSuiteOpen-source, multi-cloud, turns a scan into one browsable HTML reportA human-readable, shareable report is the actual deliverable rather than a CLI exit code or a machine-readable feedLess oriented toward a CI gate or a compliance-framework rollup than Prowler's --compliance mode
AWS Security Hub (native)Always-on, AWS-only, aggregates GuardDuty/Inspector/Macie/Config plus its own standardsContinuous native monitoring across every AWS security service you already run, with near-real-time drift detectionAWS-only; per-finding cost once enabled; narrower built-in framework coverage than Prowler's dedicated implementations
Commercial CNAPP (Wiz, Prisma Cloud, Orca)Correlated risk graph spanning CSPM, workload, identity, and data findings under one vendorCross-domain "is this exploitable" prioritization matters more than a straight benchmark pass rateLicensing cost that scales with estate size; see CNAPP & the unified cloud security stack for the full trade-off
SteampipeQueries live cloud resources as SQL tables through a Postgres foreign-data-wrapper interfaceAd hoc investigation and custom reporting matter more than a fixed, published check libraryYou're writing and maintaining your own SQL-based checks rather than consuming a maintained compliance-mapped library

A pipeline already gating on Prowler rarely needs a second open-source CSPM tool running the same job — the built-in check library and compliance mapping cover more ground than most teams write custom rules for in their first year. Findings from a Prowler run, like findings from every other scanner this course covers, are usually worth deduplicating into one queue rather than living in their own separate report; DefectDojo ingests Prowler's output alongside everything else in the pipeline for exactly that reason. See the tooling landscape for where CSPM sits among the other seven scanner categories, and cloud security posture for the shared-responsibility and least-privilege context a CSPM finding usually sits inside.

🎬 At the Shift-Left Squad
🦥

Sol the Sloth: Ran the full account audit overnight. One finding I actually want to talk through — root account, no hardware MFA.

🦊

Foxy: Wait, doesn't Security Hub already watch for that? Why are we running a second tool against the same account?

🦥

Sol: Security Hub's watching what its own standards check. I asked Prowler for the full CIS Benchmark and PCI-DSS in the same pass — same finding, mapped to both, computed once.

🦝

Rocky the Raccoon: A root account with no hardware MFA is exactly the kind of gap I'd go looking for on purpose. Glad someone found it before I had to.

🐢

Timmy the Turtle: Before this closes out — did you push it to Security Hub, or does it just live in Sol's report until someone remembers to look?

🦥

Sol: Pushed it. --security-hub. It's sitting in the same queue as everything GuardDuty's already watching, not off in a corner nobody checks.

🐿️

Nutty the Squirrel: And I've already filed it three ways — CIS 1.5, the SOC 2 criterion, the PCI-DSS requirement. One inspection, three drawers. That's the whole point of the mapping.

✓ Checkpoint

1. What does Prowler actually do to a cloud account when it runs a check, and why does that make it safe to point at production with no change window? 2. What's attached to each check that makes --compliance mode possible, and when would a requirement show as MANUAL instead of PASS or FAIL? 3. Name two concrete things Prowler adds on top of what AWS Security Hub already checks natively, and one concrete thing Security Hub does that Prowler alone doesn't. 4. What two AWS managed policies does Prowler typically need attached to run a full scan, and why is a mutelist entry with no reason attached functionally as bad as no mutelist at all?

Check your answers
  1. Every check is read-only — describe/list/get API calls only, never a write or a remediation action — so a scan can't modify anything it inspects. That's what makes running a full audit against a production account safe without a change window: nothing about the audit itself can cause an incident.
  2. Compliance metadata baked into each check — a metadata.json declaring which frameworks and which specific requirement within each it satisfies — computed once and reported many ways via --compliance. A requirement shows MANUAL when it describes something an API call can't verify at all, like a policy document existing or a process being followed, and Prowler reports that honestly rather than defaulting it to a pass.
  3. Prowler adds deeper, more complete CIS Benchmark coverage than Security Hub's own built-in standard, plus native mappings to frameworks Security Hub has no standard for at all (PCI-DSS, HIPAA, GDPR, SOC 2, ISO 27001, NIST 800-53), and it runs identically across AWS, Azure, GCP, and Kubernetes rather than being AWS-only. What Security Hub alone provides that Prowler doesn't replace is continuous, always-on aggregation of AWS's other native detection services — GuardDuty, Inspector, Macie — into one queue in close to real time.
  4. SecurityAudit plus ViewOnlyAccess, assumed through a role rather than issued as a standing key given how much of the account that read scope can see. A mutelist entry with no reason suppresses the finding exactly as effectively as one with a documented reason — the difference only shows up months later, when someone needs to know whether a suppressed finding was ever actually reviewed, and a bare entry gives them nothing to check.