部署期间如何使用 Azure Key Vault 传递安全参数值?

Posted

技术标签:

【中文标题】部署期间如何使用 Azure Key Vault 传递安全参数值?【英文标题】:How to use Azure Key Vault to pass secure parameter value during deployment? 【发布时间】:2020-10-02 10:28:46 【问题描述】:

我有一个用于在 Azure 管道中部署 Service Fabric 集群的 ARM 模板:

- task: AzureResourceManagerTemplateDeployment@3
  displayName: 'Deploy SF cluster'
  inputs:
    deploymentScope: 'Resource Group'
    subscriptionId: '$ parameters.SubscriptionId '
    azureResourceManagerConnection: '$ parameters.ArmConnection '
    action: 'Create Or Update Resource Group'
    resourceGroupName: '$ parameters.ResourceGroupName '
    location: 'West Europe'
    templateLocation: 'Linked artifact'
    csmFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster.json'
    csmParametersFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster-params.json'
    overrideParameters: '-certificateThumbprint $(Thumbprint) -sourceVaultResourceId $(KeyvaultId) -certificateUrlValue $(SecretId)'
    deploymentMode: 'Incremental'

当我使用 ARM 模板时(因为在 5 个不同的管道中使用了很多天):

"osProfile": 
    "adminUsername": "RdpUsername",
    "adminPassword": "RdpPassword",

    "computernamePrefix": "[variables('vmNodeType0Name')]",
    "secrets": [
        
            "sourceVault": 
                "id": "[parameters('sourceVaultResourceId')]"
            ,
            "vaultCertificates": [
                
                    "certificateStore": "My",
                    "certificateUrl": "[parameters('certificateUrlValue')]"
                
            ]
        
    ]
,

然而,拥有硬编码的 RDP 凭据是一个安全问题,所以我想Use Azure Key Vault to pass secure parameter value during deployment

所以我将 2 个随机秘密字符串添加到 Keyvault,它在管道中较早部署,然后尝试:

"osProfile": 
    "adminUsername": 
        "reference": 
            "keyVault": 
                "id": "[parameters('sourceVaultResourceId')]"
            ,
            "secretName": "RdpUsername"
        
    ,
    "adminPassword": 
        "reference": 
            "keyVault": 
                "id": "[parameters('sourceVaultResourceId')]"
            ,
            "secretName": "RdpPassword"
        
    ,

    "computernamePrefix": "[variables('vmNodeType0Name')]",
    "secrets": [
        
            "sourceVault": 
                "id": "[parameters('sourceVaultResourceId')]"
            ,
            "vaultCertificates": [
                
                    "certificateStore": "My",
                    "certificateUrl": "[parameters('certificateUrlValue')]"
                
            ]
        
    ]
,

不幸的是,这会产生错误:

解析值时遇到意外字符:。路径“properties.virtualMachineProfile.osProfile.adminUsername”,第 1 行,位置 3178。

我的问题是:为什么括号 出乎意料?

我的 ARM 模板基于 azure-quickstart-templates/service-fabric-secure-cluster-5-node-1-nodetype 并且如上所述使用硬编码值。

更新:

这是我的 sfcluster-params.json(但也请注意下面列出的管道任务中的 overrideParameters 并填充了 Keyvault 部署设置的管道变量):


    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": 
        "clusterName": 
            "value": "sfcluster"
        
    

我的 Azure 管道的更大部分在这里:

  # deploy KeyVault by ARM template and output VinHashKey and SF Cluster certificate thumbsprint
  - task: AzureResourceManagerTemplateDeployment@3
    displayName: 'Deploy Keyvault'
    inputs:
      deploymentScope: 'Resource Group'
      subscriptionId: '$ parameters.SubscriptionId '
      azureResourceManagerConnection: '$ parameters.ArmConnection '
      action: 'Create Or Update Resource Group'
      resourceGroupName: '$ parameters.ResourceGroupName '
      location: 'West Europe'
      templateLocation: 'Linked artifact'
      csmFile: '$(Build.SourcesDirectory)/pipelines/templates/keyvault.json'
      csmParametersFile: '$(Build.SourcesDirectory)/pipelines/templates/keyvault-params.json'
      deploymentMode: 'Incremental'

  # collect outputs from the above ARM task and put them into pipeline vars
  - task: ARM Outputs@5
    displayName: 'Collect Keyvault output'
    inputs:
      ConnectedServiceNameSelector: 'ConnectedServiceNameARM'
      ConnectedServiceNameARM: '$ parameters.ArmConnection '
      resourceGroupName: '$ parameters.ResourceGroupName '
      whenLastDeploymentIsFailed: 'fail'

  # import the certificate my-self-signed-cert into the Keyvault if it is missing there
  - task: AzurePowerShell@5
    displayName: 'Import certificate'
    inputs:
      azureSubscription: '$ parameters.ArmConnection '
      ScriptType: 'InlineScript'
      azurePowerShellVersion: '3.1.0'
      Inline: |
        $Cert = Get-AzKeyVaultCertificate -VaultName $(KeyVaultName) -Name my-self-signed-cert
        if (!$Cert) 
            $Pwd = ConvertTo-SecureString -String MyPassword -Force -AsPlainText
            $Base64 = 'MII....gfQ'
            $Cert = Import-AzKeyVaultCertificate -VaultName $(KeyVaultName) -Name my-self-signed-cert -CertificateString $Base64 -Password $Pwd
        
        # set the pipeline variables Thumbprint and SecretId - needed for SF deployment
        echo "##vso[task.setvariable variable=Thumbprint]$($Cert.Thumbprint)"
        echo "##vso[task.setvariable variable=SecretId]$($Cert.SecretId)"

  # deploy SF cluster by ARM template and use the SF certificate thumbsprint as admin cert
  - task: AzureResourceManagerTemplateDeployment@3
    displayName: 'Deploy SF cluster'
    inputs:
      deploymentScope: 'Resource Group'
      subscriptionId: '$ parameters.SubscriptionId '
      azureResourceManagerConnection: '$ parameters.ArmConnection '
      action: 'Create Or Update Resource Group'
      resourceGroupName: '$ parameters.ResourceGroupName '
      location: 'West Europe'
      templateLocation: 'Linked artifact'
      csmFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster.json'
      csmParametersFile: '$(Build.SourcesDirectory)/pipelines/templates/sfcluster-params.json'
      overrideParameters: '-certificateThumbprint $(Thumbprint) -sourceVaultResourceId $(KeyvaultId) -certificateUrlValue $(SecretId)'
      deploymentMode: 'Incremental'

最后,这里是sfcluster.json - 它太大了,不能放在 *** 上。

【问题讨论】:

【参考方案1】:

keyVault 引用只能用作参数值 - 因此在参数文件或部署的参数属性中。您不能直接将其用作资源的属性值。

【讨论】:

但我使用它作为参数 - 使用parameters('sourceVaultResourceId')。您能否解释一下我的情况以及如何解决?我应该改用concat(...) 吗? 可以分享更多的模板/参数文件吗?是原始的还是会重现您的问题的东西? 好的,就是这样:gist.github.com/afarber/… - 您不能仅在参数文件(或嵌套部署)中使用模板中的引用属性。如果您想使用动态 resourceId 确实会变得很棘手,那么您必须将部署嵌套在您想要使用它的位置:docs.microsoft.com/en-us/azure/azure-resource-manager/templates/…

以上是关于部署期间如何使用 Azure Key Vault 传递安全参数值?的主要内容,如果未能解决你的问题,请参考以下文章