Skip to content
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

Provide Azure Built-In role constants #1895

Open
allanlw opened this issue Mar 16, 2021 · 48 comments
Open

Provide Azure Built-In role constants #1895

allanlw opened this issue Mar 16, 2021 · 48 comments
Assignees
Labels
enhancement New feature or request intermediate language Related to the intermediate language revisit story: extensibility
Milestone

Comments

@allanlw
Copy link

allanlw commented Mar 16, 2021

Is your feature request related to a problem? Please describe.

Currently, to deploy a azure role assignment, the UUID of the role definition must be hard coded and/or provided as a parameter. This is a pain.

See https://github.com/Azure/bicep/blob/main/docs/examples/101/create-managedidentity-rbac/main.bicep for an example.

Describe the solution you'd like

Bicep is in a position to provide access to well-known constant values.

Syntax proposal 1: Introduce a new global variable that is loaded by default. Then you could access the roleDefinitionId like:

subscriptionResourceId('Microsoft.Authorization/roleDefinitions', WellKnownConstants.BuiltinRoles.StorageBlobDataContributor)

This has the advantage of (presumably) being easier to implement and has the advantage of only being one value in the namespace if there are other well-known constants that might be added in the future. Technically I suppose this would be a breaking change though.

Syntax proposal 2: The other option would be a new function for this specific case:

builtiInRoleDefinitionId('Storage Blob Data Contributor')

This is also a breaking change but is slightly simpler easier to use. It could also have an optional argument for targeting other scopes.

Downsides

Providing this information means that bicep must have some source of truth which would need to be vended with it (in which case it could become stale) or added as a new dependency. Also, it is not clear to me if the well known role definition ids are constant between different Azure clouds.

Regardless of the ergonomics this would essentially be adding resource-specific support into the bicep language, which as far as I can tell so far is relatively resource agnostic (or at least as much as ARM templates themselves are). Adding stuff like this starts to get into the "standard library" territory, which bicep might be trying to avoid.

This seems bite sized enough that if it's a desirable feature I'm actually considering implementing it myself and sending a PR, but I wanted to start a discussion first.

@allanlw allanlw added the enhancement New feature or request label Mar 16, 2021
@ghost ghost added the Needs: Triage 🔍 label Mar 16, 2021
@alex-frankel
Copy link
Collaborator

This would be a great addition, but I'd prefer to see this added to the deployments runtime so that both ARM and Bicep can benefit and we do as little "magic" in the bicep transpiler as possible. If it's alright, I'd like us to have an internal conversation to see if this is something we can prioritize, otherwise it may make sense for you to pick it up. Thanks for offering!

bicep must have some source of truth which would need to be vended with it

I'm hoping that this doc is generated off of that source of truth. At the very least, if we can tie updates to the bicep implementation to updates of this doc, that would be "current enough" IMO.

Also, it is not clear to me if the well known role definition ids are constant between different Azure clouds.

I think these are consistent between all clouds, but we should double-check.

@alex-frankel alex-frankel added discussion This is a discussion issue and not a change proposal. intermediate language Related to the intermediate language and removed Needs: Triage 🔍 labels Mar 16, 2021
@alex-frankel alex-frankel added this to the Committed Backlog milestone Mar 18, 2021
@alex-frankel alex-frankel changed the title Feature Request / Proposal - Provide Azure Built-In role constants Provide Azure Built-In role constants May 12, 2021
@alex-frankel
Copy link
Collaborator

Discussed that this should be a list*() type function provided by the AAD team. We will need to revisit this as we better understand how we could/will talk to MSGraph more directly.

@alex-frankel alex-frankel added revisit story: extensibility and removed discussion This is a discussion issue and not a change proposal. labels May 12, 2021
@NeilMacMullen
Copy link

It seems to me likely that there will always be sets of "constants" which are either customer-specific or unavailable via MSGrpah or just "not imported yet".

I'm hugely in favour of making the role constants available as built-ins but also raised #3039 to suggest a few mechanisms which might make it easier for users to provide their own constant-sets when they are not available directly from BICEP.

@JustinGrote
Copy link

I personally just generate a module with Powershell and then either stick that var directly in the file or use it as a module input.

Powershell to generate:

Get-AzRoleDefinition | % {"$($PSItem.Name -replace '[^\w]',''): '$($PSItem.ID)'"}
var roles = {
  AcrPush: '8311e382-0749-4cb8-b61a-304f252e45ec'
  APIManagementServiceContributor: '312a565d-c81f-4fd8-895a-4e21e48d571c'
  AcrPull: '7f951dda-4ed3-4680-a7ca-43fe172d538d'
  AcrImageSigner: '6cef56e8-d556-48e5-a04f-b8e64114680f'
  AcrDelete: 'c2f4ef07-c644-48eb-af81-4b1b4947fb11'
  AcrQuarantineReader: 'cdda3590-29a3-44f6-95f2-9f980659eb04'
  AcrQuarantineWriter: 'c8d4ff99-41c3-41a8-9f60-21dfdad59608'
  APIManagementServiceOperatorRole: 'e022efe7-f5ba-4159-bbe4-b44f577e9b61'
  APIManagementServiceReaderRole: '71522526-b88f-4d52-b57f-d31fc3546d0d'
  ApplicationInsightsComponentContributor: 'ae349356-3a1b-4a5e-921d-050484c6347e'
  ApplicationInsightsSnapshotDebugger: '08954f03-6346-4c2e-81c0-ec3a5cfae23b'
  AttestationReader: 'fd1bd22b-8476-40bc-a0bc-69b95687b9f3'
  AutomationJobOperator: '4fe576fe-1146-4730-92eb-48519fa6bf9f'
  AutomationRunbookOperator: '5fb5aef8-1081-4b8e-bb16-9d5d0385bab5'
  AutomationOperator: 'd3881f73-407a-4167-8283-e981cbba0404'
  AvereContributor: '4f8fab4f-1852-4a58-a46a-8eaf358af14a'
  AvereOperator: 'c025889f-8102-4ebf-b32c-fc0c6f0c6bd9'
  AzureKubernetesServiceClusterAdminRole: '0ab0b1a8-8aac-4efd-b8c2-3ee1fb270be8'
  AzureKubernetesServiceClusterUserRole: '4abbcc35-e782-43d8-92c5-2d3f1bd2253f'
  AzureMapsDataReader: '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa'
  AzureStackRegistrationOwner: '6f12a6df-dd06-4f3e-bcb1-ce8be600526a'
  BackupContributor: '5e467623-bb1f-42f4-a55d-6e525e11384b'
  BillingReader: 'fa23ad8b-c56e-40d8-ac0c-ce449e1d2c64'
  BackupOperator: '00c29273-979b-4161-815c-10b084fb9324'
  BackupReader: 'a795c7a0-d4a2-40c1-ae25-d81f01202912'
  BlockchainMemberNodeAccessPreview: '31a002a1-acaf-453e-8a5b-297c9ca1ea24'
  BizTalkContributor: '5e3c6656-6cfa-4708-81fe-0de47ac73342'
  CDNEndpointContributor: '426e0c7f-0c7e-4658-b36f-ff54d6c29b45'
  CDNEndpointReader: '871e35f6-b5c1-49cc-a043-bde969a0f2cd'
  CDNProfileContributor: 'ec156ff8-a8d1-4d15-830c-5b80698ca432'
  CDNProfileReader: '8f96442b-4075-438f-813d-ad51ab4019af'
  ClassicNetworkContributor: 'b34d265f-36f7-4a0d-a4d4-e158ca92e90f'
  ClassicStorageAccountContributor: '86e8f5dc-a6e9-4c67-9d15-de283e8eac25'
  ClassicStorageAccountKeyOperatorServiceRole: '985d6b00-f706-48f5-a6fe-d0ca12fb668d'
  ClearDBMySQLDBContributor: '9106cda0-8a86-4e81-b686-29a22c54effe'
  ClassicVirtualMachineContributor: 'd73bb868-a0df-4d4d-bd69-98a00b01fccb'
  CognitiveServicesUser: 'a97b65f3-24c7-4388-baec-2e87135dc908'
  CognitiveServicesDataReaderPreview: 'b59867f0-fa02-499b-be73-45a86b5b3e1c'
  CognitiveServicesContributor: '25fbc0a9-bd7c-42a3-aa1a-3b75d497ee68'
  CosmosBackupOperator: 'db7b14f2-5adf-42da-9f96-f2ee17bab5cb'
  Contributor: 'b24988ac-6180-42a0-ab88-20f7382dd24c'
  CosmosDBAccountReaderRole: 'fbdf93bf-df7d-467e-a4d2-9458aa1360c8'
  CostManagementContributor: '434105ed-43f6-45c7-a02f-909b2ba83430'
  CostManagementReader: '72fafb9e-0641-4937-9268-a91bfd8191a3'
  DataBoxContributor: 'add466c9-e687-43fc-8d98-dfcf8d720be5'
  DataBoxReader: '028f4ed7-e2a9-465e-a8f4-9c0ffdfdc027'
  DataFactoryContributor: '673868aa-7521-48a0-acc6-0f60742d39f5'
  DataPurger: '150f5e0c-0603-4f03-8c7f-cf70034c4e90'
  DataLakeAnalyticsDeveloper: '47b7735b-770e-4598-a7da-8b91488b4c88'
  DevTestLabsUser: '76283e04-6283-4c54-8f91-bcf1374a3c64'
  DocumentDBAccountContributor: '5bd9cd88-fe45-4216-938b-f97437e15450'
  DNSZoneContributor: 'befefa01-2a29-4197-83a8-272ff33ce314'
  EventGridEventSubscriptionContributor: '428e0ff0-5e57-4d9c-a221-2c70d0e0a443'
  EventGridEventSubscriptionReader: '2414bbcf-6497-4faf-8c65-045460748405'
  GraphOwner: 'b60367af-1334-4454-b71e-769d9a4f83d9'
  HDInsightDomainServicesContributor: '8d8d5a11-05d3-4bda-a417-a08778121c7c'
  IntelligentSystemsAccountContributor: '03a6d094-3444-4b3d-88af-7477090a9e5e'
  KeyVaultContributor: 'f25e0fa2-a7c8-4377-a976-54943a77a395'
  KnowledgeConsumer: 'ee361c5d-f7b5-4119-b4b6-892157c8f64c'
  LabCreator: 'b97fb8bc-a8b2-4522-a38b-dd33c7e65ead'
  LogAnalyticsReader: '73c42c96-874c-492b-b04d-ab87d138a893'
  LogAnalyticsContributor: '92aaf0da-9dab-42b6-94a3-d43ce8d16293'
  LogicAppOperator: '515c2055-d9d4-4321-b1b9-bd0c9a0f79fe'
  LogicAppContributor: '87a39d53-fc1b-424a-814c-f7e04687dc9e'
  ManagedApplicationOperatorRole: 'c7393b34-138c-406f-901b-d8cf2b17e6ae'
  ManagedApplicationsReader: 'b9331d33-8a36-4f8c-b097-4f54124fdb44'
  ManagedIdentityOperator: 'f1a07417-d97a-45cb-824c-7a7467783830'
  ManagedIdentityContributor: 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59'
  ManagementGroupContributor: '5d58bcaf-24a5-4b20-bdb6-eed9f69fbe4c'
  ManagementGroupReader: 'ac63b705-f282-497d-ac71-919bf39d939d'
  MonitoringMetricsPublisher: '3913510d-42f4-4e42-8a64-420c390055eb'
  MonitoringReader: '43d0d8ad-25c7-4714-9337-8ba259a9fe05'
  NetworkContributor: '4d97b98b-1d4f-4787-a291-c67834d212e7'
  MonitoringContributor: '749f88d5-cbae-40b8-bcfc-e573ddc772fa'
  NewRelicAPMAccountContributor: '5d28c62d-5b37-4476-8438-e587778df237'
  Owner: '8e3af657-a8ff-443c-a75c-2fe8c4bcb635'
  Reader: 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
  RedisCacheContributor: 'e0f68234-74aa-48ed-b826-c38b57376e17'
  ReaderandDataAccess: 'c12c1c16-33a1-487b-954d-41c89c60f349'
  ResourcePolicyContributor: '36243c78-bf99-498c-9df9-86d9f8d28608'
  SchedulerJobCollectionsContributor: '188a0f2f-5c9e-469b-ae67-2aa5ce574b94'
  SearchServiceContributor: '7ca78c08-252a-4471-8644-bb5ff32d4ba0'
  SecurityAdmin: 'fb1c8493-542b-48eb-b624-b4c8fea62acd'
  SecurityManagerLegacy: 'e3d13bf0-dd5a-482e-ba6b-9b8433878d10'
  SecurityReader: '39bc4728-0917-49c7-9d2c-d95423bc2eb4'
  SpatialAnchorsAccountContributor: '8bbe83f1-e2a6-4df7-8cb4-4e04d4e5c827'
  SiteRecoveryContributor: '6670b86e-a3f7-4917-ac9b-5d6ab1be4567'
  SiteRecoveryOperator: '494ae006-db33-4328-bf46-533a6560a3ca'
  SpatialAnchorsAccountReader: '5d51204f-eb77-4b1c-b86a-2ec626c49413'
  SiteRecoveryReader: 'dbaa88c4-0c30-4179-9fb3-46319faa6149'
  SpatialAnchorsAccountOwner: '70bbe301-9835-447d-afdd-19eb3167307c'
  SQLManagedInstanceContributor: '4939a1f6-9ae0-4e48-a1e0-f2cbe897382d'
  SQLDBContributor: '9b7fa17d-e63e-47b0-bb0a-15c516ac86ec'
  SQLSecurityManager: '056cd41c-7e88-42e1-933e-88ba6a50c9c3'
  StorageAccountContributor: '17d1049b-9a84-46fb-8f53-869881c3d3ab'
  SQLServerContributor: '6d8ee4ec-f05a-4a1d-8b00-a9b17e38b437'
  StorageAccountKeyOperatorServiceRole: '81a9662b-bebf-436f-a333-f67b29880f12'
  StorageBlobDataContributor: 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
  StorageBlobDataOwner: 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b'
  StorageBlobDataReader: '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1'
  StorageQueueDataContributor: '974c5e8b-45b9-4653-ba55-5f855dd0fb88'
  StorageQueueDataMessageProcessor: '8a0f0c08-91a1-4084-bc3d-661d67233fed'
  StorageQueueDataMessageSender: 'c6a89b2d-59bc-44d0-9896-0f6e12d7b80a'
  StorageQueueDataReader: '19e7f393-937e-4f77-808e-94535e297925'
  SupportRequestContributor: 'cfd33db0-3dd1-45e3-aa9d-cdbdf3b6f24e'
  TrafficManagerContributor: 'a4b10055-b0c7-44c2-b00f-c7b5b3550cf7'
  VirtualMachineAdministratorLogin: '1c0163c0-47e6-4577-8991-ea5c82e286e4'
  UserAccessAdministrator: '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9'
  VirtualMachineUserLogin: 'fb879df8-f326-4884-b1cf-06f3ad86be52'
  VirtualMachineContributor: '9980e02c-c2be-4d73-94e8-173b1dc7cf3c'
  WebPlanContributor: '2cc479cb-7b4d-49a8-b449-8c00fd0f0a4b'
  WebsiteContributor: 'de139f84-1756-47ae-9be6-808fbbe84772'
  AzureServiceBusDataOwner: '090c5cfd-751d-490a-894a-3ce6f1109419'
  AzureEventHubsDataOwner: 'f526a384-b230-433a-b45c-95f59c4a2dec'
  AttestationContributor: 'bbf86eb8-f7b4-4cce-96e4-18cddf81d86e'
  HDInsightClusterOperator: '61ed4efc-fab3-44fd-b111-e24485cc132a'
  CosmosDBOperator: '230815da-be43-4aae-9cb4-875f7bd000aa'
  HybridServerResourceAdministrator: '48b40c6e-82e0-4eb3-90d5-19e40f49b624'
  HybridServerOnboarding: '5d1e5ee4-7c68-4a71-ac8b-0739630a3dfb'
  AzureEventHubsDataReceiver: 'a638d3c7-ab3a-418d-83e6-5f17a39d4fde'
  AzureEventHubsDataSender: '2b629674-e913-4c01-ae53-ef4638d8f975'
  AzureServiceBusDataReceiver: '4f6d3b9b-027b-4f4c-9142-0e5a2a2247e0'
  AzureServiceBusDataSender: '69a216fc-b8fb-44d8-bc22-1f3c2cd27a39'
  StorageFileDataSMBShareReader: 'aba4ae5f-2193-4029-9191-0cb91df5e314'
  StorageFileDataSMBShareContributor: '0c867c2a-1d8c-454a-a3db-ab2ea1bdc8bb'
  PrivateDNSZoneContributor: 'b12aa53e-6015-4669-85d0-8515ebb3ae7f'
  StorageBlobDelegator: 'db58b8e5-c6ad-4a2a-8342-4190687cbf4a'
  DesktopVirtualizationUser: '1d18fff3-a72a-46b5-b4a9-0b38a3cd7e63'
  StorageFileDataSMBShareElevatedContributor: 'a7264617-510b-434b-a828-9731dc254ea7'
  BlueprintContributor: '41077137-e803-4205-871c-5a86e6a753b4'
  BlueprintOperator: '437d2ced-4a38-4302-8479-ed2bcb43d090'
  AzureSentinelContributor: 'ab8e14d6-4a74-4a29-9ba8-549422addade'
  AzureSentinelResponder: '3e150937-b8fe-4cfb-8069-0eaf05ecd056'
  AzureSentinelReader: '8d289c81-5878-46d4-8554-54e1e3d8b5cb'
  WorkbookReader: 'b279062a-9be3-42a0-92ae-8b3cf002ec4d'
  WorkbookContributor: 'e8ddcd69-c73f-4f9f-9844-4100522f16ad'
  PolicyInsightsDataWriterPreview: '66bb4e9e-b016-4a94-8249-4c0511c2be84'
  SignalRAccessKeyReader: '04165923-9d83-45d5-8227-78b77b0a687e'
  SignalRContributor: '8cf5e20a-e4b2-4e9d-b3a1-5ceb692c2761'
  AzureConnectedMachineOnboarding: 'b64e21ea-ac4e-4cdf-9dc9-5b892992bee7'
  AzureConnectedMachineResourceAdministrator: 'cd570a14-e51a-42ad-bac8-bafd67325302'
  ManagedServicesRegistrationassignmentDeleteRole: '91c1777a-f3dc-4fae-b103-61d183457e46'
  AppConfigurationDataOwner: '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b'
  AppConfigurationDataReader: '516239f1-63e1-4d78-a4de-a74fb236a071'
  KubernetesClusterAzureArcOnboarding: '34e09817-6cbe-4d01-b1a2-e0eac5743d41'
  ExperimentationContributor: '7f646f1b-fa08-80eb-a22b-edd6ce5c915c'
  CognitiveServicesQnAMakerReader: '466ccd10-b268-4a11-b098-b4849f024126'
  CognitiveServicesQnAMakerEditor: 'f4cc2bf9-21be-47a1-bdf1-5c5804381025'
  ExperimentationAdministrator: '7f646f1b-fa08-80eb-a33b-edd6ce5c915c'
  RemoteRenderingAdministrator: '3df8b902-2a6f-47c7-8cc5-360e9b272a7e'
  RemoteRenderingClient: 'd39065c4-c120-43c9-ab0a-63eed9795f0a'
  ManagedApplicationContributorRole: '641177b8-a67a-45b9-a033-47bc880bb21e'
  SecurityAssessmentContributor: '612c2aa1-cb24-443b-ac28-3ab7272de6f5'
  TagContributor: '4a9ae827-6dc8-4573-8ac7-8239d42aa03f'
  IntegrationServiceEnvironmentDeveloper: 'c7aa55d3-1abb-444a-a5ca-5e51e485d6ec'
  IntegrationServiceEnvironmentContributor: 'a41e2c5b-bd99-4a07-88f4-9bf657a760b8'
  AzureKubernetesServiceContributorRole: 'ed7f3fbd-7b88-4dd4-9017-9adb7ce333f8'
  AzureDigitalTwinsDataReader: 'd57506d4-4c8d-48b1-8587-93c323f6a5a3'
  AzureDigitalTwinsDataOwner: 'bcd981a7-7f74-457b-83e1-cceb9e632ffe'
  HierarchySettingsAdministrator: '350f8d15-c687-4448-8ae1-157740a3936d'
  FHIRDataContributor: '5a1fc7df-4bf1-4951-a576-89034ee01acd'
  FHIRDataExporter: '3db33094-8700-4567-8da5-1501d4e7e843'
  FHIRDataReader: '4c8d0bbc-75d3-4935-991f-5f3c56d81508'
  FHIRDataWriter: '3f88fce4-5892-4214-ae73-ba5294559913'
  ExperimentationReader: '49632ef5-d9ac-41f4-b8e7-bbe587fa74a1'
  ObjectUnderstandingAccountOwner: '4dd61c23-6743-42fe-a388-d8bdd41cb745'
  AzureMapsDataContributor: '8f5e0ce6-4f7b-4dcf-bddf-e6f48634a204'
  CognitiveServicesCustomVisionContributor: 'c1ff6cc2-c111-46fe-8896-e0ef812ad9f3'
  CognitiveServicesCustomVisionDeployment: '5c4089e1-6d96-4d2f-b296-c1bc7137275f'
  CognitiveServicesCustomVisionLabeler: '88424f51-ebe7-446f-bc41-7fa16989e96c'
  CognitiveServicesCustomVisionReader: '93586559-c37d-4a6b-ba08-b9f0940c2d73'
  CognitiveServicesCustomVisionTrainer: '0a5ae4ab-0d65-4eeb-be61-29fc9b54394b'
  KeyVaultAdministrator: '00482a5a-887f-4fb3-b363-3b7fe8e74483'
  KeyVaultCryptoOfficer: '14b46e9e-c2b7-41b4-b07b-48a6ebf60603'
  KeyVaultCryptoUser: '12338af0-0e69-4776-bea7-57ae8d297424'
  KeyVaultSecretsOfficer: 'b86a8fe4-44ce-4948-aee5-eccb2c155cd7'
  KeyVaultSecretsUser: '4633458b-17de-408a-b874-0445c86b69e6'
  KeyVaultCertificatesOfficer: 'a4417e6f-fecd-4de8-b567-7b0420556985'
  KeyVaultReader: '21090545-7ca7-4776-b22c-e363652d74d2'
  KeyVaultCryptoServiceEncryptionUser: 'e147488a-f6f5-4113-8e2d-b22465e65bf6'
  AzureArcKubernetesViewer: '63f0a09d-1495-4db4-a681-037d84835eb4'
  AzureArcKubernetesWriter: '5b999177-9696-4545-85c7-50de3797e5a1'
  AzureArcKubernetesClusterAdmin: '8393591c-06b9-48a2-a542-1bd6b377f6a2'
  AzureArcKubernetesAdmin: 'dffb1e0c-446f-4dde-a09f-99eb5cc68b96'
  AzureKubernetesServiceRBACClusterAdmin: 'b1ff04bb-8a4e-4dc4-8eb5-8693973ce19b'
  AzureKubernetesServiceRBACAdmin: '3498e952-d568-435e-9b2c-8d77e338d7f7'
  AzureKubernetesServiceRBACReader: '7f6c6a51-bcf8-42ba-9220-52d62157d7db'
  AzureKubernetesServiceRBACWriter: 'a7ffa36f-339b-4b5c-8bdf-e2c188b2c0eb'
  ServicesHubOperator: '82200a5b-e217-47a5-b665-6d8765ee745b'
  ObjectUnderstandingAccountReader: 'd18777c0-1514-4662-8490-608db7d334b6'
  AzureArcEnabledKubernetesClusterUserRole: '00493d72-78f6-4148-b6c5-d3ce8e4799dd'
  SignalRAppServerPreview: '420fcaa2-552c-430f-98ca-3264be4806c7'
  SignalRServerlessContributorPreview: 'fd53cd77-2268-407a-8f46-7e7863d0f521'
  CollaborativeDataContributor: 'daa9e50b-21df-454c-94a6-a8050adab352'
  DeviceUpdateReader: 'e9dba6fb-3d52-4cf0-bce3-f06ce71b9e0f'
  DeviceUpdateAdministrator: '02ca0879-e8e4-47a5-a61e-5c618b76e64a'
  DeviceUpdateContentAdministrator: '0378884a-3af5-44ab-8323-f5b22f9f3c98'
  DeviceUpdateDeploymentsAdministrator: 'e4237640-0e3d-4a46-8fda-70bc94856432'
  DeviceUpdateDeploymentsReader: '49e2f5d2-7741-4835-8efa-19e1fe35e47f'
  DeviceUpdateContentReader: 'd1ee9a80-8b14-47f0-bdc2-f4a351625a7b'
  CognitiveServicesMetricsAdvisorAdministrator: 'cb43c632-a144-4ec5-977c-e80c4affc34a'
  CognitiveServicesMetricsAdvisorUser: '3b20f47b-3825-43cb-8114-4bd2201156a8'
  SchemaRegistryReaderPreview: '2c56ea50-c6b3-40a6-83c0-9d98858bc7d2'
  SchemaRegistryContributorPreview: '5dffeca3-4936-4216-b2bc-10343a5abb25'
  AgFoodPlatformServiceReader: '7ec7ccdc-f61e-41fe-9aaf-980df0a44eba'
  AgFoodPlatformServiceContributor: '8508508a-4469-4e45-963b-2518ee0bb728'
  AgFoodPlatformServiceAdmin: 'f8da80de-1ff9-4747-ad80-a19b7f6079e3'
  ManagedHSMcontributor: '18500a29-7fe2-46b2-a342-b16a415e101d'
  SecurityDetonationChamberSubmitter: '0b555d9b-b4a7-4f43-b330-627f0e5be8f0'
  SignalRServiceReaderPreview: 'ddde6b66-c0df-4114-a159-3618637b3035'
  SignalRServiceOwnerPreview: '7e4f1700-ea5a-4f59-8f37-079cfe29dce3'
  ReservationPurchaser: 'f7b75c60-3036-4b75-91c3-6b41c27c1689'
  AzureMLMetricsWriterpreview: '635dd51f-9968-44d3-b7fb-6d9a6bd613ae'
  StorageAccountBackupContributorRole: 'e5e2a7ff-d759-4cd2-bb51-3152d37e2eb1'
  ExperimentationMetricContributor: '6188b7c9-7d01-4f99-a59f-c88b630326c0'
  ProjectBabylonDataCurator: '9ef4ef9c-a049-46b0-82ab-dd8ac094c889'
  ProjectBabylonDataReader: 'c8d896ba-346d-4f50-bc1d-7d1c84130446'
  ProjectBabylonDataSourceAdministrator: '05b7651b-dc44-475e-b74d-df3db49fae0f'
  PurviewDataCurator: '8a3c2885-9b38-4fd2-9d99-91af537c1347'
  PurviewDataReader: 'ff100721-1b9d-43d8-af52-42b69c1272db'
  PurviewDataSourceAdministrator: '200bba9e-f0c8-430f-892b-6f0794863803'
  ApplicationGroupContributor: 'ca6382a4-1721-4bcf-a114-ff0c70227b6b'
  DesktopVirtualizationReader: '49a72310-ab8d-41df-bbb0-79b649203868'
  DesktopVirtualizationContributor: '082f0a83-3be5-4ba1-904c-961cca79b387'
  DesktopVirtualizationWorkspaceContributor: '21efdde3-836f-432b-bf3d-3e8e734d4b2b'
  DesktopVirtualizationUserSessionOperator: 'ea4bfff8-7fb4-485a-aadd-d4129a0ffaa6'
  DesktopVirtualizationSessionHostOperator: '2ad6aaab-ead9-4eaa-8ac5-da422f562408'
  DesktopVirtualizationHostPoolReader: 'ceadfde2-b300-400a-ab7b-6143895aa822'
  DesktopVirtualizationHostPoolContributor: 'e307426c-f9b6-4e81-87de-d99efb3c32bc'
  DesktopVirtualizationApplicationGroupReader: 'aebf23d0-b568-4e86-b8f9-fe83a2c6ab55'
  DesktopVirtualizationApplicationGroupContributor: '86240b0e-9422-4c43-887b-b61143f32ba8'
  DesktopVirtualizationWorkspaceReader: '0fa44ee9-7a7d-466b-9bb2-2bf446b1204d'
  DiskBackupReader: '3e5e47e6-65f7-47ef-90b5-e5dd4d455f24'
  AutonomousDevelopmentPlatformDataContributorPreview: 'b8b15564-4fa6-4a59-ab12-03e1d9594795'
  AutonomousDevelopmentPlatformDataReaderPreview: 'd63b75f7-47ea-4f27-92ac-e0d173aaf093'
  AutonomousDevelopmentPlatformDataOwnerPreview: '27f8b550-c507-4db9-86f2-f4b8e816d59d'
  DiskRestoreOperator: 'b50d9833-a0cb-478e-945f-707fcc997c13'
  DiskSnapshotContributor: '7efff54f-a5b4-42b5-a1c5-5411624893ce'
  MicrosoftKubernetesconnectedclusterrole: '5548b2cf-c94c-4228-90ba-30851930a12f'
  SecurityDetonationChamberSubmissionManager: 'a37b566d-3efa-4beb-a2f2-698963fa42ce'
  SecurityDetonationChamberPublisher: '352470b3-6a9c-4686-b503-35deb827e500'
  CollaborativeRuntimeOperator: '7a6f0e70-c033-4fb1-828c-08514e5f4102'
  CosmosRestoreOperator: '5432c526-bc82-444a-b7ba-57c5b0b5b34f'
  FHIRDataConverter: 'a1705bd2-3a8f-45a5-8683-466fcfd5cc24'
  AzureSentinelAutomationContributor: 'f4c81013-99ee-4d62-a7ee-b3f1f648599a'
  QuotaRequestOperator: '0e5f05e5-9ab9-446b-b98d-1e2157c94125'
  EventGridContributor: '1e241071-0855-49ea-94dc-649edcd759de'
  SecurityDetonationChamberReader: '28241645-39f8-410b-ad48-87863e2951d5'
  ObjectAnchorsAccountReader: '4a167cdf-cb95-4554-9203-2347fe489bd9'
  ObjectAnchorsAccountOwner: 'ca0835dd-bacc-42dd-8ed2-ed5e7230d15b'
  WorkloadBuilderMigrationAgentRole: 'd17ce0a2-0697-43bc-aac5-9113337ab61c'
  WebPubSubServiceOwnerPreview: '12cf5a90-567b-43ae-8102-96cf46c7d9b4'
  WebPubSubServiceReaderPreview: 'bfb1c7d2-fb1a-466b-b2ba-aee63b92deaf'
  AzureSpringCloudDataReader: 'b5537268-8956-4941-a8f0-646150406f0c'
  CognitiveServicesSpeechUser: 'f2dc8367-1007-4938-bd23-fe263f013447'
  CognitiveServicesSpeechContributor: '0e75ca1e-0464-4b4d-8b93-68208a576181'
  CognitiveServicesFaceRecognizer: '9894cab4-e18a-44aa-828b-cb588cd6f2d7'
  MediaServicesAccountAdministrator: '054126f8-9a2b-4f1c-a9ad-eca461f08466'
  MediaServicesLiveEventsAdministrator: '532bc159-b25e-42c0-969e-a1d439f60d77'
  MediaServicesMediaOperator: 'e4395492-1534-4db2-bedf-88c14621589c'
  MediaServicesPolicyAdministrator: 'c4bba371-dacd-4a26-b320-7250bca963ae'
  MediaServicesStreamingEndpointsAdministrator: '99dba123-b5fe-44d5-874c-ced7199a5804'
  StreamAnalyticsQueryTester: '1ec5b3c1-b17e-4e25-8312-2acb3c3c5abf'
  AnyBuildBuilder: 'a2138dac-4907-4679-a376-736901ed8ad8'
  IoTHubDataReader: 'b447c946-2db7-41ec-983d-d8bf3b1c77e3'
  IoTHubTwinContributor: '494bdba2-168f-4f31-a0a1-191d2f7c028c'
  IoTHubRegistryContributor: '4ea46cd5-c1b2-4a8e-910b-273211f9ce47'
  IoTHubDataContributor: '4fc6c259-987e-4a07-842e-c321cc9d413f'
  TestBaseReader: '15e0f5a1-3450-4248-8e25-e2afe88a9e85'
  SearchIndexDataReader: '1407120a-92aa-4202-b7e9-c0e197c71c8f'
  SearchIndexDataContributor: '8ebe5a00-799e-43f5-93ac-243d3dce84a7'
  StorageTableDataReader: '76199698-9eea-4c19-bc75-cec21354c6b6'
  StorageTableDataContributor: '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'
  DICOMDataReader: 'e89c7a3c-2f64-4fa1-a847-3e4c9ba4283a'
  DICOMDataOwner: '58a3b984-7adf-4c20-983a-32417c86fbc8'
  EventGridDataSender: 'd5a91429-5739-47e2-a06b-3470a27159e7'
}

output roles object = roles

I've considered making a deployment script one that would fetch my custom roles and then output at runtime, I wouldn't get intellisense but I could specify them by name rather than guid.

@JustinGrote
Copy link

JustinGrote commented Jul 7, 2021

Here's a slightly more complex one for policy definitions. Works for Policy Initiatives too, just swap get-azpolicydefinition for get-azpolicydefinitionset

[ScriptBlock]$PolicyNameResolver = {
    $baseDisplayName = $PSItem.properties.displayname -replace '[^\s\w]',''
    $category = $PSItem.properties.metadata.category -replace '\s',''
    $name = (Get-Culture).TextInfo.ToTitleCase($baseDisplayName) -replace '\s',''
    $category + "_" + $name
}

Get-AzPolicyDefinition | 
    Where-Object {$_.properties.PolicyType -match 'BuiltIn|Static'} |
    Select-Object @{N='Name';E=$PolicyNameResolver}, PolicyDefinitionId |
    Sort-Object Name |
    Foreach-Object {
        "{0}: {1}" -f $_.Name,$_.PolicyDefinitionId
    }

@anthony-c-martin
Copy link
Member

Here's a slightly more complex one for policy definitions. Works for Policy Initiatives too, just swap get-azpolicydefinition for get-azpolicydefinitionset

Very cool, thank you for sharing! Your comment reminded me of an idea we'd been discussing a while back - providing completions for imported or in-lined JSON, which as it turns out was extremely simple to implement! #3510

@slavizh
Copy link
Contributor

slavizh commented Jul 9, 2021

One thing to keep in mind is the change in the display name. Often teams change the display name of built-in role. Definitely happens when they have published the role with Preview in the name. Display names changes for policies and initiatives is even more common.

@JustinGrote
Copy link

@slavizh I don't know about "often", I've rarely seen it in the hundreds of customers at my MSP, but it is certainly a consideration. That said, this process will still work, either you include your own builtin json that will resolve to the same builtin GUIDs regardless of what the customer specified as the display name, or you can generate a "customer" json that has their specific names.

Now that #3510 is merged, I propose that approach is sufficient to close this issue, as a json of builtin constants can be generated and supplied, and provides intellisense.

@allanlw
Copy link
Author

allanlw commented Jul 9, 2021

The approach in #3510 could be used or the approach laid out above using a " list*() type function" could be used, but this issue is specifically about Bicep (and perhaps ARM under the hood), and not the end-user, being responsible for the mapping.

@alex-frankel
Copy link
Collaborator

I agree - I'd prefer to leave this issue open for now. Thought I do like the creative solution @JustinGrote :)

@JustinGrote
Copy link

JustinGrote commented Jul 12, 2021

After playing with #3510 this is what I would see as being ideal:

  1. Bicep implements the MSAL azure library same way the Azure Function, etc. extensions do and user "signs in" to their context
  2. User hits ctrl-space on a supported "discovery" context with a defined discoverable type (lets say the vm sku property)
  3. Bicep LS runs a non-blocking azure query in the background to fetch possibilities. IF user types, the filter is updated based on what the user typed.
  4. Bicep displays an intellisense of friendly "names" for that item (for instance a combined Publisher/VM/SKU description)
  5. If the user picks the selection, bicep generates a json for that object, adds a var for that json "import", and then sets the value at the user cursor to the generated json value.

The last step could potentially be more transparent. Also for performance there could just be a task to update the "master library" of these builtin types in the background at LSP startup.

@JustinGrote
Copy link

Did some modifications for my "creative" solution, here it is in action for Policy
image

@skurhse
Copy link

skurhse commented Sep 14, 2021

Dumping this jq script; it expands on @JustinGrote's approach with handling for capitalization and parentheticals.

az role definition list --query "[?roleType=='BuiltInRole'].{roleName: roleName, name: name}" | \
jq -nr '[inputs|.[] | .roleName |= (gsub("[(].*[)]"; ""; "i") | gsub("[./-]"; " ") | gsub("(?<x>[A-z])(?<y>[A-z]+)"; "\(.x|ascii_upcase)\(.y)") | gsub(" "; "")) | [.roleName, .name]] | sort | .[] | @tsv'

Obviously, dumping and transforming these from the CLI is a pessimal solution.

@KaiWalter
Copy link
Contributor

@anthony-c-martin I also miss this feature comparing Terraform to Bicep. Is there any plan to support resolving roleDefinitionId by name?

@ChristopherGLewis
Copy link
Contributor

As a temporary workaround, I've created an Azure Deployment Script that returns a GUID of a role given its name. It's SLOW, but it does work.

BicepDeploymentScripts

@AlexanderSehr
Copy link

Thinking about it more, another option which avoids the size expansion issue you mentioned would be to just have a file with exported variables:

  • roles.bicep
    @export()
    @description('Push artifacts to or pull artifacts from a container registry.')
    var AcrPush = '8311e382-0749-4cb8-b61a-304f252e45ec'
    
    @export()
    @description('Can manage service and the APIs')
    var APIManagementServiceContributor = '312a565d-c81f-4fd8-895a-4e21e48d571c'
    
    @export()
    @description('Pull artifacts from a container registry.')
    var AcrPull = '7f951dda-4ed3-4680-a7ca-43fe172d538d'
    
    @export()
    @description('Push trusted images to or pull trusted images from a container registry enabled for content trust.')
    var AcrImageSigner = '6cef56e8-d556-48e5-a04f-b8e64114680f'
  • main.bicep
import { AcrImageSigner } from 'roles.bicep'

As of Bicep v0.25.3, imports are now GA.

@AlexanderSehr would you have any objections to a contribution to https://github.com/Azure/bicep-registry-modules to add a module like this?

Hey @anthony-c-martin an option definitely, thanks for bringing this up. The only concern (I can't help it) would be the size increase if referenced in each AVM module. Just did a test and with all (non-custom) roles you end up with a compiled JSON of about 40kb. That isn't too bad and I guess could start becoming an issue if you have let's say 10 modules which would then push this to 400kb etc.

@jtracey93 @eriqua @ChrisSidebotham, a pint for your thoughts.

@anthony-c-martin
Copy link
Member

Hey @anthony-c-martin an option definitely, thanks for bringing this up. The only concern (I can't help it) would be the size increase if referenced in each AVM module. Just did a test and with all (non-custom) roles you end up with a compiled JSON of about 40kb. That isn't too bad and I guess could start becoming an issue if you have let's say 10 modules which would then push this to 400kb etc.

@jtracey93 @eriqua @ChrisSidebotham, a pint for your thoughts.

FYI, the mechanism for consumption is the import statement, not via a module - this actually does dead code elimination, so should avoid bloating the template. Here's what my example looks like, compiled - note that only the role I have referenced is present:

image

@AlexanderSehr
Copy link

sumption is the import statement, not via a module - this actually does dead code elimination, so should avoid bloating the template. Here's what my examp

As they say "You had my curiosity now attention". I'll go ahead and create an issue to PoC this.

@AlexanderSehr
Copy link

AlexanderSehr commented Feb 9, 2024

@export()
@description('Push artifacts to or pull artifacts from a container registry.')
var AcrPush = '8311e382-0749-4cb8-b61a-304f252e45ec'

@export()
@description('Can manage service and the APIs')
var APIManagementServiceContributor = '312a565d-c81f-4fd8-895a-4e21e48d571c'

@export()
@description('Pull artifacts from a container registry.')
var AcrPull = '7f951dda-4ed3-4680-a7ca-43fe172d538d'

@export()
@description('Push trusted images to or pull trusted images from a container registry enabled for content trust.')
var AcrImageSigner = '6cef56e8-d556-48e5-a04f-b8e64114680f'

I may have some bad news - at least for using this for AVM. I created the following small snippet to generate the content of a roles.bicep file for testing:

$res = [System.Collections.ArrayList]@()

$def = Get-AzRoleDefinition | Where-Object { 
    -not $_.IsCustom 
}
$def | Sort-Object -Property 'Name' | ForEach-Object {
    $validNameRegex = '[^a-zA-Z0-9]'
    $item = @('@export()')
    # Sometimes the description is just the name - ignore those cases + only add a description if not empty
    if (-not [String]::IsNullOrEmpty($_.description) -and ($_.description -replace '\s') -ne ($_.name -replace $validNameRegex)) { 
        $item += "@description('{0}')" -f ($_.description -replace "'", "\'" -replace "")
    }
    $item += "var {0} = '{1}'" -f ($_.name -replace $validNameRegex), $_.id; $item += ''
    $res += $item 
}

The resulting file has a small collection of 495 roles. Which is a bit unfortunate, given that this leads to an error
image

Mind you - not all 495 roles are valid. Some have for example 'deprecated' in their name (10 total) - but not matter how rigerious I'd be throwing out roles, I doubt I'd be able to cut them down by half :D

Is there any way to increase this limit @anthony-c-martin? I still think the idea is great - unless it fails facing reality ;)

I'd also be curious how this could be used in an AVM module - I guess we'd need to publish the file as it's own module an then reference it from the Public Registry, right? A similar approach is described: #13279.


Edit

Another way might be to create the file in the same way we currently allow role-name usage in the AVM modules (e.g. Key Vault):

@export()
@description('Available Azure role definitions to reference by name.')
var builtInRoleNames = {
  'Access Review Operator Service Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '76cc9ee4-d5d3-4a45-a930-26add3d73475')
  AcrDelete: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c2f4ef07-c644-48eb-af81-4b1b4947fb11')
  AcrImageSigner: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')
  AcrPull: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')
  AcrPush: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')
  AcrQuarantineReader: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'cdda3590-29a3-44f6-95f2-9f980659eb04')
  AcrQuarantineWriter: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c8d4ff99-41c3-41a8-9f60-21dfdad59608')
  'Advisor Reviews Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8aac15f0-d885-4138-8afa-bfb5872f7d13')
  'Advisor Reviews Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c64499e0-74c3-47ad-921c-13865957895c')
  'AgFood Platform Dataset Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a8d4b70f-0fb9-4f72-b267-b87b2f990aec')
  'AgFood Platform Sensor Partner Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6b77f0a0-0d89-41cc-acd1-579c22c17a67')
  'AgFood Platform Service Admin': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f8da80de-1ff9-4747-ad80-a19b7f6079e3')
  'AgFood Platform Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8508508a-4469-4e45-963b-2518ee0bb728')
  'AgFood Platform Service Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7ec7ccdc-f61e-41fe-9aaf-980df0a44eba')
  'AnyBuild Builder': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'a2138dac-4907-4679-a376-736901ed8ad8')
  'API Management Developer Portal Content Editor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c031e6a8-4391-4de0-8d69-4706a7ed3729')
  'API Management Service Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')
  (...)
}

That one does actually not produce an error. But I can't say I have worked with type imports yet, so maybe that doesn't help at all :D

@slavizh
Copy link
Contributor

slavizh commented Feb 9, 2024

I will chime in once again. It is ridiculous this to be in module and having to be maintained.

@anthony-c-martin
Copy link
Member

I will chime in once again. It is ridiculous this to be in module and having to be maintained.

I see the point, but ultimately it has to be maintained by someone, somewhere (either in the platform, or publicly), and we are already maintaining a list in documentation. Other than it being more work on our side, I don't see a significant problem with us doing both.

The upsides I see in leveraging imports are being able to provide a higher quality editor experience (descriptions in hovers, completions, type inference, validation, speed), and in shifting more errors left.

@alex-frankel
Copy link
Collaborator

alex-frankel commented Feb 13, 2024

That one does actually not produce an error. But I can't say I have worked with type imports yet, so maybe that doesn't help at all

@AlexanderSehr - I think this is a good workaround. I don't see any obvious reason why this wouldn't work.

+1 on Anthony's comment re: maintenance. If we have a reliable script for keeping this file up to date using the available PS cmdlet, that seems like it should be ok maintenance-wise (at least in the short term). If this proves problematic, we can always revisit it.

@ChristopherGLewis
Copy link
Contributor

I think you are trying to boil the ocean here. Given this wonderful website: AzAdvertizer you can see that this will be perpetually out of date (two new roles added 2024-02-12, looks like an average of 20-30 a month. There's an RSS feed of changes!).

I do like the ability to be able to use these in code as expressed above, but I think, from a community standpoint (and an Azure standpoint!) there should be a concerted effort on MS's side to have proper change release management for RBAC - we've FINALLY gotten this for Az CLI and PS's AZ module with monthly updates on patch Tuesday, but RBAC/Policy/Initiatives seem like they are releases via fire-hose.

Obviously, each resource provider team is in the end responsible for their RBAC/Policy (I would assume) but it just seems like it's the wild west out there...

@alex-frankel
Copy link
Collaborator

I'm not sure I agree that we are boiling the ocean - Anthony/Alex's proposal is a very inexpensive option and I suspect solves 95% of the problem. I recognize new roles are released and that requires an update, but that is a different question of maintenance. (As an aside, how many people need the newest roles?)

In other words, there are two questions to answer:

  1. How do we ship this built-in role information in bicep?
  2. How do we keep the list of built-in roles up to date?

I might be missing something -- is there something inherent in what we choose for number 1 that affects the speed of maintenance for 2? If we chose to implement number 1 as some sort of built-in functionality, does that enable us to maintain this list better in some way?

@slavizh
Copy link
Contributor

slavizh commented Feb 16, 2024

Also you need to think how to make this non-breakable. Sometimes roles change their display name. One option is when role name is changed you add another record even though you have already a record for the same ID. Others is to increase major version once such change is introduced. The downside of the latter is that such breaking change can be applicable for only small users, for the rest it will not be breaking one.

@ChristopherGLewis
Copy link
Contributor

I'm not sure I agree that we are boiling the ocean - Anthony/Alex's proposal is a very inexpensive option and I suspect solves 95% of the problem. I recognize new roles are released and that requires an update, but that is a different question of maintenance. (As an aside, how many people need the newest roles?)

In other words, there are two questions to answer:

  1. How do we ship this built-in role information in bicep?
  2. How do we keep the list of built-in roles up to date?

I might be missing something -- is there something inherent in what we choose for number 1 that affects the speed of maintenance for 2? If we chose to implement number 1 as some sort of built-in functionality, does that enable us to maintain this list better in some way?

@alex-frankel addressing above:

1, You nailed it - this approach is perfect for that, and I look forward to using this in my code. There's no question that your approach to this is the "right way".

  1. This is my biggest concern - it appears like RBAC roles get released at no set time. My ask is nothing do do with how you do releases, just more on a coordinated time -

One of:

  • I know that RBAC changes only get released on first tuesday of the month, I can expect the Bicep module with that RBAC change is available some set number of days after.
  • I know that RBAC changes only get released on first tuesday of the month, I can expect the bicep module with that RBAC change is available the first tuesday of the following month
  • I know that RBAC changes only get released on first tuesday of the month, I can expect the bicep module with that RBAC change is available with the next release of Bicep

vs what we have right now

  • An RBAC change gets released on an arbitrary date, and I have no idea when I can expect the RBAC change in the bicep module.

@slavizh
Copy link
Contributor

slavizh commented Mar 11, 2024

@anthony-c-martin @alex-frankel judging by Azure/bicep-registry-modules#965 this has gone to dead end due to number of variables limit and import not being able to import specify property within an object via dot notation. May be the latter is something that can be enabled? From end user perspective sounds like it should not be hard to implement but someone on the bicep project should conclude that. Of course if you have some other ideas how this issue can be resolved let us know.

@AlexanderSehr
Copy link

@anthony-c-martin @alex-frankel judging by Azure/bicep-registry-modules#965 this has gone to dead end due to number of variables limit and import not being able to import specify property within an object via dot notation. May be the latter is something that can be enabled? From end user perspective sounds like it should not be hard to implement but someone on the bicep project should conclude that. Of course if you have some other ideas how this issue can be resolved let us know.

Hey @slavizh the original lead went a bit cold, yes. However, a few leads are looked into still. I'm myself waiting to see if something comes out of it, so fingers crossed :)

@OskarKlintrot
Copy link

A downside of import that I noticed is that they can't be used with parameters; you can't use them for @allow or as default value.

@slavizh
Copy link
Contributor

slavizh commented Mar 12, 2024

@AlexanderSehr which are those leads? I do not see anything proposed here that could work.

@AlexanderSehr
Copy link

A downside of import that I noticed is that they can't be used with parameters; you can't use them for @allow or as default value.

I think the suggestion with a published rbac file would work something like this:

import { AcrPush } from '../../../../../../../../../../../roles.bicep'

@batchSize(1)
module testDeployment '../../../main.bicep' = [for iteration in [ 'init', 'idem' ]: {
  scope: resourceGroup
  name: '${uniqueString(deployment().name, resourceLocation)}-test-${serviceShort}-${iteration}'
  params: {
    name: '${namePrefix}${serviceShort}001'
    roleAssignments: [
      {
        roleDefinitionIdOrName: AcrPush
        principalId: nestedDependencies.outputs.managedIdentityPrincipalId
        principalType: 'ServicePrincipal'
      }
    ]
}

where the roles.bicep files looks like this

@export()
@description('Push artifacts to or pull artifacts from a container registry.')
var AcrPush = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8311e382-0749-4cb8-b61a-304f252e45ec')

@export()
@description('Can manage service and the APIs')
var APIManagementServiceContributor = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '312a565d-c81f-4fd8-895a-4e21e48d571c')

@export()
@description('Pull artifacts from a container registry.')
var AcrPull = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '7f951dda-4ed3-4680-a7ca-43fe172d538d')

@export()
@description('Push trusted images to or pull trusted images from a container registry enabled for content trust.')
var AcrImageSigner = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '6cef56e8-d556-48e5-a04f-b8e64114680f')

But yes, you can't use them in the metadata as anything in there must be available at compile time.

@AlexanderSehr which are those leads? I do not see anything proposed here that could work.

The main question was to find out if something can be done about the var-count limit.

@slavizh
Copy link
Contributor

slavizh commented Mar 13, 2024

@AlexanderSehr that is not good solution. It means you need to know in advance the role that will be assigned, The role needs to be picked from bicep parameters file. The main problem is that when you read bicep parameters file to know what kind of roles you are assigning and not having to look at some GUIDs which you will have to check online to understand the role assigned. The above example is the same like defining a single variable in your bicep templates named AcrPush with the GUID for a value. We need something that can be used by end users (in bicep parameters files). Everything else is just workaround on what we can already do and nothing new. As pointed out clearly bicep language constrains are prohibiting that scenario so we need Bicep team (@anthony-c-martin , @alex-frankel ) to lift those constrains. I do not think they will lift the variable count limit as that is also ARM template limit which means they have to do changes on ARM. If that limit is lifted it is lifted for all scenarios not just this one. The dot notation thing seems easier for me as it is just bicep compile time constrain which for me it seems easier to lift.

@AlexanderSehr
Copy link

d solution. It means you need to know in advance the role that will be assigned, The role needs to be picked from bicep parameters file. The main problem is that when you read bicep parameters file to know what kind of roles you are assigning and not having to look at some GUIDs which you will have to check online to understand the role assigned. The above example is the same like defining a single variable in your bicep templates named AcrPush with the GUID for a value. We need something that can be used by end users (in bicep parameters files). Everything else is just w

Hey @slavizh,
please note that I'm not a member of a product group but am working with the same constraints as everybody else. Using a (published) roles.bicep file is, I think, a good workaround for the time being. Would a native lookup feature be better - certainly, but I cannot do anything about that.
Using the roles.bicep file, you wouldn't need to know the GUIDs nor look them up. The reference would contain that information and as per my example above all you'd need is something like import { roleName1, roleName2, ... } from 'br/public:roles:1.0.0' to use the role's name and would not need to interact with any GUID.

@slavizh
Copy link
Contributor

slavizh commented Mar 14, 2024

@AlexanderSehr yes I know that is why I have called explicitly Bicep members as the workaround you are proposing just does not work for me and I think does not work for many others. It might work for you but definitely not for me and as I have said it is nothing new, it is the same like just defining only the roles you need in variables. I need end users those who provide the input in bicep parameters what role they want to assign to choose from all latest available, not to just have 5 roles and ask them to choose one of them. You have responded thus why I have responded but the initial questions were towards @alex-frankel and @anthony-c-martin :) . Sorry for tagging you again. I know you are currently busy it was to able to make the point. Ideally whatever solution is found for this I want to do the same thing for built-in policy definitions and policy set definitions. I would want end users (in bicep parameters file) to be able to find IDs of those by just picking up the name, You already know that are even way more policy definitions than roles.

@slavizh
Copy link
Contributor

slavizh commented Apr 2, 2024

@anthony-c-martin @alex-frankel friendly reminder.

@slavizh
Copy link
Contributor

slavizh commented Apr 26, 2024

@anthony-c-martin @alex-frankel friendly reminder once again. Sorry but I will continue to ping you in order to receive some answer what path will be followed about this if any.

@alex-frankel
Copy link
Collaborator

We currently have it in our semester plan to create a new dedicated function for this. Thanks for keeping this top of mind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request intermediate language Related to the intermediate language revisit story: extensibility
Projects
Status: Todo
Development

No branches or pull requests