azure 将包含带有空格的键的Map用作资源名称时,将无法正确验证这些键

mcdcgff0  于 2023-06-24  发布在  其他
关注(0)|答案(1)|浏览(88)

当我必须在terraform中导入一些role_assignment资源时,我遇到了一个问题,特别是关于APP CONFIG DATA READER角色分配的问题。
我必须解决的问题是由于我们的IAC的进化,使地形计划更加可读和明确。
以下是更改的角色分配代码:

module "my_role_assignment_slot_to_app_config" {
  for_each = local.map_slot_app_config
  source = "../../resourceModules/role_assignment"
  scope = each.value.config_id
  role_definition_names = ["Reader","App Configuration Data Reader"]
  principal_id = each.value.slot_guid
}

with the following module for role assignments : 

```hcl
resource "azurerm_role_assignment" "my_role_assignment" {
  for_each              = toset(var.role_definition_names)
  scope                = var.scope
  role_definition_name = each.value
  principal_id         = var.principal_id
}

此代码将计划以下内容,更易读:

但正如您所看到的,azurerm_role_assignment.my_role_assignment的索引包含空格。
这阻止了我们在azure Devops上的azureCli任务中使用powershell脚本terraform导入角色分配(因为它是在iac编码之前手动创建的):

- task: AzureCli@2
        displayName: Runs tfImport.ps1
        condition: and(succeeded(), eq(variables['toUpdate.scriptExists'], 'true'))  # test script presence
        name: tfImport.ps1
        inputs:
          azureSubscription: ${{ parameters.serviceConnection }}
          scriptType: ps
          scriptLocation: InlineScript
          inlineScript: |
            $Env:ARM_CLIENT_ID       = "$Env:servicePrincipalId"
            $Env:ARM_CLIENT_SECRET   = "$Env:servicePrincipalKey"
            $Env:ARM_TENANT_ID       = "$Env:tenantId"
            $Env:ARM_SUBSCRIPTION_ID = az account list --query "[?isDefault].id" -o tsv        
            $Env:TF_LOG = "${{ parameters.TF_LOG }}"
        
            terraform init `
              -migrate-state `
              -backend-config="resource_group_name=${{ parameters.storageAccountResourceGroup }}"`
              -backend-config="storage_account_name=${{ parameters.storageAccount}}" `
              -backend-config="key=${{ parameters.storageContainer }}" `
              -backend-config="container_name=${{ parameters.stateBlobContainer }}"
        
            // runs my tfImport.ps1 script here
            ./tfImport.ps1 
        
          workingDirectory: $(pipeline_artefact_folder_extract)/   
          addSpnToEnvironment: true
          failOnStderr: false  
        continueOnError: true

我使用的脚本有以下terraform导入行,

terraform import  'module.my_role_assignment_slot_to_app_config[\"sit03_z-adf-ftnd-shrd-npd-ew1-cfg01\"].azurerm_role_assignment.my_role_assignment[\"App Configuration Data Reader\"]'  /subscriptions/**********/resourceGroups/*********/providers/Microsoft.AppConfiguration/configurationStores/z-adf-ftnd-shrd-npd-ew1-cfg01/providers/Microsoft.Authorization/roleAssignments/<role_assignment_id>

所以我得到了以下错误:

(id数据删除)
经过一些研究,我发现了以下链接,解释了为什么,并给予了我一个解决方案的开始:
https://github.com/hashicorp/terraform/issues/25116
但是我不得不更进一步,找到一种方法来使用我的powershell脚本,而不需要startProcess方法。
而且我还必须从其PrincipalId中获取role_assignment resourceId(因为我们可以使用以下内容获取在app_config上具有“App Configuration Data Reader”角色的资源的PrincipalId)

# role assignment over a specific scope (such as app_config)
    $rsRolesCfg = az role assignment list  --scope /subscriptions/******/resourceGroups/*******/providers/Microsoft.AppConfiguration/configurationStores/******-cfg01 | ConvertFrom-Json
    $myRole = $rsRolesCfg | Where-Object roleDefinitionName -eq 'App Configuration Data Reader'  | Where-Object id -like "*<app_config_resourceId>"
    ## principalId is the id of the object that get the role over the scope !
    
    # GetsresourceId from PrincipalId / ObjetcId (without the '<>' on body, off course :) ) : 
    $resourceId = (az rest --method POST --url 'https://graph.microsoft.com/v1.0/directoryObjects/getByIds' --headers 'Content-Type=application/json'  --body '{\"ids\":[\"<PrincipalId>\"]}' | ConvertFrom-Json | Select-Object value).value.alternativeNames[1]

来自How to Get Azure AD Object by Object ID Using Azure CLI的解决方案(非常感谢!)
我不得不在powershell终端中本地测试它。。所以它没有像预期的那样工作。
然后,我稍微修改了一下脚本,得到了解决方案(下一篇文章,作为我的问题的解决方案)。

pwuypxnk

pwuypxnk1#

因此,我不得不在powershellVSCode终端上用本地测试我的get_ResourceId方法,这个终端不接受上面的代码(因为powershell解释得很糟糕)
所以,在快速搜索之后,我向我解释了“`”是PowerShell的转义字符,我测试了这个有效的方法,并给予了role_assignment的预期resourceId:

$rsRolesCfg = az role assignment list  --scope /subscriptions/************/resourceGroups/******/providers/Microsoft.AppConfiguration/configurationStores/<app_configuration_name> | ConvertFrom-Json

($rsRolesCfg | Where-Object roleDefinitionName -eq 'App Configuration Data Reader') | ForEach-Object {$local=$_.principalId; (az rest --method POST --url 'https://graph.microsoft.com/v1.0/directoryObjects/getByIds' --headers 'Content-Type=application/json'  --body "{\`"ids\`":[\`"$local\`"]}" | ConvertFrom-Json | Select-Object value).value.alternativeNames[1] }

所以,“`”的使用是我的观点的解决方案,所以我尝试在terraform导入脚本中使用它(在第一篇文章中),它也工作得很好:

terraform import "module.my_role_assignment_slot_to_app_config[\`"sit03_z-adf-ftnd-shrd-npd-ew1-cfg01\`"].azurerm_role_assignment.my_role_assignment[\`"App Configuration Data Reader\`"]"  /subscriptions/*****/resourceGroups/******/providers/Microsoft.AppConfiguration/configurationStores/z-adf-ftnd-shrd-npd-ew1-cfg01/providers/Microsoft.Authorization/roleAssignments/<role_assignment_id>

但我也必须更改yaml任务,使用pscore而不是ps,如下所示:

- task: AzureCli@2
        displayName: Runs tfImport.ps1
        condition: and(succeeded(), eq(variables['toUpdate.scriptExists'], 'true'))  # test script presence
        name: tfImport.ps1
        inputs:
          azureSubscription: ${{ parameters.serviceConnection }}
          scriptType: **pscore**

所以,terform导入脚本运行成功了!
我已经使用了与GitHub中相同的“标题”这个stackOverflow问题/解决方案,所以那些寻找该解决方案的人可以很容易地找到问题的解决方案。至少我希望如此:P
感谢阅读!

相关问题