The Grouper Azure provisioner is a changelog consumer that synchronizes Grouper groups and users to Microsoft Azure Active Directory/Office 365. This currently only supports security or Office 365 (unified) groups. Support for mail-enabled groups is unavailable due to lack of support in the Microsoft API.
The provisioner started as a Unicon project, before being incorporated into the Grouper project. The library included with Grouper container 2.5.23 includes many enhancements from the original:
- can now create Office 365 (unified) groups as well as security groups
- supports more than one provisioner
- custom names, descriptions using jexl expressions
- custom mail nicknames, using jexl, for unified groups
- custom UPN, can be derived from attribute, jexl, or customizable domain
- Public, Private, and HiddenMembership options for unified groups
- ability to set up multiple provisioners with different option groups
The provisioning attribute to add to the provisionable object is, by default,
etc:attribute:office365:o365Sync. If set on a folder, all groups under this folder (recursively) will be automatically provisioned. Alternatively, the attribute can be set on an individual group. It is not recommended to assign directly to a group, as there is currently a race condition that may occur in the current version of this code (i.e., if the changelog consumer runs after group creation but before attribute assignment, provisioning will not occur). It is also required to create attribute
etc:attribute:office365:o365Id, which will store the Azure group Id on the Grouper group to be kept in sync.
1. Set up stem for provisioning and ID attribute
2. Configure loader job in grouper-loader.properties. Note that you will need to set up an application with access to your domain. See documentation at http://graph.microsoft.io/en-us/docs, and Notes for Developers below.
Custom configuration parameters
tenantId, clientId, clientSecret
@o365.clientSecret@ with appropriate values from the application configuration. Note that the clientSecret is sensitive information.
Property domain defines the domain name to be used with user principals. If not defined, the tenantId property will be used to construct user principals.
idAttribute specifies what attribute is used to build the Azure user principal, and will default to "uid" if not set. The Azure principal will get built as idattribute + "@" + domain or tenantId. Whatever attribute is used must be available as a key in the set returned in
subject.getAttributes(); i.e., if you want to use the subject's id or identifier, it needs to be defined in the subject attributes too.
If subjects reliably have the Azure principal name as one of their attributes, setting upnAttribute will use this value as is to identify Azure users, rather than calculating it through other methods.
groupJexl, mailNicknameJexl, and descriptionJexl
Optional *Jexl properties support jexl2 expressions in deriving custom values. Variable
group is provided to the group jexl expressions, while
subjectIdValue are for subjectJexl. Variables common to both are
idAttribute. Brackets are not needed around the expression.
|property||associated Azure property||default||default example||Max length in Azure|
To aid in developing jexl expressions, a minimal consumer instance can be bootstrapped enough to test jexl expressions using gsh. All the documented variables, except for consumerName (which is only defined while processing changelog entries), are available during evaluation.
The defaultIfExpressionNull parameter is intended mainly for internal code to avoid extra tests for a null expression.
groupType property can set the provisioned groups as either a security group (
groupType = Security) or an Office 365 group (
groupType = Unified). If not set, the default will be a security group. Mail-enabled groups are not currently available, as they cannot be set through the Microsoft web service API.
For a Unified group provisioner only, the
visibility property sets the Office 365 visibility. Possible values are Public (default), Private, or HiddenMembership*. See Microsoft's documentation on the option and also the GitHub documentation for more information.
proxyType, proxyHost, proxyPort
If the daemon server requires a proxy to access the internet, a HTTP or SOCKS proxy can be defined using
proxyPort. Currently, the SOCKS5 proxy only supports anonymous access.
Fallback methods for subject principal name calculations
Methods for determining the subject principal will try properties in the following order, when they are defined. If a method returns null or blank, the next method will be tried.
- idAttribute (before appending "@" + domain)
If all three methods return blank values, a runtime exception will be thrown.
It is possible to set up multiple Azure provisioners, each with different settings. One scenario for this would be to have one folder for security groups and another for Office 365 groups. Or, different folders can have different Jexl expressions, etc. To distinguish them, they need separate consumer attributes created. Then, each loader configuration would reference their respective attribute names, and folders would set the distinguishing syncAttributeName attribute to select a provisioner. Other required properties need to be repeated for each provisioner For example:
The Java library and its dependencies are included with the Grouper container >=2.5.26. But it should be usable with earlier Grouper 2.4 or 2.5 versions by downloading and adding the required libraries. Those libraries are:
Grouper containers 2.5.16 through 2.5.25 ship with an earlier version of the grouper-azure-provisioner.jar. If you happen to be running these versions, you should upgrade to 2.5.26 or greater.
Office 365 Notes for Developers
Login to the app management console:
For first time use, create Office 365 account first:
- Enroll in Office 365 (30-day trail account is fine), during enrollment, note the tenant value of the form "abcdef.onmicrosoft.com"
- At Office 365 management portal, click "Azure AD" link
- In Azure AD portal, click "Azure Activity Directory"
- Under "Manage" tab, click "App registrations"
- In intro text "To view and manage your registrations for converged applications, please visit the Microsoft Application Console.", click that link
Once in the App Mgmt Console, create an app:
- Note the "Application Id" that is generated (this will be the client id for OAuth2 tokens)
- Use "Generate New Password" when creating keys (this is the client secret for OAuth2 tokens)
- Under "Platforms" tab, click "Add Platform" and specify a redirect URL like "http://localhost/grouper"
- Under "Microsoft Graph Permissions", in "Application Permissions" specify required Graph API permissions:
- User.Read (may already be set)
- At bottom of page, click "Save"
- IMPORTANT: after permissions are added (or modified) admin consent must be granted at the URL template:
Graph API Notes
To get a token for making Graph API calls, do the following:
- POST http method
- URL is of the form https://login.microsoftonline.com/$TENANT/oauth2/v2.0/token
Use the following request parameters:
- client_secret - specify password generated from "Generate New Password" above
- client_id - specify Application Id that's generated when creating app
- grant_type - specify client_credentials, this value implies "Application Permissions" (as opposed to "Delegated Permissions")
- redirect_uri - specify http://localhost/grouper
- scope - specify https://graph.microsoft.com/.default
Official description of relevant group fields (from Microsoft)
Maximum lengths for displayName, description, and mailNickname for provisioned groups must be within the length limits as described by Microsoft (https://github.com/microsoftgraph/microsoft-graph-docs/blob/master/api-reference/v1.0/api/group-post-groups.md), otherwise group creation will fail.
|displayName||string||The name to display in the address book for the group. Maximum length: 256 characters. Required.|
|description||string||A description for the group. Max. length: 1024 characters. Optional.|
|mailEnabled||boolean||Set to true for mail-enabled groups. Required.|
|mailNickname||string||The mail alias for the group. Max. length: 64 characters. Required.|
|securityEnabled||boolean||Set to true for security-enabled groups, including Office 365 groups. Required.|
|owners||string collection||This property represents the owners for the group at creation time. Optional.|
|members||string collection||This property represents the members for the group at creation time. Optional.|
|visibility||String||Specifies the visibility of an Office 365 group. Possible values are: Private, Public, HiddenMembership, or empty (which is interpreted as Public).|
The Office365/Azure provisioner for Grouper originated as a project from Unicon, Inc. Primary developers were Bill Thompson, Jj!, and John Gasper, with other contributions by Chris Hyzer and Russ Trotter. The source project can be found at https://github.com/Unicon/office365-and-azure-ad-grouper-provisioner.
This project includes contributions from Kansas State University, project https://github.com/kstateome/office365-and-azure-ad-grouper-provisioner.git. Principal development was done by David Malia, with contribution by Kurt Zoglmann.