练习 - 添加参数文件和安全参数

已完成

在此练习中,你将创建一个参数文件,该文件为之前创建的 Bicep 文件提供值。 在同一参数文件中,还将添加 Azure Key Vault 引用来安全地提供敏感信息。

在此过程中,你将执行以下任务:

  • 添加一些安全参数。
  • 创建参数文件。
  • 测试部署,确保参数文件有效。
  • 创建密钥保管库和机密。
  • 更新参数文件以引用密钥保管库机密。
  • 重新测试部署,确保参数文件仍然有效。

删除应用服务计划 SKU 的默认值

若要使模板跨环境工作,Azure 应用服务计划的 SKU 详细信息将在参数文件中提供,而不是按默认值提供。

在 Visual Studio Code 的 main.bicep 文件中,更新 appServicePlanSku 参数以删除其默认值。

@description('The name and tier of the App Service plan SKU.')
param appServicePlanSku object

添加新参数

现在,需要添加 SQL Server 和数据库。 首先,为管理员登录名和密码以及数据库 SKU 添加参数。 稍后将设置其值。

在 Visual Studio Code 的 main.bicep 文件中,在当前参数声明下面添加 sqlServerAdministratorLoginsqlServerAdministratorPasswordsqlDatabaseSku 参数。 完成时,你的参数声明应如以下示例所示:

@description('The name of the environment. This must be dev, test, or prod.')
@allowed([
  'dev'
  'test'
  'prod'
])
param environmentName string = 'dev'

@description('The unique name of the solution. This is used to ensure that resource names are unique.')
@minLength(5)
@maxLength(30)
param solutionName string = 'toyhr${uniqueString(resourceGroup().id)}'

@description('The number of App Service plan instances.')
@minValue(1)
@maxValue(10)
param appServicePlanInstanceCount int = 1

@description('The name and tier of the App Service plan SKU.')
param appServicePlanSku object

@description('The Azure region into which the resources should be deployed.')
param location string = 'eastus'

@secure()
@description('The administrator login username for the SQL server.')
param sqlServerAdministratorLogin string

@secure()
@description('The administrator login password for the SQL server.')
param sqlServerAdministratorPassword string

@description('The name and tier of the SQL database SKU.')
param sqlDatabaseSku object

请注意,没有为 sqlServerAdministratorLoginsqlServerAdministratorPassword 参数指定默认值。 为安全参数添加默认值是一种错误的安全做法。 此外,没有为 sqlDatabaseSku 指定默认值。 你将在参数文件中指定一个值。

添加新变量

在 Visual Studio Code 的 main.bicep 文件中,将 sqlServerNamesqlDatabaseName 变量添加到现有变量下面。 完成时,你的变量声明应如以下示例所示:

var appServicePlanName = '${environmentName}-${solutionName}-plan'
var appServiceAppName = '${environmentName}-${solutionName}-app'
var sqlServerName = '${environmentName}-${solutionName}-sql'
var sqlDatabaseName = 'Employees'

添加 SQL Server 和数据库资源

  1. 在 Visual Studio Code 的 main.bicep 文件中,将以下代码添加到文件底部:

    resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = {
      name: sqlServerName
      location: location
      properties: {
        administratorLogin: sqlServerAdministratorLogin
        administratorLoginPassword: sqlServerAdministratorPassword
      }
    }
    
    resource sqlDatabase 'Microsoft.Sql/servers/databases@2022-05-01-preview' = {
      parent: sqlServer
      name: sqlDatabaseName
      location: location
      sku: {
        name: sqlDatabaseSku.name
        tier: sqlDatabaseSku.tier
      }
    }
    
  2. 保存对文件所做的更改。

验证 Bicep 文件

完成上述所有更改后,Bicep 文件应如以下示例所示:

@description('The name of the environment. This must be dev, test, or prod.')
@allowed([
  'dev'
  'test'
  'prod'
])
param environmentName string = 'dev'

@description('The unique name of the solution. This is used to ensure that resource names are unique.')
@minLength(5)
@maxLength(30)
param solutionName string = 'toyhr${uniqueString(resourceGroup().id)}'

@description('The number of App Service plan instances.')
@minValue(1)
@maxValue(10)
param appServicePlanInstanceCount int = 1

@description('The name and tier of the App Service plan SKU.')
param appServicePlanSku object

@description('The Azure region into which the resources should be deployed.')
param location string = 'eastus'

@secure()
@description('The administrator login username for the SQL server.')
param sqlServerAdministratorLogin string

@secure()
@description('The administrator login password for the SQL server.')
param sqlServerAdministratorPassword string

@description('The name and tier of the SQL database SKU.')
param sqlDatabaseSku object

var appServicePlanName = '${environmentName}-${solutionName}-plan'
var appServiceAppName = '${environmentName}-${solutionName}-app'
var sqlServerName = '${environmentName}-${solutionName}-sql'
var sqlDatabaseName = 'Employees'

resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
  name: appServicePlanName
  location: location
  sku: {
    name: appServicePlanSku.name
    tier: appServicePlanSku.tier
    capacity: appServicePlanInstanceCount
  }
}

resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
  name: appServiceAppName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    httpsOnly: true
  }
}

resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = {
  name: sqlServerName
  location: location
  properties: {
    administratorLogin: sqlServerAdministratorLogin
    administratorLoginPassword: sqlServerAdministratorPassword
  }
}

resource sqlDatabase 'Microsoft.Sql/servers/databases@2022-05-01-preview' = {
  parent: sqlServer
  name: sqlDatabaseName
  location: location
  sku: {
    name: sqlDatabaseSku.name
    tier: sqlDatabaseSku.tier
  }
}

如果不是,请复制示例或调整模板以与该示例一致。

创建参数文件

  1. 打开 Visual Studio Code,然后打开 main.bicep 文件所在的文件夹。 在同一文件夹中,创建名为 main.parameters.dev.json 的新文件。

  2. 在 main.parameters.dev.json 文件中,添加以下代码:

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "appServicePlanSku": {
          "value": {
            "name": "F1",
            "tier": "Free"
          }
        },
        "sqlDatabaseSku": {
          "value": {
            "name": "Standard",
            "tier": "Standard"
          }
        }
      }
    }
    
  3. 保存对文件所做的更改。

使用参数文件部署 Bicep 模板

在终端中运行以下 Azure CLI 命令。 请注意,你要为部署提供参数文件。

az deployment group create \
  --template-file main.bicep \
  --parameters main.parameters.dev.json

在终端中运行以下 Azure PowerShell 命令。 请注意,你要为部署提供参数文件。

New-AzResourceGroupDeployment `
  -TemplateFile main.bicep `
  -TemplateParameterFile main.parameters.dev.json

执行部署时,系统会提示输入 sqlServerAdministratorLoginsqlServerAdministratorPassword 参数的值。 无需指定 solutionName,因为它在模板中指定了默认值。 无需指定其他参数值,因为它们的值在参数文件中指定。

提示

当你输入安全参数时,选择的值必须遵循以下规则:

  • sqlServerAdministratorLogin 不能是容易猜到的登录名,如 adminroot。 名称只能包含字母数字字符,并且必须以字母开头。
  • sqlServerAdministratorPassword 必须至少为 8 个字符,并且包含小写字母、大写字母、数字和符号。 有关密码复杂性的详细信息,请参阅 SQL Azure 密码策略

如果参数值不满足要求,Azure SQL 将不会部署服务器。

此外,请确保记下输入的登录名和密码。 下一部分你将用到它们。

部署可能需要几分钟时间才能完成。

创建密钥保管库和机密

玩具公司已有一个密钥保管库,该保管库具有部署所需的机密。 若要模拟此场景,需要创建新的密钥保管库并添加一些要使用的机密。

在终端中,执行以下命令以创建密钥保管库和机密。 执行这些命令之前,请更新变量值。 密钥保管库名称必须是 3 到 24 个字符的全局唯一字符串,只能包含大写字母和小写字母、连字符 (-) 和数字。 例如 demo-kv-1234567abcdefg。

注意

请确保使用在上一步骤中使用的相同登录名和密码。 如果没有,下一个部署将不会成功完成。

对于 keyVaultName,请将 YOUR-KEY-VAULT-NAME 替换为密钥保管库的名称。 loginpassword 变量的 read 命令将提示你输入值。 键入时,这些值不会显示在终端中,也不会保存在命令历史记录中。

若要保护 Bash 终端会话中的变量值,请注意以下各项:

  • 变量值不存储为安全字符串,可以通过输入命令(如在命令行上输入 $yourVariableName 或使用 echo 命令)来进行显示。 在本练习中,在创建保管库机密后,可以在不输入值的情况下通过运行 read 命令而来删除每个变量的现有值。
  • az keyvault secret set 使用 --value 参数创建机密的值。 命令的输出显示名为 value 的属性,其中包含机密的值。 可以使用 --output none 参数禁止显示命令的整个输出,如示例所示。

若要创建 keyVaultNameloginpassword 变量,请单独运行每个命令。 然后,可以运行命令块来创建密钥保管库和机密。

keyVaultName='YOUR-KEY-VAULT-NAME'
read -s -p "Enter the login name: " login
read -s -p "Enter the password: " password

az keyvault create --name $keyVaultName --location eastus --enabled-for-template-deployment true
az keyvault secret set --vault-name $keyVaultName --name "sqlServerAdministratorLogin" --value $login --output none
az keyvault secret set --vault-name $keyVaultName --name "sqlServerAdministratorPassword" --value $password --output none

备注

在保管库上设置 --enabled-for-template-deployment 设置,以便 Azure 可以在部署期间使用保管库中的机密。 如果未设置此设置,则默认情况下,部署无法访问保管库中的机密。

此外,执行部署的用户还必须具有访问保管库的权限。 由于你创建了密钥保管库,因此你是所有者,在本练习中不需要显式授予权限。 对于自己的保管库,需要授予对机密的访问权限

对于 keyVaultName,请将 YOUR-KEY-VAULT-NAME 替换为密钥保管库的名称。 loginpassword 变量的 Read-Host 命令将提示你输入值。 键入时,这些值不会显示在终端中,也不会保存在命令历史记录中。 将值以安全字符串的形式存储。

若要创建 keyVaultNameloginpassword 变量,请单独运行每个命令。 然后,可以运行命令块来创建密钥保管库和机密。

$keyVaultName = 'YOUR-KEY-VAULT-NAME'
$login = Read-Host "Enter the login name" -AsSecureString
$password = Read-Host "Enter the password" -AsSecureString

New-AzKeyVault -VaultName $keyVaultName -Location eastus -EnabledForTemplateDeployment
Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'sqlServerAdministratorLogin' -SecretValue $login
Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'sqlServerAdministratorPassword' -SecretValue $password

备注

在保管库上设置 -EnabledForTemplateDeployment 设置,以便 Azure 可以在部署期间使用保管库中的机密。 如果未设置此设置,则默认情况下,部署无法访问保管库中的机密。

此外,执行部署的用户还必须具有访问保管库的权限。 由于你创建了密钥保管库,因此你是所有者,在本练习中不需要显式授予权限。 对于自己的保管库,需要授予对机密的访问权限

获取密钥保管库的资源 ID

若要在部署中使用密钥保管库机密,需要保管库的资源 ID。 运行以下命令以检索密钥保管库的资源 ID:

az keyvault show --name $keyVaultName --query id --output tsv
(Get-AzKeyVault -Name $keyVaultName).ResourceId

资源 ID 将如以下示例所示:

/subscriptions/f0750bbe-ea75-4ae5-b24d-a92ca601da2c/resourceGroups/PlatformResources/providers/Microsoft.KeyVault/vaults/toysecrets

复制资源 ID。 在下一步骤中将使用它。

向参数文件添加密钥保管库引用

  1. 在 main.parameters.dev.json 文件中,在 sqlDatabaseSku 参数的右大括号后面追加以下代码。 请确保将 YOUR-KEY-VAULT-RESOURCE-ID 替换为在上一步中复制的密钥保管库资源 ID 的值。 完成后,参数文件应如以下示例所示:

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "appServicePlanSku": {
          "value": {
            "name": "F1",
            "tier": "Free"
          }
        },
        "sqlDatabaseSku": {
          "value": {
            "name": "Standard",
            "tier": "Standard"
          }
        },
        "sqlServerAdministratorLogin": {
          "reference": {
            "keyVault": {
              "id": "YOUR-KEY-VAULT-RESOURCE-ID"
            },
            "secretName": "sqlServerAdministratorLogin"
          }
        },
        "sqlServerAdministratorPassword": {
          "reference": {
            "keyVault": {
              "id": "YOUR-KEY-VAULT-RESOURCE-ID"
            },
            "secretName": "sqlServerAdministratorPassword"
          }
        }
      }
    }
    
  2. 保存对文件所做的更改。

使用参数文件和 Azure Key Vault 引用部署 Bicep 模板

在终端中运行以下 Azure CLI 命令。 你要提供参数文件以及 Bicep 文件。

az deployment group create \
  --template-file main.bicep \
  --parameters main.parameters.dev.json

在终端中运行以下 Azure PowerShell 命令。 你要提供参数文件以及 Bicep 文件。

New-AzResourceGroupDeployment `
  -TemplateFile main.bicep `
  -TemplateParameterFile main.parameters.dev.json

本次执行部署时,系统会提示输入 sqlServerAdministratorLoginsqlServerAdministratorPassword 参数的值。 Azure 改为从密钥保管库中检索值。

由于 Azure 资源已存在,因此本次部署会更快完成。

检查你的部署

  1. 在浏览器中返回到 Azure 门户。 转到你的资源组。 你仍然会看到一个成功的部署,因为部署使用了与第一个部署相同的名称。

  2. 选择“1 个成功”链接。

  3. 选择名为“main”的部署。

  4. 在左侧菜单中,选择“输入”。

  5. 请注意,appServicePlanSkusqlDatabaseSku 参数值都设置为参数文件中的值。 另请注意,sqlServerAdministratorLoginsqlServerAdministratorPassword 参数值不会显示,因为已对它们应用 @secure() 修饰器。

    Screenshot of the Azure portal interface for the specific deployment showing the parameter values.