首页 > 解决方案 > 如何通过 Azure DevOps Release Pipeline 中的 Azure Powershell 更新暂存槽的 IP 白名单?

问题描述

我有一个托管在 Azure 中的应用程序,我使用 Azure DevOps 来管理我的构建和发布管道。作为发布的一部分,我通过向根 url 发出请求来预热应用程序(例如https://myapp.azurewebsites.net)。为了提出这个请求,我必须首先确保运行部署的托管构建代理可以访问该 url(否则我会得到 403)。我编写了一个简短的 powershell 脚本来实现这一点,并将其放入 Azure Powershell 任务中。它将构建代理的 IP 添加到应用服务的 IpSecurityConfiguration。到目前为止,一切都很好。它非常适合只是应用程序的应用程序。当我尝试在暂存环境中使用它时,它会失败。当我们发布到生产环境时,我们首先将代码推送到一个暂存槽,然后在我们运行测试并确保一切正常时将其翻转以运行。正确处理应用程序服务的 IpSecurityConfiguration 的 powershell 脚本在暂存槽上不起作用。要访问暂存槽,我们使用 myappname/slots/staging 变量 $(WebApiName),通常它只是应用服务本身的名称。同样,如果我从本地环境运行脚本,这将非常有效,它只会在管道中失败。代码如下:

# Whitelist Azure Agent IPs

$agentIP = Invoke-RestMethod http://ipinfo.io/json | Select -exp ip

Write-Host "Connecting to Azure"

$APIVersion = ((Get-AzureRmResourceProvider -ProviderNamespace Microsoft.Web).ResourceTypes | Where-Object ResourceTypeName -eq sites).ApiVersions[0]
Write-Host "API Version is $APIVersion. Getting web app config for $(WebApiName) in $(ResourceGroupName)"

$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites/config -ResourceName $(WebApiName) -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)


Write-Host "Got web app config: $WebApiConfig" 

$webIP = [PSCustomObject]@{
                          ipAddress = "$agentIP/32";
                          action = "Allow";
                          tag = 'Default';
                          priority = 300;
                          name = $agentIP.ToString();
                          description = $agentIP.ToString() 
                                }
Write-Host "Adding $agentIP to security restrictions"

$WebApiConfig.Properties.ipSecurityRestrictions += $webIP
Write-Host "Updating security restrictions"
# update app restrictions, do not prompt for confirmation
$result = Set-AzureRmResource -ResourceId $WebApiConfig.ResourceId -Properties $WebApiConfig.Properties -ApiVersion $APIVersion -Force

为了使水有些混乱,我可以通过更改在本地获得完全相同的代码以完美地与暂存槽配合使用

$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites/config -ResourceName $(WebApiName) -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)

$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites -ResourceName $(WebApiName)/config -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)

但这在 Azure Powershell 任务中不起作用。相反,我无法部署到任何环境,因为在尝试访问 $WebApiConfig 对象上的 IpSecurityRestrictions 时任务失败。例外是“ Exception setting "ipSecurityRestrictions": "The property 'ipSecurityRestrictions' cannot be found on this object. Verify that the property exists and can be set.

正如我之前所说,如果我在本地以这种形式运行脚本,它会完美运行。显然,我必须手动替换来自构建管道的变量,但除此之外,在我的本地机器上完全按照我想要的方式工作的代码和在发布中失败的代码之间没有区别。您可以通过将 $(WebApiName) 换成有效的应用程序服务名称和 $(ResourceGroupName) 换出应用程序服务所在的资源组来验证这一点。我在输出 $WebApiConfig 的大约一半处放了一条线,以便我可以看到什么是的,在我的本地机器上我看到了一个有效的对象,而在任务的输出中我什么也没得到。该行只是说“得到网络应用程序配置:”

有人有什么想法吗?

最后一件事,以防有人想知道。我这样做不是将微软列表(https://www.microsoft.com/en-us/download/confirmation.aspx?id=41653)中的所有IP列入白名单,原因有两个,首先它更容易维护我们自己的 IP 的简短列表,其次,Azure 处理这些 CIDR 定义的方式似乎存在一个错误,因为在我们的部署期间,即使我们将整个文件列入白名单,在这些范围内的 IP 也经常被阻止。这样,我只需将当前正在动态使用的任何 IP 添加到白名单中,并在完成后将其删除。假设我可以让它工作......

标签: powershellazure-devopsazure-pipelinesazure-web-app-service

解决方案


终于想出了解决这个问题的办法。为了使用插槽,资源类型必须略有不同。此行适用于 Azure Powershell 任务:

$WebApiConfig = (Get-AzureRmResource -ResourceType Microsoft.Web/sites/slots/config -ResourceName $(WebApiName) -ResourceGroupName $(ResourceGroupName) -ApiVersion $APIVersion)

发帖以防其他人遇到同样的问题。我可以确认,我采用的方法在管理构建代理对 Azure 站点的访问方面非常有效,并且可以避免大量使用 Microsoft 的构建代理 xml 文件。


推荐阅读