> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloudeval.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Azure Cloud sync permissions

> Least-privilege Azure RBAC setup for CloudEval Cloud sync connections.

CloudEval Cloud sync reads Azure Resource Manager metadata, exports resource-group templates for analysis, and stores a project snapshot. It does **not** need `Contributor` for normal sync.

## Recommended role

Create a custom role scoped to each resource group you want CloudEval to evaluate.

| Permission                                              | Why CloudEval needs it                                                                                               |
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `*/read`                                                | Read subscription, resource group, resource, provider, deployment, and topology metadata inside the assigned scope.  |
| `Microsoft.Resources/deployments/exportTemplate/action` | Export deployment templates used to build report inputs from live Azure resources.                                   |
| `Microsoft.Network/networkWatchers/topology/action`     | Read Network Watcher topology relationships used to enrich the live architecture graph.                              |
| Data actions                                            | None. CloudEval Cloud sync does not need data-plane access such as storage blob contents or Key Vault secret values. |

## Create the service principal and role

Run this from an Azure CLI session that can create app registrations and role definitions in the target subscription. The command also uses `jq` to extract the generated service principal fields. Replace `RG` with the resource group CloudEval should evaluate.

```bash theme={null}
SUB_ID="$(az account show --query id -o tsv)"
RG="<target-resource-group>"
NW_RG="NetworkWatcherRG"
SP_NAME="cloudeval-live-sync"
ROLE_NAME="CloudEval Live Sync Reader"
SCOPE="/subscriptions/$SUB_ID/resourceGroups/$RG"
NW_SCOPE="/subscriptions/$SUB_ID/resourceGroups/$NW_RG"

SP_JSON="$(
az ad sp create-for-rbac \
  --name "$SP_NAME" \
  --skip-assignment \
  -o json
)"

APP_ID="$(echo "$SP_JSON" | jq -r .appId)"
CLIENT_SECRET="$(echo "$SP_JSON" | jq -r .password)"
TENANT_ID="$(echo "$SP_JSON" | jq -r .tenant)"

cat > cloudeval-live-sync-reader.json <<EOF
{
  "Name": "$ROLE_NAME",
  "IsCustom": true,
  "Description": "Read Azure resources and export deployment templates for CloudEval Cloud sync.",
  "Actions": [
    "*/read",
    "Microsoft.Resources/deployments/exportTemplate/action",
    "Microsoft.Network/networkWatchers/topology/action"
  ],
  "NotActions": [],
  "DataActions": [],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/$SUB_ID"
  ]
}
EOF

az role definition create --role-definition cloudeval-live-sync-reader.json

az role assignment create \
  --assignee "$APP_ID" \
  --role "$ROLE_NAME" \
  --scope "$SCOPE"

if az group show --name "$NW_RG" >/dev/null 2>&1; then
  az role assignment create \
    --assignee "$APP_ID" \
    --role "$ROLE_NAME" \
    --scope "$NW_SCOPE"
else
  echo "Skipped Network Watcher topology assignment: resource group '$NW_RG' was not found."
fi

echo "Client ID: $APP_ID"
echo "Client Secret: $CLIENT_SECRET"
echo "Tenant ID: $TENANT_ID"
echo "Subscription ID: $SUB_ID"
echo "Resource Group Scope: $RG"
```

Use the printed client ID, client secret, tenant ID, subscription ID, and
resource group in the CloudEval Cloud sync connection form or CLI:

```bash theme={null}
cloudeval projects create \
  --cloud-sync \
  --azure-tenant-id "$TENANT_ID" \
  --azure-client-id "$APP_ID" \
  --azure-client-secret "$CLIENT_SECRET" \
  --azure-subscription-id "$SUB_ID" \
  --resource-group "$RG" \
  --name "Cloud sync $RG" \
  --format json \
  --output ./cloudeval-project.json
```

If the role definition already exists and you are changing assignable scopes,
use `az role definition update` with the same JSON.

For multiple resource groups, repeat the target resource-group `az role assignment create` step for each group and select the same groups in the CloudEval connection form.

The `NetworkWatcherRG` assignment is needed only when CloudEval should enrich the graph with Network Watcher topology and the Network Watcher resource lives outside the target resource group. If your tenant uses a different Network Watcher resource group, replace `NW_RG`. If that assignment is omitted, Cloud sync can still read resources and export templates, but Network Watcher relationship enrichment may be incomplete.

## When subscription scope is acceptable

Resource-group scope is the default recommendation. Use subscription scope only when CloudEval should discover and sync every accessible resource group in the subscription.

```bash theme={null}
az role assignment create \
  --assignee "$APP_ID" \
  --role "CloudEval Live Sync Reader" \
  --scope "/subscriptions/$SUB_ID"
```

## Do not use Contributor for production sync

This smoke-test command is intentionally broader than CloudEval needs:

```bash theme={null}
az ad sp create-for-rbac \
  --name cloudeval-sync-smoke \
  --role Contributor \
  --scopes "/subscriptions/$SUB_ID/resourceGroups/$RG"
```

Use it only for disposable validation in a throwaway resource group. Replace it with the custom role above before connecting real environments.

## Troubleshooting

| Symptom                                                                  | Likely cause                                                                                                                             | Fix                                                                                                                   |
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Connection test authenticates but no resource groups appear              | Role assignment has not propagated or is scoped to a different subscription/resource group                                               | Wait a few minutes, verify the assignment scope, then test again.                                                     |
| Sync sees the resource group but reports fail to build                   | The custom role is missing `Microsoft.Resources/deployments/exportTemplate/action`                                                       | Update the role definition and rerun sync.                                                                            |
| Graph sync works but network relationships are sparse                    | The custom role is missing `Microsoft.Network/networkWatchers/topology/action` or lacks assignment on the Network Watcher resource group | Add the topology action and assign the role on `NetworkWatcherRG` or the subscription scope used for Network Watcher. |
| Sync unexpectedly includes too many resource groups                      | The role is assigned at subscription scope or the CloudEval resource-group list is empty                                                 | Assign at resource-group scope and select target resource groups in CloudEval.                                        |
| Key Vault secret values or storage blob contents are expected in reports | Cloud sync uses management-plane metadata only                                                                                           | Do not add data actions unless a separate workflow explicitly requires them.                                          |
