J’utilise depuis assez longtemps des Template ARM pour déployer les ressources Azure. De manière générale, l’utilisation de ces templates est plutôt simple mais certaines actions peuvent être un peu laborieuses.
Prenons un exemple concret. J’ai besoin de déployer une Function App Azure qui va devoir accéder à Azure App Configuration. Mon service Azure doit donc être autorisé via le via le système d’autorisations Azure RBAC.
Pour mon cas, je vais attribuer une identité système à ma Function App. L’assignation de l’identité peut se faire via le Template ARM de déploiement de la Function App.
"resources": [ { "type": "Microsoft.Web/sites", "apiVersion": "2016-08-01", "name": "[parameters('azureServiceName')]", "location": "[parameters('azureLocation')]", "tags": { }, "kind": "functionapp", "identity": { "type": "SystemAssigned" }, "properties": { "enabled": true,
Dans l’exemple ci-dessus, la propriété « identity » précise un type « SystemAssigned ». Azure se chargera de créer une identité pour mon service. Par ailleurs, Azure supprime cette identité de manière automatique au décommissionnement de cette ressource.
C’est assez simple d’assigner le rôle au moment du déploiement de Azure App Configuration. Mais dans mon cas, ce n’est pas envisageable car mon service Azure App Configuration existe depuis longtemps et je ne souhaite pas le redéployer. Par ailleurs, il est aussi possible de réaliser cette assignation de rôle dans le même Template ARM que celui de ma Function App Azure. Mais je souhaite réutiliser mon Template ARM pour d’autres services Azure. Donc je vais réaliser cette assignation de rôle dans un fichier ARM autonome que voici :
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "azureServiceName": { "type": "String", "defaultValue": "", "metadata": { "description": "Azure service name to grant access" } }, "appConfigurationName": { "type": "String", "defaultValue": "", "metadata": { "description": "App configuration name" } } }, "variables": { "appConfigurationDataReaderRoleId": "[concat(subscription().Id, '/providers/Microsoft.Authorization/roleDefinitions/516239f1-63e1-4d78-a4de-a74fb236a071')]", "azureServicePrincipalId": "[resourceId('Microsoft.Web/sites', parameters('azureServiceName'))]", "appConfigurationId": "[resourceId('Microsoft.AppConfiguration/configurationStores', parameters('appConfigurationName'))]" }, "resources": [ { "type": "Microsoft.AppConfiguration/configurationStores/providers/roleAssignments", "apiVersion": "2018-01-01-preview", "name": "[concat(parameters('appConfigurationName'), '/Microsoft.Authorization/', guid(uniqueString(parameters('azureServiceName'))))]", "properties": { "roleDefinitionId": "[variables('appConfigurationDataReaderRoleId')]", "principalId": "[reference(variables('azureServicePrincipalId'), '2018-11-01', 'Full').identity.principalId]", "scope": "[variables('appConfigurationId')]" } } ], "outputs": {} }
Sans le pousser à l’extrême, j’ai rendu cet ARM un paramétrable. Il y a donc deux paramètres qui sont le nom du service Azure (nom de la Function App) et le nom du service Azure App Configuration.
Pour attribuer un rôle à une identité, il est nécessaire d’aller chercher l’identifiant du rôle comme définit par Azure. Dans mon cas, je souhaite donner le rôle « App Configuration Data Reader ». C’est un rôle natif Azure et ces identifiants sont fournis par Microsoft. C’est pourquoi, ma variable « appCofnigurationDataReaderRoleId » se compose d’une chaîne de caractères qui se termine par un Guid.
Ensuite, j’ai besoin de l’identité du service Azure à laquelle je vais assigner le rôle (dans mon cas, ma Function App). Je récupère une référence à la ressource que je stock dans la variable « azureServicePrincipalId ».
Puis, j’ai besoin de l’identifiant de ma ressource sur laquelle je vais assigner l’autorisation (dans mon cas c’est Azure App Configuration). Cela est réalisé dans ma variable « appConfigurationId ».
Finalement, il y a 2 spécificités très importantes à noter: