In a patch grouper_v2_4_0_ui_patch_35 in 2.4 we added provisioning in the UI. This can be for multiple provisioners including PSPNG and other things like Box provisioning. Note the provisioner needs to be able to key off the the attributes on groups and folders, which is not yet available for PSPNG. It is currently (grouper_v2_4_0_ui_patch_35) available for the Duo connector. We will add more provisioners.
Getting started
Enable provisioning in the grouper.properties
######################################### ## Provisioning in UI ######################################### # if provisioning in ui should be enabled # {valueType: "boolean", required: true} provisioningInUi.enable = true
Set a group in the grouper-ui.properties if you dont want all group / folder admins to control provisioning
################################### ## V2 UI provisioning settings ################################### # put in a group here if you want to restrict the provisioning tab to certin users. # note, admins can always see the tab # ${valueType: "group"} uiV2.provisioning.must.be.in.group =
Target specific properties
For each target, the following properties can be configured. They need to be set in grouper.properties
#name and key you want to give to your target. key is used to configure the label for the UI provisioning.target.pspngLdap1.key = pspngLdap1Key #members of the configured group are allowed to assign this target provisioning.target.pspngLdap1.groupAllowedToAssign = #if this target should only be assigned to one stem provisioning.target.pspngLdap1.allowAssignmentsOnlyOnOneStem = false #if this target is read only and cannot be assigned from provisioning UI. provisioning.target.pspngLdap1.readOnly = false
To assign label for the key configured above, a corresponding entry needs to go in grouper.text.en.us.base.properties or grouper.text.en.us.properties for English. For other languages, add an entry into corresponding externalized language file.
provisioningUiLabelForKey_pspngLdap1Key = OpenLDAP production
Example of setting up provisioning in the UI with Duo
Enable provisioning in the UI in grouper.properties (per above)
Add a provisioner in the grouper.properties and optionally configure text in externalized text file : grouper.textNg.en.us.base.properties
######################################### ## Provisioning in UI ######################################### # if provisioning in ui should be enabled # {valueType: "boolean", required: true} provisioningInUi.enable = true # key for target # {valueType: "string"} provisioning.target.duo.key = duo # members of this group, wheel group members and system user are allowed to assign this target # {valueType: "stem"} provisioning.target.duo.groupAllowedToAssign = # should this target be assigned to only one stem # {valueType: "boolean", required: false} provisioning.target.duo.allowAssignmentsOnlyOnOneStem = true # should this target be read only # {valueType: "boolean", required: false} provisioning.target.duo.readOnly = false
Assign this on a folder:
See that groups in the folder will be provisioned
Edit the grouper-loader.properties to use provisioning in the UI, and not a direct configuration
REMOVE: # put groups in here which go to duo, the name in duo will be the extension here # this ust be blank if using UI provisioning configuration grouperDuo.folder.name.withDuoGroups = test:duo ADD: # use ui provisioning configuration, not config file grouperDuo.use.ui.provisioning.configuration = true # links the ui provisioner config to this provisioner code grouperDuo.ui.provisioning.targetName = duo # use ui provisioning configuration, not config file grouperDuo.use.ui.provisioning.configuration = true
UI actions
- Edit LDAP configs (grouper loader properties)
- Enable a provisioning target type (grouper loader properties)
- Enable a provisioning target
- Disable/Enable a provisioning target for folder or group
- See grouper loader logs for change log consumers
- Manage change log bookmark for change log listeners
- Trigger a full sync (send message), look at provisioningLastFullMillisSince1970 until complete
- Reporting can do a report of a full sync
Privileges
- ADMIN on folder you can see configs?
- READ on group you can see the configs?
- By default you have to be grouper admin to do provisioning
- Provisioning target type Java implementation could allow group/folder ADMINs to be able to edit? Anyone need this? Might be nice for
Screenshots
Use the "More actions" button to access Provisioning
List of assigned targets for a folder
Assigning a target to a folder
Attribute definitions
Definition | Assigned To | Purpose | Value | Cardinality |
---|---|---|---|---|
provisioningDef | folder, group | identify a group type | marker | Multi assign |
provisioningValueDef | folder assignment, group assignment | name/value pairs | string | Single assign, single valued |
Attribute names
Name | Definition | Value |
---|---|---|
provisioningMarker | provisioningDef | <none> |
provisioningTarget | provisioningValueDef | Related to a config in grouper-loader.properties which links this provisioner to entend the class GrouperProvisionerBase |
provisioningDirectAssign | provisioningValueDef | if this is directly assigned or inherited |
provisioningOwnerStemId | provisioningValueDef | if this is not a direct assignment, then this is the stem id where it is inherited from |
provisioningStemScope | provisioningValueDef | If folder provisioning applies to only this folder or this folder and subfolders. one|sub |
provisioningDoProvision | provisioningValueDef | If you should provisioning (default to true) |
provisioningLastFullMillisSince1970 | provisioningValueDef | Millis since 1970 that this was last full provisioned |
provisioningLastIncrementalMillisSince1970 | provisioningValueDef | Millis since 1970 that this was last incremental provisioned. Even if the incremental did not change the target |
provisioningLastFullSummary | provisioningValueDef | Summary of last full run |
provisioningLastIncrementalSummary | provisioningValueDef | Summary of last incremental run |
Developer notes
This is integrated with Duo, see GrouperDuoUtils
/** * cache the folder for duo */ private static ExpirableCache<Boolean, Stem> duoStemCache = new ExpirableCache<Boolean, Stem>(5); /** * get duo stem from expirable cache or from database * duo stem * @param debugMap * @return the stem */ public static Stem duoStem(Map<String, Object> debugMap) { Stem duoStem = duoStemCache.get(Boolean.TRUE); if (debugMap != null) { debugMap.put("duoStemInExpirableCache", duoStem != null); } if (duoStem == null) { duoStem = duoStemHelper(debugMap); duoStemCache.put(Boolean.TRUE, duoStem); } return duoStem; } /** * duo stem * @param debugMap * @return the stem */ public static Stem duoStemHelper(Map<String, Object> debugMap) { //# put groups in here which go to duo, the name in duo will be the extension here //grouperDuo.folder.name.withDuoGroups = duo String grouperDuoFolderName = GrouperLoaderConfig.retrieveConfig().propertyValueString("grouperDuo.folder.name.withDuoGroups"); boolean useUiProvisioningConfiguration = GrouperLoaderConfig.retrieveConfig().propertyValueBoolean("grouperDuo.use.ui.provisioning.configuration", true); if (useUiProvisioningConfiguration && !StringUtils.isBlank(grouperDuoFolderName)) { throw new RuntimeException("If you are using ui provisioning configuration, you cant configure a folder in the grouper-loader.properties 'grouperDuo.folder.name.withDuoGroups'!!!!"); } Stem grouperDuoFolder = null; if (useUiProvisioningConfiguration) { String uiProvisioningTargetName = GrouperLoaderConfig.retrieveConfig().propertyValueStringRequired("grouperDuo.ui.provisioning.targetName"); if (debugMap != null) { debugMap.put("uiProvisioningTargetName", uiProvisioningTargetName); } List<Stem> stems = new ArrayList<Stem>(new StemFinder().assignAttributeCheckReadOnAttributeDef(false) .assignNameOfAttributeDefName(GrouperProvisioningSettings.provisioningConfigStemName()+":"+GrouperProvisioningAttributeNames.PROVISIONING_TARGET) .addAttributeValuesOnAssignment(uiProvisioningTargetName) .assignNameOfAttributeDefName2(GrouperProvisioningSettings.provisioningConfigStemName()+":"+GrouperProvisioningAttributeNames.PROVISIONING_DO_PROVISION) .addAttributeValuesOnAssignment2("true") .findStems()); GrouperUtil.stemRemoveChildStemsOfTopStem(stems); if (debugMap != null) { debugMap.put("folderCount", GrouperUtil.length(stems)); } if (GrouperUtil.length(stems) > 1) { throw new RuntimeException("Folder count can only be 0 or 1!!! " + GrouperUtil.length(stems)); } if (GrouperUtil.length(stems) == 1) { grouperDuoFolder = stems.iterator().next(); } } else { grouperDuoFolder = StemFinder.findByName(GrouperSession.staticGrouperSession(), grouperDuoFolderName, true); } return grouperDuoFolder; }
Issues
- Do not provisioning internal groups list systemOfRecord
- Decide how that works with DoProvision
2 Comments
Carey Black (osu.edu)
It would be great if attributesNames could supply a "search" (to use a list of Grouper objects: groups, attribute names from another attribute definition, a grouper config property set of values, others?) to provide the user a fixed list of values that can be used for that attributeName.
Which would be very specifically useful for the provisioningTarget, provisioningDirectAssign, provisioningStemScope, attribute names above. ( And I would think for a whole host of attribute names.)
Carey Black (osu.edu)
"By default you have to be grouper admin to do provisioning" What do you specifically mean by that?
Maybe this access control? "groups.wheel.group= ..." Something else?
Maybe it could be driven by the ability to see Grouper objects that feed provisioningTarget ? That way each provisioner could be managed by different groups ( after being established by the Grouper System owners/operators.