Metadata-Version: 2.4
Name: certifyclouds
Version: 1.2.2
Summary: Scan Azure Key Vaults for expiring secrets, certificates, and keys
Project-URL: Homepage, https://certifyclouds.com/scanner
Project-URL: Documentation, https://docs.certifyclouds.com/scanner
Project-URL: Repository, https://codeberg.org/hus/cc
Author-email: CertifyClouds <hello@certifyclouds.com>
License: Apache-2.0
License-File: LICENSE
Keywords: azure,certificates,expiry,keyvault,rotation,scanner,secrets,security
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.9
Requires-Dist: azure-core>=1.30
Requires-Dist: azure-identity>=1.20
Requires-Dist: azure-keyvault-certificates>=4.9
Requires-Dist: azure-keyvault-keys>=4.10
Requires-Dist: azure-keyvault-secrets>=4.9
Requires-Dist: azure-mgmt-keyvault>=13.0
Requires-Dist: azure-mgmt-resource>=24.0
Requires-Dist: click>=8.0
Requires-Dist: httpx>=0.27
Requires-Dist: rich>=13.0
Requires-Dist: tenacity>=9.0
Provides-Extra: dev
Requires-Dist: pytest-mock>=3.10; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# certifyclouds

**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 certifyclouds                              # or: pipx install certifyclouds
cc-scan                                                # or: brew tap certifyclouds/certifyclouds && brew install certifyclouds
```

## 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

```bash
# 1. Install (pick one)
pip install certifyclouds              # pip
pipx install certifyclouds             # pipx (isolated install)
brew tap certifyclouds/certifyclouds   # Homebrew (macOS/Linux)
brew install certifyclouds

# 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.2
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

```bash
# 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):

```bash
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`):

```bash
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 (no key found or registration failed) |

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 skip license server validation calls (key telemetry and version checks). Azure SDK calls are unaffected — the scanner still requires Azure connectivity to read Key Vault data.

Source code is open and auditable: [codeberg.org/hus/cc/scanner](https://codeberg.org/hus/cc)

## 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](#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](LICENSE).

## Links

- [CertifyClouds](https://certifyclouds.com) - Automate secret rotation & compliance
- [Documentation](https://docs.certifyclouds.com/scanner)
- [Source Code](https://codeberg.org/hus/cc)
