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 szablonie lub pliku parametrów, możesz pobrać tę wartość z pliku Azure Key Vault podczas wdrażania. Tę wartość można pobrać, odwołując się do magazynu kluczy i klucza 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 przekazania wartości poufnej jako parametru szablonu. Gdy klucz tajny zostanie przekazany jako parametr, magazyn kluczy może istnieć w innej subskrypcji niż grupa zasobów, w ramach których wdrażasz.

W tym artykule nie opisano sposobu ustawienia właściwości maszyny wirtualnej na adres URL certyfikatu w magazynie kluczy. Aby uzyskać szablon szybkiego startu dla tego scenariusza, zobacz Instalowanie certyfikatu z 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 on na wdrożenia szablonów.

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

Aby utworzyć nowy magazyn kluczy i dodać klucz 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 pozwolić inowi 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ą wymagane, jeśli użytkownik wdraża szablon, który pobiera klucz tajny. Dodaj użytkownika do zasad dostępu tylko wtedy, gdy użytkownik musi pracować bezpośrednio z wpisami tajnymi. Uprawnienia do wdrażania są definiowane w następnej sekcji.

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

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

Użytkownik, który wdraża szablon, musi mieć uprawnienia do zakresu grupy zasobów i Microsoft.KeyVault/vaults/deploy/action magazynu kluczy. Sprawdzając ten dostęp, Azure Resource Manager niezatwierdzony użytkownik nie może uzyskać dostępu do klucza tajnego, przekazując identyfikator zasobu dla magazynu kluczy. Użytkownikom można udzielić dostępu do wdrożenia bez udzielania dostępu do zapisu wpisów tajnych.

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

W przypadku innych użytkowników przyznaj Microsoft.KeyVault/vaults/deploy/action uprawnienie. W poniższej procedurze przedstawiono sposób tworzenia roli z minimalnymi uprawnieniami i przypisywania jej do użytkownika.

  1. Utwórz plik JSON definicji roli niestandardowej:

    {
      "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 "00000000-0000-0000-0000-00000000000" 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" \
      --assignee <user-principal-name> \
      --resource-group ExampleGroup
    

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

W przypadku używania magazynu kluczy z szablonem dla aplikacji zarządzanejnależ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(Dostęp do Key Vault tajny podczas wdrażania Azure Managed Applications .

Odwołania do wpisów tajnych za pomocą identyfikatora statycznego

W przypadku tej metody odwołujesz się do magazynu kluczy w pliku parametrów, a nie w szablonie. Na poniższej ilustracji pokazano, jak plik parametrów odwołuje się do tajnego dokumentu i przekazuje wartość do szablonu.

Resource Manager integracji magazynu kluczy — diagram identyfikatorów statycznych

Samouczek: integracja Azure Key Vault w Resource Manager Template deployment, w których jest używana ta metoda.

Poniższy szablon wdraża serwer SQL, który zawiera hasło administratora. Parametr password jest ustawiony na bezpieczny ciąg. Jednak szablon nie określa, skąd pochodzi ta wartość.

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

Teraz utwórz plik parametrów dla poprzedniego szablonu. W pliku parametrów określ parametr, który odpowiada nazwie parametru w szablonie. Jako wartość parametru odwołuj się do klucza tajnego z magazynu kluczy. Należy odwołać się do klucza tajnego, przekazując identyfikator zasobu magazynu kluczy i nazwę klucza tajnego:

W poniższym pliku parametrów klucz tajny magazynu kluczy musi już istnieć i należy podać statyczną wartość 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 tajnej innej niż bieżąca wersja, uwzględnij secretVersion właściwość .

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

Wd wdrażaj 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 za pomocą identyfikatora dynamicznego

W poprzedniej sekcji popisano sposób przekazania statycznego identyfikatora zasobu dla klucza tajnego magazynu kluczy z parametru . W niektórych scenariuszach należy odwoływać się do klucza 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, zamiast tworzyć parametr referencyjny w pliku parametrów. Rozwiązaniem jest dynamiczne generowanie identyfikatora zasobu dla klucza 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 należy dodać zagnieżdżony szablon i przekazać parametr zawierający dynamicznie generowany identyfikator zasobu. Na poniższej ilustracji pokazano, jak parametr w połączonym szablonie odwołuje się do tajnego.

Identyfikator dynamiczny

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": "2018-06-01-preview",
              "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')]"
            }
          }
        }
      }
    }
  ],
  "outputs": {
  }
}

Następne kroki