Skip to content

Commit

Permalink
Merge pull request #101 from internet2/PC_GrouperWS
Browse files Browse the repository at this point in the history
re-work identifiers
  • Loading branch information
pcaskey authored Jan 4, 2021
2 parents cca4520 + 2be373f commit 4aaabfb
Show file tree
Hide file tree
Showing 14 changed files with 781 additions and 565 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ subjectApi.source.ldap.param.searchAttribute0.value = searchAttribute0

#searchSubject: find a subject by ID. ID is generally an opaque and permanent identifier, e.g. 12345678.
# Each subject has one and only on ID. Returns one result when searching for one ID.
subjectApi.source.ldap.search.searchSubject.param.filter.value = (&(uid=%TERM%)(objectclass=person))
subjectApi.source.ldap.search.searchSubject.param.filter.value = (&(uid=%TERM%)(objectClass=person))
subjectApi.source.ldap.search.searchSubject.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.searchSubject.param.base.value = ou=people

#searchSubjectByIdentifier: find a subject by identifier. Identifier is anything that uniquely
# identifies the user, e.g. jsmith or jsmith@institution.edu.
# Subjects can have multiple identifiers. Note: it is nice to have if identifiers are unique
# even across sources. Returns one result when searching for one identifier.
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.filter.value = (&(|(uid=%TERM%)(employeeNumber=%TERM%))(objectclass=person))
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.filter.value = (&(|(uid=%TERM%)(employeeNumber=%TERM%)(incwbPersonEmployeeID=%TERM%)(incwbPersonStudentID=%TERM%)(incwbPersonGuestID=%TERM%))(objectClass=person))
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.scope.value = SUBTREE_SCOPE
subjectApi.source.ldap.search.searchSubjectByIdentifier.param.base.value = ou=people

Expand Down
3 changes: 2 additions & 1 deletion Workbench/directory/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ RUN useradd ldapadmin \
&& setup-ds.pl --silent --file /seed-data/ds-setup.inf \
&& /usr/sbin/ns-slapd -D /etc/dirsrv/slapd-dir \
&& while ! curl -s ldap://localhost:389 > /dev/null; do echo waiting for ldap to start; sleep 1; done; \
ldapadd -H ldap:/// -f /seed-data/data.ldif -x -D "cn=Directory Manager" -w password
ldapadd -H ldap:/// -f /seed-data/data.ldif -x -D "cn=Directory Manager" -w password \
&& ldapmodify -H ldap:/// -f /seed-data/incwbperson-obj.ldif -x -D "cn=Directory Manager" -w password

EXPOSE 389 443

Expand Down
36 changes: 36 additions & 0 deletions Workbench/directory/container_files/seed-data/incwbperson-obj.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# incwbPerson Objectclass
#
#
# "incwbperson" attributes
#
dn: cn=schema
changetype: modify
#
add: attributetypes
attributeTypes: ( 1.3.6.1.4.1.5923.999.1.1.1
NAME 'incwbPersonStudentID'
DESC 'incwbPerson Student ID'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )
attributeTypes: ( 1.3.6.1.4.1.5923.999.1.1.2
NAME 'incwbPersonEmployeeID'
DESC 'incwbPerson Employee ID'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )
#
attributeTypes: ( 1.3.6.1.4.1.5923.999.1.1.3
NAME 'incwbPersonGuestID'
DESC 'incwbPerson Guest ID'
EQUALITY caseIgnoreMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'user defined' )
-
#
add: objectclasses
objectClasses: ( 1.3.6.1.4.1.5923.999.1.2 NAME 'incwbPerson'
AUXILIARY
MAY ( incwbPersonStudentID $ incwbPersonEmployeeID $ incwbPersonGuestID )
)
#
# end of LDIF
#
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ group.setAttribute("grouperLoaderScheduleType", "CRON")
group.setAttribute("grouperLoaderQuartzCron", "0 * * * * ?")
group.setAttribute("grouperLoaderDbName", "sis")
group.setAttribute("grouperLoaderGroupTypes", "addIncludeExclude")
group.setAttribute("grouperLoaderQuery", "SELECT concat('ref:affiliation:',affiliation,'_systemOfRecord') as GROUP_NAME, uid as SUBJECT_ID, 'ldap' as SUBJECT_SOURCE_ID from SIS_AFFILIATIONS")
group.setAttribute("grouperLoaderQuery", "SELECT concat('ref:affiliation:',affiliation,'_systemOfRecord') as GROUP_NAME, uid as SUBJECT_IDENTIFIER, 'ldap' as SUBJECT_SOURCE_ID from SIS_AFFILIATIONS")

group = new GroupSave(gs).assignName("etc:deptLoader").assignCreateParentStemsIfNotExist(true).save()
group.addType(GroupTypeFinder.find("grouperLoader"))
Expand All @@ -48,7 +48,7 @@ group.setAttribute("grouperLoaderType", "SQL_GROUP_LIST")
group.setAttribute("grouperLoaderScheduleType", "CRON")
group.setAttribute("grouperLoaderQuartzCron", "0 * * * * ?")
group.setAttribute("grouperLoaderDbName", "sis")
group.setAttribute("grouperLoaderQuery", "SELECT concat('ref:dept:',department) as GROUP_NAME, uid as SUBJECT_ID, 'ldap' as SUBJECT_SOURCE_ID from SIS_PERSONS where department is not null")
group.setAttribute("grouperLoaderQuery", "SELECT concat('ref:dept:',department) as GROUP_NAME, uid as SUBJECT_IDENTIFIER, 'ldap' as SUBJECT_SOURCE_ID from SIS_PERSONS where department is not null")

group = new GroupSave(gs).assignName("etc:coursesLoader").assignCreateParentStemsIfNotExist(true).save()
group.addType(GroupTypeFinder.find("grouperLoader"))
Expand All @@ -57,7 +57,7 @@ group.setAttribute("grouperLoaderType", "SQL_GROUP_LIST")
group.setAttribute("grouperLoaderScheduleType", "CRON")
group.setAttribute("grouperLoaderQuartzCron", "0 * * * * ?")
group.setAttribute("grouperLoaderDbName", "sis")
group.setAttribute("grouperLoaderQuery", "SELECT concat('ref:course:',courseId) as GROUP_NAME, uid as SUBJECT_ID, 'ldap' as SUBJECT_SOURCE_ID from SIS_COURSES")
group.setAttribute("grouperLoaderQuery", "SELECT concat('ref:course:',courseId) as GROUP_NAME, uid as SUBJECT_IDENTIFIER, 'ldap' as SUBJECT_SOURCE_ID from SIS_COURSES")

edu.internet2.middleware.grouper.app.loader.GrouperLoaderType.scheduleLoads()

Expand Down
10 changes: 5 additions & 5 deletions Workbench/midpoint_server/container_files/csv/source-hr.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
uid,firstname,lastname,department,mail,validFrom,validTo
hr.jsmith,John R,Smith,HR_SOR,xjsmith@example.com,2018-01-01,9999-12-31
hr.aanderson,Alice,Anderson,HR_SOR,xaanderson@example.com,2016-03-15,9999-12-31
hr.ejohnson,Ellen,Johnson,HR_SOR,xejohnson@example.com,2019-10-01,2019-12-31
hr.rvasquez,Ron,Vasquez,HR_SOR,xrvasquez@example.com,2019-01-01,2019-10-31
uid,firstname,lastname,department,mail,validFrom,validTo
E600001,John R,Smith,HR_SOR,xjsmith@example.com,2018-01-01,9999-12-31
E600002,Alice,Anderson,HR_SOR,xaanderson@example.com,2016-03-15,9999-12-31
E600003,Ellen,Johnson,HR_SOR,xejohnson@example.com,2019-10-01,2019-12-31
E600004,Ron,Vasquez,HR_SOR,xrvasquez@example.com,2019-01-01,2019-10-31
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,131 @@
~ and European Union Public License. See LICENSE file for details.
-->

<objectTemplate xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3" xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3" oid="8098b124-c20c-4965-8adf-e528abedf7a4">
<name>template-user</name>
<objectTemplate oid="8098b124-c20c-4965-8adf-e528abedf7a4"
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://midpoint.evolveum.com/xml/ns/public/common/common-3'
xmlns:c='http://midpoint.evolveum.com/xml/ns/public/common/common-3'
xmlns:t='http://prism.evolveum.com/xml/ns/public/types-3'>

<name>User Template</name>
<iterationSpecification>
<maxIterations>99</maxIterations>
<tokenExpression>
<script>
<code>
if (iteration == 0) {
return "";
} else {
return "_"+iteration;
}
</code>
</script>
</tokenExpression>
<postIterationCondition>
<variable>
<name>givenName</name>
<path>$focus/givenName</path>
</variable>
<variable>
<name>familyName</name>
<path>$focus/familyName</path>
</variable>
<script>
<code>
import com.evolveum.midpoint.xml.ns._public.common.common_3.*
import com.evolveum.midpoint.schema.constants.*
import com.evolveum.midpoint.schema.*
import javax.xml.namespace.*
import com.evolveum.midpoint.util.*
import com.evolveum.midpoint.prism.path.*
import com.evolveum.midpoint.prism.polystring.*
import com.evolveum.midpoint.prism.PrismContainer.*

def nameunique = false
def uidunique = false
if (givenName == null || familyName == null) {
return true;
} else {
def testname = basic.norm(basic.stringify(givenName))?.tr(' ', '_') + '_' + basic.norm(basic.stringify(familyName))?.tr(' ', '_') + "" + iterationToken;
//log.info('post-iterate for name for {}', testname.toString());
//nameunique = midpoint.isUniquePropertyValue(focus, 'name', PolyString.fromOrig(testname.toString()));
nameunique = midpoint.isUniquePropertyValue(focus, 'name', PolyString.fromOrig(testname.toString()));
//midpoint.isUniquePropertyValue(focus, 'name', PolyString.fromOrig(testname.toString()));

def testuid = basic.norm(basic.stringify(givenName))?.tr(' ', '_').substring(0,1) + basic.norm(basic.stringify(familyName))?.tr(' ', '_') + "" + iterationToken;
//log.info('post-iterate for uid for {}', testname.toString());
//uidunique = midpoint.isUniquePropertyValue(focus, 'UserID', PolyString.fromOrig(testuid.toString()));
uidunique = midpoint.isUniquePropertyValue(focus, 'employeeNumber', testuid.toString());
}

return (nameunique &amp;&amp; uidunique)

</code>
</script>
</postIterationCondition>
</iterationSpecification>


<item>
<ref>name</ref>
<mapping>
<!--<trace>true</trace>-->
<strength>weak</strength>
<source>
<path>familyName</path>
</source>
<source>
<path>givenName</path>
</source>
<expression>
<script>
<language>http://midpoint.evolveum.com/xml/ns/public/expression/language#Groovy</language>
<code>
//log.info('mapping expression for {}', basic.norm(basic.stringify(givenName))?.tr(' ', '_') + '_' + basic.norm(basic.stringify(familyName))?.tr(' ', '_') + "" + iterationToken)
basic.norm(basic.stringify(givenName))?.tr(' ', '_') + '_' + basic.norm(basic.stringify(familyName))?.tr(' ', '_') + "" + iterationToken
</code>
</script>
</expression>
<condition>
<script>
<code>givenName != null &amp;&amp; familyName != null</code>
</script>
</condition>
</mapping>
</item>
<item>
<ref>employeeNumber</ref>
<mapping>
<!--<trace>true</trace>-->
<strength>weak</strength>
<source>
<path>familyName</path>
</source>
<source>
<path>givenName</path>
</source>
<expression>
<script>
<language>http://midpoint.evolveum.com/xml/ns/public/expression/language#Groovy</language>
<code>
tmpGivenName = basic.norm(basic.stringify(givenName))?.tr(' ', '_')
tmpFamilyName = basic.norm(basic.stringify(familyName))?.tr(' ', '_')
tmpGivenName.substring(0, 1) + tmpFamilyName + iterationToken
</code>
</script>
</expression>
<condition>
<script>
<code>givenName != null &amp;&amp; familyName != null</code>
</script>
</condition>
</mapping>
</item>

<mapping>
<strength>strong</strength>
<source>
<path>name</path>
<path>employeeNumber</path>
</source>
<expression>
<script>
Expand All @@ -35,13 +154,13 @@
.and().item(ShadowType.F_KIND).eq(ShadowKindType.ENTITLEMENT)
.and().item(ShadowType.F_INTENT).eq('group')
.and().block().item(ShadowType.F_DEAD).isNull().or().item(ShadowType.F_DEAD).eq(false).endBlock()
.and().item(ItemPath.create(ShadowType.F_ATTRIBUTES, MEMBER_NAME), memberDef).eq(basic.stringify(name))
.and().item(ItemPath.create(ShadowType.F_ATTRIBUTES, MEMBER_NAME), memberDef).eq(basic.stringify(employeeNumber))
.build()

//log.info('shadowQuery = {}\n{}', shadowQuery, shadowQuery.debugDump())
options = SelectorOptions.createCollection(GetOperationOptions.createNoFetch())
shadows = midpoint.searchObjects(ShadowType.class, shadowQuery, options)
//log.info('shadows found for {}: {}', name, shadows)
//log.info('shadows found for {}: {}', employeeNumber, shadows)

orgNames = shadows.collect { basic.stringify(it.name) } // todo - use attributes
log.info('org names = {}', orgNames)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@
<gen956:uidAttribute>nsUniqueId</gen956:uidAttribute>
<gen956:pagingStrategy>spr</gen956:pagingStrategy>
<gen956:baseContext>ou=Guests,dc=internet2,dc=edu</gen956:baseContext>
<!--<gen956:passwordHashAlgorithm>SSHA</gen956:passwordHashAlgorithm>-->
<gen956:pagingStrategy>spr</gen956:pagingStrategy>
<!--<gen956:vlvSortAttribute>uid</gen956:vlvSortAttribute>
<gen956:vlvSortOrderingRule>2.5.13.3</gen956:vlvSortOrderingRule>-->
<gen956:operationalAttributes>memberOf</gen956:operationalAttributes>
<gen956:operationalAttributes>createTimestamp</gen956:operationalAttributes>
<gen956:allowUnknownAttributes>true</gen956:allowUnknownAttributes>
Expand Down Expand Up @@ -114,7 +111,7 @@
<c:ref>ri:uid</c:ref>
<inbound id="34">
<target>
<c:path>name</c:path>
<c:path>extension/Guest_ID</c:path>
</target>
</inbound>
<inbound>
Expand Down Expand Up @@ -202,7 +199,7 @@
<enabled>true</enabled>
<correlation>
<q:equal>
<q:path>name</q:path>
<q:path>c:extension/Guest_ID</q:path>
<expression>
<path>
declare namespace ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<generationConstraints>
<generateObjectClass>ri:inetOrgPerson</generateObjectClass>
<generateObjectClass>ri:eduPerson</generateObjectClass>
<generateObjectClass>ri:incwbPerson</generateObjectClass>
<generateObjectClass>ri:organizationalPerson</generateObjectClass>
<generateObjectClass>ri:person</generateObjectClass>
<generateObjectClass>ri:groupOfUniqueNames</generateObjectClass>
Expand All @@ -76,6 +77,7 @@
<default>true</default>
<objectClass>ri:inetOrgPerson</objectClass>
<auxiliaryObjectClass>ri:eduPerson</auxiliaryObjectClass>
<auxiliaryObjectClass>ri:incwbPerson</auxiliaryObjectClass>
<attribute>
<ref>ri:dn</ref>
<displayName>Distinguished Name</displayName>
Expand All @@ -87,18 +89,12 @@
<outbound>
<strength>strong</strength>
<source>
<path>familyName</path>
</source>
<source>
<path>givenName</path>
<path>employeeNumber</path>
</source>
<expression>
<script>
<code>
tmpGivenName = basic.norm(basic.stringify(givenName))?.tr(' ', '.')
tmpFamilyName = basic.norm(basic.stringify(familyName))?.tr(' ', '.')
tmpuid = tmpGivenName.substring(0, 1) + tmpFamilyName + iterationToken
'uid=' + tmpuid + ',ou=People,dc=internet2,dc=edu'
'uid=' + employeeNumber + ',ou=People,dc=internet2,dc=edu'
</code>
</script>
</expression>
Expand All @@ -116,6 +112,48 @@
<source>
<path>fullName</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:incwbPersonStudentID</ref>
<displayName>Student ID</displayName>
<limitations>
<minOccurs>0</minOccurs>
</limitations>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>extension/SIS_ID</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:incwbPersonEmployeeID</ref>
<displayName>Employee ID</displayName>
<limitations>
<minOccurs>0</minOccurs>
</limitations>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>extension/HR_ID</path>
</source>
</outbound>
</attribute>
<attribute>
<ref>ri:incwbPersonGuestID</ref>
<displayName>Guest ID</displayName>
<limitations>
<minOccurs>0</minOccurs>
</limitations>
<tolerant>false</tolerant>
<outbound>
<strength>strong</strength>
<source>
<path>extension/Guest_ID</path>
</source>
</outbound>
</attribute>
<attribute>
Expand Down Expand Up @@ -154,20 +192,8 @@
<outbound>
<strength>strong</strength>
<source>
<path>familyName</path>
</source>
<source>
<path>givenName</path>
<path>employeeNumber</path>
</source>
<expression>
<script>
<code>
tmpGivenName = basic.norm(basic.stringify(givenName))?.tr(' ', '.')
tmpFamilyName = basic.norm(basic.stringify(familyName))?.tr(' ', '.')
return tmpGivenName.substring(0, 1) + tmpFamilyName + iterationToken
</code>
</script>
</expression>
</outbound>
</attribute>
<attribute>
Expand Down
Loading

0 comments on commit 4aaabfb

Please sign in to comment.