Azure security collector
om scan azure requires AZURE_SUBSCRIPTION_ID. Authentication is
DefaultAzureCredential: Azure CLI (az login), environment variables
(AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET),
or a managed identity. The scan covers one subscription. Key Vault is not inventoried.
export AZURE_SUBSCRIPTION_ID=00000000-0000-0000-0000-000000000000
az login
./om scan azure
./om rules run AZURE_LOCATION (default eastus) is the location segment in every
node id, and the fallback region when a resource has none. A VM’s own location is stored on
the node’s region field, but it does not change the id. Two scans with different
AZURE_LOCATION values write different ids for the same VM.
Resources
| API | Graph |
|---|---|
| Resource groups, then virtual machines in each group | Workload. Properties: resource_id (ARM id) and public_ip (the address string, or empty). |
| NIC, public IP, network security group, and load balancer reads | Fills public_ip and decides REACHABLE. A public IP or a public load balancer is internet-facing when the NIC and subnet NSGs allow it. A VM with a public IP and no NSG stays reachable. The NSG is a Network node. |
| Storage accounts and blob containers | Datastore with resource_id, public_access, and sensitivity when an account tag names it. |
| Role assignments at the subscription and on each storage account | Identity named by principal id, with role_definition_id and admin_access. A VM’s system-assigned or user-assigned managed identity gets an ASSUMES edge from the workload. |
| Activity Log for the last 24 hours | Up to five audit_events on the identity and the resource the event names. See below. |
Node ids are azure:{subscription}:{AZURE_LOCATION}:{kind}:{name}.
kind is workload, datastore, identity, or network.
The identity resource is the principal id, so every assignment for that principal is one node.
admin_access is true when any unconditional assignment grants admin.
role_definition_id is one of those admin roles when one exists, otherwise an
unconditional assignment’s role id.
When storage is public
public_access is true only when both of these hold:
allowBlobPublicAccessis unset or true. An explicit false stops the check. The account is not public.- At least one blob container has public access
bloborcontainer.
An account that allows public blobs but has no container set to blob or container access is
stored with public_access: false. A missing resource group on the storage account
id fails the scan. A tag named sensitivity or data-class is stored
as sensitivity. sensitivity wins when both are set, and a blank
value is omitted. Logical SQL servers copy the same property from the server’s resource tags.
Admin identities
admin_access follows the role definition, not a substring of its GUID. Built-in
Owner, Contributor, and User Access Administrator are admin. Reader is not. A custom role is
admin when an action entry grants *, or grants
Microsoft.Authorization/roleAssignments/write, after that entry’s
NotActions. A role assignment with a condition does not set the flag.
Edges
ASSUMESfrom a virtual machine to each system-assigned or user-assigned managed identity. The workload is the source.CAN_ACCESSfrom that identity to a storage account when an unconditional role assignment covers the account and the role allows storage data. Coverage is the assignment scope: a subscription or resource group scope includes the accounts under it, and an account scope includes that account only.
Storage access is an action of *, Microsoft.Storage/storageAccounts/listKeys/action,
or a data action that reads blobs, files, queues, or tables. NotActions and
NotDataActions on the same permission entry remove the grant. Reader
(*/read) does not. A public storage account with no such assignment has no
CAN_ACCESS edge, and a private account does when the role covers it. An
internet-facing VM is not linked to storage unless its identity is.
Activity Log
After inventory is built, the scan lists administrative Activity Log events for the
subscription from the last 24 hours. The call uses the subscription time-range filter and
stops after four pages. A failed lookup omits audit_events and does not fail
the scan.
An event is kept when its operation is on a fixed management list (for example
Microsoft.Compute/virtualMachines/write,
Microsoft.Storage/storageAccounts/write,
Microsoft.Network/networkSecurityGroups/securityRules/write,
Microsoft.Authorization/roleAssignments/write) and its object id matches an
identity already in the batch. The resource has to sit on an exposed path: an
internet-reachable workload, a node that workload assumes or can access, a network that
workload affects, a public datastore, or an identity that can access a public datastore.
Resource ids are matched without regard to case. A security rule or firewall rule walks up
to the network or datastore node. A role assignment uses the assignment scope when the
assignment id is not itself a node. The same event is stored on the identity and the
resource, newest first, at most five per node.
GET /v1/graph/query and om paths run list those events in
audits when the resource node is on the returned path. The console prints the
same lines under the path. Entra ID sign-in logs and storage data-plane reads are not in
the Activity Log, so this slice does not collect them. GCP Admin Activity logs are collected
by om scan gcp.
Read access
The scan lists resource groups, virtual machines, storage accounts, blob containers, role
assignments at the subscription and on each storage account, and Activity Log events. It
reads network interfaces, public IP addresses, and role definitions that are not in the
built-in set above. A subscription Reader covers the ARM calls, including
Microsoft.Insights/eventtypes/values/read. Listing containers also needs
Microsoft.Storage/storageAccounts/blobServices/containers/read. The collector
does not call mutating APIs.
Copyright © 2026 OpenSourceOM. Licensed under Apache-2.0.