> For the complete documentation index, see [llms.txt](https://cortex-docs.paloaltonetworks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cortex-docs.paloaltonetworks.com/microsoft-azure-manual-onboarding/azure-manual-onboarding-guide/azure-manual-onboarding-subscription-scope/phase-3-create-security-capability-roles.md).

# Phase 3: Create security capability roles

## Phase 3: Create security capability roles

Create the roles in the following sections based on the security capabilities you enabled in the Azure onboarding wizard in Cortex during Phase 1. Since each capability is independent, you only need to apply the permissions for the specific features you selected.

### 3.1 DSPM - Data Security Posture Management (optional)

Module: DSPM

Execute the steps in this section if you enabled Data Security Posture Management in the Azure onboarding wizard in Cortex.

#### 3.1.1 Create the Cortex-DSPM custom role

```shell
cat > /tmp/Cortex-DSPM.json << EOF
{
  "Name": "<DSPM_ROLE_NAME>",
  "IsCustom": true,
  "Description": "DSPM subscription-scoped actions: PE approvals, SQL writes, storage/cosmos/cognitive reads.",
  "Actions": [
    "Microsoft.Storage/storageAccounts/PrivateEndpointConnectionsApproval/action",
    "Microsoft.Sql/servers/databases/write",
    "Microsoft.Sql/managedInstances/databases/write",
    "Microsoft.Storage/storageAccounts/read",
    "Microsoft.Storage/storageAccounts/blobServices/containers/read",
    "Microsoft.Storage/storageAccounts/fileServices/shares/read",
    "Microsoft.Search/searchServices/read",
    "Microsoft.Search/searchServices/indexes/read",
    "Microsoft.Search/searchServices/indexers/read",
    "Microsoft.Search/searchServices/dataSources/read",
    "Microsoft.Search/searchServices/listAdminKeys/action",
    "Microsoft.Search/searchServices/listQueryKeys/action",
    "Microsoft.Search/searchServices/PrivateEndpointConnectionsApproval/action",
    "Microsoft.DocumentDB/databaseAccounts/readOnlyKeys/action"
  ],
  "DataActions": [
    "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read",
    "Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read",
    "Microsoft.CognitiveServices/accounts/OpenAI/files/read",
    "Microsoft.CognitiveServices/accounts/OpenAI/fine-tunes/read",
    "Microsoft.CognitiveServices/accounts/OpenAI/models/read",
    "Microsoft.CognitiveServices/accounts/AIServices/connections/read",
    "Microsoft.CognitiveServices/accounts/AIServices/fine_tuning/read",
    "Microsoft.CognitiveServices/accounts/AIServices/agents/read",
    "Microsoft.Search/searchServices/indexes/documents/read"
  ],
  "NotActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION_ID>"
  ]
}
EOF

az role definition create --role-definition /tmp/Cortex-DSPM.json
```

Where:

* `<DSPM_ROLE_NAME>` is your chosen role name (e.g., Cortex-DSPM)
* `<SUBSCRIPTION_ID>` is your subscription ID

#### 3.1.2 Create the Cortex-DSPM-RG custom role

```shell
cat > /tmp/Cortex-DSPM-RG.json << EOF
{
  "Name": "<DSPM_RG_ROLE_NAME>",
  "IsCustom": true,
  "Description": "DSPM resource-group-scoped: VNET/subnet/NSG/RouteTable/SQL writes inside the shared resource group.",
  "Actions": [
    "*/read",
    "Microsoft.Network/routeTables/write",
    "Microsoft.Network/routeTables/join/action",
    "Microsoft.Network/routeTables/delete",
    "Microsoft.Network/virtualNetworks/delete",
    "Microsoft.Network/virtualNetworks/join/action",
    "Microsoft.Network/virtualNetworks/subnets/delete",
    "Microsoft.Network/virtualNetworks/subnets/join/action",
    "Microsoft.Network/virtualNetworks/subnets/write",
    "Microsoft.Network/virtualNetworks/write",
    "Microsoft.Network/networkSecurityGroups/securityRules/write",
    "Microsoft.Network/networkSecurityGroups/securityRules/delete",
    "Microsoft.Network/networkSecurityGroups/join/action",
    "Microsoft.Network/networkSecurityGroups/delete",
    "Microsoft.Network/networkSecurityGroups/write",
    "Microsoft.Sql/servers/databases/read",
    "Microsoft.Sql/servers/databases/write",
    "Microsoft.Sql/servers/databases/resume/action",
    "Microsoft.Sql/servers/databases/delete",
    "Microsoft.Sql/servers/delete",
    "Microsoft.Sql/servers/write",
    "Microsoft.Sql/servers/virtualNetworkRules/write",
    "Microsoft.Sql/servers/privateEndpointConnectionsApproval/action",
    "Microsoft.Sql/managedInstances/*"
  ],
  "DataActions": [],
  "NotActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RG_NAME>"
  ]
}
EOF

az role definition create --role-definition /tmp/Cortex-DSPM-RG.json
```

Where:

* `<DSPM_RG_ROLE_NAME>` is your chosen role name (e.g. Cortex-DSPM-RG)
* `<SUBSCRIPTION_ID>` is your subscription ID
* `<RG_NAME>` is your chosen resource group name

#### 3.1.3 Assign the DSPM roles to the Cortex service principal

```shell
# Subscription-scoped
az role assignment create \
    --role "<DSPM_ROLE_NAME>" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>"

az role assignment create \
    --role "Key Vault Crypto Service Encryption User" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>"

# Resource-group-scoped
az role assignment create \
    --role "<DSPM_RG_ROLE_NAME>" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RG_NAME>"
```

Where:

* `<DSPM_ROLE_NAME>` is your chosen role name (e.g., Cortex-DSPM)
* `<CORTEX_OBJECT_ID>` is the Cortex service principal object ID, obtained from the identifiers file
* `<SUBSCRIPTION_ID>` is your subscription ID
* `<DSPM_RG_ROLE_NAME>` is your chosen role name (e.g. Cortex-DSPM-RG)

### 3.2 ADS - Agentless Disk Scanning (optional)

Module: ADS

Execute the steps in this section if you enabled Agentless Disk Scanning in the Azure onboarding wizard in Cortex.

#### 3.2.1 Create the Azure Computer Gallery

```shell
az sig create \
    --resource-group "<RG_NAME>" \
    --gallery-name "<ADS_GALLERY_NAME>" \
    --location "<LOCATION>" \
    --tags managed_by=paloaltonetworks

# Store the gallery id, need to report back to cortex
export ADS_IMAGE_GALLERY_RESOURCE_ID=$(az sig show \
   --resource-group "${RG_NAME}" \
   --gallery-name "${ADS_GALLERY_NAME}" \
   --query id -o tsv)
echo "ADS_IMAGE_GALLERY_RESOURCE_ID=${ADS_IMAGE_GALLERY_RESOURCE_ID}"
```

Where:

* `<RG_NAME>` is your chosen resource group name (e.g. cortex-platform-rg)
* `<LOCATION>` is the Azure region where you want to create your resource group (e.g. eastus)
* `<ADS_GALLERGY_NAME>` is your chosen gallery name (e.g. cortex\_ads\_gallery)

This command outputs the ADS\_IMAGE\_GALLERY\_RESOURCE\_ID. Save this value; you will need to enter it into the Cortex onboarding wizard in Phase 5.

#### 3.2.2 Create the Cortex-ADS custom role

```shell
cat > /tmp/Cortex-ADS.json << EOF
{
  "Name": "<ADS_ROLE_NAME>",
  "IsCustom": true,
  "Description": "ADS subscription-scoped: snapshots, gallery image versions, disks, VM tagging.",
  "Actions": [
    "Microsoft.Compute/virtualMachines/read",
    "Microsoft.Compute/snapshots/read",
    "Microsoft.compute/snapshots/write",
    "Microsoft.Compute/disks/write",
    "Microsoft.Compute/disks/read",
    "Microsoft.Compute/disks/delete",
    "Microsoft.Compute/galleries/images/read",
    "Microsoft.compute/galleries/images/versions/read",
    "Microsoft.Compute/disks/beginGetAccess/action"

  ],
  "DataActions": [],
  "NotActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION_ID>"
  ]
}
EOF

az role definition create --role-definition /tmp/Cortex-ADS.json
```

Where:

* `<ADS_ROLE_NAME>` is your chosen role name (e.g. Cortex-ADS)
* `<SUBSCRIPTION_ID>` is your subscription ID

#### 3.2.3 Create the Cortex-ADS-RG custom role

```shell
cat > /tmp/Cortex-ADS-RG.json << EOF
{
  "Name": "<ADS_RG_ROLE_NAME>",
  "IsCustom": true,
  "Description": "ADS resource-group-scoped: snapshot operations and gallery write inside the shared resource group.",
  "Actions": [
    "Microsoft.Compute/snapshots/write",
    "Microsoft.Compute/snapshots/delete",
    "Microsoft.Compute/galleries/images/write",
    "Microsoft.Compute/galleries/images/delete",
    "Microsoft.Compute/galleries/images/versions/read",
    "Microsoft.Compute/galleries/images/versions/write",
    "Microsoft.Compute/galleries/images/versions/delete"
  ],
  "DataActions": [],
  "NotActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RG_NAME>"
  ]
}
EOF

az role definition create --role-definition /tmp/Cortex-ADS-RG.json
```

Where:

* `<ADS_RG_ROLE_NAME>` is your chosen role name (e.g. Cortex-ADS-RG)
* `<SUBSCRIPTION_ID>` is your subscription ID

#### 3.2.4 Assign ADS custom roles to the Cortex service principal

```shell
az role assignment create \
    --role "<ADS_ROLE_NAME>" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>"

az role assignment create \
    --role "<ADS_RG_ROLE_NAME>" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RG_NAME>"
```

Where:

* `<ADS_ROLE_NAME>` is your chosen role name (e.g. Cortex-ADS)
* `<CORTEX_OBJECT_ID>` is the Cortex service principal object ID, obtained from the identifiers file
* `<SUBSCRIPTION_ID>` is your subscription ID
* `<ADS_RG_ROLE_NAME>` is your chosen role name (e.g. Cortex-ADS-RG)
* `<RG_NAME>` is your chosen resource group name (e.g. cortex-platform-rg)

### 3.3 Registry Scanning (optional)

Module: REGISTRY

Execute the steps in this section if you enabled Registry Scanning in the Azure onboarding wizard in Cortex.

#### 3.3.1 Create the Cortex-Registry custom role

```shell
cat > /tmp/Cortex-Registry.json << EOF
{
  "Name": "<REGISTRY_ROLE_NAME>",
  "IsCustom": true,
  "Description": "Registry scanning (public + private endpoints).",
  "Actions": [
    "Microsoft.ContainerRegistry/registries/pull/read",
    "Microsoft.ContainerRegistry/registries/read",
    "Microsoft.ContainerRegistry/registries/PrivateEndpointConnectionsApproval/action"
  ],
  "DataActions": [],
  "NotActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION_ID>"
  ]
}
EOF

az role definition create --role-definition /tmp/Cortex-Registry.json
```

Where:

* `<REGISTRY_ROLE_NAME>` is your chosen role name (e.g. Cortex-Registry)
* `<SUBSCRIPTION_ID>` is your subscription ID

#### 3.3.2 Assign the Cortex-Registry custom role to the Cortex service principal

```shell
az role assignment create \
    --role "<REGISTRY_ROLE_NAME>" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>"
```

Where:

* `<REGISTRY_ROLE_NAME>` is your chosen role name (e.g. Cortex-Registry)
* `<CORTEX_OBJECT_ID>` is the Cortex service principal object ID, obtained from the identifiers file
* `<SUBSCRIPTION_ID>` is your subscription ID

### 3.4 Automation (optional)

Module: AUTOMATION

Execute the steps in this section if you enabled Automation in the Azure onboarding wizard in Cortex.

#### 3.4.1 Create the Cortex-Automation custom role

```shell
cat > /tmp/Cortex-Automation.json << EOF
{
  "Name": "<AUTOMATION_ROLE_NAME>",
  "IsCustom": true,
  "Description": "Automation actions including Storage blob data reads/writes.",
  "Actions": [
    "Microsoft.Network/networkSecurityGroups/read",
    "Microsoft.Network/networkSecurityGroups/securityRules/read",
    "Microsoft.Network/networkSecurityGroups/securityRules/write",
    "Microsoft.Network/networkSecurityGroups/securityRules/delete",
    "Microsoft.Network/networkInterfaces/read",
    "Microsoft.Network/publicIPAddresses/read",
    "Microsoft.Storage/storageAccounts/read",
    "Microsoft.Storage/storageAccounts/write",
    "Microsoft.Storage/storageAccounts/blobServices/read",
    "Microsoft.Storage/storageAccounts/blobServices/write",
    "Microsoft.Storage/storageAccounts/blobServices/containers/delete",
    "Microsoft.Storage/storageAccounts/blobServices/containers/write",
    "Microsoft.Storage/storageAccounts/blobServices/containers/read",
    "Microsoft.Storage/storageAccounts/blobServices/containers/setAcl/action",
    "Microsoft.Authorization/policyAssignments/read",
    "Microsoft.Authorization/policyAssignments/write",
    "Microsoft.Web/sites/config/read",
    "Microsoft.Web/sites/config/write",
    "Microsoft.Web/sites/read",
    "Microsoft.Web/sites/write",
    "Microsoft.DBforMySQL/flexibleServers/configurations/read",
    "Microsoft.DBforMySQL/flexibleServers/configurations/write",
    "Microsoft.Insights/logprofiles/read",
    "Microsoft.Insights/logprofiles/write",
    "Microsoft.Compute/disks/read",
    "Microsoft.Compute/disks/write",
    "Microsoft.Compute/virtualMachines/start/action",
    "Microsoft.Compute/virtualMachines/powerOff/action",
    "Microsoft.Compute/virtualMachines/read",
    "Microsoft.ContainerRegistry/registries/read",
    "Microsoft.ContainerRegistry/registries/write",
    "Microsoft.KeyVault/vaults/read",
    "Microsoft.KeyVault/vaults/write",
    "Microsoft.Sql/servers/databases/securityAlertPolicies/read",
    "Microsoft.Sql/servers/databases/securityAlertPolicies/write",
    "Microsoft.DocumentDB/databaseAccounts/read",
    "Microsoft.DocumentDB/databaseAccounts/write",
    "Microsoft.Sql/servers/databases/transparentDataEncryption/read",
    "Microsoft.Sql/servers/databases/transparentDataEncryption/write",
    "Microsoft.Resources/subscriptions/read",
    "Microsoft.Resources/subscriptions/resourceGroups/read",
    "Microsoft.Consumption/usageDetails/read",
    "Microsoft.Consumption/budgets/read",
    "Microsoft.CostManagement/forecast/read",
    "Microsoft.Network/networkSecurityGroups/write",
    "Microsoft.Network/networkInterfaces/write",
    "Microsoft.Network/virtualNetworks/subnets/join/action",
    "Microsoft.Network/publicIPAddresses/join/action",
    "Microsoft.Network/networkSecurityGroups/join/action",
    "Microsoft.Network/loadBalancers/backendAddressPools/join/action"
  ],
  "DataActions": [
    "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read",
    "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/read",
    "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags/write",
    "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write"
  ],
  "NotActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION_ID>"
  ]
}
EOF

az role definition create --role-definition /tmp/Cortex-Automation.json
```

Where:

* `<AUTOMATION_ROLE_NAME>` is your chosen role name (e.g., Cortext-Automation)
* `<SUBSCRIPTION_ID>` is your subscription ID

#### 3.4.2 Assign the Cortex-Automation custom role to the Cortex service principal

```shell
az role assignment create \
    --role "<AUTOMATION_ROLE_NAME>" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>"
```

Where:

* `<AUTOMATION_ROLE_NAME>` is your chosen role name (e.g., Cortext-Automation)
* `<CORTEX_OBJECT_ID>` is the Cortex service principal object ID, obtained from the identifiers file
* `<SUBSCRIPTION_ID>` is your subscription ID

### 3.5 Serverless Scanning (optional)

Module: SERVERLESS

If you enabled Serverless Scanning in the Azure onboarding wizard in Cortex, no additional permission configuration is required. The necessary permissions were already applied via the Cortex-Platform-Base role created in Phase 2.

### 3.6 Kubernetes Security (optional)

Module: KUBERNETES

Execute the steps in this section if you enabled Kubernetes Security in the Azure onboarding wizard in Cortex.

#### 3.6.1 Create the Cortex-KSPM custom role

```shell
cat > /tmp/Cortex-KSPM.json << EOF
{
  "Name": "<KSPM_ROLE_NAME>",
  "IsCustom": true,
  "Description": "KSPM Agentless K8s Reader: lists AKS cluster-user credentials and reads Kubernetes data-plane resources via Azure RBAC for Kubernetes Authorization.",
  "Actions": [
    "Microsoft.ContainerService/managedClusters/listClusterUserCredential/action"
  ],
  "DataActions": [
    "Microsoft.ContainerService/managedClusters/namespaces/read",
    "Microsoft.ContainerService/managedClusters/pods/read",
    "Microsoft.ContainerService/managedClusters/services/read",
    "Microsoft.ContainerService/managedClusters/endpoints/read",
    "Microsoft.ContainerService/managedClusters/configmaps/read",
    "Microsoft.ContainerService/managedClusters/serviceaccounts/read",
    "Microsoft.ContainerService/managedClusters/nodes/read",
    "Microsoft.ContainerService/managedClusters/secrets/read",
    "Microsoft.ContainerService/managedClusters/apps/deployments/read",
    "Microsoft.ContainerService/managedClusters/apps/replicasets/read",
    "Microsoft.ContainerService/managedClusters/apps/statefulsets/read",
    "Microsoft.ContainerService/managedClusters/apps/daemonsets/read",
    "Microsoft.ContainerService/managedClusters/batch/jobs/read",
    "Microsoft.ContainerService/managedClusters/batch/cronjobs/read",
    "Microsoft.ContainerService/managedClusters/networking.k8s.io/ingresses/read",
    "Microsoft.ContainerService/managedClusters/networking.k8s.io/networkpolicies/read",
    "Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/roles/read",
    "Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterroles/read",
    "Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/rolebindings/read",
    "Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterrolebindings/read",
    "Microsoft.ContainerService/managedClusters/discovery.k8s.io/endpointslices/read"
  ],
  "NotActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/<SUBSCRIPTION_ID>"
  ]
}
EOF
az role definition create --role-definition /tmp/Cortex-KSPM.json
```

Where:

* `<KSPM_ROLE_NAME>` is your chosen role name (e.g., Cortex-KSPM).
* `<SUBSCRIPTION_ID>` is your subscription ID

#### 3.6.2 Assign the Cortex-KSPM custom role to the Cortex service principal

```shell
az role assignment create \
    --role "<KSPM_ROLE_NAME>" \
    --assignee-object-id "<CORTEX_OBJECT_ID>" --assignee-principal-type ServicePrincipal \
    --scope "/subscriptions/<SUBSCRIPTION_ID>"
```

Where:

* `<KSPM_ROLE_NAME>` is your chosen role name (e.g., Cortex-KSPM).
* `<CORTEX_OBJECT_ID>` is the Cortex service principal object ID, obtained from the identifiers file
* `<SUBSCRIPTION_ID>` is your subscription ID


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://cortex-docs.paloaltonetworks.com/microsoft-azure-manual-onboarding/azure-manual-onboarding-guide/azure-manual-onboarding-subscription-scope/phase-3-create-security-capability-roles.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
