Using Azure Automation to Invite Entra ID B2B Users

In a previous article about using Entra ID B2B users, I needed to set up some user extensions. In that article, I also mentioned that many customers needed to access the environment, which meant that multiple users needed to be changed.
As this is an ongoing business and we like to automate these kinds of tasks, I looked for an automation option. Creating a script wasn’t the problem, but using it to connect to Entra ID by entering credentials every time or putting them into the script was the hard part of the search.

After some time, I stumbled upon Azure Automation, where you can create runbooks (scripts) and add them to a scheduled task.

What’s Azure automation

Azure Automation is a cloud-based service provided by Microsoft Azure that enables users to automate various manual, time-consuming, and repetitive tasks across Azure and on-premises environments. It offers tools for process automation, configuration management, and update management. Using PowerShell or Python to automate complex tasks, users can create, schedule, and manage runbooks (workflow scripts). Azure Automation also provides Desired State Configuration (DSC) to define and enforce system configurations. Additionally, it integrates with other Azure services, allowing users to orchestrate end-to-end workflows for efficient and consistent management of resources in the Azure cloud.

Creating an Azure Automation account

We must create an Azure Automation account before using Azure Automation and deploying our script. Sign in to the Azure portal and search for Azure Automation. Click on “Create” and follow the wizard, here, you will see the output of “Review + Create.”

Powershell Modules

When using Azure Automation, verifying the availability of the intended PowerShell modules is crucial. For this situation, the following modules are essential:

  • Microsoft.Graph.Authentication:
    Responsible for establishing connections (Connect-MgGraph) and severing connections (Disconnect-MgGraph) to MgGraph.
  • Microsoft.Graph.Groups:
    Required for retrieving group members (Get-MgGroupMember) and obtaining information based on a group ID (Get-MgGroup).
  • Microsoft.Graph.Identity.SignIns:
    Necessary for initiating invitations (New-MgInvitation) through identity sign-ins.
  • Microsoft.Graph.Users:
    Utilized for fetching user information (Get-MgUser) and facilitating user updates (Update-MgUser).

To add the modules to the Azure Automation account, open the account and go to “Modules,” then follow the below steps to add the module. Repeat these steps until all required modules are added:

  1. Click on “Add a Module”
  2. Select “Browse from gallery”
  3. Click on “Click here to browse from gallery”
    • Search the module and select
    • click on “Select” at the bottom of the page.
  4. Now set the “Runtime Version”. In our case, it’s 5.1.
  5. Click “Import”

To verify if all of the required Powershell modules are available or still being imported, click on “Modules” within the Azure Automation account.

After adding the appropriate Powershell modules, we need to add the required permissions.

Permissions

To get our script working with the appropriate permissions, we need the following permissions:

  • User.ReadWrite.All
  • User.Invite.All
  • Directory.Read.All

As we use a Managed Identity, we need to add the permissions using Graph Explorer. First, we must connect to the Graph Explorer: https://aka.ms/ge and sign in using an account in the correct tenant. You can’t switch tenant/directory when using Graph Explorer.

Step 1: Finding the Service Principal

We first need to find the service principal for our managed identity (automation account). To do so, we need to perform the following query, where displayname equals our Managed Identity name, in our case, “CTX-DaaS”:

HTML
GET https://graph.microsoft.com/v1.0/servicePrincipals?$search="displayName:CTX-Daas"

Write down the ID. We need this in step 4.

Step 2: Finding the Microsoft Graph Service principal ID

As the Microsoft Graph API always has the following AppId “00000003-0000-0000-c000-000000000000”, we can create a filter and only look for this AppId. We can use the following query to get the ID:

HTML
GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '00000003-0000-0000-c000-000000000000'

Write down the ID. We need this in steps 3 and 4.

Step 3: Finding the Application Roles (Permissions) id

Now, we need to get the App Role IDs, as these are always the same and well-documented by Microsoft. We can search for them on the following site: https://learn.microsoft.com/en-us/graph/permissions-reference.

  • User.ReadWrite.All: “741f803b-c850-494e-b5df-cde7c675a1ca”
  • User.Invite.All: “09850681-111b-4a89-9bed-3f2cae46d706”
  • Directory.Read.All”: “7ab1d382-f21e-4acd-a863-ba3e13f7da61”

When you would like to use Graph Explorer, this is also possible, and you follow the below step: As we can’t add a filter to the query, we need to use the old-fashioned way and use CTRL+F to search for the appropriate IDs. First, we need to run the below query, replacing the {ServicePrincipalID} with the ID we found in step 2.

HTML
GET https://graph.microsoft.com/v1.0/servicePrincipals/{ServicePrincipalID}/approles

After running the query, we get a list of all the Application Roles. Luckily, the output only shows 100 results. Now, use CTRL+F to search for the permissions mentioned above and write down the IDs.

Step 4: Assigning the Application Roles to the Managed Identity

To assign the Application Roles, we need the following IDs:

  1. PrincipalId (step 1)
  2. ResourceId (step 2)
  3. AppRoleIId (step 3)

To add the Application Roles to the Managed Identity, we need to use a POST query in combination with a Content-Type application/json in the header and the following request body:

HTML
POST https://graph.microsoft.com/v1.0/servicePrincipals/{your-graph-serviceprincipal-id}/appRoleAssignedTo

Content-Type: application/json

JSON
{
"principalId": "{your-managed-identity-service-principal-id}",
"resourceId": "{your-graph-serviceprincipal-id}",
"appRoleId": "{your-app-role-id}"
}

Repeat step 4 until you assigned all the Application Roles.

Step 5: Verifying the permissions in Entra ID

Now that we have set the Application Roles (Permissions), we can verify this within the Entra ID portal. To do so, we go to Entra ID, Enterprise Applications, then set the Application Type to “Managed Identities”.

Now, we select the Managed Identity we create to perform the Azure Automation tasks and go to Permissions. Here, we will see the permissions we just assigned.

Creating the runbook

Now that we have set all the appropriate permissions, we can start creating the runbook. For this case, we will look for users who are members of a certain security group called “CTX-DaaS-B2B” and verify if the Extension (Created in the previous blog) and CreationType are equal to Invitation. We will check this for each user who’s a member of the security group and check each setting, and if needed, we will apply changes.

Below, you can see the script we are using to automate the process of invitations and setting the extensions so the user can sign in to the Citrix Environment, which is mentioned in the previous blog.

PowerShell
Connect-MgGraph -Identity -NoWelcome
$Group = "CTX-DaaS-B2B"
$group = Get-MgGroup -Filter "DisplayName eq '$Group'"
$members = Get-MgGroupMember -GroupId $group.Id
$ExtensionUPN = "extension_c8ef4d2cb6694d76974c5a05be13affa_guestShadowUPN"
$ExtensionSID = "extension_c8ef4d2cb6694d76974c5a05be13affa_guestUserOnPremSID"
$CreationType = "Invitation" 
$RedirectURL = "https://newyard.Cloud.com"
$UserMessage = "You have been invited to the Citrix New Yard environment. `
                Redeem this invitation to get started and you’ll be redirected to the Citrix New Yard"

foreach ($member in $members) {
    $user = Get-MgUser -UserId $member.Id -Property ID, DisplayName, Mail, UserPrincipalName, UserType, CreationType, ExternalUserState, OnPremisesSecurityIdentifier

    if ($user.UserType -ne "Guest"){
        Write-output "User $($user.displayname) is Member, changing to Guest!"
        Update-MgUser -UserId $user.Id -UserType "Guest"
    } 

    $UserExtensions = (Get-mguser -UserID $user.Id -Property $ExtensionUPN).AdditionalProperties
    if ($UserExtensions.keys -NotContains $ExtensionUPN) {
        Write-Output "User $($user.displayname) has nu Extension, updating UPN and SID Extensions"
        Update-mguser -UserId $user.id -AdditionalProperties @{$ExtensionUPN = $user.UserPrincipalName}
        Update-mguser -UserId $user.id -AdditionalProperties @{$ExtensionSID = $user.OnPremisesSecurityIdentifier}
    }

    Write-output "$($user.displayname) has CreationType $($user.creationType)"
    if ($user.CreationType -ne $CreationType) {
        Write-output "User $($user.displayname) isn't invited, inviting user!"
        New-MgInvitation -InvitedUser $user -InvitedUserEmailAddress $user.Mail -InviteRedirectUrl $RedirectURL -SendInvitationMessage:$true -InvitedUserMessageInfo:@{CustomizedMessageBody=$UserMessage}
    }

}

disconnect-MgGraph

We published the runbook to production once we tested it (using the test pane in the PowerShell runbook) and verified everything was correct. This can be done using the Publish button inside the PowerShell runbook.

Create a Schedule

Now that we have the runbook published, we can start with scheduling the runbook. As we start migrating users to the new environment, we have set the schedule to run every hour. When the migration is done, we can change the schedule to once a day, as we normally don’t make that many changes or create multiple users a day.

Let’s start with creating the schedule. We go to the Schedules from the Automation account and add a schedule.

Once the schedule is created, we need to assign the runbook to the schedule. Therefore, we go to the runbook, click on the “Link to schedule” button, click on the link to a schedule in your runbook, select the correct schedule, and click OK. To verify if the runbook is successfully linked to the schedule, click “Schedules” within the runbook and verify that the correct schedule is linked.

Verify the Azure Automation Task

Now that we successfully have followed all the steps:

  1. Creating Azure Automation Account
  2. Add PowerShell Modules
  3. Set permissions
  4. Create the runbook
  5. Create and linked a Schedule

We can now see in the overview of the Azure Automation account if the runs are completed successfully. As you can see in the screenshot below, the job has run once and was successful. The users will receive an invite every hour unless they already received one.

Conclusion

We can conclude that Azure Automation is a powerful tool for automating repetitive tasks, such as sending invites to new guests. I couldn’t achieve this without the guidance of GoToGuy’s blog, where the Graph Explorer is explained to configure all the necessary permissions. I will undoubtedly utilize Azure Automation more frequently now that I know its capabilities.

Facebook
WhatsApp
Twitter
LinkedIn
Pinterest
Follow me