OSIRIS JSON Producer for Microsoft Azure
The OSIRIS JSON Azure producer connects to Microsoft Azure via the Azure CLI (az) and generates OSIRIS JSON snapshots of your subscription topology. As of v0.4.0 the producer covers networking, compute, storage, identity, databases, containers, integration, observability and backup tiers, including their cross-resource dependency edges (Private Endpoint to PaaS targets, App Service to App Insights, Log Analytics, RSV, Backup Vault to protected items, AKS to subnets and node pools, etc.).
To begin using OSIRIS JSON for Microsoft Azure, install the core dispatcher and the Microsoft Azure OSIRIS JSON producer:
go install go.osirisjson.org/producers/cmd/osirisjson-producer@latest
go install go.osirisjson.org/producers/cmd/osirisjson-producer-azure@latest
The core dispatcher lets you run osirisjson-producer azure .... Without it, invoke the vendor binary directly as osirisjson-producer-azure ....
Make sure $GOPATH/bin (or $HOME/go/bin) is in your PATH. See the getting started page for more install options.
Prerequisites
- Install the Azure CLI
- Authenticate:
az login - The authenticated user must have Reader role (or equivalent read permission) on the target subscription(s). For full data collection including effective routes, the user also needs
Microsoft.Network/networkInterfaces/effectiveRouteTable/actionpermission (included in Network Contributor and above). If this permission is absent, the producer skips effective route collection with an INFO log and continues normally.
You can execute the producer on your local machine or invoke it using a scheduled job with a service account on your preferred platform.
CLI usage
osirisjson-producer azure [flags]
osirisjson-producer azure template --generate
Single mode
Start by collecting one subscription that will be automatically saved as microsoft-azure-<timestamp>-<name>.json:
osirisjson-producer azure -S a1b2c3d4-e5f6-7890-abcd-ef1234567890
Interactive mode
Run without flags to get an interactive subscription picker:
osirisjson-producer azure
The producer discovers all accessible subscriptions and presents a numbered list. Select using individual numbers (1,3,5), ranges (30-55), combinations (1,3,30-55), or type all.
Multi-subscription mode
Collect multiple subscriptions to an output directory:
# Specific subscriptions
osirisjson-producer azure -S sub-id-1,sub-id-2,sub-id-3 -o ./output
# All accessible subscriptions (auto-discover)
osirisjson-producer azure --all -o ./output
# All subscriptions in a specific tenant
osirisjson-producer azure --all --tenant f1e2d3c4-b5a6-9078-fedc-ba9876543210 -o ./output
Batch mode (CSV)
Generate a CSV template:
osirisjson-producer azure template --generate
Collect from a CSV file:
osirisjson-producer azure -s subscriptions.csv -o ./output
The CSV template uses these columns:
| Column | Required | Description |
|---|---|---|
subscription_id | yes | Azure subscription UUID |
subscription_name | yes | Human-readable label (used as output filename) |
tenant_id | Azure AD / Entra ID tenant UUID | |
environment | Deployment stage: dv, np, pr (development, non-production, production) | |
region | Filter to Azure region (empty = all regions) | |
notes | Free-text notes (ignored by producer) |
Output hierarchy
Single mode: saves to microsoft-azure-<timestamp>-<name>.json in the current directory.
Multi/batch/all modes: organized by tenant and timestamp:
output/
<TenantID>/
<timestamp>/
<SubscriptionName>.json
Each subscription produces a self-contained OSIRIS document. Cross-subscription references (e.g. VNet peerings or ExpressRoute connections to remote subscriptions) are emitted as stub resources with provider.subscription set to the remote subscription ID, so the topology edge survives the boundary while the document remains valid.
Multi-tenant environments
Run the producer once per tenant. Each az login authenticates to one tenant. Use az login --tenant <tenant-id> to switch. The output hierarchy groups documents by tenant automatically.
Flags reference
| Flag | Short | Description |
|---|---|---|
--subscription | -S | Azure subscription ID(s), comma-separated |
--all | Auto-discover all accessible subscriptions | |
--source | -s | CSV file with subscription targets |
--output | -o | Output directory (required for multi/all/CSV mode) |
--tenant | Azure AD / Entra ID tenant ID (optional) | |
--region | Filter to a specific Azure region (optional) | |
--purpose | Output detail grade: documentation (default) or audit. See Purpose below | |
--safe-failure-mode | Secret handling: fail-closed (default), log-and-redact, off | |
--version / -v | Display version and exit | |
--help | Display help and exit |
Purpose
The --purpose flag implements OSIRIS JSON specification chapter 13.1.3 (data minimization). Collection is always exhaustive; emission is shaped by the declared purpose so the same producer run can serve both lightweight visualization use cases and audit / compliance use cases.
| Value | Behavior |
|---|---|
documentation (default) | Minimal fields: identity, type, provider traceability, names, tags and high-level relationships. Per-resource properties and extensions maps are stripped. Suited for diagrams, inventory dashboards and high-level documentation. |
audit | Every readable field, after sensitive-field redaction. Full properties and extensions maps for every resource, connection and group. Suited for compliance reviews, audits, configuration drift or deep documentation and accurate topology design. |
The selected value is recorded in the document under metadata.scope.purpose so consumers can tell which grade of detail they are reading.
[!IMPORTANT] Secrets are always redacted regardless of purpose. The audit projection adds detail (IP addresses, NSG rules, SKU subfields, BGP details, etc.); it never adds authentication material. Database admin passwords, Cosmos / Redis / Service Bus / Event Hubs access keys, App Insights instrumentation keys and Log Analytics shared keys are never collected.
# Default: documentation (minimal projection)
osirisjson-producer azure -S a1b2c3d4-e5f6-7890-abcd-ef1234567890
# Audit: full ARM fidelity
osirisjson-producer azure -S a1b2c3d4-e5f6-7890-abcd-ef1234567890 --purpose audit
What OSIRIS JSON producer for Microsoft Azure collects
The OSIRIS JSON producer for Microsoft Azure collects a complete inventory of supported resource types via the Azure CLI on every run. The following table groups what is queried.
Networking
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| Virtual Networks | network.vpc |
| Subnets | network.subnet |
| Network Interfaces | network.interface |
| Network Security Groups | network.security.group |
| Application Security Groups | osiris.azure.asg |
| Route Tables | osiris.azure.routetable |
| Public IP Addresses | osiris.azure.publicip |
| Load Balancers (L4) | network.loadbalancer |
| Application Gateways (L7) | network.loadbalancer |
| Azure Firewalls | network.firewall |
| NAT Gateways | osiris.azure.gateway.nat |
| VNet Gateways (VPN / ExpressRoute) | osiris.azure.gateway.vnet |
| ExpressRoute Circuits | osiris.azure.expressroute |
| Private Endpoints | osiris.azure.privateendpoint |
| DNS Zones | osiris.azure.dns.zone |
| Private DNS Zones | osiris.azure.dns.privatezone |
Compute and storage
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| Virtual Machines | compute.vm |
| Managed Disks | osiris.azure.disk |
| Managed Snapshots | osiris.azure.snapshot |
| Storage Accounts | osiris.azure.storageaccount |
App Service / web tier
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| App Service Plan | osiris.azure.appserviceplan |
| Web App | osiris.azure.webapp |
| Function App | osiris.azure.functionapp |
App Service routing: sites whose kind contains functionapp are emitted as osiris.azure.functionapp; all other sites are emitted as osiris.azure.webapp.
Identity and security
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| Key Vault | osiris.azure.keyvault |
| Container Registry | osiris.azure.containerregistry |
| User-Assigned Managed Identity | osiris.azure.managedidentity |
Backup and disaster recovery
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| Recovery Services Vault | osiris.azure.recoveryvault |
| Backup Vault (Azure Backup) | osiris.azure.backupvault |
Databases
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| SQL Server | osiris.azure.sqlserver |
| SQL Database | osiris.azure.sqldatabase |
| PostgreSQL Flexible Server | osiris.azure.postgresqlserver |
| MySQL Flexible Server | osiris.azure.mysqlserver |
| Cosmos DB account | osiris.azure.cosmosaccount |
| Redis Cache | osiris.azure.redis |
Containers and integration
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| AKS Cluster | osiris.azure.aks.cluster |
| AKS Agent Pool | osiris.azure.aks.nodepool |
| Container App Managed Environment | osiris.azure.containerapp.environment |
| Container App | osiris.azure.containerapp |
| Container Group / ACI | osiris.azure.containergroup |
| Service Bus Namespace | osiris.azure.servicebus.namespace |
| Event Hubs Namespace | osiris.azure.eventhubs.namespace |
| API Management Service | osiris.azure.apim |
| Front Door (Standard / Premium) | osiris.azure.frontdoor.profile |
Observability
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| Application Insights | osiris.azure.applicationinsights |
| Log Analytics Workspace | osiris.azure.loganalytics |
Containment
| Microsoft Azure resource | OSIRIS JSON type |
|---|---|
| Resource Groups | container.resourcegroup |
What is intentionally not collected
OSIRIS JSON defines a vendor-neutral JSON format for describing infrastructure resources, their properties and their topological relationships it is not an Infrastructure-as-Code or similar format you cen read more here What is OSIRIS JSON. The following are intentionally out of scope:
- Monitoring policy: alert rules, action groups, metric alerts, scheduled query rules.
- Backup / retention policies under Recovery Services Vault and Backup Vault (the vaults and protected-item edges are emitted; the policy bodies are not).
- Database-tier policy: SQL auditing, threat-detection, TDE, firewall rules, security-alert-policy.
- API Management policies, products, operations, named values.
- Front Door routes, rule sets, endpoints, WAF policy associations (the profile is emitted; the routing is not).
- Container App secrets and ACI environment variables.
- Per-resource diagnostic-setting enumeration (would add one
azcall per resource). - Classic Azure Front Door (
Microsoft.Network/frontDoors, deprecated). - Legacy
Microsoft.DBforPostgreSQL/servers(single server, end-of-life on Azure’s roadmap).
OSIRIS JSON output structure for Microsoft Azure
{
"$schema": "https://osirisjson.org/schema/v1.0/osiris.schema.json",
"version": "1.0.0",
"metadata": {
"generator": {
"name": "osirisjson-producer-azure",
"version": "0.4.0",
"url": "https://osirisjson.org"
},
"scope": {
"name": "<subscription-id> - <subscription-name>",
"purpose": "documentation",
"providers": ["azure"],
"accounts": ["<tenant-id>"],
"subscriptions": ["<subscription-id>"],
"regions": ["westeurope", "eastus2"]
}
},
"topology": {
"resources": [ ... ],
"connections": [ ... ],
"groups": [ ... ]
}
}
Connection types
Connection edges use OSIRIS JSON v1.0 standard subtypes per specification chapter 5.2.3 so consumers can tell topology layers apart.
| OSIRIS JSON connection type | Used for |
|---|---|
contains | Containment (Subnet within VNet, App Service Plan within site, AKS Cluster within node pool, RG within Subscription, SQL Server within SQL Database, source Disk within Snapshot, VM within attached Disk) |
network | Generic network connectivity (NIC to subnet, NSG associations, DNS links, gateway connections, App Insights to workspace, Web App to App Insights, AKS / Redis / ACI to subnet, APIM to subnet) |
network.peering | VNet peerings |
network.vpn | VPN gateway connections |
network.bgp | ExpressRoute circuit connections |
dependency | Private Endpoint to PaaS target (Web App, Function App, Key Vault, Container Registry, Recovery Services Vault, AKS cluster, Service Bus, Event Hubs, APIM) |
dependency.storage | Private Endpoint to Storage Account |
dependency.database | Private Endpoint to database (SQL Server, Cosmos DB, Redis) |
Group types
| OSIRIS JSON group type | Used for |
|---|---|
logical.subscription | Top-level subscription group |
logical.resourcegroup | Resource group groups (children of the subscription) |
container.region | One group per distinct provider.region observed in the subscription, membering every resource in that region. Region global and empty-region resources are skipped (they are not geographically scoped). The boundary token is <subscription-id>/<region>, so groups never collide across subscriptions. |
Resource types
Resource types follow the OSIRIS JSON v1.0 specification. Standard types are used where defined; Azure-specific types use the osiris.azure.* namespace.
Standard types:
container.resourcegroup- Resource groupsnetwork.vpc- Virtual networksnetwork.subnet- Subnetsnetwork.interface- Network interfacesnetwork.security.group- Network security groupsnetwork.loadbalancer- Load balancers (L4 and L7 / Application Gateway)network.firewall- Azure Firewallscompute.vm- Virtual machines
Extensions (osiris.azure)
Azure-specific data that does not map to portable OSIRIS JSON properties is emitted under the osiris.azure extension namespace. This follows the OSIRIS JSON spec: properties holds common / portable data, extensions holds vendor-specific deep data. Extensions are only emitted under --purpose audit.
Representative extensions include:
| OSIRIS JSON Resource type | Selected extension fields |
|---|---|
network.interface | enable_accelerated_networking, effective_routes[] |
network.security.group | security_rules[], default_security_rules[] |
osiris.azure.expressroute | sku, sku_tier, service_provider, peerings[] (BGP peering type, state, peer ASN, VLAN ID, address prefixes) |
osiris.azure.webapp / osiris.azure.functionapp | managed_identity, outbound_vnet_routing, private_endpoint_connection_ids[], app_insights_id |
osiris.azure.storageaccount / osiris.azure.keyvault / osiris.azure.containerregistry / osiris.azure.recoveryvault / osiris.azure.sqlserver / osiris.azure.cosmosaccount | private_endpoint_connection_ids[] |
osiris.azure.applicationinsights | workspace_resource_id (bound Log Analytics workspace) |
osiris.azure.loganalytics | customer_id (workspace UUID used by KQL; not a secret) |
Provider metadata
Every resource includes provider.type with the native ARM resource type (e.g. Microsoft.Network/virtualNetworks, Microsoft.Compute/virtualMachines). Cross-subscription stubs include provider.subscription with the remote subscription ID. All resources include provider.source set to azure-cli.
Resource IDs
Azure resource IDs follow the pattern azure::<ARM-resource-id>, using the full ARM resource ID as the native identifier. This ensures globally unique, deterministic IDs that survive cross-subscription correlation.
Region canonicalization
provider.region and metadata.scope.regions are canonicalized to Azure’s slug form (lowercase, no spaces). The az CLI returns location inconsistently across resource types: most ARM resources use westeurope / eastus2, while App Service Plans and Web Apps surface the display form (West Europe). The producer normalizes to the slug so a single-region subscription does not appear as two regions in metadata.scope.regions.
RBAC requirements
| Permission level | What gets collected |
|---|---|
| Reader | All resource types, properties, extensions (NSG rules, ER peerings, gateway connections, VNet peerings, DNS links, Private Endpoint to target edges, App Service to App Insights, AKS, container, database, messaging and observability resources) |
Reader + effectiveRouteTable/action | Everything above + NIC effective routes |
| Network Contributor / Owner | Full dataset without restrictions |
The producer tests permission on the first NIC and gracefully skips effective route collection if the permission is denied. All other data is collected regardless.
Examples
Single subscription
We are going to explore a single subscription in our tenant and generate from Microsoft Azure an OSIRIS JSON document.
osirisjson-producer azure -S a1b2c3d4-e5f6-7890-abcd-ef1234567890 --purpose audit
OSIRIS JSON output document (trimmed, --purpose audit):
{
"$schema": "https://osirisjson.org/schema/v1.0/osiris.schema.json",
"version": "1.0.0",
"metadata": {
"generator": {
"name": "osirisjson-producer-azure",
"version": "0.4.0",
"url": "https://osirisjson.org"
},
"scope": {
"name": "a1b2c3d4-e5f6-7890-abcd-ef1234567890 - my-nonprod-subscription",
"purpose": "audit",
"providers": ["azure"],
"accounts": ["f1e2d3c4-b5a6-9078-fedc-ba9876543210"],
"subscriptions": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"],
"regions": ["westeurope"]
}
},
"topology": {
"resources": [
{
"id": "azure::/subscriptions/a1b2c3d4/resourceGroups/network-rg/providers/Microsoft.Network/virtualNetworks/hub-vnet",
"type": "network.vpc",
"name": "hub-vnet",
"status": "active",
"provider": {
"name": "azure",
"native_id": "/subscriptions/a1b2c3d4/resourceGroups/network-rg/providers/Microsoft.Network/virtualNetworks/hub-vnet",
"type": "Microsoft.Network/virtualNetworks",
"region": "westeurope",
"source": "azure-cli",
"subscription": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenant": "f1e2d3c4-b5a6-9078-fedc-ba9876543210"
},
"properties": {
"resource_group": "network-rg",
"address_space": ["10.0.0.0/16"],
"dns_servers": ["10.0.0.4"],
"subnet_count": 4,
"enable_ddos_protection": false,
"peerings": [
{
"name": "hub-to-spoke",
"peering_state": "Connected",
"remote_vnet_id": "/subscriptions/a1b2c3d4/.../spoke-vnet",
"allow_gateway_transit": true,
"allow_forwarded_traffic": true
}
]
}
},
{
"id": "azure::/subscriptions/a1b2c3d4/resourceGroups/data-rg/providers/Microsoft.Storage/storageAccounts/mystg",
"type": "osiris.azure.storageaccount",
"name": "mystg",
"status": "active",
"provider": {
"name": "azure",
"native_id": "/subscriptions/a1b2c3d4/resourceGroups/data-rg/providers/Microsoft.Storage/storageAccounts/mystg",
"type": "Microsoft.Storage/storageAccounts",
"region": "westeurope",
"source": "azure-cli",
"subscription": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenant": "f1e2d3c4-b5a6-9078-fedc-ba9876543210"
},
"properties": {
"resource_group": "data-rg",
"sku_tier": "Standard",
"sku_name": "Standard_LRS",
"kind": "StorageV2",
"access_tier": "Hot",
"https_only": true,
"min_tls_version": "TLS1_2",
"public_network_access": "Disabled",
"allow_blob_public_access": false
},
"extensions": {
"osiris.azure": {
"private_endpoint_connection_ids": [
"/subscriptions/a1b2c3d4/.../privateEndpoints/pe-mystg"
]
}
}
}
],
"connections": [
{
"source": "azure::/subscriptions/a1b2c3d4/.../subnets/default",
"target": "azure::/subscriptions/a1b2c3d4/.../virtualNetworks/hub-vnet",
"type": "contains",
"direction": "forward"
},
{
"source": "azure::/subscriptions/a1b2c3d4/.../privateEndpoints/pe-mystg",
"target": "azure::/subscriptions/a1b2c3d4/.../storageAccounts/mystg",
"type": "dependency.storage",
"direction": "forward"
}
],
"groups": [
{
"id": "azure::subscription::a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "logical.subscription",
"name": "my-nonprod-subscription",
"children": [
"azure::resourcegroup::network-rg",
"azure::resourcegroup::data-rg"
]
},
{
"id": "azure::region::a1b2c3d4-e5f6-7890-abcd-ef1234567890/westeurope",
"type": "container.region",
"name": "westeurope",
"members": [
"azure::/subscriptions/a1b2c3d4/.../virtualNetworks/hub-vnet",
"azure::/subscriptions/a1b2c3d4/.../storageAccounts/mystg"
]
}
]
}
}
The same run with the default --purpose documentation returns the identical resource graph, but with the properties and extensions maps stripped from each resource, connection and group, suiting it for high-level topology views and documentation.