Skip to content

Instantly share code, notes, and snippets.

@jonjozwiak
Created December 17, 2024 14:39
Show Gist options
  • Save jonjozwiak/8c8db0326d63a0829a085ceaefe6df2c to your computer and use it in GitHub Desktop.
Save jonjozwiak/8c8db0326d63a0829a085ceaefe6df2c to your computer and use it in GitHub Desktop.
Attribute-based provisioning to GHEC with EntraID

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 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, 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
# 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.

$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
# 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 for reference). To do this take the following steps:

  • Go to your Azure Portal, 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment