bicep icon indicating copy to clipboard operation
bicep copied to clipboard

Allow targeting multiple scopes in a single file with `targetScope`

Open anthony-c-martin opened this issue 4 years ago • 17 comments

Implementation for the syntax discussed e.g.

targetScope = [
  'tenant'
  'subscription'
]

anthony-c-martin avatar Nov 03 '20 19:11 anthony-c-martin

Can plan to use the symbolic name when that is implemented for ARM Template JSON

alex-frankel avatar Nov 05 '20 00:11 alex-frankel

@alex-frankel do we have "soon" plans of doing this? How might this interface with the right click deploy command?

ucheNkadiCode avatar Mar 23 '22 23:03 ucheNkadiCode

Not soon, but I still feel we should do it. Right click deploy would need to somehow allow you to choose which scope "type" you want to use prior to loading the list of the list of those scopes.

alex-frankel avatar Mar 23 '22 23:03 alex-frankel

I would like to be able to parameterize this as well. i.e. pass in the scope to a template

jongio avatar May 10 '22 17:05 jongio

@jongio how would you use that (parameterization)?

bmoore-msft avatar Jun 14 '22 15:06 bmoore-msft

We have a scenario where we want to allow the user to deploy to either a sub or to an existing rg. As some users will have access to sub deployments and others to rgs level and we won't know which level until they deploy.

jongio avatar Jun 14 '22 18:06 jongio

got it - wouldn't the proposal in the OP allow for that though? e.g.

targetScope = [
  'subscription'
  'resourceGroup'
]

The file can then be used at either scope...

bmoore-msft avatar Jun 14 '22 19:06 bmoore-msft

Gotcha, I didn't realize that we're proposing that when the scope is specified then the scope would be adjusted. Does that mean that the calling code needs to either call sub deployment or rg deployment commands?

if so, It would be nice if we had one CLI command that could work with any scope.

jongio avatar Jun 15 '22 17:06 jongio

targetScope is really just for tooling to go grab proper context when validating the template...

if so, It would be nice if we had one CLI command that could work with any scope.

And I really like this... we've talked about it in the past and it's tricky due to parametersets changing... TBH I don't recall too much more than that but certainly interested in feedback as to whether a single deployment cmd resonates with folks...

bmoore-msft avatar Jun 15 '22 19:06 bmoore-msft

It does with me as I now need to have a conditional and some sort of user interaction for them to choose which one. But it's not a P0.

jongio avatar Jun 15 '22 22:06 jongio

@jongio curious what your thoughts are on my ramblings under https://github.com/Azure/bicep/issues/399#issuecomment-936054550 - specifically the "Setting other deployment properties" section.

anthony-c-martin avatar Jun 16 '22 00:06 anthony-c-martin

adjacent scenario for different scopes, though this is on the resource itself....

I want a module for a roleAssignment. A module is needed because the name for a roleAssignment needs to be unqiue based on principalId, roleDef and scope of the assignment. When the principalId is from an MSI in the same deployment, a runtime function is needed to retrieve it. The runtime function cannot be used in the name property unless that resource is nested in a module. When I go through a dev/test cycle with an MSI, everytime the MSI is created a new principalId is used... but in a template, to avoid nesting, the roleAssignment name uses the resourceId of the MSI. Since the roleAssignment is not cleaned up, you can only deploy said template once.

In JSON you can do this because the scope property need not be known until deploy time. In bicep this needs to be known at compile time.

Also, the scope property in bicep is strongly typed (cannot be a string), IOW must be a resource. The type of a resource must be known at compile time.

In JSON I would do:

      {
        "scope": "[if(equals(parameters('scope'), resourceGroup().id), json('null'), variables('roleScope'))]",
        "type": "Microsoft.Authorization/roleAssignments",
        "apiVersion": "2022-01-01-preview",
        "name": "[variables('roleAssignmentName')]",
        "properties": {
          "roleDefinitionId": "[variables('roleDefinitionId')]",
          "principalId": "[parameters('principalId')]",
          "principalType": "[parameters('principalType')]"
        }
      }

Where variables('roleScope') is the back half of a resourceId.

via decompile this would be:

resource roleAssignmentName 'Microsoft.Authorization/roleAssignments@2022-01-01-preview' = {
  scope: ((scope == resourceGroup().id) ? json('null') : roleScope)
  name: roleAssignmentName_var
  properties: {
    roleDefinitionId: roleDefinitionId
    principalId: principalId
    principalType: principalType
  }
}

Which is not allowed.

Some ideas - allow the scope to be a string... or allow an existing resource declaration to be dynamic, e.g.

resource storageAccount existing = {
     id: resourceId('blah')
}

bmoore-msft avatar Jul 28 '22 20:07 bmoore-msft

@bmoore-msft - my understanding is this will be enabled with #2245/#2246

alex-frankel avatar Aug 01 '22 13:08 alex-frankel

I think one difference may be that in roleAssignment case, the type is not known at compile time... so in 2245/2246 the type declaration would be parameterized.

bmoore-msft avatar Aug 01 '22 20:08 bmoore-msft

My understanding is the resource parameter type can be generic, so you can have a module like:

param myRes resource // can be any resource type

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
  scope: myRes
  ...
} 

Does that cover it?

alex-frankel avatar Aug 01 '22 21:08 alex-frankel

As long as the type can be specified at deploy time (not compile time) - yes, that would cover it. I didn't see anything that suggested that would be the case though.

bmoore-msft avatar Aug 01 '22 22:08 bmoore-msft

Very much like the idea!

Although modules are a great way of structuring your deployments, it would be a great advantage to have all the deployment definitions for all target scopes in a single file. This would greatly improve sharing Bicep code, e.g. in tutorials etc.

/ref #7860

SetTrend avatar Aug 09 '22 09:08 SetTrend

Just like Terraform Plan and Apply on a whole project regardless of the scope resources being provisioned belong to, as long there's authorization for it, I was attempting to have a single bicep orchestration file that would call all the modules that provision those resources in different scopes for my ALZ (RGs, policies, VNETs, KeyVault, etc). With that a single 'what-if' call to validate the entire orchestration plan and later a deploy if all modifications are approved. It would streamline the process, reduce the number of artifacts to manage and increase visibility

diogocatossi avatar Oct 06 '22 09:10 diogocatossi

Did we start consider about this implementation so far?

There is a lot of duplication for basic tasks like assigning policies or role assignments based on having to provide the single targetScope.

This is "not as fast as you would like", however it would be ideal to get this in by v1.0.1?

brwilkinson avatar Jun 23 '23 02:06 brwilkinson

Also, there were some comments about this being enabled with preview feature resourceTypedParamsAndOutputs that is now available, so perhaps there is some testing around this that I can consider...?!

brwilkinson avatar Jun 23 '23 03:06 brwilkinson

It appears that we have both of below, so perhaps we can consolidate to track in single issue?

  • https://github.com/Azure/bicep/issues/4698
  • https://github.com/Azure/bicep/issues/10131

brwilkinson avatar Jun 23 '23 03:06 brwilkinson

It would be nice if the Module simply inherited the Scope from the parent Module as the default.

Then you only specify targetScope = when you are changing scope when calling a Module or for any Top Level Module.

brwilkinson avatar Jun 23 '23 03:06 brwilkinson