Freigeben über


Verwenden von Bicep zur Geheimnisverwaltung

Bereitstellungen erfordern häufig, dass Geheimnisse gespeichert und in der gesamten Azure-Umgebung sicher verteilt werden. Bicep und Azure bieten zahlreiche Funktionen, die Ihnen bei der Verwaltung von Geheimnissen in ihrer Bereitstellung der virtuellen Maschine helfen.

Vermeiden Sie Geheimnisse, wo Sie können

In vielen Fällen ist es möglich, die Verwendung von Geheimnissen komplett zu vermeiden. Viele Azure-Ressourcen ermöglichen es verwalteten Identitäten, sich zu authentifizieren und autorisiert zu werden, um auf andere Ressourcen in Azure zuzugreifen, ohne dass Anmeldeinformationen verwendet oder verwaltet werden müssen. Darüber hinaus können einige Azure-Dienste HTTPS-Zertifikate automatisch für Sie generieren, sodass Sie sich nicht um Zertifikate und private Schlüssel kümmern müssen. Verwenden Sie wo möglich verwaltete Identitäten und vom Dienst verwaltete Zertifikate.

Nutzen Sie sichere Parameter

Wenn Sie Geheimnisse Ihrer Bicep-Bereitstellungen als Parameter zur Verfügung stellen müssen, verwenden Sie den @secure() Decorator. Wenn Sie einen Parameter als sicher markieren, verhindert Azure Resource Manager die Protokollierung oder Anzeige dieses Parameters im Azure-Portal, in der Azure CLI oder in Azure PowerShell.

Vermeiden von Geheimnis-Ausgaben

Verwenden Sie keine Bicep-Ausgaben für sichere Daten. Ausgaben werden im Bereitstellungsverlauf protokolliert und jeder Benutzer mit Zugriff auf die Bereitstellung kann die Werte der Ausgaben einer Bereitstellung ansehen.

Wenn Sie ein Geheimnis in einer Bicep-Bereitstellung generieren und für die aufrufende Funktion oder andere Ressourcen verfügbar machen müssen, sollten Sie einen der folgenden Ansätze in Betracht ziehen.

Dynamisches Abrufen von Geheimnissen

Manchmal müssen Sie auf ein Geheimnis über eine Ressource zugreifen, um eine andere Ressource zu konfigurieren. Zum Beispiel haben Sie in einer anderen Bereitstellung ein Speicherkonto erstellt und müssen auf den Primärschlüssel zugreifen, um eine Azure Functions-App zu konfigurieren. Sie können das Schlüsselwort existing verwenden, um einen stark typisierten Verweis auf das vorab erstellte Speicherkonto zu erhalten, und dann die listKeys()-Methode des Speicherkontos nutzen, um eine Verbindungszeichenfolge mit dem Primärschlüssel zu erstellen.

Das folgende Beispiel ist Teil eines umfassenderen Beispiels. Eine Bicep-Datei, die Sie bereitstellen können, finden Sie in der vollständigen Datei.

param location string = resourceGroup().location
param storageAccountName string
param functionAppName string = 'fn-${uniqueString(resourceGroup().id)}'

var appServicePlanName = 'MyPlan'
var applicationInsightsName = 'MyApplicationInsights'

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-06-01' existing = {
  name: storageAccountName
}

var storageAccountConnectionString = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageAccount.id, storageAccount.apiVersion).keys[0].value}'

resource functionApp 'Microsoft.Web/sites@2023-12-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  properties: {
    httpsOnly: true
    serverFarmId: appServicePlan.id
    siteConfig: {
      appSettings: [
        {
          name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
          value: applicationInsights.properties.InstrumentationKey
        }
        {
          name: 'AzureWebJobsStorage'
          value: storageAccountConnectionString
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~3'
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'dotnet'
        }
        {
          name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
          value: storageAccountConnectionString
        }
      ]
    }
  }
}

resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: 'Y1' 
    tier: 'Dynamic'
  }
}

resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: applicationInsightsName
  location: location
  kind: 'web'
  properties: { 
    Application_Type: 'web'
    publicNetworkAccessForIngestion: 'Enabled'
    publicNetworkAccessForQuery: 'Enabled'
  }
}

Mit diesem Ansatz vermeiden Sie es, Geheimnisse in oder aus der Bicep-Datei zu übergeben und Geheimnisse in einem Schlüsseltresor zu speichern.

Verwenden des Key Vaults

Azure Key Vault ist zum Speichern und Verwalten sicherer Daten konzipiert. Verwenden Sie einen Schlüsseltresor um Ihre geheimen Daten, Zertifikate, Schlüssel und andere Daten zu verwalten, die geschützt und geteilt werden müssen.

Sie können Tresore und Geheimnisse mithilfe von Bicep erstellen und verwalten. Definieren Sie Ihre Tresore, indem Sie eine Ressource mit dem Typ Microsoft.KeyVault/vaults erstellen.

Wenn Sie einen Tresor erstellen, müssen Sie bestimmen, wer und was auf die darin enthaltenen Daten zugreifen kann. Wenn Sie die Geheimnisse des Tresors aus einer Bicep-Datei lesen möchten, legen Sie die Eigenschaft enabledForTemplateDeployment auf true fest.

Hinzufügen von Geheimnissen zu einem Schlüsseltresor

Geheimnisse sind eine untergeordnete Ressource und können mit dem Typ erstellt werden Microsoft.KeyVault/vaults/secrets. Das folgende Beispiel zeigt, wie ein Tresor und ein Geheimnis erstellt werden.

Das folgende Beispiel ist Teil eines umfassenderen Beispiels. Eine Bicep-Datei, die Sie bereitstellen können, finden Sie in der vollständigen Datei.

param location string = resourceGroup().location
param keyVaultName string = 'mykv${uniqueString(resourceGroup().id)}'

resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' = {
  name: keyVaultName
  location: location
  properties: {
    enabledForTemplateDeployment: true
    tenantId: tenant().tenantId
    accessPolicies: [
    ]
    sku: {
      name: 'standard'
      family: 'A'
    }
  }
}

resource keyVaultSecret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = {
  parent: keyVault
  name: 'MySecretName'
  properties: {
    value: 'MyVerySecretValue'
  }
}

Tipp

Wenn Sie automatisierte Bereitstellungspipelines verwenden, kann es manchmal schwierig sein festzustellen, wie Sie wichtige Tresor-Geheimnisse für Ihre Bereitstellungen bootstrapen. Wenn Ihnen beispielsweise ein API-Schlüssel zur Kommunikation mit einer externen API zur Verfügung gestellt wurde, muss der geheime Schlüssel einem Tresor hinzugefügt werden, bevor er in Ihren Bereitstellungen verwendet werden kann.

Wenn Sie mit Geheimnissen arbeiten, die von einem Drittanbieter stammen, müssen Sie sie möglicherweise manuell Ihrem Tresor hinzufügen, bevor Sie bei nachfolgenden Verwendungen darauf verweisen können.

Verwenden eines Schlüsseltresor mit Modulen

Wenn Sie Bicep-Module verwenden, können Sie mithilfe der getSecret Funktion sichere Parameter bereitstellen.

Sie können auch auf einen Schlüsseltresor verweisen, der in einer anderen Ressourcengruppe definiert ist, indem Sie die Schlüsselwörter existing und scope zusammen verwenden. Im folgenden Beispiel wird die Bicep-Datei bereitgestellt für eine Ressourcengruppe mit dem Namen Netzwerk. Der Wert des Modulparameters mySecret wird in einem Schlüsseltresor namens contosonetworkingsecrets definiert, der sich in der Ressourcengruppe Geheimnisse befindet:

resource networkingSecretsKeyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
  scope: resourceGroup('Secrets')
  name: 'contosonetworkingsecrets'
}

module exampleModule 'module.bicep' = {
  name: 'exampleModule'
  params: {
    mySecret: networkingSecretsKeyVault.getSecret('mySecret')
  }
}

Verwenden eines Schlüsseltresors in einer .bicepparam-Datei

Wenn Sie das Dateiformat .bicepparam verwenden, können Sie mithilfe der getSecret-Funktion sichere Werte für Parameter angeben.

Verweisen Sie auf den Schlüsseltresor, indem Sie die Abonnement-ID, den Namen der Ressourcengruppe und den Namen des Schlüsseltresors angeben. Sie können den Wert des Geheimnisses abrufen, indem Sie den Geheimnisnamen angeben. Optional können Sie die Geheimnisversion angeben, andernfalls wird die aktuelle Version verwendet.

using './main.bicep'

param secureUserName = az.getSecret('<subscriptionId>', '<resourceGroupName>', '<keyVaultName>', '<secretName>', '<secretVersion>')
param securePassword = az.getSecret('<subscriptionId>', '<resourceGroupName>', '<keyVaultName>', '<secretName>')

Arbeiten mit Geheimnissen in Pipelines

Die folgenden bewährten Methoden helfen Ihnen dabei, Ihre Geheimnisse mit Vorsicht zu behandeln, wenn Sie eine Pipeline zum Bereitstellen Ihrer Azure-Ressourcen verwenden:

  • Speichern Sie keine Geheimnisse in Ihrem Coderepository. Fügen Sie z. B. in Parameterdateien oder YAML-Dateien für die Pipelinedefinition keine Geheimnisse hinzu.
  • In GitHub Actions verwenden Sie Verschlüsselte Geheimnisse, um sichere Daten zu speichern. Verwenden Sie Geheimnis Scan, um versehentliche Commits von Geheimnissen zu erkennen.
  • Verwenden Sie in Azure Pipelines Geheimnis Variablen, um sichere Daten zu speichern.