Connect a Microsoft Azure tenant
Create a read-only Azure service principal (Reader role) to inventory cloud resources and report posture findings and Defender for Cloud recommendations.
Access: organization administrator. Beta feature; the connector must be enabled on your platform.
Prerequisites
- Be an organization administrator in CISAPP.
- Be able to create an app registration in Microsoft Entra ID and assign a role on the target subscriptions (or on their management group): owner, User Access Administrator or equivalent rights.
- An Azure tenant can only be connected to one CISAPP organization; an organization can, however, connect several tenants.
- Public Azure cloud only: the China (21Vianet) and US Government clouds are not supported.
Minimum permissions
The Reader role is enough, on each subscription to analyze or on a management group. The Security Reader role is not needed: Reader already reads Microsoft Defender for Cloud recommendations.
Never grant Contributor, Owner, User Access Administrator, or any data-access role (for example Key Vault Secrets User, Storage Blob Data Reader): CISAPP does not need them. No Microsoft Graph permission is required either.
Create the access in Azure
CISAPP never uses your personal account: create a dedicated, read-only service principal with a client secret.
With the Azure CLI
Replace <subscriptionId> with the ID of the subscription to analyze.
az ad sp create-for-rbac --name cisapp-reader --role Reader --scopes /subscriptions/<subscriptionId> --years 1Several subscriptions: separate the scopes with spaces.
az ad sp create-for-rbac --name cisapp-reader --role Reader --scopes /subscriptions/<subscriptionId1> /subscriptions/<subscriptionId2>A management group (covers current and future subscriptions). Use its ID, not its display name:
az ad sp create-for-rbac --name cisapp-reader --role Reader --scopes /providers/Microsoft.Management/managementGroups/<managementGroupId>Run only one of these three commands (each creates the service principal). To extend the scope afterwards, use az role assignment create:
az role assignment create --assignee <appId> --role Reader --scope /subscriptions/<subscriptionId>The creation command prints a JSON document, only once; the secret cannot be read again afterwards:
| Field printed by Azure | CISAPP field |
|---|---|
tenant | Tenant |
appId | Client ID |
password | Client secret (this is the secret value) |
displayName | Informational only, not requested |
The secret is valid for one year (--years 1). To read its end date (to enter in CISAPP, see below; keep the first 10 characters, in YYYY-MM-DD format):
az ad app credential list --id <appId> --query "[].[displayName,keyId,endDateTime]" -o tsvThe command also prints each secret's keyId, needed to delete the old one during a rotation. The date entered in CISAPP must be in the future.
From the portal
- In the Microsoft Entra admin center, App registrations → New registration: single tenant, no redirect URI, and do not add any API permission (Microsoft Graph). Copy the Application (client) ID and the Directory (tenant) ID.
- Certificates & secrets → New client secret: choose an expiry, then immediately copy the Value (not the Secret ID).
- In the Azure portal, open Subscriptions (or Management groups), pick the scope, then Access control (IAM) → Add → Add role assignment.
- Choose the Reader role, then Members → Select members, search for the application name, select it and confirm with Review + assign. Repeat for each subscription.
A role assignment can take up to 10 minutes to propagate (sometimes longer for a management group). If CISAPP does not see any subscription yet, wait and try again.
Connect in CISAPP
- Open My company → Connectors, then Connect on the Azure card.
- Fill in:
- Tenant: the directory GUID (the
tenantfield of the command), or a verified domain of the tenant (for examplecontoso.onmicrosoft.com); - Client ID: the application ID (
appId); - Client secret: the secret value (not its ID);
- The secret expires on (optional, format
YYYY-MM-DD, must be a future date): lets you be alerted 30 days before the secret expires; - Subscriptions (optional): GUID identifiers, 100 at most. Empty: every subscription the principal can read (beyond 100 subscriptions, leave the field empty or assign the Reader role on a management group). The list can be edited later from the record.
- Tenant: the directory GUID (the
- Verify the credentials: CISAPP tests the credentials with Microsoft before saving anything.
- At the Confirm the Azure tenant step, check the displayed tenant ID, then Connect. An Azure tenant can only be connected to one CISAPP organization. The first synchronization starts.
If you close the panel before confirmation, the connection stays Pending: use Confirm the account from its record.
Subscriptions in the Disabled state are not collected (see "Subscription not collected" below). Connecting a tenant that is already attached to another CISAPP organization is refused ("This Azure tenant is already connected by another CISAPP organization.").
What CISAPP collects
CISAPP queries Azure Resource Graph and a few targeted Azure Resource Manager reads. It only reads configuration, never content:
- storage accounts (blob service configuration, not the objects);
- network security groups, virtual networks and subnets, public IP addresses;
- virtual machines and managed disks;
- SQL servers (Azure SQL), PostgreSQL and MySQL flexible servers, Cosmos DB accounts;
- Key Vault vaults (vault properties only), AKS clusters;
- App Service and Functions apps;
- subscriptions and their number of owners (Owner role assignments);
- Microsoft Defender for Cloud recommendations.
CISAPP changes nothing in your tenant. It never reads access keys, secrets, app settings, connection strings or kubeconfig files, and does not use the Key Vault data plane. The Reader role does not allow the actions that reveal these values anyway, and CISAPP never calls them. Resources appear in the Operational Safety → Cloud inventory menu entry and its Map view.
Posture findings
Findings appear in security findings with the Azure posture source. A rule only triggers when the information is certain: an unknown state (missing permission, absent data, resource not collected) neither creates nor resolves a finding.
| ID | Rule | Severity |
|---|---|---|
azure-storage-public-blob-access | Storage account allowing public blob access | High |
azure-storage-http-allowed | Storage account accepting unencrypted HTTP traffic | Medium |
azure-storage-weak-tls | Storage account accepting TLS 1.0 or 1.1 | Medium |
azure-storage-network-open | Storage account open to all networks | Medium |
azure-storage-blob-soft-delete-disabled | Storage account without blob soft delete | Low |
azure-nsg-remote-admin-exposed | Network security group exposing SSH or RDP to the Internet | High |
azure-nsg-database-ports-exposed | Network security group exposing a database port to the Internet | High |
azure-sql-public-network-access | SQL server reachable from the public network | Medium |
azure-sql-weak-tls | SQL server accepting TLS below 1.2 | Medium |
azure-sql-firewall-open-to-internet | SQL server with a firewall rule open to all IP addresses | Critical |
azure-dbflex-public-network-access | PostgreSQL/MySQL flexible server reachable from the public network | Medium |
azure-dbflex-tls-not-required | PostgreSQL/MySQL flexible server not enforcing TLS | High |
azure-keyvault-purge-protection-disabled | Key vault without purge protection | Medium |
azure-keyvault-public-network-open | Key vault open to all networks | Medium |
azure-aks-api-server-public | AKS cluster whose Kubernetes API is exposed without IP restriction | High |
azure-aks-rbac-disabled | AKS cluster without Kubernetes RBAC | High |
azure-webapp-https-only-disabled | Web app not enforcing HTTPS | Medium |
azure-webapp-weak-tls | Web app accepting TLS 1.0 or 1.1 | Medium |
azure-cosmos-public-network-open | Cosmos DB account publicly reachable without a filter | High |
azure-subscription-too-many-owners | Subscription with more than 3 owners (Owner) | Medium |
A SQL firewall is only flagged for the full range 0.0.0.0 to 255.255.255.255; the special "Azure services" rule (0.0.0.0 to 0.0.0.0) does not trigger a finding, and a server whose public network access is disabled is compliant.
For network security groups, rules are evaluated by priority: an unreadable rule placed before the deciding rule makes the state unknown, and a deny rule only closes a port for the whole group when its destination is any (*, 0.0.0.0/0, ::/0).
Subscription not collected
If a selected subscription is not collected (Disabled state, configured ID that is no longer listed, or not yet visible to Azure Resource Graph), CISAPP still creates new findings but automatically resolves no CISAPP rule finding during that synchronization, and deletes nothing of that subscription. Defender for Cloud recommendations of the collected subscriptions still resolve normally. The cause is reported by an English note shown under the last incomplete synchronization text: Posture findings are not auto-resolved while these subscriptions are not collected: <ids>. Remove them from subscriptionIds, or wait until Azure deletes them.
Azure deletes a Disabled subscription about 90 days later; it then leaves the listing. If you entered a subscription list, remove it from the list. If a Disabled subscription stays listed (default mode: all subscriptions), enter an explicit subscription list that does not contain it to resume automatic resolution.
Defender for Cloud recommendations
If Microsoft Defender for Cloud is enabled on a subscription, CISAPP also imports its recommendations in the Unhealthy state as findings, with the same Azure posture source. One finding is created per recommendation and per affected resource. Their titles, descriptions and severities come from Microsoft and are shown in English. The number of imported recommendations is capped per subscription (most severe first). When a recommendation is no longer unhealthy, its finding is resolved. If Defender for Cloud is not enabled or returns no data, nothing is imported or resolved. Nothing is resolved either when the cap is reached.
Secret expiry
The expiry date (The secret expires on) is handled separately from the rules: without a date, no warning is shown; less than 30 days before the declared deadline, a Credentials expiring soon badge appears on the record.
Replace the secret (rotation)
Create a new secret while keeping the old one:
bashaz ad app credential reset --id <appId> --append --years 1 --display-name cisapp-AAAANever forget
--append: without it, the command deletes all existing secrets and the connection fails immediately.On the connection record, Update credentials: in the Replace the Azure secret panel, paste the new secret value, fill in The secret expires on with its new date (it must be in the future: the field is prefilled with the old date, which you must replace, especially after an expiry), then Verify and replace. The old secret stays in use until the new one is validated.
The new secret must belong to the same Azure tenant; otherwise it is refused and the current secret is kept.
Then delete the old secret: find its
keyIdwithaz ad app credential list --id <appId> --query "[].[displayName,keyId,endDateTime]" -o tsv, thenaz ad app credential delete --id <appId> --key-id <keyId>.
Subscriptions can be changed from the record (Edit, Edit the scope panel), without re-entering the secret. Removing a subscription from the connection removes its resources from the inventory at the next sync. The expiry date (The secret expires on), however, is updated together with the secret, not from Edit.
An expired secret puts the connection in Error (Expired credentials): create a new secret and rotate it from the record.
Common issues
When connecting, Azure does not detail the cause in the interface: every refusal shows the message "Azure refused these credentials: invalid secret (paste the secret value, not its ID) or expired, application or tenant not found, access blocked by a conditional access policy, or Reader role missing...". At synchronization, the AADSTS codes below appear under Last synchronization incomplete (connection record) when an already saved secret is refused; their meaning there sometimes differs from the connection one.
| Message | What to do |
|---|---|
| The Azure connector is unavailable on this CISAPP instance (secret encryption not configured). Contact support. | The connector is not configured on your platform yet: contact support. |
| Azure refused these credentials... | Check, in order: the secret value (not its ID), its expiry date, the Tenant and the Client ID, that no conditional access policy blocks the application, and the Reader role assignment on each listed subscription (propagation: up to 10 minutes). |
| AADSTS7000215 / AADSTS70002 at synchronization (invalid client secret) | The saved secret was deleted or replaced on the Azure side (for example az ad app credential reset without --append): create a new secret and rotate it from the record. When connecting, the usual cause is the secret ID pasted instead of its value (password in the command output). |
| AADSTS7000222 (expired secret) | The client secret has expired: create a new one and rotate it from the record. |
| AADSTS700016 (application not found) | When connecting: the client ID or the tenant is wrong, check that the application belongs to this tenant. At synchronization: the application was deleted in Microsoft Entra ID; recreate it, then rotate from the record. |
| AADSTS90002 (tenant not found) | The tenant ID or domain is wrong: use the directory GUID. |
| This service principal belongs to another Azure tenant: the current secret is kept. | When rotating, the new secret must belong to the same tenant as the connection. |
Insufficient permissions status and last synchronization no readable subscription (English message) | The Reader role is not assigned to the application (or was removed), or the assignment has not propagated yet (up to 10 minutes): check the assignment, wait and try again. |
A subscription is reported as unreadable in the synchronization (English message, Subscription ... not readable) | The Reader role is missing on that subscription, or its ID is wrong in the list: the other subscriptions are analyzed normally. Fix the assignment or remove it from the list. |
| Subscription missing from the inventory, or findings that no longer resolve | A selected subscription is not collected (Disabled state, no longer listed, not yet visible to Azure Resource Graph): the synchronization reports it (note under the last incomplete synchronization) and suspends automatic resolution of CISAPP rule findings. See "Subscription not collected". |
| Recent resource missing | Azure Resource Graph is eventually consistent: a resource created just now appears at the next synchronization. |
| This Azure tenant is already connected by another CISAPP organization. | An Azure tenant has a single connection: disconnect it from the other CISAPP organization first. |
| Expired credentials or Credentials rejected | Create a new secret and rotate it from the record. |
Limits
- Public Azure cloud only (no China or US Government).
- An Azure tenant can only be connected to one CISAPP organization; an organization can connect several tenants.
- Synchronization follows the same schedule as the other cloud connectors: automatic every night, and on demand with Synchronize on the record.
- The secret expiry date is declarative: CISAPP cannot read it from Azure, and it must be in the future. Without a date, expiry is only detected when Microsoft refuses the secret.
- Selected subscriptions are limited to 100 (beyond that: empty field, or Reader role on a management group).
- When a subscription leaves the scope (removed from the list, or deleted by Azure), its resources are removed from the inventory and its CISAPP rule findings are resolved, but its already imported Defender for Cloud recommendations stay open until the connector is disconnected.
Disconnect
Disconnect deletes the connection and its cloud inventory, and marks its posture findings as resolved. Then delete the secret (or the app registration and its role assignments if they are no longer used) in Microsoft Entra ID and in the Azure portal.
Expected result
The connection is active, the cloud inventory is populated and Azure posture findings, along with Defender for Cloud recommendations, appear in CISAPP.
See also: Configure connectors.