01Overview
Azure Security Scanner is a pair of read-only Bash audit scripts that interrogate a live Microsoft Azure subscription and grade its security posture against the CIS Microsoft Azure Foundations Benchmark v4.0.0. Instead of shipping a heavyweight agent or requiring API keys, it rides the operator's existing `az login` session, runs entirely with Azure CLI + Python 3, and never mutates a single resource. Every check emits a color-coded PASS / FAIL / WARN / INFO verdict with the exact CIS control reference, so a security engineer can go from `az login` to a prioritized findings list in one command.
The project ships two tiers. The base script (`azure_security_audit_scripts.sh`) covers 8 sections and ~36 checks spanning IAM, Storage, Networking, Logging, Key Vault, VMs, App Service and Databases. The enhanced script (`azure_security_audit_enhanced.sh`) is broader: 16 sections and 70+ effective checks that add Microsoft Defender for Cloud plan coverage, Conditional Access / MFA policy inspection via Microsoft Graph, resource locks, NSG flow logs, Azure Bastion, Container Registry, AKS hardening and orphaned-resource hygiene. Both scripts implement the same Sections 1-8 core domains, but the two files are NOT byte-identical — the enhanced script is a more compact rewrite and the per-section check sets differ slightly (e.g. the enhanced script adds Database and Logging checks while the base script carries an extra VM check).
Under the hood it's a deliberately simple, dependency-free design: a Bash driver with `log/pass/fail/warn` helper functions and ANSI counters, hybrid Bash-plus-inline-Python (33 `python3` heredocs) for the multi-resource checks, and Entra ID coverage delivered through `az rest` calls to the Microsoft Graph API. Each run creates a timestamped evidence directory holding per-check JSON/CSV artifacts plus an `AUDIT_MANIFEST.txt` catalog — turning an audit into a reproducible, auditor-friendly evidence package.
It's built for cloud security engineers, Azure admins, compliance teams and consultants who need a fast, transparent, offline-inspectable posture check they can read line-by-line before running it against production. Because it's read-only by design, needs only Reader/Global Reader permissions, and hardcodes no secrets, it's safe to drop into a hardening review, a client engagement, or a pre-audit dry run.
02Key Capabilities
CIS Azure Foundations v4.0.0 alignment
Every check cites its exact CIS control (e.g. 6.1.1, 8.5, 9.1.x) so findings map directly to the benchmark auditors already use.
Two-tier audit depth
A base 8-section script for a quick core review and an enhanced 16-section script for comprehensive coverage, both covering the same Sections 1-8 core domains (though the section code is not byte-identical between the two files).
70+ checks across 16 security domains
IAM, Storage, Networking, Logging, Key Vault, Compute, App Service, Databases, Defender for Cloud, Conditional Access, Locks, Flow Logs, Bastion, ACR, AKS and hardening hygiene.
Read-only by design
All calls are `show`/`list`/`rest GET` operations — the scanner inspects but never modifies Azure resources, making it safe against production.
Entra ID inspection via Microsoft Graph
Sections 1 and 10 use `az rest` Graph API calls to audit Security Defaults, Global Admin counts, guest access and Conditional Access / MFA policies.
Microsoft Defender for Cloud plan coverage
A single loop checks pricing tiers for Servers, SQL, App Services, Storage, Key Vault, ARM, Containers, Cosmos DB and open-source databases (DEF-01 to DEF-10).
Timestamped evidence collection
Each run writes per-check JSON/CSV artifacts plus an AUDIT_MANIFEST.txt into an `azure_audit_<sub>_<timestamp>/` directory for reproducible audit trails.
Color-coded PASS/FAIL/WARN verdicts
ANSI-colored terminal output with automatic counters and a final tally makes misconfigurations pop immediately.
Zero external dependencies
Runs on nothing but Bash 5.0+, Azure CLI 2.50+ and Python 3 — no pip installs, no vendored libraries, no API keys.
Subscription targeting
Audits the active subscription by default or any target via `--subscription <id>`, with tenant/subscription context resolved and printed at startup.
Structured check-ID taxonomy
Consistent prefixes (IAM-, STG-, NET-, KV-, DEF-, AKS-, etc.) give every finding a stable, greppable identifier tied to a service domain.
Crash-resistant execution
Broad exception handling in each Python block ensures one failing check degrades to a WARN rather than aborting the whole audit run.
03Architecture
A single-file Bash driver per tier orchestrates the audit: it resolves Azure context from the active `az login` session, sets up a timestamped evidence directory, then runs sequential section blocks. Simple checks call Azure CLI directly and score via `pass/fail/warn` helpers; complex multi-resource and Entra ID checks execute inline Python heredocs that shell out through `subprocess`, parse JSON, print colored verdicts, and persist evidence files. A summary stage tallies results and writes an evidence manifest.
04Project Structure
azure_security_audit_enhanced.shEnhanced audit script — 16 sections, 70+ checks, 923 lines; superset covering Defender, Conditional Access, AKS, ACR, Bastion, locks and more.azure_security_audit_scripts.shBase audit script — 8 sections, ~36 checks, 901 lines; core IAM/Storage/Network/Logging/KeyVault/VM/App/DB coverage (same Sections 1-8 domains as the enhanced script, but the code is not byte-identical).README.mdFull documentation: overview, prerequisites, usage, per-section check tables, CIS mapping, architecture and contribution conventions.docs/banner.svgProject banner asset referenced at the top of the README.test_data/azure_report.jsonSample findings report (severity summary + rule findings with CWE mappings) used as illustrative output data.LICENSEMIT license (Copyright 2026 KRISH)..gitignoreIgnore rules (IDE/build artifacts) excluded from version control.05Security Controls
06Technology Stack
- Language
- Bash 5.0+ (driver) with inline Python 3.8+ heredocs
- Cloud tooling
- Azure CLI 2.50+ (`az`) and Microsoft Graph API via `az rest`
- Python libraries
- Standard library only — `subprocess`, `json`, `os` (no pip dependencies)
- External dependencies
- None beyond Azure CLI + Python 3 — zero vendored libs, no API keys
- Auth model
- Ambient `az login` session; requires Reader on subscription + Global Reader on tenant
- Testing
- No automated suite; validated via `bash -n` syntax check and live subscription runs
- CI/CD
- None — no pipelines, hooks or automated releases; `main` is the primary branch
- License
- MIT (LICENSE file; note the README badge/tree mislabel it GPL-3.0)
07Quick Start
$ az login # authenticate the executing identity (Reader + Global Reader) $ bash azure_security_audit_scripts.sh # base audit, Sections 1-8 $ bash azure_security_audit_enhanced.sh # enhanced audit, Sections 1-16 $ bash azure_security_audit_enhanced.sh --subscription <subscription-id> # target a specific subscription $ ls azure_audit_*/ # inspect the timestamped evidence directory and AUDIT_MANIFEST.txt $ bash -n azure_security_audit_enhanced.sh # syntax-check without executing
08Compliance & Frameworks
09Integrations & Outputs
Explore Azure Security Scanner
Full source, documentation, and deployment guides live on GitHub.