Del via


Opprett Azure-ressurser ved hjelp av Azure PowerShell- eller ARM-maler

Denne artikkelen beskriver hvordan du bruker Microsoft Azure PowerShell- eller Azure Resource Manager-maler (ARM) til å opprette ressurser som kreves for elektronisk fakturering.

Hvis du vil aktivere e-fakturering i Dynamics 365 Finance, må du opprette og konfigurere flere Azure-ressurser, for eksempel et Azure-nøkkelhvelv, en Azure-lagringskonto og en Azure-lagringskontocontainer. Denne prosessen kan være tidkrevende og utsatt for feil hvis den gjøres manuelt. For å forenkle og automatisere denne prosessen kan du bruke et PowerShell-skript eller en ARM-mal som oppretter og konfigurerer alle de nødvendige Azure-ressursene for deg.

Bruk Azure PowerShell

Forutsetninger

Før du kjører PowerShell-skriptet må følgende forutsetninger være oppfylt:

  • Du har et Azure-abonnement som har tilstrekkelige tillatelser til å opprette og administrere ressurser.
  • Du har installert Azure PowerShell-modulen. (En støttet versjon av PowerShell versjon 7 eller senere anbefales for bruk med Azure PowerShell-modulen.)
  • Du har PowerShell-skriptfilen.

PowerShell-skript

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."

Kjør PowerShell-skriptet

Følg fremgangsmåten nedenfor for å kjøre PowerShell-skriptet.

  1. Åpne PowerShell, og gå til mappen der PowerShell-skriptfilen og konfigurasjonsfilen er plassert.

  2. Hvis du vil kjøre PowerShell-skriptet ved hjelp av dine egne parametere, kjører du kommandoen nedenfor.

    .\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>
    

PowerShell-skriptet utfører følgende handlinger.

  1. Skriptet ber deg om å logge deg på Azure-kontoen. Angi legitimasjonen din, og velg deretter Logg på.
  2. Skriptet bestemmer om sikkerhetskontohaveren for e-fakturatjenesten allerede finnes. Hvis den ikke finnes, oppretter skriptet den.
  3. Skriptet finner ut om følgende Azure-ressurser allerede finnes: en Azure-ressursgruppe, et Azure-nøkkelhvelv, en Azure-lagringskonto og en Azure-lagringskontocontainer. Hvis noen av dem ikke finnes, oppretter og konfigurerer skriptet dem.
  4. Skriptet genererer et SAS-token (signatur for delt tilgang) for lagringskontocontaineren og legger det til som en Key Vault-hemmelighet i nøkkelhvelvet.
  5. Skriptet angir tilgangspolicyen for nøkkelhvelvet for å gi tillatelsene hent og liste til e-fakturaappen.
  6. Som utdata genererer skriptet detaljene for Azure-ressursene som ble opprettet. Disse detaljene omfatter navn og nettadresser.

Obs!

Du kan kjøre det samme skriptet hvis du må fornye et SAS-token som er utløpt. I så fall oppretter ikke skriptet ressursene. I stedet genererer det bare et nytt SAS-token og oppdaterer det i nøkkelhvelvet.

Bruk en ARM-mal

ARM-mal

{
    "$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": {}
}

Distribuer ARM-malen

Følg fremgangsmåten nedenfor for å distribuere ARM-malen.

  1. Logg deg på Azure-portalen, og søk etter Distribuer en egendefinert mal.

  2. Velg Bygg din egen mal i redigeringsprogrammet.

  3. Kopier ARM-malen fra den forrige delen av denne artikkelen, lim den inn i redigeringsprogrammet og velg deretter Lagre.

  4. Oppgi de nødvendige parameterne.

    Skjermbilde som viser ARM-malparameterne for oppretting av Azure-ressurser.

  5. Velg Se gjennom + Opprett.

  6. Gå gjennom detaljene, og velg deretter Opprett.

Verifiser Azure-ressursene

For å verifisere om Azure-ressursene ble opprettet og riktig konfigurert, kan du følge denne fremgangsmåten.

  • Logg på Azure-portalen, og gå til ressursgruppen som inneholder Azure-ressursene. Du skal se ressurser som har navnene du har angitt i parameterne for PowerShell-skriptet eller ARM-malen.
  • Åpne Key Vault-ressursen, og bekreft at SAS-tokenet for Azure-lagringskontoen er opprettet og har den riktige verdien.