Używanie usługi Azure Key Vault do przekazywania bezpiecznej wartości parametru podczas wdrażania

Zamiast umieszczać bezpieczną wartość (na przykład hasło) bezpośrednio w pliku szablonu lub parametrów, możesz pobrać wartość z usługi Azure Key Vault podczas wdrażania. Pobierasz wartość, odwołując się do magazynu kluczy i wpisu tajnego w pliku parametrów. Wartość nigdy nie jest uwidoczniana, ponieważ używane jest tylko odwołanie do jej identyfikatora magazynu kluczy.

Ważne

W tym artykule opisano sposób przekazywania poufnej wartości jako parametru szablonu. Po przekazaniu wpisu tajnego jako parametru magazyn kluczy może istnieć w innej subskrypcji niż wdrażana grupa zasobów.

W tym artykule nie opisano sposobu ustawiania właściwości maszyny wirtualnej na adres URL certyfikatu w magazynie kluczy. Aby zapoznać się z szablonem przewodnika Szybki start tego scenariusza, zobacz Instalowanie certyfikatu z platformy Azure Key Vault na maszynie wirtualnej.

Wdrażanie magazynów kluczy i wpisów tajnych

Aby uzyskać dostęp do magazynu kluczy podczas wdrażania szablonu, ustaw enabledForTemplateDeployment dla magazynu kluczy wartość true.

Jeśli masz już magazyn kluczy, upewnij się, że zezwala na wdrożenia szablonów.

az keyvault update  --name ExampleVault --enabled-for-template-deployment true

Aby utworzyć nowy magazyn kluczy i dodać wpis tajny, użyj:

az group create --name ExampleGroup --location centralus
az keyvault create \
  --name ExampleVault \
  --resource-group ExampleGroup \
  --location centralus \
  --enabled-for-template-deployment true
az keyvault secret set --vault-name ExampleVault --name "ExamplePassword" --value "hVFkk965BuUv"

Jako właściciel magazynu kluczy masz automatycznie dostęp do tworzenia wpisów tajnych. Jeśli musisz zezwolić innemu użytkownikowi na tworzenie wpisów tajnych, użyj:

az keyvault set-policy \
  --upn <user-principal-name> \
  --name ExampleVault \
  --secret-permissions set delete get list

Zasady dostępu nie są potrzebne, jeśli użytkownik wdraża szablon, który pobiera wpis tajny. Dodaj użytkownika do zasad dostępu tylko wtedy, gdy użytkownik musi pracować bezpośrednio z wpisami tajnymi. Uprawnienia wdrożenia są definiowane w następnej sekcji.

Aby uzyskać więcej informacji na temat tworzenia magazynów kluczy i dodawania wpisów tajnych, zobacz:

Udzielanie dostępu wdrożenia do wpisów tajnych

Użytkownik, który wdraża szablon, musi mieć Microsoft.KeyVault/vaults/deploy/action uprawnienie do zakresu grupy zasobów i magazynu kluczy. Sprawdzając ten dostęp, usługa Azure Resource Manager uniemożliwia niezatwierdzonym użytkownikowi dostęp do wpisu tajnego przez przekazanie identyfikatora zasobu dla magazynu kluczy. Dostęp do wdrożenia można udzielić użytkownikom bez udzielania dostępu do zapisu wpisów tajnych.

Role Właściciel i Współautor przyznają ten dostęp. Jeśli utworzono magazyn kluczy, jesteś właścicielem i masz uprawnienie.

W przypadku innych użytkowników przyznaj Microsoft.KeyVault/vaults/deploy/action uprawnienie. Poniższa procedura pokazuje, jak utworzyć rolę z minimalnym uprawnieniem i przypisać ją do użytkownika.

  1. Utwórz niestandardowy plik JSON definicji roli:

    {
      "Name": "Key Vault resource manager template deployment operator",
      "IsCustom": true,
      "Description": "Lets you deploy a resource manager template with the access to the secrets in the Key Vault.",
      "Actions": [
        "Microsoft.KeyVault/vaults/deploy/action"
      ],
      "NotActions": [],
      "DataActions": [],
      "NotDataActions": [],
      "AssignableScopes": [
        "/subscriptions/00000000-0000-0000-0000-000000000000"
      ]
    }
    

    Zastąp ciąg "00000000-0000-0000-0000-0000000000" identyfikatorem subskrypcji.

  2. Utwórz nową rolę przy użyciu pliku JSON:

    az role definition create --role-definition "<path-to-role-file>"
    az role assignment create \
      --role "Key Vault resource manager template deployment operator" \
      --scope /subscriptions/<Subscription-id>/resourceGroups/<resource-group-name> \
      --assignee <user-principal-name> \
      --resource-group ExampleGroup
    

    Przykłady przypisują rolę niestandardową do użytkownika na poziomie grupy zasobów.

W przypadku korzystania z magazynu kluczy z szablonem dla aplikacji zarządzanej należy udzielić dostępu do jednostki usługi dostawcy zasobów urządzenia . Aby uzyskać więcej informacji, zobacz Access Key Vault secret when deploying Azure Managed Applications (Uzyskiwanie dostępu Key Vault wpisu tajnego podczas wdrażania aplikacji zarządzanych platformy Azure).

Odwołania do wpisów tajnych z identyfikatorem statycznym

Dzięki temu podejściu należy odwołać się do magazynu kluczy w pliku parametrów, a nie szablonu. Na poniższej ilustracji pokazano, jak plik parametrów odwołuje się do wpisu tajnego i przekazuje te wartości do szablonu.

Diagram przedstawiający integrację Resource Manager magazynu kluczy z identyfikatorem statycznym.

Samouczek: integrowanie usługi Azure Key Vault we wdrożeniu szablonu Resource Manager używa tej metody.

Poniższy szablon wdraża serwer SQL zawierający hasło administratora. Parametr hasła jest ustawiony na bezpieczny ciąg. Jednak szablon nie określa miejsca, z którego pochodzi ta wartość.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "sqlServerName": {
      "type": "string"
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    },
    "adminLogin": {
      "type": "string"
    },
    "adminPassword": {
      "type": "securestring"
    }
  },
  "resources": [
    {
      "type": "Microsoft.Sql/servers",
      "apiVersion": "2021-11-01",
      "name": "[parameters('sqlServerName')]",
      "location": "[parameters('location')]",
      "properties": {
        "administratorLogin": "[parameters('adminLogin')]",
        "administratorLoginPassword": "[parameters('adminPassword')]",
        "version": "12.0"
      }
    }
  ]
}

Teraz utwórz plik parametrów dla poprzedniego szablonu. W pliku parametrów określ parametr zgodny z nazwą parametru w szablonie. Dla wartości parametru odwołaj się do wpisu tajnego z magazynu kluczy. Odwołujesz się do wpisu tajnego, przekazując identyfikator zasobu magazynu kluczy i nazwę wpisu tajnego:

W poniższym pliku parametrów wpis tajny magazynu kluczy musi już istnieć i podać wartość statyczną identyfikatora zasobu.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminLogin": {
      "value": "exampleadmin"
    },
    "adminPassword": {
      "reference": {
        "keyVault": {
          "id": "/subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.KeyVault/vaults/<vault-name>"
        },
        "secretName": "ExamplePassword"
      }
    },
    "sqlServerName": {
      "value": "<your-server-name>"
    }
  }
}

Jeśli musisz użyć wersji wpisu tajnego innego niż bieżąca wersja, dołącz secretVersion właściwość .

"secretName": "ExamplePassword",
"secretVersion": "cd91b2b7e10e492ebb870a6ee0591b68"

Wdróż szablon i przekaż plik parametrów:

az group create --name SqlGroup --location westus2
az deployment group create \
  --resource-group SqlGroup \
  --template-uri <template-file-URI> \
  --parameters <parameter-file>

Odwołania do wpisów tajnych z identyfikatorem dynamicznym

W poprzedniej sekcji pokazano, jak przekazać statyczny identyfikator zasobu dla wpisu tajnego magazynu kluczy z parametru . W niektórych scenariuszach należy odwołać się do wpisu tajnego magazynu kluczy, który różni się w zależności od bieżącego wdrożenia. Możesz też przekazać wartości parametrów do szablonu, a nie utworzyć parametru referencyjnego w pliku parametrów. Rozwiązaniem jest dynamiczne generowanie identyfikatora zasobu dla wpisu tajnego magazynu kluczy przy użyciu połączonego szablonu.

Nie można dynamicznie wygenerować identyfikatora zasobu w pliku parametrów, ponieważ wyrażenia szablonu nie są dozwolone w pliku parametrów.

W szablonie nadrzędnym dodajesz zagnieżdżony szablon i przekazujesz parametr zawierający dynamicznie wygenerowany identyfikator zasobu. Na poniższej ilustracji pokazano, jak parametr w połączonym szablonie odwołuje się do wpisu tajnego.

Diagram przedstawiający generowanie identyfikatorów dynamicznych dla wpisu tajnego magazynu kluczy.

Poniższy szablon dynamicznie tworzy identyfikator magazynu kluczy i przekazuje go jako parametr.

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
      "location": {
        "type": "string",
        "defaultValue": "[resourceGroup().location]",
        "metadata": {
          "description": "The location where the resources will be deployed."
        }
      },
      "vaultName": {
        "type": "string",
        "metadata": {
          "description": "The name of the keyvault that contains the secret."
        }
      },
      "secretName": {
        "type": "string",
        "metadata": {
          "description": "The name of the secret."
        }
      },
      "vaultResourceGroupName": {
        "type": "string",
        "metadata": {
          "description": "The name of the resource group that contains the keyvault."
        }
      },
      "vaultSubscription": {
        "type": "string",
        "defaultValue": "[subscription().subscriptionId]",
        "metadata": {
          "description": "The name of the subscription that contains the keyvault."
        }
      }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2020-10-01",
      "name": "dynamicSecret",
      "properties": {
        "mode": "Incremental",
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
            "adminLogin": {
              "type": "string"
            },
            "adminPassword": {
              "type": "securestring"
            },
            "location": {
              "type": "string"
            }
          },
          "variables": {
            "sqlServerName": "[concat('sql-', uniqueString(resourceGroup().id, 'sql'))]"
          },
          "resources": [
            {
              "type": "Microsoft.Sql/servers",
              "apiVersion": "2021-11-01",
              "name": "[variables('sqlServerName')]",
              "location": "[parameters('location')]",
              "properties": {
                "administratorLogin": "[parameters('adminLogin')]",
                "administratorLoginPassword": "[parameters('adminPassword')]"
              }
            }
          ],
          "outputs": {
            "sqlFQDN": {
              "type": "string",
              "value": "[reference(variables('sqlServerName')).fullyQualifiedDomainName]"
            }
          }
        },
        "parameters": {
          "location": {
            "value": "[parameters('location')]"
          },
          "adminLogin": {
            "value": "ghuser"
          },
          "adminPassword": {
            "reference": {
              "keyVault": {
                "id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
              },
              "secretName": "[parameters('secretName')]"
            }
          }
        }
      }
    }
  ]
}

Następne kroki