Use deterministic, semantically correct identifiers for ARM template parameters and resource names—especially where idempotency and uniqueness are required.
Rules:
- Match the expected identifier shape
- If a parameter/property expects a resource ID path, provide the full ARM resource ID (e.g., “/subscriptions//resourcegroups//providers//")—don’t use generic placeholders like "GEN-UNIQUE".
- Use the correct placeholder token
- For credentials, use the password placeholder (e.g., “GEN-PASSWORD”), not “GEN-UNIQUE”.
- For length-limited names, use a bounded placeholder (e.g., “GEN-UNIQUE-15”) to avoid invalid identifiers.
- Make roleAssignment names idempotent
- For Microsoft.Authorization/roleAssignments, set the assignment resource name using guid() seeded with the exact principalId (full principal resourceId or objectId), roleId (full roleDefinition resourceId), and scopeId (full scope resourceId).
Example pattern:
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2020-04-01-preview",
"name": "[concat('Microsoft.Authorization/', guid(
variables('principalId'),
variables('roleId'),
variables('scopeId')
))]",
"properties": {
"principalId": "[variables('principalId')]",
"roleDefinitionId": "[variables('roleId')]",
"scope": "[variables('scopeId')]"
}
}
- Preserve required string formatting
- When building scope/resource strings via concat(), ensure the exact expected path separators (slashes) are present (e.g., “/virtualMachines/").