Azure Security Scanner

Cloud Securityv1.0.0

Live Azure subscription audit with 70+ checks across 16 sections, CIS Azure Foundations Benchmark v4.0.0 alignment, and evidence collection

70+
checks
16
sections
1
loc

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.

1
Context & setup layer
`set -euo pipefail`, `--subscription` arg parsing, `az account show` resolution of subscription/tenant, and creation of the timestamped `OUTPUT_DIR` evidence folder.
2
Helper / scoring layer
`log()`, `pass()`, `fail()`, `warn()` functions emit ANSI-colored output and auto-increment PASS/FAIL/WARN counters used in the final tally.
3
Sectioned check engine
16 labeled `SECTION N: SERVICE` blocks (8 in the base script), each grouping domain checks with consistent headers and CIS control references.
4
Hybrid Bash + Python execution
Lightweight checks run Azure CLI inline; heavier checks run 33 `python3 - <<'PYEOF'` heredocs using `subprocess` + `json` for multi-resource iteration and logic.
5
Microsoft Graph query layer
Identity and Conditional Access sections issue `az rest --method GET` calls to the Microsoft Graph API to audit Entra ID policies and role membership.
6
Evidence & reporting layer
Per-check JSON/CSV files (e.g. `storage_accounts.json`, `defender_pricing.json`) plus a final PASS/FAIL/WARN summary and `AUDIT_MANIFEST.txt` written to OUTPUT_DIR.

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

Identity & Access Management (IAM-01..08)
Security Defaults status, Global Admin count (break-glass 2-4), guest access restrictions, user consent for apps, app registration, custom subscription-admin roles, tenant creation and guest-invite controls via Microsoft Graph.
Storage Accounts (STG-01..06)
HTTPS-only secure transfer, default-deny network rules, minimum TLS 1.2, public blob access disabled, infrastructure encryption, and shared-key access disabled.
Networking & NSGs (NET-01..05)
Detects NSG rules exposing RDP 3389, SSH 22, DNS 53 and HTTP 80 to 0.0.0.0/0, and verifies Network Watcher is enabled per region.
Logging & Monitoring (LOG-01..04)
Activity Log diagnostic settings, Activity Log alerts on 10 critical operations, Key Vault diagnostic logging and resource-level logging (CIS 7.x). Note: the base script implements only LOG-01..03.
Key Vault (KV-01..04)
Soft delete, purge protection, RBAC authorization model and network access restrictions.
Compute / VMs (VM-01..03)
OS + data disk encryption, public IP exposure on VMs, managed identity usage and installed-extension auditing (the base script also carries an extra VM-04 check).
App Service (APP-01..05)
HTTPS-only enforcement, minimum TLS version, managed identity, FTP/FTPS state and HTTP logging.
Database Services (DB-01..09)
SQL auditing + TDE + public access + Entra admin; PostgreSQL and MySQL Flexible Server SSL & public-access; Cosmos DB public access and network rules. Note: the base script implements only DB-01..04.
Microsoft Defender for Cloud (DEF-01..10)
Pricing-tier verification for Servers, Azure SQL, SQL-on-machines, App Services, Storage, Key Vault, Resource Manager, open-source RDB, Containers and Cosmos DB.
Conditional Access & posture hardening (CA / LOCK / FLOW / BASTION / ACR / AKS / MISC)
MFA for all/risky/admin sign-ins and trusted locations; resource delete/readonly locks; NSG flow-log retention >=90d + Traffic Analytics; Bastion deployment; ACR admin-user/public-access/SKU; AKS RBAC/network-policy/private-cluster/identity; unattached disk encryption and orphaned public IP hygiene.

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

CIS Microsoft Azure Foundations Benchmark v4.0.0
Primary alignment; every check references its CIS control across benchmark sections 2, 4, 6, 7, 8 and 9.
Microsoft Defender for Cloud plans
Section 9 verifies Defender pricing-tier enablement across 10 resource plan types (CIS 9.1.x).
CWE (sample report)
The bundled sample findings report annotates issues with CWE identifiers (e.g. CWE-250, CWE-269, CWE-284) for weakness classification.

09Integrations & Outputs

Azure CLI (`az`) as the primary data sourceMicrosoft Graph API via `az rest` for Entra ID / Conditional AccessJSON & CSV evidence artifacts per check written to OUTPUT_DIRAUDIT_MANIFEST.txt run catalog for audit evidenceSample structured JSON findings report (test_data/azure_report.json)

Explore Azure Security Scanner

Full source, documentation, and deployment guides live on GitHub.