Compare Azure resources with Terraform Enterprise workspaces
Reason this release was yanked:
updated README
Project description
zephy
TODO:
- validate reports
- test with --tfe-creds-file and --azure-creds-file
- test with in self-hosted TFE -> self-signed SSL cert
Version 1.0.0
Azure TFE Resources Toolkit
Compare Azure resources deployed in a subscription against resources managed by Terraform Enterprise (TFE) workspaces. Identifies resource coverage gaps, unmanaged resources, and provides detailed resource inventory reports.
Features
- Resource Discovery: Automatically discover all Azure resources in a subscription
- TFE Integration: Connect to Terraform Enterprise to analyze workspace state files
- Coverage Analysis: Identify which Azure resources are NOT managed by Terraform
- Resource Matching: Advanced matching algorithm using Azure resource IDs
- CSV Reports: Generate Excel-compatible CSV reports with UTF-8 BOM encoding
- Caching: Optional file system caching for improved performance
- Manual Mode: Fallback to manual Azure CLI commands when API access fails
- Dry Run: Preview execution plan without making API calls
Installation
Requires Python 3.10 or higher.
1. From Source
git clone https://github.com/henrybravo/zephy.git
cd zephy
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements.txt
pip install -e .
--or--
2. From Source Using uv (recommended)
git clone https://github.com/henrybravo/zephy.git
cd zephy
uv venv .venv
source .venv/bin/activate
uv pip install -r requirements.txt
uv pip install -e .
Quick Start
Basic Usage
# Login with az cli
az login
# Set environment variables
export TFE_TOKEN="your-tfe-token"
export AZURE_SUBSCRIPTION_ID="your-subscription-id"
# Run comparison
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID
Using Configuration File
# Create config.json (see config.example.json)
zephy --config config.json
Manual Azure CLI Mode
# Generate commands for manual execution
# change to your id:
export AZURE_SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--azcli-manually
# Run the generated az commands manually, then:
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--azure-input-file azure_resources_$AZURE_SUBSCRIPTION_ID.json
Authentication
Azure Authentication
Uses DefaultAzureCredential with automatic fallback:
- Environment variables (
AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_TENANT_ID) - Azure CLI (
az login) - Managed Identity (for CI/CD)
For service principal authentication, create a JSON file with the following format and use --azure-creds-file:
{
"client_id": "your-service-principal-client-id",
"client_secret": "your-service-principal-client-secret",
"tenant_id": "your-azure-tenant-id",
"subscription_id": "your-azure-subscription-id"
}
TFE Authentication
Set the TFE_TOKEN environment variable or use --tfe-token parameter.
For token from file, create a plain text file containing only the TFE API token and use --tfe-creds-file:
your-tfe-api-token-here
For self-hosted TFE instances with self-signed SSL certificates, use --no-tfe-ssl-verify to skip SSL certificate verification.
Configuration
Command Line Arguments
zephy --help
Configuration File
Create a config.json file (see config.example.json for template):
{
"tfe_base_url": "https://app.terraform.io/api/v2",
"tfe_ssl_verify": true,
"tfe_org": "your-tfe-organization",
"azure_subscription": "your-azure-subscription-id",
"workspaces": ["workspace-1", "workspace-2"],
"resource_groups": ["prod-rg", "shared-rg"],
"tfe_token": null,
"tfe_creds_file": null,
"azure_creds_file": null,
"azcli_manually": false,
"azure_input_file": null,
"resource_mode": "primary",
"cache_ttl": 60,
"no_cache": false,
"output_dir": "./reports",
"save_resources": false,
"logfile_dir": "./logs",
"debug": false,
"dry_run": false,
"parallel": 10
}
Output
Generates five CSV files:
resources_comparison_TIMESTAMP.csv: All resources with match statusunmanaged_resources_TIMESTAMP.csv: Azure resources NOT in TFEmulti_workspace_resources_TIMESTAMP.csv: Resources managed by multiple workspacestfe_resources_inventory_TIMESTAMP.csv: Complete inventory of all TFE resourcesazure_resources_inventory_TIMESTAMP.csv: Complete inventory of all Azure resources
Generating Primary Resource Types
To generate the PRIMARY_RESOURCE_TYPES.json file with the correct Azure resource types:
# Ensure you're logged in to Azure CLI
az login
# Run the generation script
python generate_primary_resource_types.py
This script:
- Queries Azure for all available resource types
- Filters for primary infrastructure resources (VMs, databases, networks, etc.)
- Excludes auxiliary/support resource types
- Saves the filtered list to
PRIMARY_RESOURCE_TYPES.json
Examples
Filter by Workspaces
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--workspaces "prod-app,prod-db"
Detailed Resource Mode
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--resource-mode detailed
Dry Run
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--dry-run
Advanced Options
# Filter by resource groups
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--resource-groups "prod-rg,shared-rg"
# Use detailed resource mode and increase parallel requests
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--resource-mode detailed \
--parallel 20
# Disable caching and set custom cache TTL
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--no-cache \
--cache-ttl 120
# Use service principal credentials from file
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--azure-creds-file azure-creds.json
# Use TFE token from file
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--tfe-creds-file tfe-token.txt
# Skip SSL verification for self-hosted TFE
zephy \
--tfe-org your-org \
--azure-subscription $AZURE_SUBSCRIPTION_ID \
--tfe-base-url https://your-self-hosted-tfe.com/api/v2 \
--no-tfe-ssl-verify
Development
Setup Development Environment
pip install -e .[dev]
Run Tests
uv pip install pytest
pytest tests/ -v --cov=zephy --cov-report=html
Code Quality
black zephy/
flake8 zephy/
mypy zephy/
Security
- Credentials are never logged in plain text
- Sensitive data is redacted in logs
- Config files with credentials trigger warnings
- Use environment variables for credentials in production
Configure Azure App Registration for SDK Access
This guide assumes you already created an App Registration in Azure AD and have the following environment variables set:
export AZURE_CLIENT_ID="" export AZURE_CLIENT_SECRET="" export AZURE_TENANT_ID="" export AZURE_SUBSCRIPTION_ID=""
- Login with Azure CLI
Login with a user that has Owner or User Access Administrator on the subscription:
az login --tenant $AZURE_TENANT_ID
az account set --subscription $AZURE_SUBSCRIPTION_ID
- Assign RBAC Role to the Service Principal
The app registration (service principal) needs at least Reader role to list resources.
If you need deployment/management rights, use Contributor instead.
az role assignment create \
--assignee $AZURE_CLIENT_ID \
--role "Reader" \
--scope /subscriptions/$AZURE_SUBSCRIPTION_ID
For Contributor role:
az role assignment create \
--assignee $AZURE_CLIENT_ID \
--role "Contributor" \
--scope /subscriptions/$AZURE_SUBSCRIPTION_ID
- Verify the Role Assignment
Check if the role was applied correctly:
az role assignment list \
--assignee $AZURE_CLIENT_ID \
--scope /subscriptions/$AZURE_SUBSCRIPTION_ID \
--output table
- Refresh Tokens if Access Was Just Granted
If you get AuthorizationFailed after role assignment:
az account clear
Then restart your app to pick up fresh tokens.
License
MIT License
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 zephy-1.0.0.tar.gz.
File metadata
- Download URL: zephy-1.0.0.tar.gz
- Upload date:
- Size: 37.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c7b8be8918e77061ac355f399da4e0f0aa09185c9ab253ae2ac373b952b859e
|
|
| MD5 |
b6868c39b3c7a5b4854add6379b59e59
|
|
| BLAKE2b-256 |
24072688bc94f5fd6d3879c45ab175dbc1eef0906bad3b7e9189ecd4a93882c1
|
File details
Details for the file zephy-1.0.0-py3-none-any.whl.
File metadata
- Download URL: zephy-1.0.0-py3-none-any.whl
- Upload date:
- Size: 41.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7cdee41fe1f9e385fa188f413bfc2e3694c998844a0f915d6a5fe1067a75fc5
|
|
| MD5 |
8af302874570020c415bceccd86bc306
|
|
| BLAKE2b-256 |
6d24c9d82dfb6f627975127667a8bb42dbbc2fa71c28d34b10acb683c81217e7
|