【问题标题】:Upload Key Vault Certificate and access it in App Service through ARM Template上传 Key Vault 证书并通过 ARM 模板在 App Service 中访问
【发布时间】:2022-01-24 14:23:33
【问题描述】:

我们需要创建一个函数应用程序来访问 Office 365 实例。访问使用证书身份验证。因此,我们将证书上传到 Azure Key Vault,并且需要从 Key Vault 导入证书。

我们正在使用 ARM 模板进行 Azure 资源部署。我们正在尝试创建链接中提到的 Azure Key Vault 证书

https://erwinstaal.nl/posts/using-an-arm-template-to-deploy-your-ssl-certificate-stored-in-keyvault-on-an-web-app/

upload .pfx certificate through azure devops pipeline

如上页所述,我们可以在 Key Vault 中创建新机密。但是,我们在证书列表中看不到导入的证书(在 Azure 门户 UI 中检查时),而且我们无法在 Function App 中导入证书。当前的 ARM Template Key Vault commandlet 是否不支持此功能?如何解决这个问题?

【问题讨论】:

  • 如果回答对您有帮助,请Accept it as an Answer,以便遇到相同问题的其他人可以找到此解决方案并解决他们的问题。

标签: azure azure-keyvault arm-template


【解决方案1】:

如上页所述,我们可以在 密钥库。但是,我们在列表中没有看到导入的证书 证书(在 Azure 门户 UI 中检查时)

这是因为 ARM 模板没有上传证书的属性,因此 它存储了 PFX 证书的 base64 编码值在 application/x-pkcs12 中的 Secret 中,如下所示:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
      "keyVault": {
        "type": "string",
        "defaultValue" :"funccertimporttestkv"
      },
      "TestCedential_1": {
        "type": "secureString",
        "defaultValue":"MIIKYAIBAzCCChwXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXhp4XPejOrOIgc9/6dkfBBSgxY73wtbf+G3N7KTYP1LKKHS0YwICB9A="
      },
      "TestCedentialName_1": {
        "type": "string",
        "defaultValue": "funcAppValidationCert"
      }
    },
    "variables": {
    },
    "resources": [
      {
        "type": "Microsoft.KeyVault/vaults/secrets",
        "name": "[concat(parameters('keyVault'), '/', parameters('TestCedentialName_1'))]",
        "apiVersion": "2015-06-01",
        "properties": {
          "contentType": "application/x-pkcs12",
          "value": "[parameters('TestCedential_1')]"
        }
      }
    ],
    "outputs": {}
  }


我们无法在 Function App 中导入证书。是 当前的 ARM Template Key Vault commandlet 不支持此功能? 如何解决这个问题?

如果您使用如下模板:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "envName": {
            "defaultValue": "qa",
            "type": "String"
        },
        "certificateName": {
            "type": "string",
            "defaultValue": "funcAppValidationCert"
        },
        "domainName": {
            "type": "string",
            "defaultValue": "localhost"
        },
        "keyvaultName": {
            "type": "string",
            "defaultValue": "funccertimporttestkv"
        },
        "password": {
            "type": "string",
            "defaultValue": "Password@1234"
        }
    },
    "variables":{
        "functionStorageAccountName" :"[concat('storaccfn',parameters('envName'),resourceGroup().location)]",
        "appServicePlanName" :"[concat('plan-myapp-',parameters('envName'),resourceGroup().location)]",
        "sitesFunctionAppName" :"[concat('func-ans-',parameters('envName'),resourceGroup().location)]"
    },
    "resources": [ 
        {
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2021-04-01",
            "name": "[variables('functionStorageAccountName')]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "Standard_LRS",
                "tier": "Standard"
            },
            "kind": "Storage",
            "properties": {
                "supportsHttpsTrafficOnly": true
            }
        },
        {
            "type": "Microsoft.Web/serverfarms",
            "apiVersion": "2018-02-01",
            "name": "[variables('appServicePlanName')]",
            "location": "[resourceGroup().location]",
            "sku": {
                "name": "S1",
                "tier": "Standard",
                "size": "S1",
                "family": "S",
                "capacity": 1
            },
            "kind": "app",
            "properties": {
                "perSiteScaling": false,
                "maximumElasticWorkerCount": 1,
                "isSpot": false,
                "reserved": false,
                "isXenon": false,
                "hyperV": false,
                "targetWorkerCount": 0,
                "targetWorkerSizeId": 0
            }
        },
        {
            "type": "Microsoft.Web/sites",
            "apiVersion": "2018-11-01",
            "name": "[variables('sitesFunctionAppName')]",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
        "[resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName'))]"
            ],
            "kind": "functionapp",
    "identity": {
        "type": "SystemAssigned"
    },
            "properties": {
                "enabled": true,
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]",
                "httpsOnly": true,
                "siteConfig": {
            "appSettings":[
                {
                    "name": "AzureWebJobsStorage",
                    "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('functionStorageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName')),'2017-06-01').keys[0].value)]"
                },
                {
                    "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                    "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('functionStorageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('functionStorageAccountName')),'2017-06-01').keys[0].value)]"
                },
                {
                    "name": "WEBSITE_CONTENTSHARE",
                    "value": "[toLower(variables('sitesFunctionAppName'))]"
                },
                {
                    "name": "FUNCTIONS_EXTENSION_VERSION",
                    "value": "~3"
                },
                {
                    "name": "FUNCTIONS_WORKER_RUNTIME",
                    "value": "dotnet"
                },
                {
                    "name": "WEBSITE_RUN_FROM_PACKAGE",
                    "value": "1"
                },
                {
                    "name": "WEBSITE_TIME_ZONE",
                    "value": "UTC"
                }
            ]
                }
            }
        },
        {
            "type": "Microsoft.Web/sites/hostNameBindings",
            "apiVersion": "2016-08-01",
            "name": "[concat(variables('sitesFunctionAppName'), '/', parameters('domainName'))]",
            "location": "[resourceGroup().location]",
            "dependsOn": [
                "[resourceId('Microsoft.Web/certificates', parameters('certificateName'))]",
                 "[resourceId('Microsoft.Web/sites', variables('sitesFunctionAppName'))]"
            ],
            "properties": {
                "siteName": "[variables('sitesFunctionAppName')]",
                "hostNameType": "Verified",
                "sslState": "SniEnabled",
                "thumbprint": "[reference(resourceId('Microsoft.Web/certificates', parameters('certificateName'))).Thumbprint]"
            }
        },
        {
            "type": "Microsoft.Web/certificates",
            "name": "[parameters('certificateName')]",
            "apiVersion": "2016-03-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "keyVaultId": "[resourceId('Microsoft.KeyVault/vaults', parameters('keyvaultName'))]",
                "keyVaultSecretName": "[parameters('certificateName')]",
                "password": "[parameters('password')]",
                "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
            },
            "dependsOn":[
                    "[resourceId('Microsoft.Web/sites', variables('sitesFunctionAppName'))]"
            ]
        }
     ]
 }

并面临一个错误请求的问题,即无法访问密钥库,如下所示:

然后添加Microsoft.Azure.CertificateRegistration(即ObjectId:ed47c2a1-bd23-4341-b39c-f4fd69138dd3),Microsoft Azure App Service (Internal)(即ObjectId:505e3754-d8a9-4f8b-97b6-c3e48ac7a337@3) (即 ObjectId : f8daea97-62e7-4026-becf-13c2ea98e8b4)在 keyvault 的访问策略中。


如果您在解决上述问题后得到以下结果,那么请检查您是否已将证书值转换为正确的 base64 编码值

那么你可以参考这个SO thread来正确提供证书的base64值。


输出:

成功部署后,您可以看到以下 TLS/SSL 设置:

【讨论】:

  • 完美!你的评论真的帮助了我!非常感谢!
猜你喜欢
  • 1970-01-01
  • 2018-09-22
  • 1970-01-01
  • 2020-04-21
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
相关资源
最近更新 更多