你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

教程:使用虚拟网络集成隔离 Azure 应用服务中的后端通信

在本文中,你将配置一个应用服务应用,该应用能够与后端服务进行网络隔离的安全通信。 教程:使用密钥保管库保护从应用服务进行的认知服务连接中介绍了使用的示例方案。 完成后,你将获得一个应用服务应用,它通过 Azure 虚拟网络访问密钥保管库和 Azure AI 服务;其他流量均不能访问这些后端资源。 使用虚拟网络集成专用终结点在虚拟网络中隔离所有流量。

作为多租户服务,从应用服务应用到其他 Azure 服务的出站网络流量与其他应用甚至其他订阅共享同一环境。 虽然流量本身可以加密,但某些方案可能需要通过将后端通信与其他网络流量相隔离来提高安全级别。 这些方案通常由拥有较高专业水平的大型企业使用,但应用服务通过虚拟网络集成使得这种方案不再遥不可及。

scenario architecture

使用此体系结构:

  • 发往后端服务的公共流量将被阻止。
  • 来自应用服务的出站流量将路由到虚拟网络并可以进入后端服务。
  • 应用服务能够通过专用 DNS 区域对后端服务执行 DNS 解析。

要学习的知识:

  • 为应用服务虚拟网络集成创建虚拟网络和子网
  • 创建专用 DNS 区域
  • 创建专用终结点
  • 在应用服务中配置虚拟网络集成

先决条件

本教程假设你已完成教程:使用密钥保管库保护从应用服务进行的认知服务连接,并已创建语言检测器应用。

本教程沿用上一篇教程中的以下环境变量。 请务必正确设置这些变量。

    groupName=myKVResourceGroup
    region=westeurope
    csResourceName=<cs-resource-name>
    appName=<app-name>
    vaultName=<vault-name>

创建虚拟网络和子网

  1. 创建虚拟网络。 将 <virtual-network-name> 替换为唯一名称。

    # Save vnet name as variable for convenience
    vnetName=<virtual-network-name>
    
    az network vnet create --resource-group $groupName --location $region --name $vnetName --address-prefixes 10.0.0.0/16
    
  2. 为应用服务虚拟网络集成创建子网。

    az network vnet subnet create --resource-group $groupName --vnet-name $vnetName --name vnet-integration-subnet --address-prefixes 10.0.0.0/24 --delegations Microsoft.Web/serverfarms --disable-private-endpoint-network-policies false
    

    对于应用服务,建议在虚拟网络集成子网中至少包含 /26 CIDR 块(请参阅虚拟网络集成子网要求)。 /24 绰绰有余。 --delegations Microsoft.Web/serverfarms 指定将子网委托给应用服务虚拟网络集成

  3. 为专用终结点创建另一个子网。

    az network vnet subnet create --resource-group $groupName --vnet-name $vnetName --name private-endpoint-subnet --address-prefixes 10.0.1.0/24 --disable-private-endpoint-network-policies true
    

    对于专用终结点子网,必须禁用专用终结点网络策略

创建专用 DNS 区域

密钥保管库和 Azure AI 服务资源放在专用终结点的后面,因此需要为这些资源定义专用 DNS 区域。 这些区域用于托管专用终结点的 DNS 记录,并允许客户端按名称查找后端服务。

  1. 创建两个专用 DNS 区域,一个用于 Azure AI 服务资源,另一个用于密钥保管库。

    az network private-dns zone create --resource-group $groupName --name privatelink.cognitiveservices.azure.com
    az network private-dns zone create --resource-group $groupName --name privatelink.vaultcore.azure.net
    

    有关这些设置的详细信息,请参阅 Azure 专用终结点 DNS 配置

  2. 将专用 DNS 区域链接到虚拟网络。

    az network private-dns link vnet create --resource-group $groupName --name cognitiveservices-zonelink --zone-name privatelink.cognitiveservices.azure.com --virtual-network $vnetName --registration-enabled False
    az network private-dns link vnet create --resource-group $groupName --name vaultcore-zonelink --zone-name privatelink.vaultcore.azure.net --virtual-network $vnetName --registration-enabled False
    

创建专用终结点

  1. 在虚拟网络的专用终结点子网中,为认知服务创建专用终结点。

    # Get Cognitive Services resource ID
    csResourceId=$(az cognitiveservices account show --resource-group $groupName --name $csResourceName --query id --output tsv)
    
    az network private-endpoint create --resource-group $groupName --name securecstext-pe --location $region --connection-name securecstext-pc --private-connection-resource-id $csResourceId --group-id account --vnet-name $vnetName --subnet private-endpoint-subnet
    
  2. 为 Azure AI 服务专用终结点创建 DNS 区域组。 DNS 区域组是专用 DNS 区域和专用终结点之间的链接。 当专用终结点进行了更新时,此链接可帮助你自动更新专用 DNS 区域。

    az network private-endpoint dns-zone-group create --resource-group $groupName --endpoint-name securecstext-pe --name securecstext-zg --private-dns-zone privatelink.cognitiveservices.azure.com --zone-name privatelink.cognitiveservices.azure.com
    
  3. 阻止流向 Azure AI 服务资源的公共流量。

    az rest --uri $csResourceId?api-version=2021-04-30 --method PATCH --body '{"properties":{"publicNetworkAccess":"Disabled"}}' --headers 'Content-Type=application/json'
    
    # Repeat following command until output is "Succeeded"
    az cognitiveservices account show --resource-group $groupName --name $csResourceName --query properties.provisioningState
    

    注意

    确保更改操作的预配状态为 "Succeeded"。 然后可以观察示例应用的行为变更。 你仍可以加载该应用,但如果尝试单击“检测”按钮,将会收到 HTTP 500 错误。 该应用已断开其通过共享网络与 Azure AI 服务资源建立的连接。

  4. 针对密钥保管库重复上述步骤。

    # Create private endpoint for key vault
    vaultResourceId=$(az keyvault show --name $vaultName --query id --output tsv)
    az network private-endpoint create --resource-group $groupName --name securekeyvault-pe --location $region --connection-name securekeyvault-pc --private-connection-resource-id $vaultResourceId --group-id vault --vnet-name $vnetName --subnet private-endpoint-subnet
    # Create DNS zone group for the endpoint
    az network private-endpoint dns-zone-group create --resource-group $groupName --endpoint-name securekeyvault-pe --name securekeyvault-zg --private-dns-zone privatelink.vaultcore.azure.net --zone-name privatelink.vaultcore.azure.net
    # Block public traffic to key vault
    az keyvault update --name $vaultName --default-action Deny
    
  5. 通过重置应用设置,强制在应用中立即重新提取密钥保管库引用(有关详细信息,请参阅轮换)。

    az webapp config appsettings set --resource-group $groupName --name $appName --settings CS_ACCOUNT_NAME="@Microsoft.KeyVault(SecretUri=$csResourceKVUri)" CS_ACCOUNT_KEY="@Microsoft.KeyVault(SecretUri=$csKeyKVUri)"
    

    注意

    同样,可以观察示例应用的行为变更。 不再可以加载该应用,因为它不再可以访问密钥保管库引用。 该应用已断开其通过共享网络与密钥保管库建立的连接。

这两个专用终结点只能由你创建的虚拟网络内部的客户端访问。 甚至无法通过 Azure 门户中的“机密”页面访问密钥保管库中的机密,因为门户会通过公共 Internet 访问这些机密(请参阅管理已锁定的资源)。

在应用中配置虚拟网络集成

  1. 将应用纵向扩展到受支持的定价层,(请参阅将应用与 Azure 虚拟网络集成)。

    az appservice plan update --name $appName --resource-group $groupName --sku S1
    
  2. 对入站请求强制实施 HTTPS,这与我们的方案无关,但同样也很重要。

    az webapp update --resource-group $groupName --name $appName --https-only
    
  3. 在应用上启用虚拟网络集成。

    az webapp vnet-integration add --resource-group $groupName --name $appName --vnet $vnetName --subnet vnet-integration-subnet
    

    虚拟网络集成允许出站流量直接流入虚拟网络。 默认情况下,只会将 RFC-1918 中定义的本地 IP 流量路由到虚拟网络,这正是专用终结点所需要的。 若要将所有流量路由到虚拟网络,请参阅管理虚拟网络集成路由。 若要通过虚拟网络路由 Internet 流量,也可以使用“路由所有流量”,例如通过 Azure 虚拟网络 NATAzure 防火墙

  4. 在浏览器中,再次导航到 <app-name>.azurewebsites.net 并等待集成生效。 如果收到 HTTP 500 错误,请等待几分钟,然后重试。 如果可以加载页面并获得检测结果,则表示你正在连接到具有密钥保管库引用的 Azure AI 服务终结点。

    注意

    如果经过较长一段时间后仍收到 HTTP 500 错误,再次强制重新提取密钥保管库引用可能会有帮助,如下所示:

    az webapp config appsettings set --resource-group $groupName --name $appName --settings CS_ACCOUNT_NAME="@Microsoft.KeyVault(SecretUri=$csResourceKVUri)" CS_ACCOUNT_KEY="@Microsoft.KeyVault(SecretUri=$csKeyKVUri)"
    

管理已锁定的资源

根据具体的方案,你可能无法通过 Azure 门户、Azure CLI 或 Azure PowerShell 管理受专用终结点保护的资源(例如密钥保管库)。 这些工具都会发出 REST API 调用以通过公共 Internet 访问资源,但会被配置阻止。 下面是访问已锁定的资源的几种做法:

  • 对于密钥保管库,添加本地计算机的公共 IP 以查看或更新受专用终结点保护的机密。
  • 如果本地网络已通过 VPN 网关ExpressRoute 扩展到 Azure 虚拟网络,则你可以直接从本地网络管理受专用终结点保护的资源。
  • 从虚拟网络中的跳转服务器管理受专用终结点保护的资源。
  • 将 Cloud Shell 部署到虚拟网络中

清理资源

在前面的步骤中,你在资源组中创建了 Azure 资源。 如果认为将来不需要这些资源,请在 Cloud Shell 中运行以下命令删除资源组:

az group delete --name $groupName

此命令可能需要花费一点时间运行。

后续步骤