Tworzenie zasobów platformy Azure przy użyciu usługi Azure PowerShell lub usługi szablonów usługi ARM
W tym artykule opisano, jak używać szablonów Microsoft Azure programu PowerShell lub Azure Resource Manager (ARM) w celu tworzenia zasobów systemu Azure, które są wymagane do fakturowania elektronicznego.
Aby włączyć fakturowanie elektroniczne w witrynie Dynamics 365 Finance, musisz utworzyć i skonfigurować kilka zasobów systemu Azure, takich jak klucz systemu Azure, konto magazynu systemu Azure i kontener konta magazynu systemu Azure. W przypadku ręcznego przetwarzania ten proces może trwać długo i tworzyć błędy. Aby uprościć i zautomatyzować ten proces, można użyć skryptu programu PowerShell lub szablonu usługi ARM, który tworzy i konfiguruje wszystkie wymagane zasoby systemu Azure.
Użyj programu Azure PowerShell
Wymagania wstępne
Aby umożliwić zainstalowanie skryptu PowerShell, należy najpierw spełnić następujące wymagania wstępne:
- Masz subskrypcję systemu Azure mającą wystarczające uprawnienia do tworzenia zasobów i zarządzania nimi.
- Zainstalowano moduł Azure PowerShell . (Obsługiwana wersja systemu Zalecane jest używanie programu PowerShell w wersji 7 lub nowszej w module Azure PowerShell.)
- Masz plik skryptu programu PowerShell.
Skrypt programu 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."
Uruchom skrypt PowerShell
Wykonaj te kroki, aby uruchomić skrypt programu PowerShell.
Otwórz program PowerShell i przejdź do folderu, w którym znajduje się plik skryptu programu PowerShell oraz plik konfiguracji.
Aby uruchomić skrypt programu PowerShell przy użyciu własnych parametrów, uruchom następujące polecenie.
.\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>
Skrypt PowerShell wykonuje następujące akcje.
- Skrypt monituje o zalogowanie się do konta systemu Azure. Wprowadź poświadczenia, a następnie wybierz Zaloguj się.
- Skrypt określa, czy główna usługa faktury elektronicznej już istnieje. Jeśli nie istnieje, skrypt go tworzy.
- Skrypt określa, czy istnieją już następujące zasoby systemu Azure: grupa zasobów systemu Azure, klucz kluczu Azure, konto magazynu systemu Azure oraz kontener kont magazynu systemu Azure. Jeśli którykolwiek z nich nie istnieje, skrypt tworzy i konfiguruje je.
- Skrypt generuje token sygnatury dostępu współdzielonego (SAS) dla kontenera konta magazynu i dodaje go jako tajny klucz Klucz w kluczu kluczy.
- Skrypt ustawia zasady dostępu do klucza, aby dostarczać i wymieniać uprawnienia do fakturowania elektronicznego.
- W wyniku tego skrypt generuje szczegóły utworzonych zasobów systemu Azure. Te szczegóły obejmują nazwy i adresy URL.
Uwaga
Ten sam skrypt można uruchomić, jeśli należy odnowić token SAS, który wygasł. W tym przypadku skrypt nie utworzy zasobów. W zamian generuje nowy token SAS i aktualizuje go w kluczu.
Użyj jako szablonu usługi ARM
Szablon usługi 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": {}
}
Wdróż szablon usługi ARM
Aby skonfigurować szablon usługi ARM, należy wykonać następujące czynności.
Zaloguj się do portalu Azure i wyszukaj wdrożenie niestandardowego szablonu.
W edytorze wybierz polecenie Kompilowanie własnego szablonu.
Skopiuj szablon usługi ARM dostarczony w poprzedniej sekcji tego artykułu, wklej go do edytora, a następnie wybierz pozycję Zapisz.
Podaj wymagane parametry.
Wybierz opcję Przejrzyj + utwórz.
Przejrzyj szczegóły, a następnie wybierz pozycję Utwórz.
Weryfikowanie zasobów platformy Azure
Aby sprawdzić, czy utworzone zasoby Azure są poprawnie skonfigurowane, wykonaj następujące czynności.
- Zaloguj się w witrynie Azure Portal przejdź do grupy zasobów zawierającej zasoby Azure. Powinny zostać wyświetlony zasoby o nazwach określonych w parametrach skryptu programu PowerShell lub szablonu usługi ARM.
- Otwórz zasób kluczy I potwierdź, że token SAS dla konta magazynu Azure został utworzony i ma poprawną wartość.