This document is a work in progress. Improvements to wiki formatting are welcome.
Usage
The psp may be run using GrouperShell (gsh).
To provision, polling every 60 seconds for changes :
bin/gsh.sh -psp -bulkSync -interval 60
To calculate how an object should be provisioned :
bin/gsh.sh -psp -calc stem:groupName
no arguments |
Display usage. |
|
Calculate provisioning for all identifiers. |
|
Determine provisioning difference for all identifiers. |
|
Synchronize provisioning for all identifiers. |
|
Calculate provisioning for an identifier. |
|
Determine provisioning difference for an identifier. |
|
Synchronize provisioning for an identifier. |
|
Provisioned object or schema entity id. For example, group, member, etc. |
|
Number of seconds between the start of recurring provisioning iterations. If omitted, only one provisioning cycle is performed. |
|
Path to configuration directory. |
|
Log SPML requests and responses. |
|
Print SPML responses to output file. Defaults to stdout. |
|
Print SPML requests as well as responses. |
|
SPML request identifier. |
|
Return data (identifier and attributes). |
|
Return everything (identifier, attributes, and references). |
|
Return identifier only. |
|
Target identifier. |
One of -bulkCalc
, -bulkDiff
, -bulkSync
, -calc <id>
, -diff <id>
, or -sync <id>
must be specified. All other arguments are optional.
Introduction
Grouper groups, memberships, and stems may be provisioned using the provisioning service provider (psp, formerly known as ldappcng).
The psp serves as an (incomplete) SPMLv2 provisioning service provider, which provisions objects to targets. Objects consist of identifiers, attributes, and references to other objects. Group memberships may be considered to be references.
Provisioned objects are calculated from source data returned by the Shibboleth Attribute Resolver. The Shibboleth Attribute Resolver accepts many data connectors (sources), including LDAP, RDBMS, and Grouper.
The psp provisions targets using a standard provisioning language, SPMLv2. An SPMLv2 to ldap connector is provided, based on VT Ldap. Provisioning non-LDAP targets requires a target specific connector, for example, SPMLv2 to RDBMS.
Currently, the psp supports SPMLv2 requests represented as java objects via the Oasis SPMLv2 implementation. The requestor is Grouper's cli, gsh.
calc
Calculate how an object should be provisioned.
Upon receipt of a calc
request, the psp will calculate how an object (or objects) should be provisioned, and will return a calc
response representing the correct provisioning.
diff
Determine the changes necessary to transform a provisioned object from how it is currently provisioned to how it should be provisioned.
Upon receipt of a diff
request, the psp first performs a calc
request to calculate how objects should be provisioned. Then, the psp queries each target to determine how objects are provisioned. The psp returns a diff
response representing the changes necessary to synchronize the provisioned objects from how it is currently provisioned to how it should be. The changes consist of add, delete, and or modify requests.
sync
Synchronize a provisioned object.
Upon receipt of a sync
request, the psp first performs a diff
request to determine provisioning changes. Then, the psp requests targets to perform the changes, and returns the results as a sync
response.
bulkCalc|bulkDiff|bulkSync
Bulk requests operate on all configured source identifiers, and includes the remove of orphan objects (provisioned objects for which no source identifier is known).
LDAPPC-NG -> PSP
The code formerly known as "ldappc-ng" has been refactored to "psp".
"Real-Time" Provisioning
Real-time provisioning is the incremental provisioning of groups, stems, and memberships triggered from the Grouper change log. Incremental provisioning is distinguished from full provisioning in that only a single or subset of an attribute's values are provisioned.
Real-time provisioning is available from the provisioning service provider as of Grouper 2.1.0. It should be possible to install and configure the psp for Grouper versions 1.6 and up.
These instructions assume that Grouper subjects are already provisioned to your ldap directory, and makes use of the vt-ldap based ldap source adapter.
Requirements
- Grouper API (requires Java 6 and a database, details are here)
- provisioning service provider (psp)
- ldap directory
Install : Grouper Installer
To install Grouper including the API, UI, WS, grouperClient, psp, etc., download and run the Grouper Installer.
As of Grouper 2.1.0, the psp may be installed but not configured via the Grouper Installer.
curl
http://www.internet2.edu/grouper/release/2.1.0/grouperInstaller.jar
-O
java -jar grouperInstaller.jar
Install : Manual
Install the provisioning service provider by copying jar files and example configuration files from the psp distribution to your Grouper API installation.
Many jars are dependencies of the Shibboleth attribute resolver and may not be necessary in your deployment.
To install manually, download and unpack the psp, then copy jars and configuration files to your Grouper API installation.
Install : Manual - Download and Unpack the PSP
Download the PSP here and unpack.
The distribution name is of the form grouper.psp-2.1.0.tar.gz
curl
http://www.internet2.edu/grouper/release/2.1.0/grouper.psp-2.1.0.tar.gz
-O
tar xzf grouper.psp-2.1.0.tar.gz
Install : Manual - Copy Jars
Copy jars located in lib/custom
from the psp distribution to the Grouper API installation.
cp -vR grouper.psp-2.1.0/lib/custom/ grouper.apiBinary-2.1.0/lib/custom/
Install : Copy Example Configuration Files
Copy example configuration files located in conf
from the psp distribution to the Grouper API installation.
Example psp configuration files are in directories named with the prefix psp-example-*
.
cp -vR grouper.psp-2.1.0/conf/ grouper.apiBinary-2.1.0/conf/
Configuration Example : Grouper to LDAP
This configuration example should apply to any ldap directory server.
examples |
|
DN structure |
bushy |
|
member DNs |
Configuration Example : Grouper to Tivoli
This configuration example targets an IBM Tivoli Directory Server with requirements from Penn State.
examples |
|
DN structure |
flat |
|
member subject ids |
|
group DNs |
|
member names |
|
group names |
Configuration Example : Grouper to OpenLDAP
This configuration example applies to OpenLDAP, and includes provisioning the mailLocalAddress
attribute sourced from the Grouper attribute framework.
examples |
|
DN structure |
bushy |
|
member names |
|
group names |
|
member DNs |
|
group DNs |
For this example, new attribute framework etc:attribute:mailLocalAddress
and etc:attribute:seeAlso
attributes will need to be created in Grouper. Here is example code using the Grouper API :
GrouperSession.startRootSession(); Stem etcAttributeStem = StemFinder.findByName(GrouperSession.staticGrouperSession(), "etc:attribute", true); AttributeDef attributeDef = etcAttributeStem.addChildAttributeDef("mailLocalAddressAttributeDef", AttributeDefType.attr); attributeDef.setAssignToGroup(true); attributeDef.setMultiValued(true); attributeDef.setValueType(AttributeDefValueType.string); attributeDef.store(); etcAttributeStem.addChildAttributeDefName(attributeDef, "mailLocalAddress", "mailLocalAddress"); AttributeDef seeAlsoAttributeDef = etcAttributeStem.addChildAttributeDef("seeAlsoAttributeDef", AttributeDefType.attr); seeAlsoAttributeDef.setAssignToStem(true); seeAlsoAttributeDef.setMultiValued(true); seeAlsoAttributeDef.setValueType(AttributeDefValueType.string); seeAlsoAttributeDef.store(); etcAttributeStem.addChildAttributeDefName(seeAlsoAttributeDef, "seeAlso", "seeAlso");
Configuration Example : Grouper to OpenLDAP MemberOf Overlay
This configuration example applies to an OpenLDAP directory with the memberOf overlay. This example is similar to the OpenLDAP example, except that the memberOf attribute is not provisioned by the psp.
examples |
|
DN structure |
bushy |
|
member names |
|
group names |
|
member DNs |
Configuration Example : Grouper to OpenLDAP Multiple
This configuration example provisions multiple OpenLDAP directories, and is based on a request from the University of Modena and Reggio Emilia on the grouper-users@internet2.edu mail list.
https://lists.internet2.edu/sympa/arc/grouper-users/2012-03/msg00005.html
This configuration example provisions two OpenLDAP directories identically while provisioning groups only to a third directory.
Grouper LDAP subjects are sourced from the identical directories allowing for failover.
edu.vt.middleware.ldap.ldapUrl=ldap://127.0.0.1:3891 ldap://127.0.0.1:3892 edu.vt.middleware.ldap.connectionHandler=edu.vt.middleware.ldap.handler.DefaultConnectionHandler{{connectionStrategy=ACTIVE_PASSIVE}} # edu.vt.middleware.ldap.connectionHandler=edu.vt.middleware.ldap.handler.DefaultConnectionHandler{{connectionStrategy=ROUND_ROBIN}}
Because multiple directories are provisioned, this example is different than those which provision a single target. In the examples which provision a single ldap target, a single ldap connection is used to lookup Grouper subjects as well as to provision. In this example, an ldap connection is created to provision each target.
The connections to the three provisioned ldap targets are defined in psp-services.xml
and psp-vt-ldap-
123
.xml
.
All three targets are provisioned in a single thread, future work should allow for one thread per target.
examples |
|
DN structure |
bushy |
|
member names |
|
group names |
|
member DNs |
|
group DNs |
Configuration Example : Grouper to Active Directory
A contribution from Sébastien Gagné, Université de Montréal.
examples |
|
DN structure |
bushy |
|
member DNs |
Configuration Example : LDAP to Grouper
This example provisions groups, stems, and memberships from an ldap directory to Grouper.
examples |
Configure LDAP Provisioning Target
The LDAP provisioning target connection is configured in ldap.properties
.
Configure the default search base DN to match your directory :
edu.vt.middleware.ldap.baseDn = dc=example,dc=edu
Configure authentication and encryption :
edu.vt.middleware.ldap.bindDn=cn=Manager,dc=example,dc=edu edu.vt.middleware.ldap.bindCredential=secret
Configure the default base DN (container) for people and groups :
# The base DN for groups. edu.internet2.middleware.psp.groupsBaseDn = ou=groups,dc=example,dc=edu # The base DN for people. edu.internet2.middleware.psp.peopleBaseDn = ou=people,dc=example,dc=edu
Configure LDAP Provisioning Structure : Flat
In a flat
structure all groups are provisioned under a single base DN (container ID). A flat
group's ldap RDN is its Grouper name or displayName.
Configure the flat
LDAP structure and name
group RDN source attribute ID in ldap.properties
:
edu.internet2.middleware.psp.structure=flat edu.internet2.middleware.psp.cnSourceAttributeID=name
Configure LDAP Provisioning Structure : Bushy
In a bushy
structure groups are provisioned hierarchically, with stems as branches (ldap organizationalUnits) in the tree. A bushy
group's RDN is its Grouper extension or displayExtension.
Configure the bushy
LDAP structure and extension
group RDN source attribute ID in ldap.properties
:
edu.internet2.middleware.psp.structure=bushy edu.internet2.middleware.psp.cnSourceAttributeID=extension
Configure LDAP Base DNs
The example default base DN is dc=example,dc=edu
. Change the base DN in ldap.properties
:
# The default base DN for searches. edu.vt.middleware.ldap.baseDn=dc=example,dc=edu # The base DN for groups. edu.internet2.middleware.psp.groupsBaseDn=ou=groups,dc=example,dc=edu # The base DN for people. edu.internet2.middleware.psp.peopleBaseDn=ou=people,dc=example,dc=edu
as well as sources.xml
:
<source adapterClass="edu.internet2.middleware.subject.provider.LdapSourceAdapter"> <id>ldap</id> <name>LdapSourceAdapter</name> <type>person</type> <search> <searchType>searchSubject</searchType> ... <param> <param-name>base</param-name> <param-value>ou=people,dc=example,dc=edu</param-value> </param> </search> <search> <searchType>searchSubjectByIdentifier</searchType> ... <param> <param-name>base</param-name> <param-value>ou=people,dc=example,dc=edu</param-value> </param> </search> <search> <searchType>search</searchType> ... <param> <param-name>base</param-name> <param-value>ou=people,dc=example,dc=edu</param-value> </param> </search>
Configure LDAP Subject Source
Configure Grouper to look for subjects in your LDAP directory by using the ldap source adapter.
The Grouper LDAP subject source connection is defined in sources.xml
.
<source adapterClass="edu.internet2.middleware.subject.provider.LdapSourceAdapter"> <id>ldap</id> <name>LdapSourceAdapter</name> <type>person</type> <init-param> <param-name>ldapProperties_file</param-name> <param-value>ldap.properties</param-value> </init-param>
Configure LDAP Subject Source : ID Other Than "ldap"
The id of the Grouper LDAP subject source adapter, <id>ldap</id>
, appears in several psp configuration files. If your Grouper LDAP subject source adapter id is not "ldap", you should read the following and make changes to your psp configuration files. In the following examples, the Grouper LDAP subject source id has been changed from "ldap" to "ad".
In the psp service configuration psp-services.xml
, the LDAP target to be provisioned re-uses the same pooled vt-ldap connection as the Grouper LDAP subject source adapter. The value of the vt-ldap pool id property ldapPoolId="ldap"
should match the Grouper LDAP subject source adapter id <id>ldap</id>
in sources.xml
. If your Grouper LDAP subject source id is <id>ad</ad>
, then the vt-ldap pool id should be ldapPoolId="ad"
.
Also in the psp service configuration psp-services.xml
, the id of the LDAP target to be provisioned, id="ldap"
, is the SPMLv2 targetId which should match the targetId attribute of <identifier/>
elements in the psp configuration file.
<Service id="ldap" xsi:type="psp-ldap-target:LdapTarget" ldapPoolId="ad" ldapPoolIdSource="grouper"> </Service>
In the psp configuration file psp.xml
, the target id of the <identifier/>
element of objects to be provisioned, targetId="ldap"
, should match the LDAP target id <Service id="ldap"/>
as defined in psp-services.xml
. If your Grouper LDAP subject source id is <id>ad</id>
, you do NOT need to change the targetId.
<!-- The ladp group DN. --> <identifier ref="groupDn" targetId="ldap" containerId="${edu.internet2.middleware.psp.groupsBaseDn}" />
In the attribute resolver configuration psp-resolver.xml
, the Grouper LDAP subject source id, <id>ldap</id>
, appears in several elements.
The first place that Grouper LDAP subject source id "ldap" appears in the attribute resolver configuration is in the element which defines that the MemberDataConnector
should return the "dn" attribute for Grouper members whose subject source is "ldap". The "dn" attribute is used as the identifier of provisioned member objects. If your Grouper LDAP subject source id is <id>ad</id>
, then the source of the "dn" attribute should be source="ad"
.
<!-- The MemberDataConnector returns attributes representing the member whose subject id or identifier is the principal name. --> <resolver:DataConnector id="MemberDataConnector" xsi:type="grouper:MemberDataConnector"> <!-- Return the "dn" attribute of members whose subject source id is "ad". --> <grouper:Attribute id="dn" source="ad" /> </resolver:DataConnector>
The second place that "ldap" appears in the attribute resolver configuration is in the element which defines that the "id" attribute should be returned as values of the "membersLdap" attribute for Grouper members whose subject source is "ldap". The values of the "membersLdap" attribute definition, Grouper LDAP subject ids, are used to calculate group memberships. If your Grouper LDAP subject source id is <id>ad</id>
, then the source of the "membersLdap" attribute should be source="ad"
.
<!-- The values of the "membersLdap" attribute are the subject ids of group members from the "ldap" source. --> <resolver:AttributeDefinition id="membersLdap" xsi:type="grouper:Member" sourceAttributeID="members"> <resolver:Dependency ref="GroupDataConnector" /> <!-- The values of the "id" attribute are the identifiers of subjects whose source id is "ad". --> <grouper:Attribute id="id" source="ad" /> </resolver:AttributeDefinition>
The third place that "ldap" appears in the attribute resolver configuration is in the element which defines that the "id" attribute should be returned as values of the "changeLogMembershipLdapSubjectId" attribute for Grouper members whose subject source is "ldap". The values of the "changeLogMembershipLdapSubjectId" attribute definition, Grouper LDAP subject ids, are used to calculate group memberships during processing of change log entries. If your Grouper LDAP subject source id is <id>ad</id>
, then the sourceId should contain "ad", for example, sourceId.getValues().contains("ad")
.
<!-- The value of the "changeLogMembershipLdapSubjectId" attribute is the subject identifier of the "ldap" source member of a membership change log entry. --> <resolver:AttributeDefinition id="changeLogMembershipLdapSubjectId" xsi:type="ad:Script"> <resolver:Dependency ref="AddMembershipChangeLogDataConnector" /> <resolver:Dependency ref="DeleteMembershipChangeLogDataConnector" /> <ad:Script><![CDATA[ // Import Shibboleth attribute provider. importPackage(Packages.edu.internet2.middleware.shibboleth.common.attribute.provider); // Create the attribute to be returned. changeLogMembershipLdapSubjectId = new BasicAttribute("changeLogMembershipLdapSubjectId"); // Return 'subjectId' attribute values if the 'sourceId' attribute is 'ad'. if (typeof sourceId != "undefined" && sourceId != null ){ if (sourceId.getValues().contains("ad")) { if (typeof subjectId != "undefined" && subjectId != null ){ changeLogMembershipLdapSubjectId.getValues().add(subjectId.getValues().get(0)); } } } ]]></ad:Script> </resolver:AttributeDefinition>
Configure LDAP Subject Source in Grouper UI
Copy sources.xml
and ldap.properties
from the Grouper API to the Grouper UI.
cp grouper.apiBinary-2.1.0/conf/ldap.properties grouper.ui-2.1.0/dist/grouper/WEB-INF/classes/
cp grouper.apiBinary-2.1.0/conf/sources.xml grouper.ui-2.1.0/dist/grouper/WEB-INF/classes/
Copy vt-ldap.jar
from the Grouper API to the Grouper UI :
cp grouper.apiBinary-2.1.0/lib/custom/vt-ldap-3.3.4.jar grouper.ui-2.1.0/dist/grouper/WEB-INF/lib
The Grouper UI will not load unless you edit ldap.properties
in your Grouper UI installation or copy psp-ldap-target-2.1.0-SNAPSHOT.jar
to your Grouper UI installation.
Comment out or remove the psp specific search result handlers in ldap.properties
in your Grouper UI installation :
# edu.vt.middleware.ldap.searchResultHandlers=edu.internet2.middleware.psp.ldap.QuotedDnResultHandler,...
Configure LDAP Subject Source in Grouper WS
TODO
Configure LDAP DNs Created from Grouper Names
A provisioned object requires a unique identifier. When provisioning an ldap target, provisioned object identifiers are ldap distinguished names (DNs).
The psp-grouper-ldap
project provides a Shibboleth attribute resolver attribute definition which maps Grouper names to ldap DNs.
<!-- The LDAP DN of a group. For example, "cn=groupExtension,ou=stem,ou=groups,dc=example,dc=edu". --> <resolver:AttributeDefinition id="groupDn" xsi:type="psp-grouper-ldap:LdapDnFromGrouperNamePSOIdentifier" structure="${edu.internet2.middleware.psp.structure}" sourceAttributeID="groupNameInStem" rdnAttributeName="cn" baseDn="${edu.internet2.middleware.psp.groupsBaseDn}" baseStem="${edu.internet2.middleware.psp.baseStem}"> <!-- Dependencies which return a "groupNameInStem" attribute whose value is the group name. --> <resolver:Dependency ref="groupNameInStem"/>
Based on a request from the University of Montreal, the Grouper base stem to be provisioned may be omitted from ldap DNs. The following table describes the affect of the base stem to be provisioned when the structure is bushy
:
grouper base stem |
grouper name |
ldap dn |
---|---|---|
|
edu:courses:course |
cn=course,ou=courses,ou=edu,ou=groups,dc=example,dc=edu |
edu |
edu:courses:course |
cn=course,ou=courses,ou=groups,dc=example,dc=edu |
By default, the psp-example-* configuration files use the Grouper name to create ldap DNs. It is also possible to create ldap DNs from the Grouper displayName by changing the relevant sourceAttributeID to "displayName".
<resolver:AttributeDefinition id="groupNameInStem" xsi:type="grouper:FilteredName" sourceAttributeID="displayName"> ...
Configure Grouper Stem to be Provisioned
Configure the name of the Grouper stem to be provisioned, by default this is the root stem, which is the empty string.
The Grouper stem to be provisioned is configured in ldap.properties
.
# The base Grouper stem to be provisioned. edu.internet2.middleware.psp.baseStem=
Configure Grouper Change Log
The Grouper change log is configured in grouper-loader.properties
.
To enable change log provisioning :
changeLog.consumer.psp.class = edu.internet2.middleware.psp.grouper.PspChangeLogConsumer
To schedule when the change log is processed :
changeLog.consumer.psp.quartzCron = 0 * * * * ?
To run full synchronizations periodically (by default every day at 5am) :
changeLog.psp.fullSync.class = edu.internet2.middleware.psp.grouper.PspChangeLogConsumer changeLog.psp.fullSync.quartzCron = 0 0 5 * * ?
To run a full synchronization job at loader startup :
changeLog.psp.fullSync.runAtStartup = true
The Quartz cron string documentation is here.
Configure Grouper Logging
You may want to change the Grouper log file appenders in grouper.apiBinary-2.1.0/conf/log4j.properties
.
log4j.appender.grouper_error = org.apache.log4j.DailyRollingFileAppender log4j.appender.grouper_error.File = ${grouper.home}logs/grouper_error.log log4j.appender.grouper_error.DatePattern = '.'yyyy-MM-dd log4j.appender.grouper_event = org.apache.log4j.DailyRollingFileAppender log4j.appender.grouper_event.File = ${grouper.home}logs/grouper_event.log log4j.appender.grouper_event.DatePattern = '.'yyyy-MM-dd
Configure Grouper Versions Prior to 2.1.0
The following changes are necessary to support provisioning Grouper API versions prior to 2.1.0 with the psp.
1. For Grouper versions prior to 2.1.0, there is a bug which will throw a NullPointerException if the following is not present in sources.xml
:
<search> <searchType>searchSubjectByIdentifierAttributes</searchType> <param> <param-name>filter</param-name> <param-value> (&(uid=%TERM%)(objectclass=person)) </param-value> </param> <param> <param-name>scope</param-name> <param-value>SUBTREE_SCOPE</param-value> </param> <param> <param-name>base</param-name> <param-value>ou=people,dc=example,dc=edu</param-value> </param> </search>
2. For versions prior to 2.1.0, the location of ldap.properties
specified in sources.xml
must be an absolute path. For versions 2.1.0 or later, the location of ldap.properties
may be an absolute path or in your Java classpath.
For example, Grouper API version 2.0.3 requires an absolute path to ldap.properties in sources.xml
:
<init-param> <param-name>ldapProperties_file</param-name> <param-value>/opt/grouper/2.0.3/grouper.apiBinary-2.0.3/conf/ldap.properties</param-value> </init-param>
For Grouper UI and WS versions prior to 2.1.0, the path to ldap.properties
specified in sources.xml
will be different than in the Grouper API since the psp specific search result handlers must be commented out or removed in the Grouper UI :
<init-param> <param-name>ldapProperties_file</param-name> <param-value>/opt/grouper/2.0.3/grouper.ui-2.0.3/dist/grouper/WEB-INF/classes/ldap.properties</param-value> </init-param>
3. For Grouper API versions prior to 2.1.0, the ldap source adapter in subject.jar
does not provide the method which allows the psp to re-use the same ldap connection as the subject source. You will need to copy lib/grouper/subject.jar
from the Grouper 2.1.0 API distribution to your pre-2.1.0 Grouper API installation.
Configure Subject API Cache
The Subject API cache is configured in grouper.ehcache.xml
.
Adjust maxElementsInMemory
to be greater than or equal to the number of subjects.
Adjust timeToIdleSeconds
and timeToLiveSeconds
... accordingly ... ?
Some words about testing via gsh.sh and looking at cache hit/miss ratio debugging.
As of Grouper version 2.1.0, which uses Ehcache 2.4, statistics
must be "true"
to collect statistics which are logged at DEBUG
level.
<!-- Subject resolving caching --> <!-- @see CachingResolver#find(...) --> <cache name="edu.internet2.middleware.grouper.subj.CachingResolver.Find" maxElementsInMemory="5000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="120" overflowToDisk="false" statistics="true" /> <!-- @see CachingResolver#findAll(...) --> <cache name="edu.internet2.middleware.grouper.subj.CachingResolver.FindAll" maxElementsInMemory="5000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="120" overflowToDisk="false" statistics="true" /> <!-- @see CachingResolver#findByIdentifier(...) --> <cache name="edu.internet2.middleware.grouper.subj.CachingResolver.FindByIdentifier" maxElementsInMemory="5000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="120" overflowToDisk="false" statistics="true" /> <!-- @see CachingResolver#findByIdOrIdentifier(...) --> <cache name="edu.internet2.middleware.grouper.subj.CachingResolver.FindByIdOrIdentifier" maxElementsInMemory="5000" eternal="false" timeToIdleSeconds="30" timeToLiveSeconds="120" overflowToDisk="false" statistics="true" />
Configure PSP : Provisioning Service Provider
The psp configuration files are :
|
Configuration for the objects, identifiers, attributes, and references to be provisioned to a target. |
|
Configuration for the Shibboleth attribute resolver. |
|
Configuration for Shibboleth services such as the attribute resolver, psp, and provisioning targets. |
|
Bootstraps Shibboleth. |
Configure PSP : SPMLv2 Provisioned Objects, Identifiers, Attributes and References
The objects, identifiers, attributes, and references to be provisioned are defined in psp.xml
.
Configure PSP : Provisioned Objects
Provisioned objects, or in SPMLv2 terms Provisioning Service Objects, consist of identifiers, attributes (probably), and references (maybe) to the identifiers of other objects, which are most likely located on the same provisioning target.
The following configures the psp to provision a group
object.
<pso id="group" authoritative="true" allSourceIdentifiersRef="groupNames"> </pso>
property |
default |
value |
---|---|---|
|
|
the unique id of the provisioned object |
|
|
If |
|
|
The id of an attribute resolver definition whose values are all source identifiers applicable to this provisioned object. |
Configure PSP : Identifiers
Identifiers consist of a string ID, a target ID, and possibly a container ID. We consider a container ID to be similar to an ldap base dn. A container ID is itself an identifier, recursing potentially indefinitely.
The following configures the psp to provision the identifier of the grouper
object as an LDAP DN returned from the groupDn
Shibboleth attribute definition from psp-resolver.xml
.
<pso id="group"> <!-- The ldap group DN. --> <identifier ref="groupDn" targetId="ldap" containerId="${edu.internet2.middleware.psp.groupsBaseDn}" /> </pso>
property |
value |
---|---|
|
The id of the Shibboleth attribute definition whose value is an SPMLv2 PSO Identifier |
|
The id of the provisioned target. Must match the id of a target configured in |
|
The string id of the pso identifier containing the object. |
<!-- The LDAP DN of a group. For example, "cn=group,ou=groups,dc=example,dc=edu". --> <resolver:AttributeDefinition id="groupDn" xsi:type="psp-grouper-ldap:LdapDnFromGrouperNamePSOIdentifier" structure="${edu.internet2.middleware.psp.structure}" sourceAttributeID="name" rdnAttributeName="cn" base="${edu.internet2.middleware.psp.groupsBaseDn}"> <!-- Dependencies which return a "name" attribute whose value is the group name. --> <resolver:Dependency ref="GroupDataConnector" /> <resolver:Dependency ref="DeleteGroupChangeLogDataConnector" /> <resolver:Dependency ref="UpdateGroupChangeLogDataConnector" /> </resolver:AttributeDefinition>
The following is an identifier expressed in SPMLv2
<psp:pso entityName='group'> <psoID ID='cn=group,ou=groups,dc=example,dc=edu' targetID='ldap'/> </psp:pso>
The following is a identifier expressed in LDIF
dn: cn=group,ou=groups,dc=example,dc=edu
Configure PSP : Identifying Attribute
The optional <identifyingAttribute/>
of a provisioned object has two purposes : (1) to determine the schema entity of target objects returned from a lookup or search request and (2) to be converted to a query when searching a target for all identifiers. If <identifyingAttribute/>
is not present, the provisioned object will be ignored during bulk requests.
<!-- Identifies ldap group objects which exist on the target by objectClass attribute value. --> <identifyingAttribute name="objectClass" value="groupOfNames" />
(1) The provisioning service provider needs to map provisioned object identifiers to provisioned objects (schema entities).
For example, given a lookup request for the id "edu", the psp needs to know if "edu" is a group or a stem. Given the following configuration, if the provisioned object with id "edu" has an "objectclass" attribute with value "organizationalUnit", then the schema entity is "stem". If the provisioned object with id "edu" has an "objectclass" attribute with value "groupOfNames", then the schema entity is "group".
The psp evaluates all <identifyingAttribute/> elements, only one should match, otherwise an exception is thrown.
<pso id="stem"> <!-- The ldap organizational unit DN. --> <identifier ref="stemDn" targetId="ldap" containerId="${edu.internet2.middleware.psp.groupsBaseDn}" /> <!-- Identifies stem objects which exist on the target by objectclass attribute value. --> <identifyingAttribute name="objectclass" value="organizationalUnit" /> </pso> <pso id="group"> <!-- The ldap group DN. --> <identifier ref="groupDn" targetId="ldap" containerId="${edu.internet2.middleware.psp.groupsBaseDn}" /> <!-- Identifies stem objects which exist on the target by objectclass attribute value. --> <identifyingAttribute name="objectclass" value="groupOfNames" /> </pso>
(2) In order to synchronize all objects during bulk[Calc|Diff|Sync] requests, the psp needs to know the identifiers of all provisioned objects (schema entities) on a target for which the psp is authoritative. The psp uses <identifyingAttribute/>
and <identifier containerId="..."/>
elements to create SPMLv2 search requests.
For example, in the configuration example above, the psp will perform an ldap search with filter "(objectClass=organizationalUnit)" to retrieve the identifiers of all provisioned stems as well as an ldap search with filter "(objectclass=groupOfNames)" to retrieve the identifiers of all provisioned groups. The base of each search will be the containerId of the <identifier/>
element.
Configure PSP : Alternate Identifier
The optional <alternateIdentifier/>
element configures the psp to rename provisioned objects. It refers to an attribute resolver definition whose value is the previous (old) identifier of an object after it has been renamed. If <alternateIdentifier/>
is not present, provisioned objects will not be renamed, instead the old object will be deleted and a new object created.
<!-- The "old" ldap group DN calculated from group update change log events. --> <alternateIdentifier ref="groupDnAlternateChangeLog" />
property |
value |
---|---|
|
The id of the Shibboleth attribute definition whose value is the previous SPMLv2 PSO Identifier. |
Configure PSP : Attributes
Name value pairs. Probably multi-valued. Case sensitive names and values. We return values in the same order as they were given to us.
The following configures the psp to provision the cn
attribute of a group
. The value of the cn
attribute is returned by the cn
Shibboleth attribute definition from psp-resolver.xml
.
<pso id="group"> <attribute name="cn" /> </pso>
<resolver:AttributeDefinition id="cn" xsi:type="ad:Simple" sourceAttributeID="cn"> <resolver:Dependency ref="GroupDataConnector" /> </resolver:AttributeDefinition>
The following is an attribute expressed in SPMLv2
<psp:pso entityName='group'> <psoID ID='cn=group,ou=groups,dc=example,dc=edu' targetID='ldap'/> <data> <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='cn'> <dsml:value>group</dsml:value> </dsml:attr> </data> </psp:pso>
The following is a attribute expressed in LDIF
dn: cn=group,ou=groups,dc=example,dc=edu cn: group
Configure PSP : References
A reference refers to the identifier of another object. It consists of two identifiers, the "from object" and the "to object". A node in a directed graph. Directional.
The following configures the psp to provision a reference from a group
to a member
as values of the member
attribute. The values of the reference are returned by the membersLdap
and membersGsa
Shibboleth attribute definitions from psp-resolver.xml
.
<pso id="group"> <references name="member"> <reference ref="membersLdap" toObject="member" /> <reference ref="membersGsa" toObject="group" /> </references> </pso>
<!-- The values of the "membersLdap" attribute are the subject ids of group members from the "ldap" source. --> <resolver:AttributeDefinition id="membersLdap" xsi:type="grouper:Member" sourceAttributeID="members"> <resolver:Dependency ref="GroupDataConnector" /> <!-- The values of the "id" attribute are the identifiers of subjects whose source id is "ldap". --> <grouper:Attribute id="id" source="ldap" /> </resolver:AttributeDefinition> <!-- The values of the "membersGsa" attribute are the names of group members which are grouper groups. --> <resolver:AttributeDefinition id="membersGsa" xsi:type="grouper:Member" sourceAttributeID="members"> <resolver:Dependency ref="GroupDataConnector" /> <!-- The values of the "name" attribute are the names of groups whose source is "g:gsa". --> <grouper:Attribute id="name" source="g:gsa" /> </resolver:AttributeDefinition>
The following is a reference expressed in SPMLv2
<psp:pso entityName='group'> <psoID ID='cn=group,ou=groups,dc=example,dc=edu' targetID='ldap'/> <capabilityData mustUnderstand='true' capabilityURI='urn:oasis:names:tc:SPML:2:0:reference'> <spmlref:reference xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlref='urn:oasis:names:tc:SPML:2:0:reference' typeOfReference='member'> <spmlref:toPsoID ID='uid=123,ou=people,dc=example,dc=edu' targetID='ldap'/> </spmlref:reference> <spmlref:reference xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlref='urn:oasis:names:tc:SPML:2:0:reference' typeOfReference='memberOf'> <spmlref:toPsoID ID='cn=group,ou=groups,dc=example,dc=edu' targetID='ldap'/> </spmlref:reference> </capabilityData> </psp:pso>
The following is a reference expressed in LDIF
dn: cn=group,ou=groups,dc=example,dc=edu cn: group member: uid=person,ou=people,dc=example,dc=edu dn: uid=person,ou=people,dc=example,dc=edu ...
Configure PSP : Attribute Resolver
The values of the identifiers, attributes, and references to be provisioned are defined by a Shibboleth attribute resolver configuration psp-resolver.xml
.
<!-- The attribute resolver. --> <Service id="psp.AttributeResolver" xsi:type="attribute-resolver:ShibbolethAttributeResolver"> <ConfigurationResource file="/psp-resolver.xml" xsi:type="resource:ClasspathResource"> <ResourceFilter xsi:type="grouper:ClasspathPropertyReplacement" xmlns="urn:mace:shibboleth:2.0:resource" propertyFile="/ldap.properties" /> </ConfigurationResource> </Service>
Configure PSP : Attribute Resolver and Grouper Integration
TODO
Configure PSP : Attribute Resolver and Grouper ChangeLog Integration
TODO
Configure PSP : Attribute Resolver and Grouper Attribute Framework Integration
To provision an attribute sourced from the Grouper Attribute Framework, the attribute must be defined in a <grouper:Attribute id="etc:attribute:name"/>
element of a Grouper data connector.
This restriction is currently in place because an early version of the Grouper Attribute Framework had not yet been tuned for this type of query. This restriction is likely to be removed in a future version.
<resolver:DataConnector id="GroupDataConnector" xsi:type="grouper:GroupDataConnector"> <!-- The "etc:attribute:mailLocalAddress" attribute framework definition. --> <grouper:Attribute id="etc:attribute:mailLocalAddress" /> </resolver:DataConnector>
Configure PSP : Logging and Output
The psp is a Shibboleth service which is configured in psp-services.xml
.
The psp uses slf4j, and with Grouper, log4j configured in log4j.properties
.
# Provisioning : PSP (version 2.1+) log4j.logger.edu.internet2.middleware.psp = INFO # Provisioning : vt-ldap log4j.logger.edu.vt.middleware.ldap = INFO # Provisioning : ldap target # log4j.logger.edu.internet2.middleware.ldap = DEBUG # Provisioning : Grouper plugin to Shibboleth attribute resolver log4j.logger.edu.internet2.middleware.grouper.shibboleth = INFO
property |
default |
value |
---|---|---|
|
|
If |
|
|
If |
|
|
If |
|
|
The path to the file to which SPML requests and responses are written. |
<!-- The provisioning service provider. --> <Service id="psp" xsi:type="psp:ProvisioningServiceProvider" depends-on="psp.AttributeAuthority" authority="psp.AttributeAuthority" logSpml="true" writeRequests="false" writeResponses="false" pathToOutputFile=""> <ConfigurationResource file="/psp.xml" xsi:type="resource:ClasspathResource"> <ResourceFilter xsi:type="grouper:ClasspathPropertyReplacement" xmlns="urn:mace:shibboleth:2.0:resource" propertyFile="/ldap.properties" /> </ConfigurationResource> </Service>
Configure PSP : LDAP Target
The LDAP target to be provisioned is a Shibboleth service configured in psp-services.xml
.
By default, the LDAP target to be provisioned re-uses the same vt-ldap
connection as the Grouper LDAP source adapter.
property |
default |
value |
---|---|---|
|
|
If |
|
|
If |
|
|
If |
|
|
The path to the file to which SPML requests and responses are written. |
|
|
Re-use the |
<!-- The ldap target. The ldapPoolIdSource is either "grouper" or "spring". --> <!-- If ldapPoolIdSource is "spring", the ldapPoolId must be the id of the ldap pool bean in the vt-ldap xml spring configuration. --> <!-- If ldapPoolIdSource is "grouper", the ldapPoolId must be the id of the LdapSourceAdapter in sources.xml --> <Service id="ldap" xsi:type="psp-ldap-target:LdapTarget" logSpml="true" ldapPoolId="ldap" ldapPoolIdSource="grouper"> <!-- A <ConfigurationResource/> is required to instantiate the <Service/>, so supply a do-nothing resource. --> <ConfigurationResource file="/edu/internet2/middleware/psp/util/empty-bean.xml" xsi:type="resource:ClasspathResource" /> </Service>
Provision Grouper
Before you can provision anything from Grouper to ldap or anywhere else, you will need to create the corresponding objects in Grouper using the UI, API, GSH, WS, loader, import, etc.
Provision Grouper : GSH
To calculate how a group should be provisioned :
bin/gsh.sh -psp -calc edu:group
To diff the current and correct provisioning of a group :
bin/gsh.sh -psp -diff edu:group
To provision or synchronize a group :
bin/gsh.sh -psp -sync edu:group
Provision Grouper : Grouper Change Log
To provision in real-time triggered by the Grouper change log, enable the psp consumer in grouper-loader.properties
and run the loader via
bin/gsh.sh -loader
Real-Time Provisioning Beta-Testing : Grouper Subject Sources
Institution |
Subject Source |
Number of Subjects |
Subject ID |
---|---|---|---|
LIGO |
LDAP |
1,000 |
dn: employeeNumber=882,ou=people,dc=ligo,dc=org |
Penn State |
LDAP |
165,000 |
dn:uid=xyx123,dc=psu,dc=edu |
UCLA |
LDAP |
40,000 |
|
UMontreal |
LDAP |
120,000 |
sAMAccountName (value same as cn) |
UVienna |
Undecided |
155,000 |
cn, uid |
UWMadison |
|
|
|
Real-Time Provisioning Beta-Testing : Provisioning Targets
Institution |
Target |
Implementation |
---|---|---|
LIGO |
LDAP |
OpenLDAP 2.4.x |
Penn State |
LDAP |
IBM Tivoli Directory Server |
UCLA |
LDAP |
Sun Java System Directory Server Enterprise Edition 6.3.1 |
UMontreal |
LDAP |
Active Directory |
UVienna |
LDAP |
Active Directory, OpenLDAP |
UWMadison |
|
|
Real-Time Provisioning Beta-Testing : Provisioning memberOf
The groups that a member is a member of may be provisioned to the memberOf attribute. Some LDAP implementations, such as Active Directory, automatically maintain the memberOf attribute. OpenLDAP maintains the memberOf attribute automatically via the memberOf overlay. The value of the memberOf attribute is typically a group DN.
Institution |
memberOf for members (people) |
memberOf for groups |
---|---|---|
LIGO |
+ |
|
Penn State |
+ |
|
UCLA |
- |
|
UMontreal |
automatic (Active Directory) |
automatic (Active Directory) |
UVienna |
automatic (Active Directory), OpenLDAP+memberOf |
automatic (Active Directory), OpenLDAP+memberOf |
UWMadison |
+ |
|
Real-Time Provisioning Beta-Testing : Provisioning eduMember
The eduMember objectClass defines the isMemberOf and hasMember attributes, whose values are identifiers which are not DNs.
Institution |
isMemberOf |
hasMember |
---|---|---|
LIGO |
+ |
+ |
Penn State |
+ |
+ |
UCLA |
uclaIsMemberOf |
uclaHasMember |
UMontreal |
- |
- |
UVienna |
- |
- |
UWMadison |
+ |
+ |
Real-Time Provisioning Beta-Testing : Provisioning eduCourse
The eduCourse objectClass defines course related attributes.
Institution |
eduCourse |
---|---|
LIGO |
- |
Penn State |
- |
UCLA |
- |
UMontreal |
- |
UVienna |
- |
UWMadison |
+ |
Real-Time Provisioning Beta-Testing : Provisioning Structure
The group provisioning structure may be either flat
or bushy
. A flat
structure provisions all groups into a single container. A bushy
structure provisions groups hierarchically.
For example, the DN of a group with name 'edu:stem:group' in a flat
structure looks like :
dn: cn=edu:stem:group,ou=groups,dc=example,dc=edu
while the DN of a group with name 'edu:stem:group' in a bushy
structure looks like :
dn: cn=group,ou=stem,ou=edu,ou=groups,dc=example,dc=edu
Institution |
Structure (flat or bushy) |
---|---|
LIGO |
bushy |
Penn State |
flat |
UCLA |
flat |
UMontreal |
bushy |
UVienna |
? |
UWMadison |
flat |
Real-Time Provisioning Beta-Testing : Membership Structure
Given groupA with memberA and groupB with memberB :
dn : cn=groupA,ou=groups member: cn=memberA,ou=people dn: cn=groupB,ou=groups member: cn=memberB,ou=people
If groupB is added as a member to groupA, how do you want groupA to be provisioned :
everything :
dn : cn=groupA,ou=groups member: cn=memberA,ou=people member: cn=memberB,ou=people member: cn=groupB,ou=people
immediate :
dn : cn=groupA,ou=groups member: cn=memberA,ou=people member: cn=groupB,ou=people
The everything membership structure handles applications which may not support nested groups and represents the nested structure of the group memberships.
The same membership structure applies to memberOf :
everything :
dn: cn=memberB,ou=people memberOf: cn=groupB,ou=groups memberOf: cn=groupA,ou=groups
immediate :
dn: cn=memberB,ou=people memberOf: cn=groupB,ou=groups
Institution |
member |
memberOf |
---|---|---|
LIGO |
everything |
everything |
Penn State |
|
|
UCLA |
|
|
UMontreal |
immediate |
immediate |
UVienna |
everything |
everything |
UWMadison |
|
|