Created
December 17, 2024 14:39
-
-
Save jonjozwiak/8c8db0326d63a0829a085ceaefe6df2c to your computer and use it in GitHub Desktop.
Revisions
-
jonjozwiak created this gist
Dec 17, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,113 @@ # Attribute-based provisioning to GHEC with EntraID One of the challenges moving to GitHub Enterprise Cloud (GHEC) Enterprise Managed Users (EMU) is the different in user provisioning compared to the typical LDAP setup with GitHub Enterprise Server. While AD groups have traditionally been used to determine who to provision, with an LDAP setup you can also create a main group that gates access. For example, a group called 'GitHubEnterprise' that determines whether a user is provisioned or not. And then other groups like TeamA, TeamB, and so on that are used for team membership. If an individual is in TeamA but not in the GitHubEnterprise group they do not get provisioned. GitHub Enterprise Cloud users SAML or OIDC with SCIM provisioning. In SCIM provisioning, group-based filtering is not an option so the above scenario cannot be completed. However, [scoping filters](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/define-conditional-rules-for-provisioning-user-accounts?pivots=app-provisioning) can be used to filter users based on custom attributes. This provides a similar functionality in GitHub Enterprise Cloud, but via different implementation. This gist is going to cover that setup. Typically with GitHub Enterprise Cloud all users added to the EMU application either directly as users or within groups are provisioned to GitHub. With scoping filters, users still need to be assigned to the EMU app. However, they only get provisioned if they meet the criteria of the filter. In this example we will create a new attribute called `GitHubBlockLicense`. If the user has this attribute set to `True` we will filter out the user so they are not provisioned. ## Setup Attributes For my testing my Azure user had the global administrator, attribute definition administrator, and attribute assignment administrator. I think just global admin will work, but haven't tested otherwise. Note in GitHub I'm an enterprise owner. In my lab I created a few new users to test. Consider doing the same, but you can target some existing users if you prefer. To do the setup I've used Powershell (on my mac). I think you just brew install this, but I don't have steps because it was previously setup. Steps to complete the setup are as follows: * Go to your [Azure Portal](https://portal.azure.com), click `Microsoft Entra ID` and click `Enterprise Applications`. * Scroll to your Github Enterprise Cloud app and click it. In my case this was `GitHub Enterprise Managed User` * Copy the `Application Id`. You will need this in the next step * In your Powershell window authenticate to Azure and verify your application exists ```pwsh # Authenticate Connect-MgGraph -Scopes "Application.ReadWrite.All" # Check Application $applicationId = "f48b4906-a466-4e98-91da-0ba91544268f" $app = $apps | Where-Object { $_.AppId -eq $applicationId } if ($app) { Write-Output "Application found: $($app.DisplayName)" } else { Write-Output "Application with ID $applicationId not found." } ``` * Create a new attribute for the application using the previously set applicationId IMPORTANT: Use the `Id` of the application! Not the applicationId above. ```pwsh $Id = $app.Id $params = @{ name = "BlockGitHubLicense" dataType = "Boolean" targetObjects = @("User") } New-MgApplicationExtensionProperty -ApplicationId $Id -BodyParameter $params ``` Record the extension name here as you will need it for the next step. Note it is the form of extension_applicationId_paramName. * Update a user to have the BlockGitHubLicense parameter set to true ```pwsh # Get a user's Id based on login name # You can do this manually by going to the user in EntraID in the Azure portal and looking at the Object Id $userId = (Get-MgUser -UserId "[email protected]" -Select "Id").Id # Set the extension name you received in the previous step $extensionName = "extension_f48b4906a4664e9891da0ba91544268f_BlockGitHubLicense" # Patch the User with the updated attribute $json = '{ "extension_f48b4906a4664e9891da0ba91544268f_BlockGitHubLicense": true }' Invoke-MgGraphRequest -Method PATCH "https://graph.microsoft.com/v1.0/users/$userId" -Body $json -Debug -Verbose # Check the attribute is set for the user Invoke-MgGraphRequest -Method GET -Uri "https://graph.microsoft.com/beta/users/$userId" You are looking for the field "extension_f48b4906a4664e9891da0ba91544268f_BlockGitHubLicense" and it should now be True ``` ## Apply Scope Filter We now have a user with an attribute set that can be used to block provisioning. Next we need to create a scope filter. ([Documentation](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/define-conditional-rules-for-provisioning-user-accounts?pivots=app-provisioning#create-scoping-filters) for reference). To do this take the following steps: * Go to your [Azure Portal](https://portal.azure.com), click `Microsoft Entra ID` and click `Enterprise Applications`. * Scroll to your Github Enterprise Cloud app and click it. In my case this was `GitHub Enterprise Managed User` * Click on `Provisioning` * Under `Manage Provisioning` you should see an option `Add scoping filters`. Click it. Note you should go to the same place if you click `Edit Provisioning` * Example the `Mappings` section and click on `Provision Microsoft Entra ID Users` * Under `Source Object Scope` click on the `All Records` link * Click `+ Add new filter group` * For `Source Attribute` select your attribute: extension_f48b4906a4664e9891da0ba91544268f_BlockGitHubLicense * For `Operator` select `NOT EQUALS` * For `Clause Value` type `True` * Enter a relevant `Scoping filter title`. I chose `GitHubBlockProvision` * Click `Apply` in the bottom left * Click `Apply` a second time to apply the source filter Here we've created a filter to say we are going to provision the user unless the BlockGitHubLicense is set to True. Note we do not need to update the `Provision Microsoft Entra ID Groups` mapping as this would apply to the entire group. We're only interested in blocking users (individually assigned or assigned in the group). Next we want to validate the effect of provisioning. Ensure you have added your user or group to the enterprise application used to provision to GitHub. Now go back to provisioning and select `Provision on demand`. Select the user or group and click `Provision`. This should block provisioning of any user that has that attribute assigned. Check in your GitHub Enterprise to ensure the people you expected to provision exist in GitHub and those to block are not there. ## Conclusion and Other thoughts Here we were able to showcase using an attribute as a filter to prevent assigned users from provisioning to GitHub. This should be a feasible way to limit who gets provisioned from a given EntraID group when it is not feasible to create GitHub-only groups. Some other things to consider as follows: * When setting up filters this will impact current provisioning logic. Be careful not to break existing user assignments. * I chose an attribute to block because it means any existing user is not impacted. Only if they happen to have the block attribute set to true. * I think some automation is needed to manage this at scale as I don't see these attributes easily exposed in the Azure portal. Specifically you'd want an easy way to list all users who have the block attribute.