Azure Policy Engine (minimal)
This is a small Python package that helps to harmonize Azure Policy management and deployment workflows programmatically.
There is no dedicated PyPI package specifically named "Azure Policy Deployment Engine," but the closest and officially supported option for managing and deploying Azure Policy programmatically in Python is the azure-mgmt-policyinsights package, which provides access to Azure Policy Insights and allows programmatic interaction with policies, assignments, and compliance data within Azure. For actual policy management and deployment (creating, updating, assigning policies), you generally use the Azure SDK for Python and various management libraries. Additionally, there are community projects such as the "Azure-Policy-Engine" on GitHub, which offers Python tooling to manage Azure Policies outside the portal, CLI, or REST API, using the Azure SDK for Python as a backend. This is not a PyPI package but can be installed from source.
For broader deployment requirements, you may also need packages like azure-mgmt-resource or azure-mgmt-deploymentmanager, but these are focused on resource and deployment management, not policy-specific automation. So this is where py_azpe (Azure Policy Engine) comes in.
| Package/Tool | Purpose | PyPI Availability | Notes |
|---|---|---|---|
| azure-mgmt-policyinsights | Policy Insights API (compliance/data) | Yes | Official Azure SDK; compliance only |
| Azure-Policy-Engine (GitHub) | Programmatic Policy CRUD operations | No | Community tool; install from source |
| azure-mgmt-resource/deploymentmanager | ARM resource + deployment mgmt | Yes | Not policy-specific |
| py_azpe - Azure Policy Engine (this Github Repo) | Create/manage/deploy Azure Policies | Yes | Lightweight Python package for policy mgmt |
This README documents the current feature set, CLI usage, packaging/dev setup, examples and a short HOWTO for mapping JSON into SDK models.
Overview
The AZURE-POLICY-ENGINE (available as py_azpe on PyPI) is a lightweight Python package designed to help users create, manage, and optionally deploy Azure Policy artifacts. The repository includes documentation covering:
- Current features
- Command-line interface (CLI) usage
- Development setup and packaging
- Practical examples
- A brief guide on converting JSON into SDK models
It's a handy tool for streamlining Azure Policy workflows in Python environments.
Supported backends
-
file: author and manage policy artifacts as local JSON files. The default folder structure (under the configured
policy_dir, defaults to the packagepolicies/folder) is:definitions/— policyDefinition JSON filesassignments/— policyAssignment JSON filesinitiatives/— policySetDefinition (initiative) JSON files
-
sdk: when the Azure management SDKs are available the engine uses
azure.mgmt.resource.PolicyClientand related models to perform operations. If the SDK is not present (or an SDK call fails and a credential is available) the engine falls back to ARM REST calls using an ARM token acquired from the provided credential. -
azcli: when the Azure CLI (
az) is installed and the user is authenticated the engine can invokeazto perform policy operations. This backend usesaz restunder the hood to call ARM endpoints and is useful when you prefer CLI tooling or when SDK/REST usage is constrained. It requiresazinstalled and an authenticated session (e.g.,az login).
Key features
- Create/list/get policy definitions and initiatives (policy sets).
- Create/update/delete/list policy assignments.
- Assign initiatives (policy sets) via assignment resources.
- Scope validation and support for different assignment scopes: subscription, resource-group and management-group levels.
- Dry-run mode that prints the prepared payload and effective scope without making API calls.
- SDK model construction: the engine attempts to construct SDK model objects (PolicyAssignment, PolicyDefinition, PolicySetDefinition) when the SDK is available; otherwise it works with raw dicts.
CLI quick reference
The CLI entry point is python -m azure_policy_engine.cli.
Common flags
--backend(file|sdk|azcli) — choose local file backend, SDK-backed operations, or Azure CLI-backed operations (default: file).--policies-dir— override the policies directory (defaults to packagepolicies/).--subscription-id— subscription id used by SDK/ARM REST calls when a scope isn't explicitly provided.--scope— provide an explicit scope for assignment operations (must start with/).--mgmt-group— convenience shorthand; builds the management group scope/providers/Microsoft.Management/managementGroups/{id}.--dry-run— print the prepared payload and scope, do not perform the SDK/REST call.
Commands (high level)
list— list local or SDK policy definitionsget <name>— get a single policy definitiondeploy <name> <file>— create/update a policy definitionassignments— list assignmentscreate-assignment <name> <file>— create an assignment (supports--dry-runand--scope/--mgmt-group)update-assignment <name> <file>delete-assignment <name>add-assignment <name> <file>— write file directly into assignments/ (file backend only)list-initiatives— list initiatives (policy sets)assign-initiative <initiative-name> <assignment-name> <file>— create an assignment that references an initiative
Examples
Dry-run creating an assignment at a management group (shorthand) using azcli backend:
python -m py_azpe.cli --backend azcli --mgmt-group my-mg --dry-run create-assignment myAssign examples/assign-mg.json
Create an assignment at a subscription scope using the SDK backend:
python -m py_azpe.cli --backend sdk --scope /subscriptions/0000 create-assignment myAssign examples/assign.json
Create an assignment at a subscription scope using the Azure CLI backend:
python -m py_azpe.cli --backend azcli --scope /subscriptions/0000 create-assignment myAssign examples/assign.json
Assign an initiative (dry-run):
python -m py_azpe.cli --backend sdk --mgmt-group my-mg --dry-run assign-initiative myInitiative myAssign examples/assign-mg.json
Scope validation and supported forms
The engine implements a pragmatic scope validator to catch common user mistakes. Accepted forms include:
- subscription root:
/subscriptions/{subscriptionId} - resource group:
/subscriptions/{subscriptionId}/resourceGroups/{rg} - management group:
/providers/Microsoft.Management/managementGroups/{mgId}
If you pass an explicit scope with --scope, it must start with /. Use --mgmt-group as a convenience shorthand to build management-group scopes.
Dry-run details
--dry-run is available for create/update/delete assignment and assign-initiative commands. When used the CLI prints a JSON object that contains:
dry_run: trueaction: the intended actionscope: effective normalized scopename: the assignment namepayload: the assignment body or SDK-model-as-dict (if SDK model was constructed)
This helps you validate payload shape and scope before making changes.
Examples folder
An examples/ folder is provided with a sample management-group assignment JSON and a small helper script:
examples/assign-mg.json— example assignment JSON that references an initiative at management-group scope.examples/run-assign-mg.sh— example script that ensuresAZURE_SUBSCRIPTION_IDis set, runsaz logininteractively if no SP credentials are present, and executes a dry-run create-assignment againstmy-mg.
Make the script executable locally and run it:
chmod +x examples/run-assign-mg.sh
bash examples/run-assign-mg.sh
Packaging, pinned SDKs and dev setup
This project includes minimal packaging and pinned dependencies to make local development and CI reproducible:
pyproject.toml— basic project metadata and pinned runtime dependencies used by the analyzer/CI.requirements.txt— pinned versions for localpip install -r requirements.txtconvenience.tox.ini— tiny tox configuration to run tests in an isolated environment.
Pinned SDKs used here (change if you need different versions):
- azure-identity==1.12.0
- azure-mgmt-resource==23.0.0
- azure-mgmt-policyinsights==1.0.0
- requests==2.31.0
Dev/test
Install editable package + dev deps in a venv:
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -e .
pip install -r requirements.txt
Run tests:
PYTHONPATH=. pytest -q
or with tox:
tox
CI
A GitHub Actions workflow is added at .github/workflows/ci.yml that:
- Checks out the repository
- Sets up Python
- Installs the package in editable mode and the pinned requirements
- Runs the test suite with pytest
You can extend the workflow (matrix Python versions, caching, linting) as needed.
Release and publishing (CI)
Detailed release and publishing instructions are maintained in RELEASE.md to keep the main README focused. See RELEASE.md for the full release workflow, repository variables, secrets, and example commands.
For convenience, the workflow file is at .github/workflows/release.yml.
HOWTO: map a policy JSON into SDK model fields
When deploying via the SDK it's more robust to construct SDK model objects and pass them to the client methods.
- Ensure
properties.policyDefinitionIdcontains the full resource id of the definition or initiative. - Construct the SDK model (PolicyAssignment / PolicyDefinition / PolicySetDefinition) using the JSON
propertiesas kwargs where possible. - Use
model.as_dict()to verify the final payload shape. - The engine contains helper methods (
_make_policy_assignment_model,_make_policy_definition_model,_make_policy_set_definition_model) that attempt to construct SDK models when the SDK is available and fall back to dicts otherwise.
Troubleshooting
- If
--backend sdkfails due to missing credentials, provide aDefaultAzureCredentialcompatible credential (e.g.,az loginfor interactive flows, or setAZURE_CLIENT_ID,AZURE_TENANT_ID, andAZURE_CLIENT_SECRETfor a service principal). - If using
--backend azcliensureazis installed and authenticated:- Install: follow https://aka.ms/azcli
- Authenticate:
az loginoraz login --service-principal -u <id> -p <secret> --tenant <tenant>
Authentication via environment variables
The engine supports authenticating using Azure environment variables. You can either provide a service principal (recommended for CI/non-interactive flows) or rely on DefaultAzureCredential (interactive az login, managed identity, etc.).
Service principal (export into your shell):
export AZURE_CLIENT_ID="<YOUR_CLIENT_ID_HERE>"
export AZURE_CLIENT_SECRET="<YOUR_CLIENT_SECRET_HERE>"
export AZURE_TENANT_ID="<YOUR_TENANT_ID_HERE>"
export AZURE_SUBSCRIPTION_ID="<YOUR_SUBSCRIPTION_ID_HERE>"
Quick dry-run example (SDK backend)
# with SP creds exported as above
python -m py_azpe.cli --backend sdk --mgmt-group my-mg --dry-run create-assignment myAssign examples/assign-mg.json
Default credential (interactive / managed identity):
- For local interactive auth, run:
az login
export AZURE_SUBSCRIPTION_ID="<YOUR_SUBSCRIPTION_ID_HERE>"
How the code uses these variables:
- If
AZURE_CLIENT_ID,AZURE_CLIENT_SECRET, andAZURE_TENANT_IDare present, the engine will create anazure.identity.ClientSecretCredentialusing those values. - Otherwise the engine falls back to
azure.identity.DefaultAzureCredential(soaz loginor a managed identity will work). AZURE_SUBSCRIPTION_IDis used when the SDK/backends need a subscription context.
Quick try-it commands (zsh/bash):
# install dependencies into a venv
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# export SP creds and run the CLI using SDK backend
export AZURE_CLIENT_ID="<ID>"
export AZURE_CLIENT_SECRET="<SECRET>"
export AZURE_TENANT_ID="<TENANT>"
export AZURE_SUBSCRIPTION_ID="<SUB>"
python -m py_azpe.cli --backend sdk list
Contributing
Thank you for considering contributing to the Azure Policy Engine project — contributions are welcome! To make collaborating smooth please follow these simple guidelines:
- Issues: Open an issue to discuss bugs, feature requests or design changes before implementing larger work.
- Branches: Use a short, descriptive branch name (e.g.
fix/readme-typo,feat/azcli-backend). - Commits: Keep commits focused and use clear messages. Prefer small commits that make review easier.
- Pull requests:
- Target the
mainbranch (or the branch named in the repository's contribution guidelines). - Include a brief description of the change and the motivation.
- Link any related issue(s).
- Add unit tests for new behavior and update existing tests if behavior changes.
- Target the
- Tests: Run the test suite locally before opening a PR:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
PYTHONPATH=. pytest -q
- Style: The project aims for straightforward, idiomatic Python. Keep changes readable and add docstrings where helpful.
- CI: Pull requests should pass the repository CI checks (tests + any linters) before merging. If you need help getting a branch to pass CI, describe the issue in the PR and maintainers can assist.
If you want to help but are unsure where to start, check the issue tracker for labels like "good first issue" or "help wanted".
License
This project is licensed under the MIT License — see the accompanying LICENSE file for the full text. In short, you are free to use, copy, modify and distribute this software with attribution and without warranty.
Metadata
Release files for py-azpe 0.1.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| py_azpe-0.1.7.tar.gz | 29.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| py_azpe-0.1.7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 56.8 kB
Release files / py_azpe-0.1.7.tar.gz
| Download URL | py_azpe-0.1.7.tar.gz |
|---|---|
| Size | 29.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e793a1c0f25305ea33152fbfe7312b7b043db58bd529235db29c1d2d323cfd9e
|
|
BLAKE2b-256 checksum How to use checksums |
accb24c5fafde71237586d840d5fda827a2a975c7f511ace67e784c3a85257c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Release files / py_azpe-0.1.7-py3-none-any.whl
| Download URL | py_azpe-0.1.7-py3-none-any.whl |
|---|---|
| Size | 26.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
932a7754e7e3bb237f35094166add0f607fb85f39e644fd1479f9f6e29160b0f
|
|
BLAKE2b-256 checksum How to use checksums |
49b3ed62cc177ee32f38d4ba90aa0a588ec52c60c7820349442541f210f25137
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Security for py-azpe 0.1.7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.