Skip to main content

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.

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. Create a custom role scoped to each resource group you want CloudEval to evaluate.
PermissionWhy CloudEval needs it
*/readRead subscription, resource group, resource, provider, deployment, and topology metadata inside the assigned scope.
Microsoft.Resources/deployments/exportTemplate/actionExport deployment templates used to build report inputs from live Azure resources.
Microsoft.Network/networkWatchers/topology/actionRead Network Watcher topology relationships used to enrich the live architecture graph.
Data actionsNone. 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.
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:
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.
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:
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

SymptomLikely causeFix
Connection test authenticates but no resource groups appearRole assignment has not propagated or is scoped to a different subscription/resource groupWait a few minutes, verify the assignment scope, then test again.
Sync sees the resource group but reports fail to buildThe custom role is missing Microsoft.Resources/deployments/exportTemplate/actionUpdate the role definition and rerun sync.
Graph sync works but network relationships are sparseThe custom role is missing Microsoft.Network/networkWatchers/topology/action or lacks assignment on the Network Watcher resource groupAdd the topology action and assign the role on NetworkWatcherRG or the subscription scope used for Network Watcher.
Sync unexpectedly includes too many resource groupsThe role is assigned at subscription scope or the CloudEval resource-group list is emptyAssign at resource-group scope and select target resource groups in CloudEval.
Key Vault secret values or storage blob contents are expected in reportsCloud sync uses management-plane metadata onlyDo not add data actions unless a separate workflow explicitly requires them.
Last modified on May 22, 2026