Démarrage rapide : utiliser Bicep pour créer et publier une définition d’application managée Azure

Ce démarrage rapide vous décrit comment utiliser Bicep pour créer et publier une définition d’application managée Azure dans votre catalogue de services. Les définitions contenues dans votre catalogue de services sont à la disposition des membres de votre organisation.

Pour créer et publier une définition d’application managée dans votre catalogue de services, effectuez les tâches suivantes :

  • Utilisez Bicep pour développer votre modèle et le convertir en modèle Azure Resource Manager (modèle ARM). Le modèle définit les ressources Azure déployées par l’application managée.
  • Convertissez Bicep en JSON en tirant parti de la commande Bicep build. Une fois le fichier converti en JSON, nous vous recommandons de vérifier l’exactitude du code.
  • Définir les éléments d’interface utilisateur du portail lors du déploiement de l’application managée.
  • Créez un package .zip qui contient les fichiers JSON nécessaires. Le fichier de package .zip a une limite de 120 Mo pour la définition d’application managée d’un catalogue de services.
  • Publiez la définition d’application managée pour qu’elle soit disponible dans votre catalogue de services.

Si votre définition d’application managée est supérieure à 120 Mo ou si vous souhaitez utiliser votre propre compte de stockage pour les raisons de conformité de votre organisation, accédez à Démarrage rapide et apportez votre propre stockage pour créer et publier une définition d’application managée Azure.

Vous pouvez également utiliser Bicep pour déployer une définition d’application managée depuis votre catalogue de services. Pour plus d’informations, consultez Démarrage rapide : utiliser Bicep pour déployer une définition d’application managée Azure.

Prérequis

Pour effectuer les tâches mentionnées dans cet article, vous avez besoin des éléments suivants :

Créer un fichier Bicep

Chaque définition d’application managée contient un fichier nommé mainTemplate.json. Le modèle définit les ressources Azure à déployer, et n’est pas différent d’un modèle ARM standard. Vous pouvez développer le modèle en utilisant Bicep, puis convertissez le fichier Bicep au format JSON.

Ouvrez Visual Studio Code, créez un fichier avec le nom mainTemplate.bicep (respecte la casse), puis enregistrez-le.

Ajoutez le code Bicep suivant et enregistrez le fichier. Il définit les ressources de l’application managée nécessaires pour déployer un App Service, plan App Service, et un compte de stockage.

param location string = resourceGroup().location

@description('App Service plan name.')
@maxLength(40)
param appServicePlanName string

@description('App Service name prefix.')
@maxLength(47)
param appServiceNamePrefix string

@description('Storage account name prefix.')
@maxLength(11)
param storageAccountNamePrefix string

@description('Storage account type allowed values')
@allowed([
  'Premium_LRS'
  'Standard_LRS'
  'Standard_GRS'
])
param storageAccountType string

var appServicePlanSku = 'F1'
var appServicePlanCapacity = 1
var appServiceName = '${appServiceNamePrefix}${uniqueString(resourceGroup().id)}'
var storageAccountName = '${storageAccountNamePrefix}${uniqueString(resourceGroup().id)}'
var appServiceStorageConnectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${environment().suffixes.storage};Key=${storageAccount.listKeys().keys[0].value}'

resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: appServicePlanSku
    capacity: appServicePlanCapacity
  }
}

resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
  name: appServiceName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
    siteConfig: {
      appSettings: [
        {
          name: 'AppServiceStorageConnectionString'
          value: appServiceStorageConnectionString
        }
      ]
    }
  }
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: storageAccountType
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
  }
}

output appServicePlan string = appServicePlan.name
output appServiceApp string = appServiceApp.properties.defaultHostName
output storageAccount string = storageAccount.properties.primaryEndpoints.blob

Convertir Bicep en JSON

Utilisez PowerShell ou Azure CLI pour générer le fichier mainTemplate.json. Accédez au répertoire dans lequel vous avez enregistré votre fichier Bicep et exécutez la build commande.

bicep build mainTemplate.bicep

Si vous souhaitez en savoir plus, accédez à la build Bicep.

Une fois le fichier Bicep converti en JSON, votre fichier mainTemplate.json doit correspondre à l’exemple suivant. Vous pouvez avoir des valeurs différentes dans les metadata propriétés pour version et templateHash.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.17.1.54307",
      "templateHash": "1234567891234567890"
    }
  },
  "parameters": {
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "appServicePlanName": {
      "type": "string",
      "maxLength": 40,
      "metadata": {
        "description": "App Service plan name."
      }
    },
    "appServiceNamePrefix": {
      "type": "string",
      "maxLength": 47,
      "metadata": {
        "description": "App Service name prefix."
      }
    },
    "storageAccountNamePrefix": {
      "type": "string",
      "maxLength": 11,
      "metadata": {
        "description": "Storage account name prefix."
      }
    },
    "storageAccountType": {
      "type": "string",
      "allowedValues": [
        "Premium_LRS",
        "Standard_LRS",
        "Standard_GRS"
      ],
      "metadata": {
        "description": "Storage account type allowed values"
      }
    }
  },
  "variables": {
    "appServicePlanSku": "F1",
    "appServicePlanCapacity": 1,
    "appServiceName": "[format('{0}{1}', parameters('appServiceNamePrefix'), uniqueString(resourceGroup().id))]",
    "storageAccountName": "[format('{0}{1}', parameters('storageAccountNamePrefix'), uniqueString(resourceGroup().id))]"
  },
  "resources": [
    {
      "type": "Microsoft.Web/serverfarms",
      "apiVersion": "2022-03-01",
      "name": "[parameters('appServicePlanName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[variables('appServicePlanSku')]",
        "capacity": "[variables('appServicePlanCapacity')]"
      }
    },
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2022-03-01",
      "name": "[variables('appServiceName')]",
      "location": "[parameters('location')]",
      "properties": {
        "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",
        "httpsOnly": true,
        "siteConfig": {
          "appSettings": [
            {
              "name": "AppServiceStorageConnectionString",
              "value": "[format('DefaultEndpointsProtocol=https;AccountName={0};EndpointSuffix={1};Key={2}', variables('storageAccountName'), environment().suffixes.storage, listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2022-09-01').keys[0].value)]"
            }
          ]
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]"
      ]
    },
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "name": "[variables('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Hot"
      }
    }
  ],
  "outputs": {
    "appServicePlan": {
      "type": "string",
      "value": "[parameters('appServicePlanName')]"
    },
    "appServiceApp": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Web/sites', variables('appServiceName')), '2022-03-01').defaultHostName]"
    },
    "storageAccount": {
      "type": "string",
      "value": "[reference(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2022-09-01').primaryEndpoints.blob]"
    }
  }
}

Définissez votre expérience du portail

En tant qu’éditeur, vous définissez l’expérience du portail pour créer l’application managée. Le fichier createUiDefinition.json génère l’interface utilisateur du portail. Vous définissez comment les utilisateurs fournissent une entrée pour chaque paramètre à l’aide d’éléments de contrôle tels que des listes déroulantes et des zones de texte.

Dans cet exemple, l’interface utilisateur vous invite à entrer le préfixe de nom App Service, le nom de plan App Service, le préfixe et le type du compte de stockage. Pendant le déploiement, les variables de mainTemplate.json utilisent la fonction uniqueString pour ajouter une chaîne de 13 caractères aux préfixes des noms afin que les noms soient globalement uniques dans Azure.

Ouvrez Visual Studio Code, créez un fichier avec le nom createUiDefinition.json (avec respect de la casse) et enregistrez-le.

Ajoutez le code JSON suivant au fichier, puis enregistrez-le.

{
  "$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
  "handler": "Microsoft.Azure.CreateUIDef",
  "version": "0.1.2-preview",
  "parameters": {
    "basics": [
      {}
    ],
    "steps": [
      {
        "name": "webAppSettings",
        "label": "Web App settings",
        "subLabel": {
          "preValidation": "Configure the web app settings",
          "postValidation": "Completed"
        },
        "elements": [
          {
            "name": "appServicePlanName",
            "type": "Microsoft.Common.TextBox",
            "label": "App Service plan name",
            "placeholder": "App Service plan name",
            "defaultValue": "",
            "toolTip": "Use alphanumeric characters or hyphens with a maximum of 40 characters.",
            "constraints": {
              "required": true,
              "regex": "^[a-z0-9A-Z-]{1,40}$",
              "validationMessage": "Only alphanumeric characters or hyphens are allowed, with a maximum of 40 characters."
            },
            "visible": true
          },
          {
            "name": "appServiceName",
            "type": "Microsoft.Common.TextBox",
            "label": "App Service name prefix",
            "placeholder": "App Service name prefix",
            "defaultValue": "",
            "toolTip": "Use alphanumeric characters or hyphens with minimum of 2 characters and maximum of 47 characters.",
            "constraints": {
              "required": true,
              "regex": "^[a-z0-9A-Z-]{2,47}$",
              "validationMessage": "Only alphanumeric characters or hyphens are allowed, with a minimum of 2 characters and maximum of 47 characters."
            },
            "visible": true
          }
        ]
      },
      {
        "name": "storageConfig",
        "label": "Storage settings",
        "subLabel": {
          "preValidation": "Configure the storage settings",
          "postValidation": "Completed"
        },
        "elements": [
          {
            "name": "storageAccounts",
            "type": "Microsoft.Storage.MultiStorageAccountCombo",
            "label": {
              "prefix": "Storage account name prefix",
              "type": "Storage account type"
            },
            "toolTip": {
              "prefix": "Enter maximum of 11 lowercase letters or numbers.",
              "type": "Available choices are Standard_LRS, Standard_GRS, and Premium_LRS."
            },
            "defaultValue": {
              "type": "Standard_LRS"
            },
            "constraints": {
              "allowedTypes": [
                "Premium_LRS",
                "Standard_LRS",
                "Standard_GRS"
              ]
            },
            "visible": true
          }
        ]
      }
    ],
    "outputs": {
      "location": "[location()]",
      "appServicePlanName": "[steps('webAppSettings').appServicePlanName]",
      "appServiceNamePrefix": "[steps('webAppSettings').appServiceName]",
      "storageAccountNamePrefix": "[steps('storageConfig').storageAccounts.prefix]",
      "storageAccountType": "[steps('storageConfig').storageAccounts.type]"
    }
  }
}

Pour en savoir plus, accédez à la page Démarrage avec CreateUiDefinition.

Empaqueter les fichiers

Ajoutez les deux fichiers au fichier de package nommé app.zip. Les deux fichiers doivent se trouver au niveau racine du fichier .zip. Si les fichiers sont dans un dossier, lorsque vous créez la définition d’application managée, une erreur vous indique que les fichiers nécessaires ne sont pas présents.

Chargez app.zip sur un compte de stockage Azure afin de pouvoir l’utiliser lorsque vous déployez la définition de l’application managée. Le nom du compte de stockage doit être globalement unique dans Azure, et la longueur doit être comprise entre trois et 24 caractères avec uniquement des lettres minuscules et des chiffres. Dans la commande, remplacez l’espace réservé <demostorageaccount>, y compris les chevrons (<>), par le nom de votre compte de stockage unique.

Dans Visual Studio Code, ouvrez un nouveau terminal PowerShell et connectez-vous à votre abonnement Azure.

Connect-AzAccount

La commande ouvre votre navigateur par défaut et vous invite à vous connecter à Azure. Pour plus d’informations, accédez à Se connecter avec Azure PowerShell.

Après vous être connecté, exécutez les commandes suivantes.

New-AzResourceGroup -Name packageStorageRG -Location westus3

$storageAccount = New-AzStorageAccount `
  -ResourceGroupName packageStorageRG `
  -Name "<demostorageaccount>" `
  -Location westus3 `
  -SkuName Standard_LRS `
  -Kind StorageV2 `
  -AllowBlobPublicAccess $true

$ctx = $storageAccount.Context

New-AzStorageContainer -Name appcontainer -Context $ctx -Permission blob

Set-AzStorageBlobContent `
  -File "app.zip" `
  -Container appcontainer `
  -Blob "app.zip" `
  -Context $ctx

Utilisez la commande suivante pour stocker l’URI du fichier de package dans une variable nommée packageuri. Vous utilisez la valeur de la variable lorsque vous déployez la définition de l’application managée.

$packageuri=(Get-AzStorageBlob -Container appcontainer -Blob app.zip -Context $ctx).ICloudBlob.StorageUri.PrimaryUri.AbsoluteUri

Créer la définition d’application gérée

Dans cette section, vous obtenez des informations d’identité à partir de Microsoft Entra ID, créez un groupe de ressources et déployez la définition d’application managée.

Obtenir l’ID du groupe et l’ID de définition de rôle

L’étape suivante consiste à sélectionner un utilisateur, un groupe de sécurité ou une application afin de gérer les ressources pour le client. Cette identité dispose des autorisations sur le groupe de ressources managées en fonction du rôle attribué. Le rôle peut être n’importe quel rôle intégré Azure comme Propriétaire ou Contributeur.

Cet exemple utilise un groupe de sécurité, et votre compte Microsoft Entra doit être membre du groupe. Pour obtenir l’ID d’objet du groupe, remplacez l’espace réservé <managedAppDemo>, y compris les chevrons (<>), par le nom de votre groupe. Vous utilisez la valeur de la variable lorsque vous déployez la définition de l’application managée.

Pour créer un groupe Microsoft Entra, accédez à Gérer les groupes Microsoft Entra et l’appartenance au groupe.

$principalid=(Get-AzADGroup -DisplayName <managedAppDemo>).Id

Obtenez ensuite l’ID de définition de rôle du rôle intégré Azure auquel vous souhaitez accorder l’accès à l’utilisateur, au groupe ou à l’application. Vous utilisez la valeur de la variable lorsque vous déployez la définition de l’application managée.

$roleid=(Get-AzRoleDefinition -Name Owner).Id

Créer le modèle de déploiement de définition

Utilisez un fichier Bicep pour déployer la définition d’application managée dans votre catalogue de services.

Ouvrez Visual Studio Code, créez un fichier nommé deployDefinition.bicep et enregistrez-le.

Ajoutez le code Bicep suivant et enregistrez le fichier.

param location string = resourceGroup().location

@description('Name of the managed application definition.')
param managedApplicationDefinitionName string

@description('The URI of the .zip package file.')
param packageFileUri string

@description('Publishers Principal ID that needs permissions to manage resources in the managed resource group.')
param principalId string

@description('Role ID for permissions to the managed resource group.')
param roleId string

var definitionLockLevel = 'ReadOnly'
var definitionDisplayName = 'Sample Bicep managed application'
var definitionDescription = 'Sample Bicep managed application that deploys web resources'

resource managedApplicationDefinition 'Microsoft.Solutions/applicationDefinitions@2021-07-01' = {
  name: managedApplicationDefinitionName
  location: location
  properties: {
    lockLevel: definitionLockLevel
    description: definitionDescription
    displayName: definitionDisplayName
    packageFileUri: packageFileUri
    authorizations: [
      {
        principalId: principalId
        roleDefinitionId: roleId
      }
    ]
  }
}

Pour plus d’informations sur les propriétés du modèle, accédez àMicrosoft.Solutions/applicationDefinitions.

Le lockLevel du groupe de ressources managées empêche le client d’effectuer des opérations indésirables sur ce groupe de ressources. Actuellement, ReadOnly est le seul niveau de verrou pris en charge. ReadOnly spécifie que le client peut uniquement lire les ressources présentes dans le groupe de ressources managées. Les identités de l’éditeur dont l’accès est octroyé au groupe de ressources managées sont exemptées du niveau verrou.

Créer le fichier de paramètres

Le modèle de déploiement de la définition d’application managée a besoin d’une entrée pour plusieurs paramètres. La commande de déploiement vous invite à entrer les valeurs ou vous pouvez créer un fichier de paramètres pour les valeurs. Dans cet exemple, nous utilisons un fichier de paramètres pour passer les valeurs des paramètres à la commande de déploiement.

Dans Visual Studio Code, créez un nouveau fichier nommé deployDefinition.parameters.json et enregistrez-le.

Ajoutez le code suivant à votre fichier de paramètres et enregistrez-le. Ensuite, remplacez le <placeholder values>, y compris les chevrons (<>), par vos valeurs.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "managedApplicationDefinitionName": {
      "value": "sampleBicepManagedApplication"
    },
    "packageFileUri": {
      "value": "<placeholder for the packageFileUri>"
    },
    "principalId": {
      "value": "<placeholder for principalid value>"
    },
    "roleId": {
      "value": "<placeholder for roleid value>"
    }
  }
}

Le tableau suivant décrit les valeurs de paramètre de la définition d’application managée.

Paramètre Valeur
managedApplicationDefinitionName Nom de la définition d’application managée. Pour cet exemple, utilisez sampleBicepManagedApplication.
packageFileUri Entrez l’URI de votre fichier de package .zip. Utilisez la valeur de votre variable packageuri. Le format est https://yourStorageAccountName.blob.core.windows.net/appcontainer/app.zip.
principalId ID du principal des éditeurs qui nécessite des autorisations pour gérer des ressources dans le groupe de ressources managées. Utilisez la valeur de votre variable principalid.
roleId ID de rôle pour les autorisations du groupe de ressources managées. Par exemple Propriétaire, Contributeur, Lecteur. Utilisez la valeur de votre variable roleid.

Pour obtenir vos valeurs de variable :

  • Azure PowerShell : dans PowerShell, tapez $variableName pour afficher la valeur d’une variable.
  • Azure CLI : dans Bash, tapez echo $variableName pour afficher la valeur d’une variable.

Déployer la définition

Lorsque vous déployez la définition de l’application managée, elle est mise à disposition dans votre catalogue de services. Ce processus ne déploie pas les ressources de l’application managée.

Créez un groupe de ressources nommé bicepDefinitionRG et déployez la définition d’application managée.

New-AzResourceGroup -Name bicepDefinitionRG -Location westus3

New-AzResourceGroupDeployment `
  -ResourceGroupName bicepDefinitionRG `
  -TemplateFile deployDefinition.bicep `
  -TemplateParameterFile deployDefinition.parameters.json

Vérifier les résultats

Exécutez la commande suivante pour vérifier la publication de la définition dans votre catalogue de services.

Get-AzManagedApplicationDefinition -ResourceGroupName bicepDefinitionRG

Get-AzManagedApplicationDefinition répertorie toutes les définitions disponibles dans le groupe de ressources spécifié, comme sampleBicepManagedApplication.

Assurez-vous que les utilisateurs peuvent accéder à votre définition

Vous avez accès à la définition de l’application managée, mais vous souhaitez vous assurer que d’autres utilisateurs de votre organisation peuvent y accéder. Accordez-leur au moins le rôle Lecteur dans la définition. Ils ont peut-être hérité de ce niveau d’accès suite à l’abonnement ou au groupe de ressources. Pour vérifier qui a accès à la définition et ajouter des utilisateurs ou des groupes, accédez à Attribuer des rôles Azure à l’aide du portail Azure.

Nettoyer les ressources

Si vous souhaitez déployer la définition, passez à la section Étapes suivantes qui établit un lien vers l’article pour déployer la définition avec Bicep.

Si vous avez terminé la définition d’application managée, vous pouvez supprimer les groupes de ressources que vous avez créés et qui se nomment packageStorageRG et bicepDefinitionRG.

La commande vous invite à confirmer que vous souhaitez supprimer le groupe de ressources.

Remove-AzResourceGroup -Name packageStorageRG

Remove-AzResourceGroup -Name bicepDefinitionRG

Étapes suivantes

Vous avez publié la définition d’application managée. L’étape suivante consiste à apprendre à déployer une instance de cette définition.