Azure / bicep

Bicep is a declarative language for describing and deploying Azure resources
MIT License
3.25k stars 754 forks source link

Modules with different deployment scopes cannot deploy the same resource type #7436

Closed cata008 closed 2 years ago

cata008 commented 2 years ago

Bicep version Bicep CLI version 0.4.1124 (66c84c8ee5)

Describe the bug

var policyExemptionsFile = json(loadTextContent('../../Policies/PolicyExemptions/policyExemptions.json'))

module A '../Folder/file1.bicep' = [for policy in policyExemptionsFile: if (contains(policy.scope, 'providers')) {
scope: managementGroup('mg-name')
name: contains(policy.scope, 'providers') ? policy.scope : 'null'
params: {
  param1: policy.scope
  param2: policy.assignmentId
  //etc
}
}]
module B '../Folder/file2.bicep' = [for policy in policyExemptionsFile: if (contains(policy.scope, 'subscriptions')) {
scope: subscription('placeholder-subscriptionId')
name: contains(policy.scope, 'subscriptions') ? policy.scope : 'null'
params: {
param1: policy.scope
param2: policy.assignmentId
//etc
}
}]

file1.bicep and file2.bicep contain the same piece of code that deploys a policy exemption, the only difference being the deployment scope (targetScope = 'managementGroup' vs targetScope = 'subscription')

To Reproduce

  1. If I deploy the modules in separate files, all deployments are successful.
  2. If I keep both modules in the same main file and "hope" for parallel deployments, I get an "internal server error."
  3. If I keep both modules in the same main file, but add the if condition in the module scope as well, I get: Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The resource '{}' at line '22' and column '9' is defined multiple times in a template. Please see https://aka.ms/arm-template/#resources for usage details.'.

Additional context Not managing to understand what the issue is but I assume it's something arround the validation process. Is there a way to have all these modules deployed in parallel or a workaround I could use? Any plans to make the targetScopes dynamic in the future?

cata008 commented 2 years ago

The issue was actually in one of the modules logic. Sorry for that.

BartDecker commented 2 years ago

@cata008 Did you also got this to work with exemptions on the resource level. I'm trying to create 1 template with a series of "existing" resources, for which the resources are in different resourcegroups, followed by a series of exemptions using the symbolicname of the defined existing resources.

But that seems not to work. When defining a scope of "resourcegroup" on the existing resource one cannot define the scope of the exemption on the resource anymore.

What I'm trying to create is a single template which just deploys an x number of exemptions on resources in different resourcegroups that were deployed earlier by the pipeline. It seems that this would only be possible with 1 template if all exemptions are on subscriptions or management group level.

`resource stg2 'Microsoft.Storage/storageAccounts@2019-06-01' existing = {
    name: 'cu2euv7zt4bsssy'
    scope:resourceGroup('cu2-sxx-d-rsg-sharexxxxlery')
    }`
`resource policyexemption2 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = {

  name: 'test-exemption2'
  scope: stg2  **<<<<<<<<<<< it doesn't allow this scope anymore**
  properties: {
    description: 'Test Exemption  144'
    displayName: displayname
    exemptionCategory: 'Waiver'
    expiresOn: '2025-01-01T00:00:00Z'
    policyAssignmentId: assignmentid
    policyDefinitionReferenceIds: policyDefinitionRefIds
  }
}`
cata008 commented 2 years ago

@BartDecker, in my current config I have created exemptions only for the mg, subscription and rg deployment scopes.

I can see why you're getting an error message. That is because you cannot create a resource at a deployment scope that is different than the one you're in - for that you need modules.

To solve this, you have to create a module and change the scope there and then reference the existing resource (storage acc). Something like:

module test 'policyExemptionTest.bicep' = { name: 'test' scope: resourceGroup('cu2-sxx-d-rsg-sharexxxxlery') params: { } } policyExemptionTest.bicep resource stg2 'Microsoft.Storage/storageAccounts@2019-06-01' existing = { name: 'cu2euv7zt4bsssy' }

// Add exemptions resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { name: 'policy' scope: stg2 properties: { } }

Hope it helps.

BartDecker commented 2 years ago

@BartDecker, in my current config I have created exemptions only for the mg, subscription and rg deployment scopes.

I can see why you're getting an error message. That is because you cannot create a resource at a deployment scope that is different than the one you're in - for that you need modules.

To solve this, you have to create a module and change the scope there and then reference the existing resource (storage acc). Something like:

module test 'policyExemptionTest.bicep' = { name: 'test' scope: resourceGroup('cu2-sxx-d-rsg-sharexxxxlery') params: { } } policyExemptionTest.bicep resource stg2 'Microsoft.Storage/storageAccounts@2019-06-01' existing = { name: 'cu2euv7zt4bsssy' }

// Add exemptions resource policyExemption 'Microsoft.Authorization/policyExemptions@2020-07-01-preview' = { name: 'policy' scope: stg2 properties: { } }

Hope it helps.

Hello @cata008 Thanks for your reply. Much appreciated.

I tried indeed with the above example and it does not work as well. It seems that exemptions currently cannot be set on the resource with bicep. I left an issue @ the bicep repo as well. Let's see what comes out of it.