Skip to content

CLI Scanner

Free command-line tool to audit Azure Key Vaults for expiring secrets, certificates, and keys.


Overview

The CertifyClouds Scanner (cc-scan) is a standalone CLI tool that scans all your Azure Key Vaults across every subscription and reports:

  • Expiring and expired secrets, certificates, and keys
  • Security misconfigurations (11 built-in checks)
  • Full inventory with metadata, tags, and status

It runs locally, uses your existing Azure credentials, and never reads secret values.


Install

pip install certifyclouds
pipx install certifyclouds

Recommended if you want an isolated install that doesn't affect your system Python.

brew tap certifyclouds/certifyclouds
brew install certifyclouds

macOS and Linux. Manages Python dependencies automatically.

Requires Python 3.9+. Works on macOS, Linux, and Windows.

Azure Cloud Shell

cc-scan works out of the box in Azure Cloud Shell — Python and az login are pre-configured.


Quick Start

# 1. Sign in to Azure
az login

# 2. Run the scanner
cc-scan

On first run, you'll be prompted to register with your email (free, no password). After that, the scan runs automatically.


Commands & Flags

Output

Flag Description Default
--format Output format: table, json, csv, html table
-o, --output FILE Write output to a file instead of stdout -

Filters

Flag Description Example
--expiring N Only show items expiring within N days --expiring 30
--expired Only show already-expired items -
--type TYPE Only show: secrets, certificates, or keys --type secrets
--vault NAME Only scan specific vault(s) (repeatable) --vault prod-kv
--subscription ID Only scan specific subscription(s) (repeatable) --subscription abc-123

Security

Flag Description
--security Show security findings only (skip vault inventory)

Authentication

Flag Description Default
--auth METHOD Azure auth: cli or default cli
--key KEY API key (overrides saved config) -
--register Re-register or change email -
--offline Skip all license server calls -

Performance

Flag Description Default
--workers N Parallel scan workers (max 20) 5
--timeout N Scan timeout in seconds 300

Other

Flag Description
-v, --verbose Increase verbosity (-v info, -vv debug)
--version Show version and exit
--help Show help and exit

Environment Variables

All flags can be set via environment variables. Flags take priority over env vars.

Variable Equivalent Flag
CC_SCAN_KEY --key
CC_SCAN_FORMAT --format
CC_SCAN_AUTH --auth
CC_SCAN_WORKERS --workers
CC_SCAN_TIMEOUT --timeout
CC_SCAN_OFFLINE --offline (set to true or 1)

Output Formats

Table (default)

Rich terminal output with a subscription tree, expiry warnings, and security findings.

cc-scan

JSON

Machine-readable output including all scan data and security findings.

cc-scan --format json
cc-scan --format json -o results.json

CSV

Flat CSV with one row per asset. Good for spreadsheets and data analysis.

cc-scan --format csv -o inventory.csv

HTML

Standalone HTML report with charts, tables, and colour-coded status. Suitable for sharing with stakeholders.

cc-scan --format html -o report.html

Security Checks

Every scan automatically runs 11 security rules:

ID Severity Finding
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
SEC-007 MEDIUM Certificate has no expiry date
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

Use --security to show only findings without the full vault inventory.


Exit Codes

For CI/CD integration:

Code Meaning
0 Scan completed, no critical or high findings
1 Scan completed, critical or high findings detected
2 Scan failed (auth error, no subscriptions, etc.)
3 Invalid or missing API key

Example: GitHub Actions gate

- name: Audit Key Vaults
  run: |
    pip install certifyclouds
    cc-scan --format json --key ${{ secrets.CC_SCAN_KEY }} -o results.json

Azure Permissions

The scanner needs two levels of access:

Subscription level

  • Reader role on each subscription (to discover Key Vaults)

Vault level

  • Key Vault Secrets User (to read secret metadata)
  • Key Vault Certificate User (to read certificate metadata)
  • Key Vault Crypto User (to read key metadata)

The scanner never reads secret values

These roles only grant access to metadata (names, expiry dates, tags). Secret values are never accessed or transmitted.

Assign roles

# Subscription-level Reader
az role assignment create \
  --assignee <your-user-or-sp> \
  --role "Reader" \
  --scope /subscriptions/<sub-id>

# Vault-level roles (repeat per vault or assign at resource group level)
az role assignment create \
  --assignee <your-user-or-sp> \
  --role "Key Vault Secrets User" \
  --scope /subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault>

Registration & API Keys

First run

On first run, cc-scan prompts for your email and registers a free API key. The key is saved to ~/.certifyclouds/config.json.

Re-register

cc-scan --register

Use a specific key

cc-scan --key cc-scan-abc1234567

Or set the environment variable:

export CC_SCAN_KEY=cc-scan-abc1234567

Offline Mode

Use --offline to skip all external calls to the license server. The scan runs fully locally using only Azure APIs.

cc-scan --offline

When online, the scanner sends only aggregate counts (number of vaults, secrets, etc.) after each scan. It never sends vault names, secret names, or any identifiable data.


Updating

pip install --upgrade certifyclouds
pipx upgrade certifyclouds
brew upgrade certifyclouds

The scanner checks for updates after each scan and shows a notification when a new version is available.

Check your current version:

cc-scan --version

Troubleshooting

"No Azure credentials found"

Run az login first, or set service principal environment variables:

export AZURE_CLIENT_ID=...
export AZURE_CLIENT_SECRET=...
export AZURE_TENANT_ID=...
cc-scan --auth default

"Access denied (check RBAC permissions)"

Your identity doesn't have the required vault-level roles. See Azure Permissions above.

"Firewall restriction"

The vault's network rules are blocking your IP. You need to either:

  • Add your IP to the vault's firewall allow list
  • Connect via a VNet that has access
  • Use Azure Cloud Shell (runs inside Azure's network)

Timeout on large environments

Increase the timeout and workers:

cc-scan --timeout 600 --workers 10

"Azure SDK not installed"

The Azure SDK packages weren't installed. Reinstall:

pip install --force-reinstall certifyclouds

What's Next?

The scanner shows you the problem. CertifyClouds Pro fixes it automatically.

  • Continuous monitoring with scheduled scans and dashboards
  • Automated rotation for secrets and certificates
  • Dependency mapping — know which App Services use which secrets
  • Multi-cloud sync — propagate secrets to AWS and GCP
  • Compliance scoring and audit trail

Start a free trial