使用 Bicep 管理祕密
部署通常需要在您的 Azure 環境中安全地儲存和傳播祕密。 Bicep 和 Azure 提供許多功能,可協助您管理部署中的秘密。
盡可能避免秘密
在許多情況下可以完全避免使用秘密。 許多 Azure 資源都支援受控識別,因此可以在驗證資源後授權存取 Azure 中的其他資源,讓您不需要處理或管理任何認證。 此外,部份 Azure 服務可以自動產生 HTTPS 憑證,讓您不需要處理憑證和私密金鑰。 盡可能使用受控識別和服務管理憑證。
使用安全參數
在您需要提供秘密給 Bicep 部署做為參數時,請使用@secure()
裝飾項目。 將參數標示為安全時,Azure Resource Manager 會避免記錄值,或避免將值顯示在 Azure 入口網站、Azure CLI 或 Azure PowerShell。
避免秘密輸出
請勿將 Bicep 輸出用於安全資料。 輸出會記錄至部署歷程記錄,而任何可存取部署的人都可以檢視部署輸出的值。
如果您需要在 Bicep 部署內產生秘密,並提供給呼叫者或其他資源使用,請考慮使用下列其中一種方法。
動態查詢秘密
有時,您會需要從一個資源存取秘密來設定其他資源。
例如,您可能已在另一個部署中建立儲存體帳戶,且需要存取帳戶的主索引鍵來設定 Azure Functions 應用程式。 您可以使用 existing
關鍵字來取得預先建立之儲存體帳戶的強型別參照,接著使用儲存體帳戶的 listKeys()
方法來建立具有主索引鍵的連接字串:
下列範例是較大範例的一部分。 如需您可以部署的 Bicep 檔案,請參閱完整檔案。
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'
}
}
透過這種方法,您可以避免將秘密傳入或傳出 Bicep 檔案。
您也可以使用此方法將秘密儲存在金鑰保存庫中。
使用 Key Vault
Azure Key Vault 是專為儲存和管理安全資料而設計。 使用金鑰保存庫來管理您的秘密、憑證、金鑰,以及其他需要保護和共用的資料。
您可以使用 Bicep 來建立和管理保存庫及秘密。 透過建立型別 Microsoft.KeyVault/vaults
的資源來定義您的保存庫。
建立保存庫時,您必須決定可以存取其中資料的使用者和項目。 如果您打算從 Bicep 檔案讀取保存庫的秘密,請將 enabledForTemplateDeployment
屬性設定為 true
。
將秘密新增至金鑰保存庫
秘密是子資源,而且可以使用型別 Microsoft.KeyVault/vaults/secrets
來建立。 下列範例示範如何建立保存庫和祕密:
下列範例是較大範例的一部分。 如需您可以部署的 Bicep 檔案,請參閱完整檔案。
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'
}
}
提示
使用自動化部署管線時,有時可能會很難判斷如何針對您的部署啟動金鑰保存庫秘密。 例如,如果您已取得 API 金鑰以用於與外部 API 通訊,就必須先將秘密新增至保存庫,才能在您的部署中使用。
當您使用來自協力廠商的秘密,可能會需要手動將其新增至您的保存庫,然後才能參照該秘密以供各種後續用途使用。
透過模組使用金鑰保存庫
採用 Bicep 模組時,您可以使用 getSecret
函式來提供安全參數。
您也可以同時使用 existing
和 scope
關鍵字,來參照另一個資源群組所定義的金鑰保存庫。 在下列範例中,Bicep 檔案是部署至名為「網路」的資源群組。 模組參數「mySecret」的值會定義在名為「contosonetworkingsecrets」的金鑰保存庫中,位於「秘密」資源群組中:
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')
}
}
在 .bicepparam 檔案中使用金鑰保存庫
當您使用 .bicepparam
檔案格式時,您可以使用 getSecret
函式為參數提供安全值。
藉由提供訂用帳戶識別碼、資源群組名稱和金鑰保存庫名稱來參考 KeyVault。 您可以藉由提供秘密名稱來取得秘密的值。 您也可以選擇性地提供祕密版本。 如果您沒有提供秘密版本,則會使用最新版本。
using './main.bicep'
param secureUserName = az.getSecret('<subscriptionId>', '<resourceGroupName>', '<keyVaultName>', '<secretName>', '<secretVersion>')
param securePassword = az.getSecret('<subscriptionId>', '<resourceGroupName>', '<keyVaultName>', '<secretName>')
在管線中使用秘密
使用管線部署 Azure 資源時,您必須謹慎適當地處理您的秘密。
- 請避免將秘密儲存在您的程式碼存放庫中。 例如,請勿將秘密新增至參數檔案,或新增至您的管線定義 YAML 檔案。
- 在 GitHub Actions 中,請使用加密的秘密來儲存安全資料。 使用秘密掃描來偵測任何意外認可的祕密。
- 在 Azure Pipelines 中,使用秘密變數來儲存安全資料。
相關資源
- 資源文件
- Azure 功能
- Bicep 功能
- 快速入門範本
- Azure Pipelines
- GitHub 動作