Parascope Docs

Azure Collector

Discover and monitor Azure infrastructure

Early Access — The Azure collector is in Early Access. Functionality is complete but may receive updates based on feedback.

The Azure collector discovers and continuously monitors Azure infrastructure across compute, networking, storage, database, and serverless services. It connects to one or more Azure subscriptions via Entra ID Service Principals and periodically scans all regions, publishing configuration items and relationships for processing.

What Gets Discovered

The collector discovers 16 CI types across 6 Azure services:

CI TypeAzure ServiceDescription
azure.subscriptionSubscriptionAzure subscription (scope container)
azure.resource_groupResource ManagerResource group (organizational container)
azure.vmComputeVirtual machine
azure.imageComputeCustom VM image
azure.vmssComputeVM Scale Set (definition)
azure.vnetNetworkVirtual network
azure.subnetNetworkVNet subnet
azure.nsgNetworkNetwork Security Group
azure.nicNetworkNetwork interface
azure.load_balancerNetworkAzure Load Balancer
azure.storage_accountStorageStorage account
azure.managed_diskComputeManaged disk
azure.snapshotComputeDisk snapshot
azure.sql_serverSQL DatabaseLogical SQL server
azure.sql_databaseSQL DatabaseAzure SQL Database
azure.function_appApp ServiceAzure Functions app

Each resource's ARM name property is used as the CI name. Unlike AWS where many resources lack a native name and rely on Name tags, Azure resources always have an explicit name in the ARM response.

Prerequisites

  • An Azure subscription
  • An Entra ID (Azure AD) Service Principal with a client secret
  • The Reader role or a custom role with the permissions listed below

The collector only makes read-only API calls. No write permissions are needed or used.

Create a Service Principal

az ad sp create-for-rbac --name "parascope-collector" --skip-assignment

Save the output. The values map to Parascope configuration fields:

Output FieldParascope Field
appIdClient ID
passwordClient Secret
tenantTenant ID

RBAC Permissions

The collector needs read access to the resource types it collects. There are two approaches.

Option A: Built-in Reader Role

The simplest setup. The built-in Reader role at subscription scope grants read access to all resource metadata:

az role assignment create \
  --assignee <client-id> \
  --role "Reader" \
  --scope "/subscriptions/<subscription-id>"

This is the recommended approach for most deployments. Reader provides more permissions than the collector needs, but it is read-only and well-understood.

Option B: Custom Least-Privilege Role

If your security policy requires granting only the exact permissions needed, create a custom role:

{
  "Name": "Parascope Collector",
  "Description": "Read-only access to infrastructure metadata for Parascope CMDB",
  "Actions": [
    "Microsoft.Compute/virtualMachines/read",
    "Microsoft.Compute/virtualMachineScaleSets/read",
    "Microsoft.Compute/images/read",
    "Microsoft.Compute/disks/read",
    "Microsoft.Compute/snapshots/read",
    "Microsoft.Network/virtualNetworks/read",
    "Microsoft.Network/networkSecurityGroups/read",
    "Microsoft.Network/networkInterfaces/read",
    "Microsoft.Network/loadBalancers/read",
    "Microsoft.Storage/storageAccounts/read",
    "Microsoft.Sql/servers/read",
    "Microsoft.Sql/servers/databases/read",
    "Microsoft.Web/sites/read",
    "Microsoft.Resources/subscriptions/read",
    "Microsoft.Resources/subscriptions/resourceGroups/read"
  ],
  "NotActions": [],
  "AssignableScopes": [
    "/subscriptions/<subscription-id>"
  ]
}

Save the JSON to a file and create the role:

az role definition create --role-definition @parascope-role.json

az role assignment create \
  --assignee <client-id> \
  --role "Parascope Collector" \
  --scope "/subscriptions/<subscription-id>"

The collector handles AuthorizationFailed errors gracefully per resource type. If a permission is missing, that resource type is skipped with a warning while collection continues for other types.

Configuration

Each Azure subscription is configured as a separate Parascope source. Configure credentials and region filters for each source:

FieldRequiredDescription
Tenant IDYesEntra ID (Azure AD) tenant ID
Client IDYesService Principal application (client) ID
Client SecretYesService Principal client secret
Subscription IDYesTarget Azure subscription ID
Region AllowlistNoCollect only these regions (comma-separated, e.g. westeurope,northeurope). Default: all regions
Region DenylistNoSkip these regions. Ignored if Region Allowlist is set

Unlike AWS where each region requires separate API calls, Azure Resource Manager APIs are subscription-scoped and return resources from all regions in a single response. Region filtering is applied as a post-fetch filter on the location field. It reduces ingested data but does not reduce API calls.

Multi-Subscription Setup

To monitor multiple Azure subscriptions, add each as a separate source in the collector configuration. Each source uses its own Service Principal credentials and has independent health tracking and circuit breaking. A misconfigured or unreachable subscription does not block collection from other healthy subscriptions.

A single Service Principal can be granted access to multiple subscriptions if they share the same Entra ID tenant. Create one source per subscription, using the same Client ID and Client Secret but different Subscription IDs.

Collected Resources

Subscriptions

The subscription CI serves as the containment root for all resources in that subscription. It captures the subscription ID, display name, and state (Enabled, Disabled, Warned).

Resource Groups

Resource groups provide the organizational layer between subscriptions and resources. Every Azure resource belongs to exactly one resource group. The collector captures the group name, location, provisioning state, and tags.

Virtual Machines

Configuration tracked in change history includes VM size, power state, OS type, OS disk configuration, data disk attachments, network interface references, availability zone, image reference, provisioning state, and tags.

Deallocated VMs are collected as active CIs. Azure distinguishes stopped (OS shutdown, still billed for compute) from deallocated (no compute billing). Both states represent resources that still exist and have configuration worth tracking.

Power state is obtained via the instance view expansion on the list_all() API call. For subscriptions with 500+ VMs, this expansion adds significant response latency.

Images

Only custom (user-created) images in the subscription are collected. Marketplace images, shared image gallery images, and community images are separate Azure APIs and are excluded. Configuration includes OS type, OS state (Generalized or Specialized), and source VM reference.

VM Scale Sets

VMSS resources are collected as definitions only. The collector captures the SKU (VM size), instance capacity, and upgrade policy mode (Manual, Rolling, Automatic). Individual VMSS instance VMs are not enumerated in this version, as they require a separate API call per scale set.

Virtual Networks

VNet configuration includes the address space (CIDR blocks), provisioning state, and tags. VNets contain their subnets via contains relationships.

Subnets

Each subnet captures its address prefix, parent VNet reference, and associated NSG reference. Subnets are linked to their parent VNet and serve as the target for NIC runs_on relationships.

Network Security Groups

Full inbound and outbound rule details are captured, including rule name, priority, protocol, direction, source and destination address prefixes, source and destination port ranges, and access action (Allow or Deny). Because security group rules define blast radius and compliance posture, changes to rules are tracked in change history.

Network Interfaces

NICs are first-class CIs in Azure, unlike AWS where network interfaces are implicit on EC2 instances. Each NIC captures its IP configurations, associated NSG, associated VM, MAC address, and tags. NICs carry the relationships between VMs and subnets (via has_attached and runs_on) and between VMs and NSGs (via uses).

Load Balancers

Configuration includes SKU (Basic, Standard, Gateway), frontend IP configurations, backend address pools, health probes, and load balancing rules.

Storage Accounts

Each storage account captures the SKU, kind (StorageV2, BlobStorage, etc.), access tier (Hot, Cool, Premium), provisioning state, primary service endpoints, and encryption configuration.

Managed Disks

Disk configuration includes SKU (Standard_LRS, Premium_LRS, etc.), size in GB, OS type (if OS disk), disk state (Attached, Unattached, Reserved), and provisioning state.

Snapshots

Each snapshot captures its source managed disk reference, disk size in GB, and provisioning state. Snapshots link back to their source disk via snapshot_of relationships.

SQL Servers

The logical SQL server CI captures the server name, FQDN, SQL version, state, and administrator login. SQL servers are containers for SQL databases, linked via contains relationships.

SQL Databases

Database configuration includes the SKU name (e.g. S0, P1, GP_S_Gen5_1), maximum size in bytes, collation, status, and parent server reference. The master system database is excluded.

Function Apps

Configuration includes the app kind, state (Running, Stopped), default hostname, runtime stack (python, node, dotnet, java), and OS type (Linux, Windows). Function apps are filtered by the kind field containing "functionapp" to exclude regular web apps.

Relationships

The collector maps the following relationships between Azure resources:

SourceRelationshipTargetDerivation
azure.subscriptioncontainsazure.resource_groupRG's subscription
azure.resource_groupcontainsazure.vmParsed from ARM resource ID
azure.resource_groupcontainsazure.vnetParsed from ARM resource ID
azure.resource_groupcontainsazure.nsgParsed from ARM resource ID
azure.resource_groupcontainsazure.storage_accountParsed from ARM resource ID
azure.resource_groupcontainsazure.load_balancerParsed from ARM resource ID
azure.resource_groupcontainsazure.sql_serverParsed from ARM resource ID
azure.resource_groupcontainsazure.function_appParsed from ARM resource ID
azure.vnetcontainsazure.subnetParsed from subnet resource ID
azure.vmhas_attachedazure.managed_diskVM's data disk references
azure.vmhas_attachedazure.nicVM's network interface references
azure.vmcreated_fromazure.imageVM's image reference (custom images only)
azure.vmssusesazure.nsgVMSS network profile NSG reference
azure.nicruns_onazure.subnetNIC's IP configuration subnet
azure.nicusesazure.nsgNIC-level NSG reference
azure.snapshotsnapshot_ofazure.managed_diskSnapshot's source disk ID
azure.sql_servercontainsazure.sql_databaseDatabase's parent server
azure.load_balancerruns_onazure.subnetFrontend IP configuration subnet
azure.function_appruns_onazure.resource_groupFunction's resource group

This gives you a navigable resource topology: subscription > resource group > resources, plus VNet topology (VNet > subnet > NIC > VM), NSG coverage, disk attachment chains, and SQL server hierarchy.

Why VMs connect to subnets through NICs: In Azure, network interfaces are independent resources with their own subnet bindings and NSG associations. The path from a VM to its subnet is vm > has_attached > nic > runs_on > subnet. There is no direct VM-to-subnet shortcut because the NIC carries the actual network configuration.

Cross-source correlation also links Azure resources to other Parascope sources:

  • azure.vm to kubernetes.node -- matched by private IP or hostname, linking Azure VMs to AKS backing nodes
  • azure.sql_database to postgresql.server -- matched by SQL server FQDN endpoint, when the PostgreSQL collector monitors the same database

Troubleshooting

AuthenticationFailed

The Service Principal credentials are invalid. Verify that the Client ID, Client Secret, and Tenant ID are correct. Client secrets expire; check the expiration date in Entra ID under App registrations.

AuthorizationFailed

The Service Principal is missing permissions for the resource type in the error message. Verify the role assignment scope matches the target subscription. If using the custom role, check that the required action is included.

TooManyRequests (429)

Azure is throttling API requests. The collector retries automatically with exponential backoff via the Azure SDK's built-in retry policy. You do not need to take action. If collection is frequently slow due to throttling, consider increasing the collection interval.

SubscriptionNotFound

The Subscription ID in the source configuration is incorrect, or the Service Principal does not have access to that subscription. Verify the subscription ID and check that the role assignment exists.

No resources collected for a region

Region allowlist and denylist filter resources by the location field after fetching. Verify the region names match Azure's location identifiers (e.g., westeurope, eastus, northeurope) not display names (e.g., "West Europe").

Parascope constructs deep links to the Azure Portal for every collected resource using the ARM resource ID:

https://portal.azure.com/#@/resource{resourceId}

Click "Open in Azure Portal" on any Azure CI detail page to navigate directly to that resource in the portal.