1

在使用 terraform 很长一段时间后,我决定开始学习 azure bicep。到目前为止,我正试图掌握逻辑。到目前为止,我一直在尝试部署存储帐户和 keyvault。我在这里做的是以下内容。

  • 创建存储帐户
  • 使用现有密钥保管库将存储帐户连接字符串存储为机密
  • 根据存储帐户名称创建密钥

这正如我所料。

所以我想向前迈出一步。这是我有点困惑的地方。

我想做的是使用相同的二头肌模板,在不同的资源组中创建一个新的秘密到不同的密钥库中。

现在,根据我对 azure 文档的理解,该模板带有一个默认值scope,在我的特定情况下,它以我的默认订阅为目标,并从终端运行我的二头肌模板,我使用命令

az deployment group create -f ./template.bicep -g <resource-group-name>

这是我的模板:

// Default values I'm using to test 
param keyVaultName string = '<keyvault-name>'
param managedIdentityName string = 'test-managed-identity'

param tenantCodes array = [
  'elhm'
  'feor'
]

// I'm using prefix so I dont need to create additional arrays
var keyVaultKeyPrefix = 'Client-Key-'
var storagePrefix = 'sthrideveur'

// Get a reference to key vault
resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
  name: keyVaultName
}

// Create a managed identity
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
  name: managedIdentityName
  location: resourceGroup().location
}

// Grant permissions to key vault
resource accessPolicy 'Microsoft.KeyVault/vaults/accessPolicies@2019-09-01' = {
  name: '${keyVault.name}/add'
  properties: {
    accessPolicies: [
      {
        tenantId: subscription().tenantId
        objectId: managedIdentity.properties.principalId
        permissions: {
          // minimum required permissions
          keys: [
            'get'
            'unwrapKey'
            'wrapKey'
          ]
        }
      }
    ]
  }
}

// Create key vault keys
resource keyVaultKeys 'Microsoft.KeyVault/vaults/keys@2021-06-01-preview' = [for tenantCode in tenantCodes: {
  name: '${keyVault.name}/${keyVaultKeyPrefix}${tenantCode}'
  properties: {
    keySize: 2048
    kty: 'RSA'
    // storage key should only needs these operations
    keyOps: [
      'unwrapKey'
      'wrapKey'
    ]
  }
}]

// Create storage accounts
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = [for tenantCode in tenantCodes: {
  name: '${storagePrefix}${tenantCode}'
  location: resourceGroup().location
  kind: 'StorageV2'
  sku: {
    name: 'Standard_RAGRS'
  }
  // Assign the identity
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${managedIdentity.id}': {}
    }
  }
  properties: {
    allowCrossTenantReplication: true
    minimumTlsVersion: 'TLS1_2'
    allowBlobPublicAccess: false
    allowSharedKeyAccess: true
    networkAcls: {
      bypass: 'AzureServices'
      virtualNetworkRules: []
      ipRules: []
      defaultAction: 'Allow'
    }
    supportsHttpsTrafficOnly: true
    encryption: {
      identity: {
        // specify which identity to use
        userAssignedIdentity: managedIdentity.id
      }
      keySource: 'Microsoft.Keyvault'
      keyvaultproperties: {
        keyname: '${keyVaultKeyPrefix}${tenantCode}'
        keyvaulturi: keyVault.properties.vaultUri
      }
      services: {
        file: {
          keyType: 'Account'
          enabled: true
        }
        blob: {
          keyType: 'Account'
          enabled: true
        }
      }
    }
    accessTier: 'Cool'
  }
}]

// Store the connectionstrings in KV if specified
resource storageAccountConnectionStrings 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = [ for (name, i) in tenantCodes :{
  name: '${keyVault.name}/${storagePrefix}${name}'
  properties: {
    value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount[i].name};AccountKey=${listKeys(storageAccount[i].id, storageAccount[i].apiVersion).keys[0].value};EndpointSuffix=${environment().suffixes.storage}'
  }
}]

根据此处的文档https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/deploy-to-resource-group?tabs=azure-cli

当我需要定位一个特定的资源组时,我可以使用资源中的范围,所以我创建了这个:

resource keyvaultApi 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
  name: keyVaultApiName
  scope: resourceGroup('secondresourcegroup')
}

到目前为止没有错误,但是当我必须创建托管标识资源时会出现问题。

resource keyvaultApi 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
  name: keyVaultApiName
  scope: resourceGroup('secondresourcegroup')
}

resource managedIdentityTwo 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
  name: managedIdentityNameTwo
  location: resourceGroup().location
}

resource accessPolicyApi 'Microsoft.Media/videoAnalyzers/accessPolicies@2021-11-01-preview' = {
  name: '${keyvaultApi.name}/add'
  properties: {
    accessPolicies: [
      {
        tenantId: subscription().tenantId
        objectId: managedIdentityTwo.properties.principalId
        permissions: {
          // minimum required permissions
          keys: [
            'get'
            'unwrapKey'
            'wrapKey'
          ]
        }
      }
    ]
  }
}

在密钥库中我可以声明范围,但对于底层资源,例如访问策略等,我不能声明范围。那么二头肌如何理解这些资源需要针对特定​​的资源组和特定的密钥库呢?

因为当我运行终端命令时,我针对的是一个特定的资源组,所以我不太明白如何使用一个模板来相应地针对不同的资源组和资源。

我希望我能说清楚我的观点,如果我没有,请随时向我询问更多信息。

非常感谢您的时间和帮助

更新:当我尝试按原样运行代码时,出现以下错误:

{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"NotFound","message":"{\r\n  \"error\": {\r\n    \"code\": \"ParentResourceNotFound\",\r\n    \"message\": \"Can not perform requested operation on nested resource. Parent resource 'secondkeyvault' not found.\"\r\n  }\r\n}"}]}}

更新:所以我跟随丹尼尔的领导,在第二个模板中我部署了第二个模板所需的代码,如下所示:

模板2.二头肌

param deploymentIdOne string = newGuid()
param deploymentIdTwo string = newGuid()
output deploymentIdOne string = '${deploymentIdOne}-${deploymentIdTwo}'
output deploymentIdTwo string = deploymentIdTwo

// Default values I'm using to test 
param keyVaultApiName string = 'secondkeyvaultapi'
param managedIdentityNameTwo string = 'second-second-identity'
var keyVaultKeyPrefixTw = 'Client-Key-'
param tenantCodes array = [
  'tgrf'
]
resource keyvaultApi 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = {
  name: keyVaultApiName
}

resource managedIdentityTwo 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
  name: managedIdentityNameTwo
  location: resourceGroup().location
}

resource accessPolicyApi 'Microsoft.KeyVault/vaults/accessPolicies@2019-09-01' = {
  name: '${keyvaultApi.name}/add'
  properties: {
    accessPolicies: [
      {
        tenantId: subscription().tenantId
        objectId: managedIdentityTwo.properties.principalId
        permissions: {
          // minimum required permissions
          keys: [
            'get'
            'unwrapKey'
            'wrapKey'
          ]
        }
      }
    ]
  }
}

// Store the connectionstrings in KV if specified
resource clientApiKeys 'Microsoft.KeyVault/vaults/secrets@2019-09-01' = [ for name in tenantCodes :{
  name: '${keyvaultApi.name}/${keyVaultKeyPrefixTw}${name}'
  properties: {
    value: '${deploymentIdOne}-${deploymentIdTwo}'
  }
}]

在我的主模板中,我添加了模块:

module clientKeyApi 'template2.bicep' = {
  name: 'testfrgs'
  scope: 'secondresourcegroup'
}

但是有些事情对我来说不是 100% 清楚的。for覆盖我在 template2.bicep 中声明的所有循环和参数名称是如何工作的,但是模块需要一个范围subscription,如果我声明范围,这不会覆盖默认值吗?

对不起,新手问题,我试图打破我的思维定势,更好地了解二头肌是如何工作的。

任何解释都会令人惊奇和有帮助

4

1 回答 1

1

您不能scope在资源上指定,但可以在模块上指定它。您需要将向 keyvault 添加访问策略的资源转换为单独的模块,然后scope在模块上指定。您还可以为您的部署确定范围subscription,但是您还需要将针对特定资源组的所有内容分解为模块。

这是由于 ARM 部署的工作方式。ARM 部署的默认范围是资源组级别。您不能将资源指向不同的资源组,因为它超出了部署的范围。

但是,模块作为子部署运行,因此可以具有不同的范围集。

这是 Terraform 更直接的情况,因为它直接调用 Azure API,而不是使用 ARM 部署模型。Terraform 不关心部署范围,因为它不使用它们。

于 2021-10-24T22:21:57.730 回答