Créer des ressources Azure à l’aide de modèles Azure PowerShell ou ARM
Cet article explique comment utiliser les modèles Microsoft Azure PowerShell ou Azure Resource Manager (ARM) pour créer les ressources Azure requises pour la facturation électronique.
Pour activer la facturation électronique dans Dynamics 365 Finance, vous devez créer et configurer plusieurs ressources Azure, telles qu’un coffre de clés Azure, un compte de stockage Azure et un conteneur de compte de stockage Azure. Ce processus peut prendre du temps et être sujet aux erreurs s’il est effectué manuellement. Pour simplifier et automatiser ce processus, vous pouvez utiliser un script PowerShell ou un modèle ARM qui crée et configure toutes les ressources Azure requises pour vous.
Utiliser Azure PowerShell
Conditions préalables
Avant de pouvoir exécuter le script PowerShell, les conditions requises suivantes doivent être remplies :
- Vous disposez d’un abonnement Azure disposant d’autorisations suffisantes pour créer et gérer des ressources.
- Vous avez installé le module Azure PowerShell. (Une version prise en charge de PowerShell version 7 ou ultérieure est recommandée pour une utilisation avec le module Azure PowerShell.)
- Vous disposez du fichier de script PowerShell.
Script PowerShell
param (
[Parameter(Mandatory=$true)]
[string]$subscriptionId,
[Parameter(Mandatory=$true)]
[string]$resourceGroup,
[Parameter(Mandatory=$true)]
[string]$location,
[Parameter(Mandatory=$true)]
[string]$storageAccountName,
[Parameter(Mandatory=$true)]
[string]$keyVaultName,
[Parameter(Mandatory=$true)]
[string]$containerName,
[Parameter(Mandatory=$true)]
[string]$storageAccountKeyVaultSecretName
)
if (!(Get-Module -ListAvailable -Name Az)) {
throw "Az PowerShell module is required to run this script. Please install from https://learn.microsoft.com/en-us/powershell/azure/install-azure-powershell."
}
function Write-ErrorMessage {
param (
[string]$errorMessage
)
Write-Host "Error: $errorMessage" -ForegroundColor Red
exit 1
}
function Write-VerboseMessage {
param (
[string]$message
)
Write-Host "Verbose: $message" -ForegroundColor DarkYellow
}
function Confirm-ResourceExists {
param (
[string]$resourceType,
[string]$resourceName,
[string]$resourceGroup = ''
)
try {
switch ($resourceType) {
'ResourceGroup' {
Get-AzResourceGroup -Name $resourceName -ErrorAction Stop | Out-Null
}
'StorageAccount' {
Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $resourceName -ErrorAction Stop | Out-Null
}
'StorageContainer' {
Get-AzStorageContainer -Name $resourceName -ErrorAction Stop | Out-Null
}
'KeyVault' {
$kv = Get-AzKeyVault -ResourceGroupName $resourceGroup -VaultName $resourceName
if ($null -eq $kv)
{
return $false
}
}
}
return $true
} catch {
return $false
}
}
# Connect to Azure account and set the subscription context
try {
Write-VerboseMessage "Connecting to Azure account..."
Connect-AzAccount -Subscription $subscriptionId -ErrorAction Stop -Verbose
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to connect to the Azure account or set subscription context."
}
try {
Write-VerboseMessage "Checking if the e-invoice service principal exists."
$objectId = (Get-AzADServicePrincipal -ApplicationId "ecd93392-c922-4f48-9ddf-10741e4a9b65" -ErrorAction SilentlyContinue -Verbose).Id
if ($null -eq $objectId)
{
Write-VerboseMessage "The e-invoice service principal does not exist. Trying to create now."
New-AzADServicePrincipal -AppId "ecd93392-c922-4f48-9ddf-10741e4a9b65" -ErrorAction Stop -Verbose
}
else {
Write-VerboseMessage "The e-invoice service principal already exists. No action required."
}
}
catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Adding e-Invoicing Service to your tenant as a service principal failed."
}
# Check if the resource group exists
if (-not (Confirm-ResourceExists -resourceType 'ResourceGroup' -resourceName $resourceGroup)) {
try {
Write-VerboseMessage "Creating Azure resource group..."
New-AzResourceGroup -Name $resourceGroup -Location $location -ErrorAction Stop -Verbose
$msg = "Resource group {0} created successfully in at location: {1}." -f $resourceGroup, $location
Write-VerboseMessage $msg
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to create Azure resource group."
}
} else {
Write-VerboseMessage "Resource group '$resourceGroup' already exists."
}
# Check if the Azure Key Vault exists
if (-not (Confirm-ResourceExists -resourceType 'KeyVault' -resourceName $keyVaultName -resourceGroup $resourceGroup)) {
try {
Write-VerboseMessage "Creating Azure Key Vault..."
New-AzKeyVault -Name $keyVaultName -ResourceGroupName $resourceGroup -Location $location -ErrorAction Stop -Verbose
$msg = "Key vault {0} created successfully in resource group: {1} at location: {2}." -f $keyVaultName, $resourceGroup, $location
Write-VerboseMessage $msg
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to create Azure Key Vault."
}
} else {
Write-VerboseMessage "Azure Key Vault '$keyVaultName' already exists."
}
# Check if the storage account exists
if (-not (Confirm-ResourceExists -resourceType 'StorageAccount' -resourceName $storageAccountName -resourceGroup $resourceGroup)) {
try {
Write-VerboseMessage "Creating Azure Storage Account..."
New-AzStorageAccount -ResourceGroupName $resourceGroup `
-Name $storageAccountName `
-Location $location `
-SkuName Standard_LRS `
-Kind StorageV2 `
-AllowBlobPublicAccess $true -ErrorAction Stop -Verbose
$msg = "Storage account {0} created successfully in resource group: {1} at location: {2}." -f $storageAccountName, $resourceGroup, $location
Write-VerboseMessage $msg
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to create Azure Storage Account."
}
} else {
Write-VerboseMessage "Storage account '$storageAccountName' already exists."
}
# Check if the storage container exists
$ctx = (Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccountName).Context
Set-AzCurrentStorageAccount -Context $ctx
if (-not (Confirm-ResourceExists -resourceType 'StorageContainer' -resourceName $containerName -resourceGroup $resourceGroup)) {
try {
Write-VerboseMessage "Creating storage container..."
New-AzStorageContainer -Name $containerName -Context $ctx -ErrorAction Stop -Verbose
$msg = "Storage container {0} created successfully in storage account: {1}." -f $containerName, $storageAccountName
Write-VerboseMessage $msg
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to create storage container."
}
} else {
Write-VerboseMessage "Storage container '$containerName' already exists."
}
# Set the start and end time for the SAS token
$StartTime = Get-Date
$EndTime = $StartTime.AddYears(3)
# Generate SAS token for the container
try {
Write-VerboseMessage "Generating SAS token for the container..."
$sasToken = New-AzStorageContainerSASToken -Name $containerName -Permission racwdli -Protocol HttpsOnly -StartTime $StartTime -ExpiryTime $EndTime -Context $ctx -ErrorAction Stop -Verbose
$msg = "SAS token for container {0} generated successfully with full permissions. The token would expire on {1}." -f $containerName, $EndTime
Write-VerboseMessage $msg
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to generate SAS token for the container."
}
# Construct the SAS URL
$sasURL = "https://$($storageAccountName).blob.core.windows.net/$($containerName)?$($sastoken)"
# Set access policy for the application to get and list secrets
try {
Write-VerboseMessage "Setting access policy for Azure Key Vault..."
Set-AzKeyVaultAccessPolicy -VaultName $keyVaultName -ObjectId $objectId -PermissionsToSecrets get,list -ErrorAction Stop -Verbose
$msg = "Get and list access policies set successfully on key vault {0} for the e-invoicing application {1}." -f $keyVaultName, $objectId
Write-VerboseMessage $msg
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to set access policy for Azure Key Vault."
}
# Convert SAS URL to secure string
$secretvalue = ConvertTo-SecureString $sasURL -AsPlainText -Force
# Create a new secret in Azure Key Vault
try {
Write-VerboseMessage "Creating secret in Azure Key Vault..."
Set-AzKeyVaultSecret -VaultName $keyVaultName -Name $storageAccountKeyVaultSecretName -SecretValue $secretvalue -Expires $EndTime -ContentType "" -ErrorAction Stop -Verbose
$msg = "Secret {0} created successfully in {1} and will expire on {2}." -f $storageAccountKeyVaultSecretName, $keyVaultName, $EndTime
Write-VerboseMessage $msg
} catch {
Write-Host $_.Exception.Message
Write-ErrorMessage "Failed to create secret in Azure Key Vault."
}
# Display the secret
Write-Host "Secret created successfully."
Exécuter le script PowerShell
Pour exécuter le script PowerShell, procédez comme suit.
Ouvrez PowerShell et accédez au dossier où se trouvent le fichier de script PowerShell et le fichier de configuration.
Pour exécuter le script PowerShell à l’aide de vos propres paramètres, exécutez la commande suivante.
.\Create-AzureResourcesForEInvoice.ps1 -subscriptionId <azure_subscription_id> -resourceGroup <resource_group_name> -location <resource_group_location> -storageAccountName <storage_account_name> -containerName <container_name> -storageAccountKeyVaultSecretName <SAS_token_keyvault_secret_name>
Le script PowerShell effectue les actions suivantes.
- Le script vous invite à vous connecter à votre compte Azure. Saisissez vos informations d’identification, puis sélectionnez Se connecter.
- Le script détermine si le principal du service de facture électronique existe déjà. S’il n’existe pas, le script le crée.
- Le script détermine si les ressources Azure suivantes existent déjà : un groupe de ressources Azure, un coffre de clés Azure, un compte de stockage Azure et un conteneur de compte de stockage Azure. Si aucun d’entre eux n’existe, le script les crée et les configure.
- Le script génère un jeton de signature d’accès partagé (SAS) pour le conteneur de compte de stockage et l’ajoute en tant que secret Key Vault dans le coffre de clés.
- Le script définit la stratégie d’accès sur le coffre de clés pour fournir les autorisations get et list à l’application de facturation électronique.
- En sortie, le script génère les détails des ressources Azure créées. Ces détails incluent les noms et les URL.
Remarque
Vous pouvez exécuter le même script si vous devez renouveler un jeton SAS qui a expiré. Dans ce cas, le script ne crée pas les ressources. Au lieu de cela, il génère simplement un nouveau jeton SAS et le met à jour dans le coffre de clés.
Utilisation d’un modèle ARM
Modèle ARM
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"keyVaultName": {
"type": "string",
"metadata": {
"description": "Name of KeyVault to Store secrets/certificates/SaS Token"
}
},
"tenantID": {
"type": "string",
"metadata": {
"description": "Azure AD Tenant ID"
}
},
"keyVaultAccessObjectID": {
"type": "string",
"metadata": {
"description": "ID of user or App to grant access to KV"
},
"defaultValue": "ecd93392-c922-4f48-9ddf-10741e4a9b65"
},
"StorageAccountName": {
"type": "string",
"metadata": {
"description": "Name of Storage Account to Create"
}
},
"ContainerName": {
"type": "string",
"metadata": {
"description": "Name of container for einvoice upload"
}
},
"accountSasProperties": {
"type": "object",
"defaultValue": {
"signedServices": "bf",
"signedPermission": "rwacld",
"signedExpiry": "2024-12-01T00:00:00Z",
"signedResourceTypes": "o"
}
}
},
"variables": {},
"resources": [
{
"name": "[parameters('StorageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2018-07-01",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "[parameters('StorageAccountName')]"
},
"sku": {
"name": "Standard_LRS"
},
"kind": "StorageV2",
"properties": {
"allowBlobPublicAccess": true
},
"resources":[
{
"type": "blobServices/containers",
"apiVersion": "2018-03-01-preview",
"name": "[concat('default/', parameters('ContainerName'))]",
"dependsOn": [
"[parameters('StorageAccountName')]"
],
"properties": {
"publicAccess": "None"
}
}
]
},
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "2018-02-14",
"name": "[parameters('keyVaultName')]",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "[parameters('keyVaultName')]"
},
"properties": {
"enabledForDeployment": true,
"enabledForTemplateDeployment": true,
"enabledForDiskEncryption": true,
"tenantId": "[parameters('tenantID')]",
"accessPolicies": [
{
"tenantId": "[parameters('tenantID')]",
"objectId": "[parameters('keyVaultAccessObjectID')]",
"permissions": {
"keys": [
"get"
],
"secrets": [
"list",
"get"
]
}
}
],
"sku": {
"name": "standard",
"family": "A"
}
}
},
{
"apiVersion": "2018-02-14",
"type": "Microsoft.KeyVault/vaults/secrets",
"dependsOn": [
"[concat('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]"
],
"name": "[concat(parameters('keyVaultName'), '/', 'StorageSaSToken')]",
"properties": {
"value": "[concat('https://', parameters('StorageAccountName'), '.blob.core.windows.net/', parameters('ContainerName'), '?', listAccountSas(parameters('StorageAccountName'), '2018-07-01', parameters('accountSasProperties')).accountSasToken)]"
}
}
],
"outputs": {}
}
Déployer le modèle ARM
Pour déployer le modèle ARM, procédez comme suit.
Connectez-vous au Portail Azure et recherchez Déployer un modèle personnalisé.
Sélectionnez Créer votre propre modèle dans l’éditeur.
Copiez le modèle ARM fourni dans la section précédente de cet article, collez-le dans l’éditeur, puis sélectionnez Enregistrer.
Fournissez les paramètres obligatoires.
Sélectionnez Réviser + Créer.
Vérifiez les détails, puis sélectionnez Créer.
Vérifier les ressources Azure
Pour vérifier que les ressources Azure ont été créées et configurées correctement, procédez comme suit.
- Connectez-vous au portail Azure et accédez au groupe de ressources qui contient les ressources Azure. Vous devriez voir les ressources portant les noms que vous avez spécifiés dans les paramètres du script PowerShell ou du modèle ARM.
- Ouvrez la ressource Key Vault et confirmez que le jeton SAS pour le compte de stockage Azure a été créé et a la valeur correcte.