来自 Azure Git Repo 的带有 Powershell 文件的 Runbook 的 Azure ARM 模板

Azure ARM Template for runbook with Powershell file from Azure Git Repo

我们正在尝试使用定期查询 Log Analytics 的 Powershell 部署 runbook。我们在门户网站上使用它,现在我们正在尝试构建一个 ARM 模板,以便将来部署到其他环境。我们在同一个 Azure Devops Git 存储库中有我们的 ARM (json) 模板和 PS1 文件,我们甚至尝试在模板中硬编码 PS1 文件的路径但是它不起作用。有人可以在这里帮助我们了解我们做错了什么。以下是 ARM 模板:-

{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
    "automationAccountName": {
        "type": "string",
        "defaultValue": "Automation-XXX-INFRA-MONITORING",
        "metadata": {
            "description": "Automation Account"
        }
    },
    "automationRegion": {
        "defaultValue": "eastus2",
        "type": "string",
        "allowedValues": [
            "westeurope",
            "southeastasia",
            "eastus2",
            "southcentralus",
            "japaneast",
            "northeurope",
            "canadacentral",
            "australiasoutheast",
            "centralindia",
            "westcentralus"
        ],
        "metadata": {
            "description": "Specify the region for your automation account"
        }
    },
    "_artifactsLocation": {
        "type": "string",
        "defaultValue": "https://ABCD.visualstudio.com/3Pager/_git/Infrastructure?path=%2FAzure.Infra%2FAppInsights%2FMonthOverMonthTrendAnalysisReport.ps1&version=GBmaster",
        "metadata": {
            "description": "URI to artifacts location"
        }
    },
    "_artifactsLocation1": {
        "type": "string",
        "defaultValue": "https://ABCD.visualstudio.com/3Pager/_git/Infrastructure?path=%2FAzure.Infra%2FAppInsights%2FMonthOverMonthTrendAnalysisReport.ps1&version=GBmaster",
        "metadata": {
            "description": "URI to artifacts location"
        }
    }
},
"variables": {
    "asrScripts": {
        "runbooks": [
            {
                "name": "Test_Runbook",
                "url": "[parameters('_artifactsLocation')]",
                "version": "1.0.0.0",
                "type": "PowerShell",
                "description": "Runbook for month over month trend analysis report"
            }
        ]
      }
},
 "resources": [

    {
        "apiVersion": "2015-10-31",
        "type": "Microsoft.Automation/automationAccounts/runbooks",
        "name": "[concat(parameters('automationAccountName'), '/', variables('asrScripts').runbooks[copyIndex()].Name)]",
        "location": "[parameters('automationRegion')]", 
        "copy": {
            "name": "runbooksLoop",
            "count": "[length(variables('asrScripts').runbooks)]"
        },
        "properties": {
            "description": "[variables('asrScripts').runbooks[copyIndex()].description]",
            "runbookType": "[variables('asrScripts').runbooks[copyIndex()].type]",
            "logProgress": false,
            "logVerbose": true,
             "publishContentLink": { 
                 "uri":"[parameters('_artifactsLocation1')]",
                 "version": "[variables('asrScripts').runbooks[copyIndex()].version]"                  } 

        }
    }
],
"outputs": {}

}

您正在向 ARM 发送一个 URI,告诉它在哪里可以找到运行手册。创建 AutomationAccount/runbooks 资源类型后,它将对 publishContentLink.url 进行 GET 调用,以便从 URI 获取内容。如果 Azure 无法访问该 URI(可能是您的 visualstudio.com URI 无法 public 访问),那么它将无法访问 runbook 内容并且部署将失败。

解决方案是确保 publishContentLink URI 可供 Azure 自动化服务访问。您可以通过几种方式做到这一点:

  1. 将内容放入 public 可访问的 URI,例如 Github 或 public Blob 存储容器。
  2. 为内容创建 SAS 令牌。 https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-tutorial-secure-artifacts shows an example of how to do this with Azure Storage, or https://xebia.com/blog/setting-up-vsts-with-arm-templates/ 因为用 VSTS 做到了。

留在这里以防有人遇到类似问题。对于私有 Azure DevOps Repo,可以通过 Azure Function 使用 HTTP 触发器和以下 PowerShell 脚本来解决:

using namespace System.Net

# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
    
# Interact with query parameters or the body of the request.
$adouri = $Request.Query.adouri
$pat = $Request.Query.pat

if (!$adouri){
    $response = "Please pass uri"
    Write-Warning "URI not passed" -Warning
} elseif (!$pat){
    $response = "Please pass pat"
    Write-Warning "PAT not passed" -Warning
} else {
    $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f "", $pat)))
    $headers = @{
        "Authorization" = ("Basic {0}" -f $base64AuthInfo)
    }
    
    $response = Invoke-RestMethod -Uri $adouri -Method Get -ContentType "application/text" -Headers $headers
}

# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
    StatusCode = [HttpStatusCode]::OK
    Body = $response
})

一旦函数准备就绪,就可以直接从 ARM 模板调用它,例如:

"variables": {    
    "runbookUri": "https://[function name].azurewebsites.net/api/[trigger name]?adouri=https://dev.azure.com/[ADO Organization]/[ADO project]/_apis/git/repositories/[Repo]/items?path=%2F[folder]%2F[subfolder]%2Fscript.ps1&pat=[token]"
  },
"resources": [    
{
  "type": "Microsoft.Automation/automationAccounts/runbooks",
  "apiVersion": "2018-06-30",
  "name": "[name]",
  "location": "[location]"
  "properties": {
    "runbookType": "PowerShell",
    "logVerbose": false,
    "logProgress": false,
    "logActivityTrace": 0,
    "publishContentLink": {
      "uri": "[variables('runbookUri')]"
    }
  }
}]

令牌只是来自 Azure DevOps 的个人访问令牌。为了确保它的安全,它可以从秘密 ADO 变量或 Azure KeyVault 传递到 ARM 模板。

我通过使用 Terraform 模板克服了这个限制。它们提供了使用本地路径将自定义内容发布到 Runbook 的可能性。因此,您可以直接从 Git 存储库文件系统(您的电脑)执行此操作,或者通过将 Azure Pipeline 链接到您的存储库并将该文件用作工件。

如果有兴趣,请查看“示例用法 - 自定义内容”中的 https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/automation_runbook