Condividi tramite


Usare Bicep per gestire i segreti

Le distribuzioni richiedono spesso che i segreti vengano archiviati e propagati in modo sicuro in tutto l'ambiente Azure. Bicep e Azure offrono molte funzionalità per facilitare la gestione dei segreti nelle distribuzioni.

Evitare segreti in cui è possibile

È possibile evitare di usare completamente i segreti in molte situazioni. Molte risorse di Azure consentono alle identità gestite di autenticarsi ed essere autorizzate ad accedere ad altre risorse all'interno di Azure e senza dover gestire o gestire le credenziali. Inoltre, alcuni servizi di Azure possono generare automaticamente certificati HTTPS, risparmiando la gestione di certificati e chiavi private. Usare le identità gestite e i certificati gestiti dal servizio laddove possibile.

Usare parametri protetti

Quando è necessario fornire segreti alle distribuzioni Bicep come parametri, usare il @secure() decorator. Quando si contrassegna un parametro come sicuro, Azure Resource Manager evita di registrare il valore o visualizzarlo nella portale di Azure, nell'interfaccia della riga di comando di Azure o in Azure PowerShell.

Evitare output per i segreti

Non usare output Bicep per i dati sicuri. Gli output vengono registrati nella cronologia di distribuzione e chiunque abbia accesso alla distribuzione può visualizzare i valori degli output di una distribuzione.

Se è necessario generare un segreto all'interno di una distribuzione Bicep e renderlo disponibile al chiamante o ad altre risorse, prendere in considerazione uno degli approcci seguenti.

Cercare i segreti in modo dinamico

In alcuni casi, è necessario accedere a un segreto da una risorsa per configurare un'altra. Ad esempio, potrebbe essere stato creato un account di archiviazione in un'altra distribuzione ed è necessario accedere alla relativa chiave primaria per configurare un'app Funzioni di Azure. È possibile usare la existing parola chiave per ottenere un riferimento fortemente tipizzato all'account di archiviazione già creato e quindi usare il metodo dell'account di listKeys() archiviazione per creare un stringa di connessione con la chiave primaria.

L'esempio seguente fa parte di un esempio più ampio. Per un file Bicep che è possibile distribuire, vedere il file completo.

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'
  }
}

L'uso di questo approccio consente di evitare di passare segreti all'interno o all'esterno del file Bicep e anche di archiviare i segreti in un insieme di credenziali delle chiavi.

Usare Key Vault

Azure Key Vault è progettato per archiviare e gestire i dati sicuri. Usare un insieme di credenziali delle chiavi per gestire segreti, certificati, chiavi e altri dati che devono essere protetti e condivisi.

È possibile usare Bicep per creare e gestire insiemi di credenziali e segreti. Definire gli insiemi di credenziali creando una risorsa con il tipo Microsoft.KeyVault/vaults.

Quando si crea un insieme di credenziali, è necessario determinare chi e cosa può accedere ai dati. Se si prevede di leggere i segreti dell'insieme di credenziali dall'interno di un file Bicep, impostare la proprietà enabledForTemplateDeployment su true.

Aggiungere segreti a un insieme di credenziali delle chiavi

I segreti sono una risorsa figlio e possono essere creati usando il tipo Microsoft.KeyVault/vaults/secrets. Nell'esempio seguente viene illustrato come creare un insieme di credenziali e un segreto.

L'esempio seguente fa parte di un esempio più ampio. Per un file Bicep che è possibile distribuire, vedere il file completo.

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'
  }
}

Suggerimento

Quando si usano pipeline di distribuzione automatizzate, a volte può essere difficile determinare come eseguire il bootstrap dei segreti dell'insieme di credenziali delle chiavi per le distribuzioni. Ad esempio, se è stata fornita una chiave API da usare durante la comunicazione con un'API esterna, il segreto deve essere aggiunto a un insieme di credenziali prima che possa essere usato nelle distribuzioni.

Quando si usano segreti provenienti da terze parti, potrebbe essere necessario aggiungerli manualmente all'insieme di credenziali prima di poter farvi riferimento per tutti gli usi successivi.

Usare un insieme di credenziali delle chiavi con i moduli

Quando si usano i moduli Bicep, è possibile fornire parametri sicuri usando la funzione getSecret.

È anche possibile fare riferimento a un insieme di credenziali delle chiavi definito in un altro gruppo di risorse usando le parole chiave existing e scope insieme. Nell'esempio seguente il file Bicep viene distribuito in un gruppo di risorse denominato Networking. Il valore per il parametro del modulo mySecret è definito in un insieme di credenziali delle chiavi denominato contosonetworkingsecrets, che si trova nel gruppo di risorse Segreti :

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')
  }
}

Usare un insieme di credenziali delle chiavi in un file con estensione bicepparam

Quando si usa il formato di file .bicepparam, è possibile fornire valori sicuri ai parametri usando la getSecret funzione.

Fare riferimento all'insieme di credenziali delle chiavi specificando l'ID sottoscrizione, il nome del gruppo di risorse e il nome dell'insieme di credenziali delle chiavi. È possibile ottenere il valore del segreto specificando il nome del segreto. Facoltativamente, è possibile specificare la versione privata; la versione più recente viene usata se non lo si è.

using './main.bicep'

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

Usare i segreti nelle pipeline

Le procedure consigliate seguenti consentono di gestire i segreti con cautela quando si usa una pipeline per distribuire le risorse di Azure:

  • Evitare di archiviare segreti nel repository di codice. Ad esempio, non aggiungere segreti ai file di parametri o ai file YAML di definizione della pipeline.
  • In GitHub Actions usare segreti crittografati per archiviare dati sicuri. Usare l'analisi dei segreti per rilevare eventuali commit accidentali dei segreti.
  • In Azure Pipelines usare variabili segrete per archiviare dati sicuri.