Microsoft Graph Bicep – Part 2

In the last blog post, I kicked off a short series on Microsoft Graph for Bicep. Today’s second part is about further expanding the initial setup of Part 1 so that we can further integrate Bicep for Microsoft Graph into our existing automation in the future and replace some PowerShell steps.

Today we will take a closer look at how the created group can be used with and without Entra ID users for Azure RBAC role assignments, for example.

Example

As a basis we use the Github repository from Part 1 and build on it further.

Security Group with Azure RBAC permissions

The first example includes the creation of an Entra Security Group which is further used to set an Azure RBAC permission on a resource. In this example, a Log Analytics Workspace (LAW), which receives the permission using the security group.

groups.bicep

extension microsoftGraphV1

@description('Name of the group to be created')
param groupName string

resource group 'Microsoft.Graph/[email protected]' = {
  displayName: groupName
  mailEnabled: false
  mailNickname: uniqueString(groupName)
  securityEnabled: true
  uniqueName: groupName
}

output groupId string = group.id
output groupDisplayName string = group.displayName

logAnalyticsWorkspace.bicep

// Parameters
@description('Name of the Log Analytics workspace.')
param logAnalyticsWorkspaceName string

@description('SKU name for the Log Analytics workspace.')
@allowed([
  'Free'
  'PerGB2018'
])
param logAnalyticsWorkspaceSkuName string

@description('Log retention in days for the Log Analytics workspace.')
param logAnalyticsWorkspaceRetentionInDays int

@description('Maximum daily ingestion in gigabytes for the Log Analytics workspace.')
param logAnalyticsWorkspaceDailyQuotaGb int

@description('Name of the RBAC Role assignment.')
param roleAssignmentName string

@description('Principal ID of the user, group, or service principal to assign the role to.')
param principalId string

@description('Role definition ID to assign to the principal.')
param roleDefinitionId string

// Resources
resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2023-09-01' = {
  name: logAnalyticsWorkspaceName
  location: resourceGroup().location
  properties: {
    sku: {
      name: logAnalyticsWorkspaceSkuName
    }
    retentionInDays: logAnalyticsWorkspaceRetentionInDays
    workspaceCapping: {
      dailyQuotaGb: logAnalyticsWorkspaceDailyQuotaGb
    }
  }
}

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  scope: logAnalyticsWorkspace
  name: roleAssignmentName
  properties: {
    principalId: principalId
    roleDefinitionId: roleDefinitionId
  }
}

main.bicep

// Extensions
extension microsoftGraphV1

// Parameters
@description('Name of the group to be created')
param groupName string

@description('Name of the Log Analytics workspace to be created')
param logAnalyticsWorkspaceName string

@description('Sku name of the Log Analytics workspace to be created')
param logAnalyticsWorkspaceSkuName string

@description('Retention period in days for the Log Analytics workspace')
param logAnalyticsWorkspaceRetentionInDays int

@description('Daily quota in GB for the Log Analytics workspace')
param logAnalyticsWorkspaceDailyQuotaGb int

@description('Role definition ID to assign to the principal.')
param roleDefinitionId string

// Variables
@description('Name of the role assignment to be created')
var roleAssignmentName = guid(groupName, roleDefinitionId, resourceGroup().id)

// Resources
module groups 'modules/groups.bicep' = {
  name: 'groups'
  params: {
    groupName: groupName
  }
}

module logAnalyticsWorkspace 'modules/logAnalyticsWorkspace.bicep' = {
  name: 'logAnalyticsWorkspace'
  params: {
    logAnalyticsWorkspaceName: logAnalyticsWorkspaceName
    logAnalyticsWorkspaceSkuName: logAnalyticsWorkspaceSkuName
    logAnalyticsWorkspaceRetentionInDays: logAnalyticsWorkspaceRetentionInDays
    logAnalyticsWorkspaceDailyQuotaGb: logAnalyticsWorkspaceDailyQuotaGb
    roleAssignmentName: roleAssignmentName
    principalId: groups.outputs.groupId
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
  }
}

// Outputs
output groupName string = groups.outputs.groupDisplayName
output groupId string = groups.outputs.groupId
output roleAssignmentName string = roleAssignmentName

main.bicepparam

using './main.bicep'

param groupName = 'sg-con-log-prod-switzerlandnorth-01'
param logAnalyticsWorkspaceName = 'con-log-prod-switzerlandnorth-01'
param logAnalyticsWorkspaceSkuName = 'PerGB2018'
param logAnalyticsWorkspaceRetentionInDays = 30
param logAnalyticsWorkspaceDailyQuotaGb = 1
param roleDefinitionId = '92aaf0da-9dab-42b6-94a3-d43ce8d16293' //Log Analytics Contributor

Result

After executing the bicep code, the security group, log analytics workspace and the defined Azure RBAC authorisation were set correctly.

The complete code of the new example can be found here: Github example: security-group-add-to-law

Security Group with Users and Azure RBAC permissions

The second example now not only includes the creation of the security group but also fills it with the users according to Part 1 and sets the Azure RBAC permission to the created Log Analytics Workspace.

users.bicep

// Extensions
extension microsoftGraphV1

// Parameters
@description('List of User Principal Names (UPNs)')
param upnList array

// Variables
@description('Length of the UPN list')
var upnListLength = length(upnList)

// Resources
resource userList 'Microsoft.Graph/[email protected]'existing = [for i in range(0, upnListLength): {
  userPrincipalName: upnList[i]
}]

// Output
output userIds array = [for i in range(0, upnListLength): userList[i].id]
output userPrincipalNames array = upnList

The users module is now added to main.bicep.

main.bicep

// Resources
module users 'modules/users.bicep' = {
  name: 'users'
  params: {
    upnList: upnList
  }
}

Result

After adding the users.bicep module and making adjustments to the main.bicep file, the security group is now also filled with the defined users, who then receive RBAC permissions for the Log Analytics workspace.

You can find the complete code here in my Github repository.

Conclusion

Once you have familiarised yourself with Microsoft Graph for Bicep, it becomes easier and easier to work with it and create new modules.
The principle or rather the structure is just as simple as, for example, Azure resource creation using Bicep.

With the help of what you have learnt, you should now be able to adapt some of your PowerShell scripts in the Microsoft Graph environment, for example, to Bicep.

References

You might also like