แชร์ผ่าน


สร้างทรัพยากร Azure โดยใช้เทมเพลต Azure PowerShell หรือ ARM

บทความนี้จะอธิบายวิธีการใช้เทมเพลต Microsoft Azure PowerShell หรือ Azure Resource Manager (ARM) เพื่อสร้างทรัพยากร Azure ที่ซึ่งต้องใช้ในการออกใบแจ้งหนี้อิเล็กทรอนิกส์

เมื่อต้องการเปิดใช้งานการออกใบแจ้งหนี้ทางอิเล็กทรอนิกส์ใน Dynamics 365 Finance คุณต้องสร้างและตั้งค่าคอนฟิกทรัพยากร Azure หลายรายการ เช่น Azure Key Vault, บัญชีที่เก็บข้อมูล Azure และคอนเทนเนอร์บัญชีที่เก็บข้อมูล Azure กระบวนการนี้อาจใช้เวลานานและมีข้อผิดพลาดถ้ามีการดำเนินการด้วยตนเอง เพื่อให้กระบวนการนี้ง่ายขึ้นและเป็นอัตโนมัติ คุณสามารถใช้สคริปต์ PowerShell หรือเทมเพลต ARM ที่จะสร้างและตั้งค่าคอนฟิกทรัพยากร Azure ที่จำเป็นทั้งหมดให้คุณ

ใช้ Azure PowerShell

ข้อกำหนดเบื้องต้น

ก่อนที่คุณจะเรียกใช้สคริปต์ PowerShell คุณต้องดำเนินการตามข้อกำหนดเบื้องต้นต่อไปนี้:

  • คุณมีการบอกรับเป็นสมาชิก Azure ที่มีสิทธิ์เพียงพอที่จะสร้างและจัดการทรัพยากร
  • คุณได้ติดตั้งโมดูล Azure PowerShell แล้ว (ขอแนะนำให้ใช้เวอร์ชันที่รองรับของ PowerShell เวอร์ชัน 7 หรือใหม่กว่า กับโมดูล Azure PowerShell)
  • คุณมีไฟล์สคริปต์ PowerShell

สคริปต์ 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."

เรียกใช้สคริปต์ PowerShell

ในการเรียกใช้สคริปต์ PowerShell ให้ทำตามขั้นตอนเหล่านี้

  1. เปิด PowerShell และไปที่โฟลเดอร์ที่เป็นที่ตั้งของไฟล์สคริปต์ PowerShell และไฟล์การตั้งค่าคอนฟิก

  2. เมื่อต้องการเรียกใช้สคริปต์ PowerShell โดยใช้พารามิเตอร์ของคุณเอง ให้เรียกใช้คำสั่งต่อไปนี้

    .\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 ต้องทำตามการดำเนินการต่อไปนี้

  1. สคริปต์จะแจ้งให้คุณลงชื่อเข้าใช้บัญชี Azure ของคุณ ป้อนข้อมูลประจำตัวของคุณ แล้วเลือก ลงชื่อเข้าใช้
  2. สคริปต์จะระบุว่ามีหลักของบริการ e-invoice อยู่แล้วหรือไม่ ถ้าไม่มี สคริปต์จะสร้างให้
  3. สคริปต์จะระบุว่ามีทรัพยากร Azure ต่อไปนี้อยู่แล้วหรือไม่: กลุ่มทรัพยากร Azure, Azure Key Vault, บัญชีที่เก็บข้อมูล Azure และคอนเทนเนอร์บัญชีที่เก็บข้อมูล Azure ถ้าไม่มีทรัพยากรใดๆ อยู่ สคริปต์จะสร้างและตั้งค่าคอนฟิกทรัพยากรให้
  4. สคริปต์จะสร้างโทเค็นลายเซ็นสำหรับการเข้าถึงที่ใช้ร่วมกัน (SAS) สำหรับคอนเทนเนอร์บัญชีที่เก็บข้อมูลและเพิ่มเป็นข้อมูลลับ Key Vault ใน Key Vault
  5. สคริปต์จะตั้งค่านโยบายการเข้าถึงบน Key Vault เพื่อมอบสิทธิ์ในการ รับ และ แสดงรายการ ให้กับแอปพลิเคชันการออกใบแจ้งหนี้อิเล็กทรอนิกส์
  6. สคริปต์จะสร้างรายละเอียดของทรัพยากร Azure ที่สร้างไว้ รายละเอียดเหล่านี้รวมถึงชื่อและ URL

หมายเหตุ

คุณสามารถเรียกใช้สคริปต์เดียวกันได้ ถ้าคุณต้องต่ออายุโทเค็น SAS ที่หมดอายุ ในกรณีนี้ สคริปต์จะไม่สร้างทรัพยากร แต่จะสร้างโทเค็น SAS ใหม่และอัปเดตโทเค็น SAS นั้นใน Key Vault

ใช้เทมเพลต ARM

เทมเพลต 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": {}
}

ปรับใช้เทมเพลต ARM

เพื่อปรับใช้เทมเพลต ARM ให้ทำตามขั้นตอนเหล่านี้

  1. ลงชื่อเข้าใช้พอร์ทัล Azure และค้นหา ปรับใช้เทมเพลตที่กำหนดเอง

  2. เลือก สร้างเทมเพลตของคุณเองในโปรแกรมแก้ไข

  3. คัดลอกเทมเพลต ARM ที่ให้ไว้ในส่วนก่อนหน้านี้ของบทความนี้ วางลงในโปรแกรมแก้ไข แล้วเลือก บันทึก

  4. ระบุพารามิเตอร์ที่ต้องใช้

    จับภาพที่แสดงพารามิเตอร์เทมเพลต ARM สำหรับการสร้างทรัพยากร Azure

  5. เลือก ตรวจสอบและสร้าง

  6. ตรวจดูรายละเอียด แล้วเลือก สร้าง

ตรวจสอบทรัพยากร Azure

หากต้องการตรวจสอบว่าทรัพยากร Azure ได้รับการสร้างและตั้งค่าคอนฟิกไว้ถูกต้องหรือไม่ คุณสามารถตามขั้นตอนเหล่านี้

  • ลงชื่อเข้าใช้พอร์ทัล Azure และไปที่กลุ่มทรัพยากรที่มีทรัพยากร Azure คุณควรเห็นทรัพยากรที่มีชื่อที่คุณระบุไว้ในสคริปต์ PowerShell หรือพารามิเตอร์เทมเพลต ARM
  • เปิดทรัพยากร Key Vault และยืนยันว่าโทเค็น SAS ของบัญชีที่เก็บข้อมูล Azure ได้รับการสร้างขึ้นแล้วและมีค่าที่ถูกต้อง