University of Colorado Boulder presented a lightning talk at 2015 Internet2 Technology Exchange on Grouper and Exchange / Office 365. See slides here (PDF format)
CU Boulder migrated from on-premise Exchange to Office 365 (O365) in June 2015. Here is a quick overview of the Active Directory environment relevant to Exchange and groups:
Overall, for our Grouper environment, we opted for not using the PSP that came with Grouper. Instead, we implemented a solution that used a messaging bus from which connectors could be developed to provision to our resources.
For an overview of our Grouper setup, please refer to slides 3 and 5 of this presentation |
The details of getting the distribution list management to be managed through Grouper are explained int the following sections. The tasks can split into two major categories: the initial bulk load and the ongoing day to day post-bulk load.
Most of our mail distribution list groups were also used as access/security groups. There were instances were some applications may have had explicit paths hard-coded to reference a group. These application are almost impossible to identify and would usually break. Luckily for us, there were just a few instances of those and we were notified by the application owners quickly. |
First, establishing a Grouper root session, setting up some variables relating to access privileges and creating the necessary stem structure
GrouperSession.startRootSession(); readers = AccessPrivilege.READ; updaters = AccessPrivilege.UPDATE; admins = AccessPrivilege.ADMIN; viewers = AccessPrivilege.VIEW; optins = AccessPrivilege.OPTIN; optouts = AccessPrivilege.OPTOUT; addRootStem("myRootStem","myRootStem"); addStem("myRootStem","Messaging"); addStem("myRootStem:Messaging","Office365"); |
Then, the commands would convert the AD DN's to Grouper paths, create all the groups, and set the group type to IncludeExclude
addGroup("myRootStem:Messaging:Office365","myTestDL1","myTestDL1"); groupAddType("myRootStem:Messaging:Office365:myTestDL1", "addIncludeExclude"); addGroup("myRootStem:Messaging:Office365","myTestDL2","myTestDL2"); groupAddType("myRootStem:Messaging:Office365:myTestDL2", "addIncludeExclude"); ...... ...... |
For every group, another group would be created and named "groupName_GROUP-ADMINS" e.g: MyTestGroup1234_GROUP-ADMINS .
addGroup("myRootStem:Messaging:Office365","myTestDL1_GROUP-ADMINS", "myTestDL1_GROUP-ADMINS"); addGroup("myRootStem:Messaging:Office365","myTestDL2_GROUP-ADMINS", "myTestDL2_GROUP-ADMINS"); ...... ...... |
For every group, the "groupName_GROUP-ADMINS" group was given the "READ" and "UPDATE" privileges. Since the groups were of type "IncludeExclude", the privs were assigned to the overall group as well as the sub groups that make it up.
grantPriv("myRootStem:Messaging:Office365:myTestDL1", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", readers); grantPriv("myRootStem:Messaging:Office365:myTestDL1", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", updaters); grantPriv("myRootStem:Messaging:Office365:myTestDL1_includes", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", readers); grantPriv("myRootStem:Messaging:Office365:myTestDL1_includes", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", updaters); grantPriv("myRootStem:Messaging:Office365:myTestDL1_excludes", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", readers); grantPriv("myRootStem:Messaging:Office365:myTestDL1_excludes", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", updaters); grantPriv("myRootStem:Messaging:Office365:myTestDL1_systemOfRecord", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", readers); grantPriv("myRootStem:Messaging:Office365:myTestDL1_systemOfRecord", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", updaters); ..... ..... |
For every "groupName_GROUP-ADMINS" group, members were given "READ" and "UPDATE" privileges on the group itself. ie, groupName_GROUP-ADMINS members could update and read the membership information of the admin group itself.
grantPriv("myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", readers); grantPriv("myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", "myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", updaters) ..... ..... |
For every group, OIT's Messaging and Collaboration team (M&C) group was given "ADMIN" privileges
grantPriv("myRootStem:Messaging:Office365:myTestDL1", "myRootStem:Messaging:OIT-MC-GROUPERADMINS", admins); grantPriv("myRootStem:Messaging:Office365:myTestDL1_includes", "myRootStem:Messaging:OIT-MC-GROUPERADMINS", admins); grantPriv("myRootStem:Messaging:Office365:myTestDL1_excludes", "myRootStem:Messaging:OIT-MC-GROUPERADMINS", admins); grantPriv("myRootStem:Messaging:Office365:myTestDL1_systemOfRecord", "myRootStem:Messaging:OIT-MC-GROUPERADMINS", admins); grantPriv("myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", "myRootStem:Messaging:OIT-MC-GROUPERADMINS", admins); ..... ..... |
For every group, the members (subjects) were added one a time to the "groupName_includes" group
addMember("myRootStem:Messaging:Office365:myTestDL1_includes", "testaccount1"); addMember("myRootStem:Messaging:Office365:myTestDL1_includes", "testaccount2"); ..... ..... |
For every "groupName_GROUP-ADMINS", the admin members (subjects) were added one a time.
addMember("myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", "testmanageraccount1"); addMember("myRootStem:Messaging:Office365:myTestDL1_GROUP-ADMINS", "testmanageraccount2"); ..... ..... |
The actual initial load was then performed
$GROUPER_HOME/bin/gsh.sh /path/to/file_containing_all_gsh_commands.gsh |
See Also
https://oit.colorado.edu/services/identity-access-management/enterprise-access-management