Scan Azure Key Vaults for expiring secrets, certificates, and keys
Project description
cc-scanner
Do you know which Azure secrets expire this month?
Scan all your Azure Key Vaults across every subscription in 30 seconds. Free, open source, works in Azure Cloud Shell.
pip install cc-scanner
cc-scan
What you get
- Cross-subscription inventory of every secret, certificate, and key
- Expiry warnings: expired, <7 days, <30 days, <90 days (color-coded)
- Security findings: public access, soft delete, RBAC, missing expiry dates
- Export to JSON, CSV, or standalone HTML report
- Works in Azure Cloud Shell with zero setup
Quick Start
# 1. Install
pip install cc-scanner
# 2. Authenticate (skip in Azure Cloud Shell)
az login
# 3. Scan
cc-scan
On first run, you'll be prompted to register with your email (free, takes 10 seconds). Your API key is saved locally to ~/.certifyclouds/config.json.
Output
CertifyClouds Scanner v1.2.0
Authenticated as: you@company.com
Scanning Azure subscriptions...
Production (sub-abc123)
vault-prod (eastus) - 45 secrets, 12 certificates, 3 keys
vault-shared (westeurope) - 23 secrets, 5 certificates, 1 key
SUMMARY
Subscriptions: 2 Vaults: 4 Total assets: 112
Secrets: 88 Certificates: 20 Keys: 4
EXPIRY WARNINGS
EXPIRED 3 secrets, 1 certificate
< 7 days 2 secrets
< 30 days 8 secrets, 2 certificates
SECURITY FINDINGS
CRITICAL: 3 HIGH: 2 MEDIUM: 47 LOW: 1
CRITICAL Expired secret still enabled vault-prod/db-password
HIGH Public network access enabled vault-legacy
MEDIUM Secret has no expiry date vault-prod/api-key
Usage
# Output formats
cc-scan --format table # Default: pretty terminal output
cc-scan --format json # Full JSON (pipe-friendly)
cc-scan --format csv # Flat CSV (for spreadsheets)
cc-scan --format html # Standalone HTML report
# Write to file
cc-scan --output report.html --format html
cc-scan --output scan.json --format json
# Filters
cc-scan --expiring 30 # Only items expiring within 30 days
cc-scan --expired # Only already-expired items
cc-scan --type secrets # Only secrets (or: certificates, keys)
cc-scan --vault vault-prod # Specific vault(s) (repeatable)
cc-scan --subscription sub-123 # Specific subscription(s) (repeatable)
# Security summary only
cc-scan --security # Show findings without per-item details
# Azure auth
cc-scan --auth cli # Azure CLI credential (default)
cc-scan --auth default # DefaultAzureCredential (managed identity/SP)
# Tuning
cc-scan --workers 10 # Parallel workers (default: 5, max: 20)
cc-scan --timeout 600 # Scan timeout in seconds (default: 300)
# Other
cc-scan --offline # Skip license server validation
cc-scan --register # Re-register / change email
cc-scan --key cc-scan-xxxxx # Use a specific API key
cc-scan --version # Show version
cc-scan --help # Show all options
Environment Variables
All flags can be set via environment variables (flags take priority):
CC_SCAN_KEY=cc-scan-xxxxx # API key
CC_SCAN_AUTH=cli # Auth method
CC_SCAN_FORMAT=json # Output format
CC_SCAN_WORKERS=10 # Workers
CC_SCAN_TIMEOUT=600 # Timeout
CC_SCAN_OFFLINE=true # Offline mode
For service principal auth (used with --auth default):
AZURE_CLIENT_ID=...
AZURE_CLIENT_SECRET=...
AZURE_TENANT_ID=...
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Scan completed, no critical/high findings |
| 1 | Scan completed, critical or high findings detected |
| 2 | Scan failed (auth error, network error, timeout) |
| 3 | Registration required / invalid API key |
Non-zero exit codes make this CI/cron-friendly: cc-scan || notify-team.
Azure Permissions
Your identity needs these roles on each Key Vault:
| Role | Why |
|---|---|
| Key Vault Secrets User | List and read secret properties |
| Key Vault Certificate User | List and read certificate properties |
| Key Vault Crypto User | List and read key properties |
| Reader | List Key Vaults across subscriptions |
Assign roles in Azure Portal: Key Vault > Access control (IAM) > Add role assignment.
If a vault has firewall restrictions, you'll see an inline error (the scan continues to the next vault).
Security Findings
The scanner checks for 11 security rules:
| ID | Severity | What it checks |
|---|---|---|
| SEC-001 | CRITICAL | Expired secret still enabled |
| SEC-002 | CRITICAL | Expired certificate still enabled |
| SEC-003 | HIGH | Public network access enabled on vault |
| SEC-004 | HIGH | Soft delete disabled |
| SEC-005 | HIGH | Purge protection disabled |
| SEC-006 | MEDIUM | Secret has no expiry date set |
| SEC-007 | MEDIUM | Certificate has no expiry date set |
| SEC-008 | MEDIUM | RBAC authorization not enabled |
| SEC-009 | LOW | Standard SKU (no HSM backing) |
| SEC-010 | INFO | Secret expiring within 30 days |
| SEC-011 | INFO | Certificate expiring within 30 days |
Privacy & Telemetry
CertifyClouds Scanner sends aggregate usage statistics to improve the product. Here's exactly what is sent:
Sent: API key, CLI version, counts (subscriptions, vaults, secrets, certificates, keys, expired, expiring soon, security findings, vaults with errors), scan duration.
Never sent: Vault names or URIs, secret/certificate/key names, secret values, subscription IDs or names, Azure tenant IDs, resource group names, tags, certificate subjects or thumbprints.
Use --offline to disable all network calls to the license server. The scan works fully offline.
Source code is open and auditable: codeberg.org/hus/cc/scanner
Troubleshooting
"No Azure credentials found"
Run az login to authenticate, or set AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID for service principal auth.
Vault shows "Firewall restriction" Run cc-scan from an allowed network or add your IP in Azure Portal (Key Vault > Networking).
Vault shows "Access denied" Your identity needs the roles listed in Azure Permissions.
"Could not reach license.certifyclouds.com"
Check internet connection. Behind a proxy? Set HTTPS_PROXY. Or use --offline mode.
Slow scans
Increase workers: cc-scan --workers 10. Each subscription is scanned in parallel.
Requirements
- Python 3.9+
- Azure CLI (
az login) or service principal credentials - Network access to Azure management and Key Vault data plane APIs
License
Apache 2.0. See LICENSE.
Links
- CertifyClouds - Automate secret rotation & compliance
- Documentation
- Source Code
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file certifyclouds-1.2.0.tar.gz.
File metadata
- Download URL: certifyclouds-1.2.0.tar.gz
- Upload date:
- Size: 28.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a91a8db181252e52ec3aabeec925622fe17d5463d472b73b4008fe623e6d675c
|
|
| MD5 |
28313e923396b617f6c9a26450b41082
|
|
| BLAKE2b-256 |
0f56fadadb4b685146b0155130c1b5e0dbde76c09e8b2c192b6dee0d67b3b049
|
File details
Details for the file certifyclouds-1.2.0-py3-none-any.whl.
File metadata
- Download URL: certifyclouds-1.2.0-py3-none-any.whl
- Upload date:
- Size: 34.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
526ab9d9d170f14d94a3a8a09f93642bee5f921b7685db79268f632735e44c25
|
|
| MD5 |
875119b7e42e0829254833224e40401c
|
|
| BLAKE2b-256 |
cb531597dbd03caa1ba704969a55f85826a230fc090ec1fe2471ea41b5a7213e
|