Включение HTTPS в личном домене Azure Front Door с развертыванием шаблона ARM

Я развертываю входную дверь Azure с помощью шаблона ARM и пытаюсь включить HTTPS в личном домене.

Согласно документации Azure для входной двери, существует шаблон быстрого запуска для "Добавить пользовательский домен к входной двери и включить для него трафик HTTPS с помощью управляемого сертификата входной двери, созданного с помощью DigiCert". Однако, хотя при этом добавляется собственный домен, HTTPS не включается.

Глядя на ссылку на шаблон ARM для Front Door, я не вижу очевидного способа включить HTTPS, но, может быть, я что-то упускаю?

Несмотря на дополнительную информацию ниже, я хотел бы иметь возможность включить HTTPS в личном домене Front Door с помощью развертывания шаблона ARM. Возможно ли это сейчас?

Дополнительная информация

Обратите внимание, что существует операция REST для включения HTTPS, но, похоже, это не работает с управляемым сертификатом Front Door -

POST https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/frontDoors/{frontDoorName}/frontendEndpoints/{frontendEndpointName}/enableHttps?api-version=2019-05-01
{
    "certificateSource": "FrontDoor",
    "protocolType": "ServerNameIndication",
    "minimumTLSVersion": "1.2"
}

Также есть AzКомандлет PowerShell для включения HTTP, который действительно работает.

Enable-AzFrontDoorCustomDomainHttps -ResourceGroupName "lmk-bvt-accounts-front-door" -FrontDoorName "my-front-door" -FrontendEndpointName "my-front-door-rg"

5 ответов

ОБНОВЛЕНИЕ: эта реализация в настоящее время кажется нестабильной и работает только с перерывами, что указывает на то, что она, возможно, еще не готова к производству.

Теперь кажется, что это возможно с шаблонами ARM после отслеживания последней версии Front Door API (2020-01-01) спецификации (которые, похоже, еще не полностью опубликованы на справочных сайтах MS):

https://github.com/Azure/azure-rest-api-specs/tree/master/specification/frontdoor/resource-manager/Microsoft.Network/stable/2020-01-01

Есть новый customHttpsConfiguration собственность в frontendEndpoint properties объект:

"customHttpsConfiguration": {
  "certificateSource": "AzureKeyVault" // or "FrontDoor",        
  "minimumTlsVersion":"1.2",
  "protocolType": "ServerNameIndication",

  // Depending on "certificateSource" you supply either:
  "keyVaultCertificateSourceParameters": {
    "secretName": "<secret name>",
    "secretVersion": "<secret version>",
    "vault": {
      "id": "<keyVault ResourceID>"
    }
  }

  // Or:
  "frontDoorCertificateSourceParameters": {
    "certificateType": "Dedicated"
  }
}

Пример управляемого SSL-сертификата KeyVault

Примечание: я проверил это и, похоже, работает.

    {
      "type": "Microsoft.Network/frontdoors",
      "apiVersion": "2020-01-01",
      "properties": {
        "frontendEndpoints": [
         {
            "name": "[variables('frontendEndpointName')]",
            "properties": {
              "hostName": "[variables('customDomain')]",
              "sessionAffinityEnabledState": "Enabled",
              "sessionAffinityTtlSeconds": 0,
              "webApplicationFirewallPolicyLink": {
                "id": "[variables('wafPolicyResourceId')]"
              },
              "resourceState": "Enabled",
              "customHttpsConfiguration": {
                "certificateSource": "AzureKeyVault",        
                "minimumTlsVersion":"1.2",
                "protocolType": "ServerNameIndication",
                "keyVaultCertificateSourceParameters": {
                  "secretName": "[parameters('certKeyVaultSecret')]",
                  "secretVersion": "[parameters('certKeyVaultSecretVersion')]",
                  "vault": {
                    "id": "[resourceId(parameters('certKeyVaultResourceGroupName'),'Microsoft.KeyVault/vaults',parameters('certKeyVaultName'))]"
                  }
                }
              }
            }
          }
        ],
        ...
      }
    }

Пример управляемого SSL-сертификата входной двери

Похоже, что для управляемого сертификата FrontDoor вам нужно будет установить:

Примечание: я не тестировал это

    {
      "type": "Microsoft.Network/frontdoors",
      "apiVersion": "2020-01-01",
      "properties": {
        "frontendEndpoints": [
         {
            "name": "[variables('frontendEndpointName')]",
            "properties": {
              "hostName": "[variables('customDomain')]",
              "sessionAffinityEnabledState": "Enabled",
              "sessionAffinityTtlSeconds": 0,
              "webApplicationFirewallPolicyLink": {
                "id": "[variables('wafPolicyResourceId')]"
              },
              "resourceState": "Enabled",
              "customHttpsConfiguration": {
                "certificateSource": "FrontDoor",        
                "minimumTlsVersion":"1.2",
                "protocolType": "ServerNameIndication",
                "frontDoorCertificateSourceParameters": {
                  "certificateType": "Dedicated"
                }
              }
            }
          }
        ],
        ...
      }
    }

Классическая передняя дверца Azure теперь поддерживает как управляемые сертификаты, так и пользовательские сертификаты для личных доменов. По крайней мере, в официальном репозитории Microsoft есть шаблоны quickstart именно для этих случаев:

Оба они используют подресурс Microsoft.Network/frontdoors/frontendEndpoints/customHttpsConfiguration передней дверцы, в настоящее время с версией API 2020-07-01. Однако в справочнике по шаблонам задокументирован только родительский подресурс .

Имя ресурса customHttpsConfiguration — «по умолчанию», поэтому, когда ресурс указан как ресурс верхнего уровня в шаблоне, его полное имя выглядит примерно так: «myfrontdoorafd/www-example-com/default».

Используя Bicep (который преобразуется в шаблоны JSON ARM и который я настоятельно рекомендую), важная часть шаблона выглядит следующим образом:

      param frontDoorName string
param customDomainName string

var frontEndEndpointCustomName = replace(customDomainName, '.', '-')

resource frontDoor 'Microsoft.Network/frontDoors@2020-01-01' = {
  name: frontDoorName
  properties: {
    frontendEndpoints: [
      {
        name: frontEndEndpointCustomName
        properties: {
          hostName: customDomainName
          ...
        }
      }
      ...
    ]
    ...
  }
  ...
  
  resource frontendEndpoint 'frontendEndpoints' existing = {
    name: frontEndEndpointCustomName
  }
}

// This resource enables a Front Door-managed TLS certificate on the frontend.
resource customHttpsConfiguration 'Microsoft.Network/frontdoors/frontendEndpoints/customHttpsConfiguration@2020-07-01' = {
  parent: frontDoor::frontendEndpoint
  name: 'default'
  properties: {
    protocolType: 'ServerNameIndication'
    certificateSource: 'FrontDoor'
    frontDoorCertificateSourceParameters: {
      certificateType: 'Dedicated'
    }
    minimumTlsVersion: '1.2'
  }
}

Обратите внимание, что развертывание будет выполняться до тех пор, пока сертификат не будет фактически выдан и развернут во всех точках присутствия (PoP) Azure. Это может занять очень много времени и даже завершиться ошибкой из-за RequestTimeout. Если вы хотите просто запустить операцию и позволить ей завершиться асинхронно, используйте, например, подкоманду enable-https в Azure CLI . Даже после сбоя состояние customHttpsProvisioningState находится в состоянии ожидания, и процесс подготовки сертификата может завершиться успешно.

Также обратите внимание, что если у вас много конечных точек внешнего интерфейса и изменения происходят часто, но большинство конечных точек внешнего интерфейса остаются неизменными, шаблон из этого шаблона нельзя обобщить, просто указав несколько экземпляров customHttpsConfiguration для нескольких конечных точек внешнего интерфейса. Такое обобщение неэффективно и, вероятно, достигает предела скорости базового API (429 TooManyRequests), поскольку API вызывается, даже если конечная точка уже имеет конфигурацию HTTPS.

В таком случае я мог использовать вложенные шаблоны и условное развертывание для развертывания подресурса customHttpsConfiguration только в том случае, если свойство customHttpsProvisioningState внешней конечной точки имело значение Disabled. Это работает нормально даже с десятками конечных точек внешнего интерфейса, когда добавляется новая конечная точка внешнего интерфейса (и она должна получить управляемый сертификат). Даже в режиме развертывания Complete сохраняется однажды примененная конфигурация.

Мне удалось успешно выполнить вызов enableHttps REST с помощью API управления Azure.

Я получил успешный ответ и могу видеть результаты ресурсов на сайтах https://portal.azure.com/ и https://resource.azure.com/. Однако я почти уверен, что Management API и методы PowerShell - единственные способы, которые поддерживаются прямо сейчас. Поскольку, вероятно, требуется некоторая проверка сертификата и обработки, они еще не включили это в шаблоны ARM. Учитывая, что проверка может быть довольно важной, лучше всего сначала подтвердить, что ваша конфигурация работает в пользовательском интерфейсе, прежде чем автоматизировать ее (IMHO).

Согласно этому обсуждению это кажется возможным только через REST API (см., Например, этот ответ ), а не (пока) через ARM.

Мне удалось заставить это работать с шаблоном ARM. По приведенной ниже ссылке показано, как это сделать, используя Azure Front Door в качестве источника сертификата:https://github.com/Azure/azure-quickstart-templates/blob/master/101-front-door-custom-domain/azuredeploy.json

Я почерпнул из этого вдохновение для развертывания сертификата из Azure Key Vault для личного домена. Вот соответствующие элементы из шаблона ARM, который я использую:

      {
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "hubName": {
            "type": "string",
            "metadata": {
                "description": "Name to assign to the hub. This name will prefix all resources contained in the hub."
            }
        },
        "frontdoorName": {
            "type": "string",
            "metadata": {
                "description": "Name to assign to the Frontdoor instance"
            }
        },
        "frontdoorCustomDomain": {
            "type": "string",
            "metadata": {
                "description": "The custom domain name to be applied to the provisioned Azure Frontdoor instance"
            }
        },
        "keyVaultCertificateName": {
            "type": "string",
            "metadata": {
                "description": "Name of the TLS certificate in the Azure KeyVault to be deployed to Azure Frontdoor for supporting TLS over a custom domain",
                "assumptions": [
                    "Azure KeyVault containing the TLS certificate is deployed to the same resource group as the resource group where Azure Frontdoor will be deployed to",
                    "Azure KeyVault name is the hub name followed by '-keyvault' (refer to variable 'keyVaultName' in this template)"
                ]
            }
        },
        ...
    },
    "variables": {
        "frontdoorName": "[concat(parameters('hubName'), '-', parameters('frontdoorName'))]",
        "frontdoorEndpointName": "[concat(variables('frontdoorName'), '-azurefd-net')]",
        "customDomainFrontdoorEndpointName": "[concat(variables('frontdoorName'), '-', replace(parameters('frontdoorCustomDomain'), '.', '-'))]",
        "keyVaultName": "[concat(parameters('hubName'), '-keyvault')]",
        "frontdoorHostName": "[concat(variables('frontdoorName'), '.azurefd.net')]",
        ...
    },
    "resources": [
        {
            "type": "Microsoft.Network/frontdoors",
            "apiVersion": "2020-05-01",
            "name": "[variables('frontdoorName')]",
            "location": "Global",
            "properties": {
                "resourceState": "Enabled",
                "backendPools": [...],
                "healthProbeSettings": [...],
                "frontendEndpoints": [
                    {
                        "id": "[concat(resourceId('Microsoft.Network/frontdoors', variables('frontdoorName')), concat('/FrontendEndpoints/', variables('frontdoorEndpointName')))]",
                        "name": "[variables('frontdoorEndpointName')]",
                        "properties": {
                            "hostName": "[variables('frontdoorHostName')]",
                            "sessionAffinityEnabledState": "Enabled",
                            "sessionAffinityTtlSeconds": 0,
                            "resourceState": "Enabled"
                        }
                    },
                    {
                        "id": "[concat(resourceId('Microsoft.Network/frontdoors', variables('frontdoorName')), concat('/FrontendEndpoints/', variables('customDomainFrontdoorEndpointName')))]",
                        "name": "[variables('customDomainFrontdoorEndpointName')]",
                        "properties": {
                            "hostName": "[parameters('frontdoorCustomDomain')]",
                            "sessionAffinityEnabledState": "Enabled",
                            "sessionAffinityTtlSeconds": 0,
                            "resourceState": "Enabled"
                        }
                    }
                ],
                "loadBalancingSettings": [...],
                "routingRules": [...],
                "backendPoolsSettings": {
                    "enforceCertificateNameCheck": "Enabled",
                    "sendRecvTimeoutSeconds": 30
                },
                "enabledState": "Enabled",
                "friendlyName": "[variables('frontdoorName')]"
            }
        },
        {
            "type": "Microsoft.Network/frontdoors/frontendEndpoints/customHttpsConfiguration",
            "apiVersion": "2020-07-01",
            "name": "[concat(variables('frontdoorName'), '/', variables('customDomainFrontdoorEndpointName'), '/default')]",
            "dependsOn": [
                "[resourceId('Microsoft.Network/frontdoors', variables('frontdoorName'))]"
            ],
            "properties": {
                "protocolType": "ServerNameIndication",
                "certificateSource": "AzureKeyVault",
                "minimumTlsVersion": "1.2",
                "keyVaultCertificateSourceParameters": {
                    "secretName": "[parameters('keyVaultCertificateName')]",
                    "vault": {
                        "id": "[resourceId(resourceGroup().name, 'Microsoft.KeyVault/vaults', variables('keyVaultName'))]"
                    }
                }
            }
        }
    ]
}
Другие вопросы по тегам