Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Warning

This page applies to Grouper 2.5. For Grouper v4+ see this page


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.

...

  • 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

Initialize

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.

...

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.

Code Block
changeLog.consumer.o365.class = edu.internet2.middleware.grouper.changeLog.consumer.Office365ChangeLogConsumer
# fire every 5 seconds
changeLog.consumer.o365.quartzCron = 0,5,10,15,20,25,30,35,40,45,50,55 * * * * ?
changeLog.consumer.o365.syncAttributeName = etc:attribute:office365:o365Sync
changeLog.consumer.o365.retryOnError = true
changeLog.consumer.o365.tenantId = @o365.tenantId@
changeLog.consumer.o365.clientId = @o365.clientId@
changeLog.consumer.o365.clientSecret = @o365.clientSecret@
#changeLog.consumer.o365.domain =
#changeLog.consumer.o365.idAttribute =
#changeLog.consumer.o365.upnAttribute =
#changeLog.consumer.o365.groupJexl =
#changeLog.consumer.o365.mailNicknameJexl =
#changeLog.consumer.o365.descriptionJexl =
#changeLog.consumer.o365.subjectJexl =
#changeLog.consumer.o365.groupType = [Security* | Unified]
#changeLog.consumer.o365.visibility = [Public* | Private | HiddenMembership]
#changeLog.consumer.o365.proxyType = [http | socks]
#changeLog.consumer.o365.proxyHost =
#changeLog.consumer.o365.proxyPort =

Custom configuration parameters

tenantId, clientId, clientSecret

Replace @o365.tenantId@, @o365.clientId@ and @o365.clientSecret@ with appropriate values from the application configuration. Note that the clientSecret is sensitive information.

domain

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

Optional property 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.

upnAttribute

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 subject and subjectIdValue are for subjectJexl. Variables common to both are consumerName, tenantId, domain, and idAttribute. Brackets are not needed around the expression.

...

The defaultIfExpressionNull parameter is intended mainly for internal code to avoid extra tests for a null expression.


groupType, visibility

The optional 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 proxyType, proxyHost, and 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.

...

If all three methods return blank values, a runtime exception will be thrown.

Multiple Provisioners

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:

Code Block
# Creates security groups
changeLog.consumer.o365.class = edu.internet2.middleware.grouper.changeLog.consumer.Office365ChangeLogConsumer
changeLog.consumer.o365.tenantId = my-tenant.onmicrosoft.com
changeLog.consumer.o365.clientId = ...
changeLog.consumer.o365.clientSecret = ...
...
changeLog.consumer.o365.syncAttributeName = etc:attribute:office365:o365Sync
changeLog.consumer.o365.groupJexl = ...

# Creates Office 365 groups
changeLog.consumer.o365Unified.class = edu.internet2.middleware.grouper.changeLog.consumer.Office365ChangeLogConsumer
changeLog.consumer.o365Unified.tenantId = my-tenant.onmicrosoft.com
changeLog.consumer.o365Unified.clientId = ...
changeLog.consumer.o365Unified.clientSecret = ...
...
changeLog.consumer.o365Unified.syncAttributeName = etc:attribute:office365:o365SyncUnified
changeLog.consumer.o365Unified.groupType = Unified
changeLog.consumer.o365Unified.visibility = Private

Install

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:

...

https://login.microsoftonline.com/$TENANT/adminconsent?client_id=$APPLICATION_ID

Graph API Notes

To get a token for making Graph API calls, do the following:

...

  • 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.

PropertyTypeDescription
displayNamestringThe name to display in the address book for the group. Maximum length: 256 characters. Required.
descriptionstringA description for the group. Max. length: 1024 characters. Optional.
mailEnabledbooleanSet to true for mail-enabled groups. Required.
mailNicknamestringThe mail alias for the group. Max. length: 64 characters. Required.
securityEnabledbooleanSet to true for security-enabled groups, including Office 365 groups. Required.
ownersstring collectionThis property represents the owners for the group at creation time. Optional.
membersstring collectionThis property represents the members for the group at creation time. Optional.
visibilityStringSpecifies the visibility of an Office 365 group. Possible values are: Private, Public, HiddenMembership, or empty (which is interpreted as Public).

Acknowledgments

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.

...