Get started

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:

  • allowBlobPublicAccess is unset or true. An explicit false stops the check. The account is not public.
  • At least one blob container has public access blob or container.

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

  • ASSUMES from a virtual machine to each system-assigned or user-assigned managed identity. The workload is the source.
  • CAN_ACCESS from 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.