Configuration Reference

All configuration is provided through environment variables with the VENDING_ prefix.
Variables can also be placed in a .env file in the project root (loaded automatically by Pydantic Settings).

Copy .env.example to .env and fill in the values before starting the service.

For guidance on which variables are secrets and how to handle them securely in each deployment context, see secrets.md.


Azure credentials

Variable Default Description
VENDING_AZURE_TENANT_ID (required) Azure Active Directory tenant ID. Must always be set.
VENDING_AZURE_CLIENT_ID "" Service principal application (client) ID. Leave empty to use Managed Identity.
VENDING_AZURE_CLIENT_SECRET "" Service principal secret. Required when VENDING_AZURE_CLIENT_ID is set.

When both VENDING_AZURE_CLIENT_ID and VENDING_AZURE_CLIENT_SECRET are populated the service uses ClientSecretCredential. If either is empty, ManagedIdentityCredential is used instead. Managed Identity is recommended for all Azure-hosted deployments.


Management group placement

Variable Default Description
VENDING_ROOT_MANAGEMENT_GROUP ITL Name of the root/default management group. Used as a fallback when no itl-environment tag is present.
VENDING_ENVIRONMENT_MG_MAPPING (JSON — see below) JSON string mapping environment names to management group names. Supports unlimited custom environments.

Environment → Management Group mapping

VENDING_ENVIRONMENT_MG_MAPPING accepts a JSON object where each key is an itl-environment tag value and each value is the target management group name.

Default mapping:

VENDING_ENVIRONMENT_MG_MAPPING='{
  "production": "ITL-Production",
  "staging": "ITL-Staging",
  "development": "ITL-Development",
  "sandbox": "ITL-Sandbox"
}'

Any number of additional environments can be added:

VENDING_ENVIRONMENT_MG_MAPPING='{
  "production":  "ITL-Production",
  "staging":     "ITL-Staging",
  "development": "ITL-Development",
  "sandbox":     "ITL-Sandbox",
  "acceptance":  "ITL-Acceptance",
  "test":        "ITL-Test",
  "customer-a":  "CustomerA-Prod",
  "customer-b":  "CustomerB-Prod"
}'

If the itl-environment tag value is not found in the mapping, the subscription falls back to the sandbox management group (or ITL-Sandbox if that key is also absent from the mapping). If the JSON value is malformed, the entire mapping falls back to {"sandbox": "ITL-Sandbox"}.


RBAC role assignments

The following variables control which Azure AD principals receive default role assignments on each new subscription. Leave a variable empty to skip the corresponding role assignment.

Variable Default Role granted Description
VENDING_PLATFORM_SPN_OBJECT_ID "" Owner Object ID of the ITL platform service principal.
VENDING_OPS_GROUP_OBJECT_ID "" Contributor Object ID of the ITL Operations Azure AD group.
VENDING_SECURITY_GROUP_OBJECT_ID "" Security Reader Object ID of the ITL Security Azure AD group.
VENDING_FINOPS_GROUP_OBJECT_ID "" Cost Management Reader Object ID of the ITL FinOps Azure AD group.

Note: These values are Azure AD object IDs, not display names or client IDs. You can look up object IDs in the Azure Portal under Azure Active Directory → Groups / Enterprise applications.


Budget alerts

Variable Default Description
VENDING_DEFAULT_ALERT_EMAIL "" Fallback e-mail address for budget alert notifications when the itl-owner subscription tag is not set. If empty and the tag is absent, no notification contact is configured.

Authorization service

Variable Default Description
VENDING_AUTHORIZATION_SERVICE_URL http://itl-authorization:8004 Base URL of the internal ITL Authorization service. Used to attach the ITL Foundation Policy Initiative to new subscriptions.

Keycloak

Variable Default Description
VENDING_KEYCLOAK_URL http://keycloak:8080 Base URL of the Keycloak identity provider.
VENDING_KEYCLOAK_REALM ITL Keycloak realm name.

Event Grid

Variable Default Description
VENDING_EVENT_GRID_SAS_KEY "" Shared-access-signature key injected by Event Grid as the aeg-sas-key header. When set, the webhook rejects any request whose header does not match. Leave empty to disable SAS key validation.
VENDING_EVENT_GRID_TOPIC_ENDPOINT "" Endpoint URL of an Azure Event Grid Custom Topic. When set, the service publishes an outbound ITL.SubscriptionVending.SubscriptionProvisioned event after each provisioning run (Step 6). Leave empty to disable outbound notifications.

Feature flags

Variable Default Description
VENDING_MOCK_MODE false Set to true to mount the POST /webhook/test mock endpoint. Intended for local development and integration testing only. Never enable in production.

Extensions

These variables are read by the built-in extension modules in extensions/. They are optional — leave them unset to disable the corresponding extension.

Webhook notify (extensions/webhook_notify.py)

Posts the provisioning result as JSON to a plain HTTPS endpoint after each workflow run.

Variable Default Description
VENDING_WEBHOOK_URL "" HTTPS endpoint to POST to. Leave empty to disable.
VENDING_WEBHOOK_SECRET "" Sent as the X-Webhook-Secret header. Leave empty to omit the header.
VENDING_WEBHOOK_TIMEOUT 10 Request timeout in seconds.

API notify (extensions/api_notify.py)

Posts the provisioning result as JSON to a REST API endpoint using Bearer token authentication.

Variable Default Description
VENDING_API_NOTIFY_URL "" API endpoint to POST to. Leave empty to disable.
VENDING_API_NOTIFY_TOKEN "" Bearer token value sent as Authorization: Bearer <token>. Leave empty to omit the header.
VENDING_API_NOTIFY_TIMEOUT 10 Request timeout in seconds.

Both extensions are auto-discovered at startup. They activate when their controlling env var is set (VENDING_WEBHOOK_URL or VENDING_API_NOTIFY_URL respectively). No code changes are required — set the env var and the extension registers itself.


ServiceNow check (extensions/servicenow_check.py)

Gate check that validates a ServiceNow ticket before any provisioning step runs. The check is read-only and runs even during dry-run.

Variable Default Description
VENDING_SNOW_INSTANCE "" ServiceNow instance hostname (e.g. myco.service-now.com). Leave empty to disable.
VENDING_SNOW_USER "" ServiceNow username for basic authentication.
VENDING_SNOW_PASSWORD "" ServiceNow password for basic authentication.
VENDING_SNOW_TABLE sc_req_item Table to query. Use change_request for CHG tickets.
VENDING_SNOW_REQUIRE_STATE approved Required value of the approval or state field. Set to "" to check existence only.
VENDING_SNOW_TIMEOUT 10 HTTP timeout in seconds.

ServiceNow feedback (extensions/servicenow_feedback.py)

Provisioning step that PATCHes the ServiceNow ticket with the outcome after STEP_NOTIFY. Feedback failures are non-fatal.

Variable Default Description
VENDING_SNOW_INSTANCE "" ServiceNow instance hostname. Shared with check extension. Leave empty to disable.
VENDING_SNOW_USER "" ServiceNow username. Shared with check extension.
VENDING_SNOW_PASSWORD "" ServiceNow password. Shared with check extension.
VENDING_SNOW_TABLE sc_req_item Table to update.
VENDING_SNOW_SUCCESS_STATE "" state value to set when provisioning succeeds (e.g. 3 = Closed Complete). Leave empty to not change state.
VENDING_SNOW_FAILURE_STATE "" state value to set when provisioning fails (e.g. 4 = Closed Incomplete). Leave empty to not change state.
VENDING_SNOW_TIMEOUT 10 HTTP timeout in seconds.

Retry strategy (retry/)

Controls how the service handles provisioning failures. Select a strategy via VENDING_RETRY_STRATEGY.

Strategy Behaviour
none (default) Runs the provisioning workflow inline and always returns 200 OK to Event Grid. Failures are logged but not retried.
dead_letter Runs inline but returns 500 on failure, causing Event Grid to retry according to its own retry policy and eventually dead-letter the event.
queue Immediately enqueues a ProvisioningJob to Azure Storage Queue and returns 200. A separate worker (POST /worker/process-job) processes jobs asynchronously with configurable max delivery and dead-letter support.
Variable Default Description
VENDING_RETRY_STRATEGY none Retry strategy: none, dead_letter, or queue.
VENDING_STORAGE_ACCOUNT_NAME "" Azure Storage Account name. Required when VENDING_RETRY_STRATEGY=queue. The Managed Identity must have Storage Queue Data Contributor on this account.
VENDING_PROVISIONING_QUEUE_NAME provisioning-jobs Name of the work queue. Created automatically on first dispatch if it does not exist.
VENDING_PROVISIONING_DLQ_NAME provisioning-jobs-deadletter Name of the dead-letter queue. Created automatically alongside the work queue.
VENDING_QUEUE_MAX_DELIVERY_COUNT 5 Number of failed deliveries before the worker moves a message to the dead-letter queue.
VENDING_QUEUE_VISIBILITY_TIMEOUT 30 Seconds a message remains invisible in the queue after a failed attempt before it reappears for retry.
VENDING_WORKER_SECRET "" Shared secret validated via the x-worker-secret / x-replay-secret header on POST /worker/process-job and POST /webhook/replay. Leave empty to disable header authentication (use only on private networks).

Soft dependency: The azure-storage-queue package is required when VENDING_RETRY_STRATEGY=queue. It is wrapped in a try/except import — the service starts normally without it, but the queue strategy will raise a RuntimeError at first dispatch if the package is missing. Install it with pip install azure-storage-queue.


Tag-based provisioning

Azure subscription tags are read at the start of the provisioning workflow. They override defaults derived from environment variables.

| Tag | Expected values | Effect | Fallback | |—–|—————-|——–|———| | itl-environment | Any string (e.g. production, staging, acceptance, customer-a) | Selects the target management group via VENDING_ENVIRONMENT_MG_MAPPING. Also determines policy enforcement mode (Default for production, DoNotEnforce for all others). | sandbox MG | | itl-aks | true, false | Marks the subscription for AKS/Flux base chart installation. | false | | itl-budget | Integer (e.g. 500) | Creates a monthly Azure Cost Management budget at the specified EUR amount with e-mail alerts at 80 % and 100 %. | No budget alert | | itl-owner | E-mail address | Contact address for budget alert notifications. Overrides VENDING_DEFAULT_ALERT_EMAIL. | VENDING_DEFAULT_ALERT_EMAIL || itl-snow-ticket | Ticket number (e.g. RITM0041872) | Validated by the ServiceNow gate check before provisioning starts. Required when servicenow_check extension is active. Updated with the provisioning outcome by the servicenow_feedback extension. | (gate skipped if absent and SNOW not configured) | Invalid tag values are silently ignored and the corresponding default is used, so provisioning always continues even when tags are malformed.

Configurable tag key names

The tag key names shown above are defaults. You can override them to match your own tagging conventions using the following environment variables:

Environment variable Default value Description
VENDING_TAG_ENVIRONMENT itl-environment Tag key used to determine the target environment / management group
VENDING_TAG_AKS itl-aks Tag key used to enable AKS/Flux setup
VENDING_TAG_BUDGET itl-budget Tag key for the monthly budget amount in EUR
VENDING_TAG_OWNER itl-owner Tag key for the budget alert e-mail address
VENDING_TAG_SNOW_TICKET itl-snow-ticket Tag key for the ServiceNow ticket number

For example, to use myorg-environment instead of itl-environment:

VENDING_TAG_ENVIRONMENT=myorg-environment
VENDING_TAG_AKS=myorg-aks
VENDING_TAG_BUDGET=cost-budget
VENDING_TAG_OWNER=cost-owner