-
Notifications
You must be signed in to change notification settings - Fork 757
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
'scope' is not working correctly when directly set conditionally #7367
Comments
@davidcho23 -- is this related to the recent fix you merged recently (but is not yet released)? |
No, my recent change was blocking ternary operators being used to set the parent property: #7254. If my fix was the cause, there should at least be an error message and not allow the bicep file to build. Interestingly, this bug is related to to the general lack of support we currently have for ternary operators. The Bicep team is currently investigating how to implement a holistic fix for support and validation of ternary expressions and other types of expressions. |
@davidcho23 - I think Alex might be wondering if we need a similar fix for |
@anthony-c-martin Ah, sorry I misunderstood. Then yes, we should implement blocking using ternary operators for |
FYI @davidcho23, I added this optimistically to the 0.9 milestone and assigned you to it you have some free cycles. No worries if it needs to be pushed out further. |
This looks similar to #1876 ... and we have seen another probably related scenario: Conditional scope where the result should be a resource scope (and not a resource group): param keyVaultName string
param principalId string
param roleDefinitionId string
param secretName string = ''
var hasSecret = secretName != null && secretName != ''
resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
name: keyVaultName
resource secret 'secrets' existing = if (hasSecret) {
name: secretName
}
}
resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
scope: subscription()
name: roleDefinitionId
}
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: hasSecret ? keyVault::secret : keyVault
name: hasSecret ? guid(resourceGroup().id, keyVaultName, secretName, principalId, roleDefinition.id) : guid(resourceGroup().id, keyVaultName, principalId, roleDefinition.id)
properties: {
roleDefinitionId: roleDefinition.id
principalId: principalId
principalType: 'ServicePrincipal'
}
} When compiling to ARM the scope of the role assignment is fully missing without any warning/error (bicep cli 0.9.1, result below). Is that covered by the ongoing work @alex-frankel / @davidcho23 ? Thanks! {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.9.1.41621",
"templateHash": "4150038258483440815"
}
},
"parameters": {
"keyVaultName": {
"type": "string"
},
"principalId": {
"type": "string"
},
"roleDefinitionId": {
"type": "string"
},
"secretName": {
"type": "string",
"defaultValue": ""
}
},
"variables": {
"hasSecret": "[and(not(equals(parameters('secretName'), null())), not(equals(parameters('secretName'), '')))]"
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2022-04-01",
"name": "[if(variables('hasSecret'), guid(resourceGroup().id, parameters('keyVaultName'), parameters('secretName'), parameters('principalId'), subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('roleDefinitionId'))), guid(resourceGroup().id, parameters('keyVaultName'), parameters('principalId'), subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('roleDefinitionId'))))]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', parameters('roleDefinitionId'))]",
"principalId": "[parameters('principalId')]",
"principalType": "ServicePrincipal"
}
}
]
} |
We have to revert #8300 unfortunately as it broke some legitimate scenarios. |
This is quite annoying to figure out because it doesn't look like you're doing anything wrong. I just hit this trying to create a module that can peer two vnets where the vnets might optionally be in different subscriptions from the original deployment, and each other: @description('vnet information { id, name, subscriptionId, resourceGroupName }')
param vnet1 object
@description('vnet information { id, name, subscriptionId, resourceGroupName }')
param vnet2 object
var vnet1RG = contains(vnet1, 'subscriptionId') ? resourceGroup(vnet1.subscriptionId, vnet1.resourceGroupName) : resourceGroup(vnet1.resourceGroupName)
var vnet2RG = contains(vnet2, 'subscriptionId') ? resourceGroup(vnet2.subscriptionId, vnet2.resourceGroupName) : resourceGroup(vnet2.resourceGroupName) results in this template: "variables": {
"vnet1RG": "[if(contains(parameters('vnet1'), 'subscriptionId'), createObject(), createObject())]",
"vnet2RG": "[if(contains(parameters('vnet2'), 'subscriptionId'), createObject(), createObject())]"
}, and eventually results in 'resource x in resource group not found' |
I am running into this bug as well trying to apply roles to resources with a conditional on the scope, and then the role is applied at the RG instead. As it is and until it is fixed, this will require me creating a conditional resource deployment for every condition, instead of just a conditional on the scope. Is this still on a schedule to get fixed? (Using 0.16.2) |
You might be able to use this syntax |
I am not trying to scope on resourceGroup, but on a resource. I already scoped the module to the correct RG. This is what I want to do: param resourceGrantedTo string //resourceId of resource that is being assigned roles to - scope of module is already at the RG of this resource resource storageAccount_res 'Microsoft.Storage/storageAccounts@2022-09-01' existing = if (contains(resourceGrantedTo,'Microsoft.Storage/storageAccounts') && length(split(resourceGrantedTo,'/')) == 9) { resource keyVault_res 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (contains(resourceGrantedTo,'Microsoft.KeyVault/vaults') && length(split(resourceGrantedTo,'/')) == 9) { resource roleAssignment_res 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (role, index) in roleDefinitionIds : { However, the roleAssignment_res does not work as expected, and always scopes it at the resourceGroup. I have outputted the storageAccount_res and the keyVault_res when calling the module, and they return the output of that resource, so I know that is working, and should never get to that last condition for the scope. I tried putting subscription() as the last conditions to see if it was getting there, and it still just applied the roles at the resourceGroup level (i.e., the current scope of the module). My workaround is to create a different roleAssignment resource for each type of resource - like this: resource roleAssignment_st_res 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (role, index) in (contains(resourceGrantedTo,'Microsoft.Storage/storageAccounts') && length(split(resourceGrantedTo,'/')) == 9 ?roleDefinitionIds : []) : { resource roleAssignment_kv_res 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for (role, index) in (contains(resourceGrantedTo,'Microsoft.KeyVault/vaults') && length(split(resourceGrantedTo,'/')) == 9 ? roleDefinitionIds : []) : { I do not know of a different type of workaround if I am scoping at a resource like you can with a ternary within resourceGroup(). So, this module will get much, much longer than it needs to be when accounting for any resourceType and sub resourceType that we need to assign rights to. |
@BigRollTide I see, in that case we have a separate workaround. Works on any scope: Just take the Example of usage: module RBAC 'x.RBAC-ALL.bicep' = [for (role, index) in rolesInfo: {
name: take(replace('dp-rbac-role-${KV.name}-${role.name}', '@', '_'), 64)
params: {
resourceId: KV.id
Global: Global
roleInfo: role
Type: contains(role, 'Type') ? role.Type : 'lookup'
deployment: Deployment
}
}]
There was more discussion on this topic here: |
@BigRollTide |
Aparently this issue is still open after 1.5 year. This just cost me half a day to figure out:) What didn't work within a azure vnet resource: What does work: So aparently if the conditional returns a resourcegroup object it fails, but if you return a string with the name, it will succeed. So this way you retrieve the resource group name and then just return that in the else statement. Would be nice to get this fixed! |
Closing this out to track in #1876 |
Bicep version
Bicep CLI version 0.7.4 (
5afc312467
)Describe the bug
I want to get existing resource which is in different resource group, than the deployment itself. When I use
scope
conditionally, it is not working. It returns resource ID with deployment resource group name, not the othe one I want.To Reproduce
Let's have a simple Bicep template, where I try to get info about some resource.
I deploy this template:
az deployment group create --resource-group rsg2 --template-file .\conditional-scope.bicep --parameters appServicePlanResourceGroupName=rsg1
So deployment goes to resource group
rsg2
, but wanted service plan is in resource grouprsg1
. The outputs of this deployment are:So basically, in both cases, I ask twice for the same resource, but as you can see, I get different results.
scope
is set directly with condition, the returned resource ID is incorrect – containsrsg2
.scope
is without condition, it works OK.Additional context
Furthermore, I recommend to improve error message, when the resource is not found. When I created my Bicep template, I used conditional
scope
definition, which is not working. In some other resource, I wanted to use that resource ID. It failed with error message:This message is not sufficient, because that service plan clearly existed. It would be really helpful to add full resource ID to the message which was not found, not just the name. I spent quite a lot of time trying to find out what's going on, because I did not know, that the problem was in resource group name in the resource ID.
The text was updated successfully, but these errors were encountered: