Skip to Content.
Sympa Menu

grouper-users - [grouper-users] ldapGroupUserConverter Not Converting DNs to Subject Identifiers

Subject: Grouper Users - Open Discussion List

List archive

[grouper-users] ldapGroupUserConverter Not Converting DNs to Subject Identifiers


Chronological Thread 
  • From: Tim Watts <>
  • To:
  • Subject: [grouper-users] ldapGroupUserConverter Not Converting DNs to Subject Identifiers
  • Date: Mon, 07 May 2018 20:03:43 +0000
  • Ironport-phdr: 9a23:zbyeABwdocpNH7vXCy+O+j09IxM/srCxBDY+r6Qd1OIWIJqq85mqBkHD//Il1AaPAd2Araocw8Pt8InYEVQa5piAtH1QOLdtbDQizfssogo7HcSeAlf6JvO5JwYzHcBFSUM3tyrjaRsdF8nxfUDdrWOv5jAOBBr/KRB1JuPoEYLOksi7ze+/94HdbglSmDaxfa55IQmrownWqsQYm5ZpJLwryhvOrHtIeuBWyn1tKFmOgRvy5dq+8YB6/ShItP0v68BPUaPhf6QlVrNYFygpM3o05MLwqxbOSxaE62YGXWUXlhpIBBXF7A3/U5zsvCb2qvZx1S+HNsDwULs6Wymt771zRRDniCkJOT03/nzJhMNsl69bug6tqgZlzoLIfI2YNvxzdb7dc9MAQmpBW95cWTJAAoO5coAAD/AOPfpEr4nmulADqhW/ChOwBOPz0T9FnWL23asm3Os7Cw3JwhEvH88XvXnSsd77OqASUeWvw6nJyzXOd+5W2THh54fSaBwuv+yDXa9ofcrK1UYvFwTFjlKUqYD/ITyay/kNvm6G5ORjTeKik3ArpgBtrjWtw8oshIrEiZkJxl3B+ih13Jo5KNO9RUFnfdKkHp5duiSEO4Z4XM8vRXxjtjwgxb0co5G7eTAHyJQ5yB7bbPyKa42I7QjiVOaVODt4g25ldK6mixe970StxPPwWtO70FZNqSpFnd3MuW4X2xPP7ciHT+Nx/kan2TmRywDe8v9ILEEomafZLpMhzL09mYEPvUnGESL6hFn6gaGTe0o45uSo5eHqb7D4qpKSKYN4kgT+Pb4vmsy7D+Q4KA8OX22D9OWyzrLj4VH5QK5Rg/0rlKnWrIrVKd4FqaGkHg9Zypwj5AqnDze6zNQYmmEKLF1feBKAkojpI0/BIOrhAfeimFSjji1rx+vdM73lA5XNNWTDkKz/cbpn6k5czhYzws5F55JSFL4BPOz/VlXvu9PFEx9qezCzlun9D8hl25lbRHmCGLSxMaXOvEWO6/51ZeSAedw7ojH4fsQk4rbRhGMlghdJYqC1wYA/dXazF7JrL1jPMimkucsIDWpf5ll2d+ftklDXCTM=

Greetings,

I am experiencing an issue with my Grouper install in which the ldapGroupUserConverter is not converting DNs to a subject identifier, but to the DN itself.

I am receiving the following error in the error log:
2018-05-07 15:49:00,327: [DefaultQuartzScheduler_Worker-9] DEBUG GrouperLoaderResultset$1.callback(763) -  - Found 1 results, (1 sub-results) for serverId: uncanet, searchDn: OU=Shared Accounts,OU=PaperCut,OU=AuxiliaryServices, filter: '(&(objectClass=group)(cn=PCSA-999999))', returning subject attribute: member, some results: {UNCA:PaperCut:PCSA-999999=[CN=watts,CN=Users,DC=uncanet,DC=unca,DC=edu]}
2018-05-07 15:49:00,328: [DefaultQuartzScheduler_Worker-9] DEBUG LdapGroupUserConverter.convertDntoSubjectIdOrIdentifier(60) -  - Converting dn 'CN=watts,CN=Users,DC=uncanet,DC=unca,DC=edu' to: 'CN=watts,CN=Users,DC=uncanet,DC=unca,DC=edu'
2018-05-07 15:49:00,328: [DefaultQuartzScheduler_Worker-9] DEBUG GrouperLoaderResultset.convertToSubjectIdIfNeeded(1188) -  - Converted subject id from 'CN=watts,CN=Users,DC=uncanet,DC=unca,DC=edu' to 'CN=watts,CN=Users,DC=uncanet,DC=unca,DC=edu' based on subjectExpression: '${ldapGroupUserConverter.convertDntoSubjectIdOrIdentifier(subjectId)}'
2018-05-07 15:49:00,329: [DefaultQuartzScheduler_Worker-9] INFO  EventLog.info(156) -  - [79ee2b26848f4be2af01bf7ddc804182,'GrouperSystem','application'] session: start (1ms)
2018-05-07 15:49:00,334: [DefaultQuartzScheduler_Worker-9] WARN  GrouperLoaderResultset$Row.getSubject(1379) -  - Subject is unresolvable 'CN=watts,CN=Users,DC=uncanet,DC=unca,DC=edu' col: subjectIdentifier, jobName: LDAP_GROUP_LIST__UNCA:loaderGroups:loaderPaperCutSharedAccounts__7bb40f661400407c84edfd37fb731b79

I can search for the account in the Grouper Shell and resolve the account by the attribute I have set in sources.xml.

The loader group configuration:
image.png

The JNDI Adapter in sources.xml (sanitized):
<source adapterClass="edu.internet2.middleware.grouper.subj.GrouperJndiSourceAdapter">
    <id>uncanet</id>
    <name>uncanet</name>
    <type>person</type>
    <init-param>
      <param-name>INITIAL_CONTEXT_FACTORY</param-name>
      <param-value>com.sun.jndi.ldap.LdapCtxFactory</param-value>
    </init-param>
    <init-param>
      <param-name>PROVIDER_URL</param-name>
      <param-value>ldap://uncanet.unca.edu:389</param-value>
    </init-param>
    <init-param>
      <param-name>SECURITY_AUTHENTICATION</param-name>
      <param-value>simple</param-value>
    </init-param>
    <init-param>
      <param-name>SECURITY_PRINCIPAL</param-name>
      <param-value></param-value>
    </init-param>
    <init-param>
      <param-name>SECURITY_CREDENTIALS</param-name>
      <param-value></param-value>
    </init-param>
     <init-param>
      <param-name>SubjectID_AttributeType</param-name>
      <param-value>employeeid</param-value>
    </init-param>
     <init-param>
      <param-name>SubjectID_formatToLowerCase</param-name>
      <param-value>false</param-value>
    </init-param>
    <init-param>
      <param-name>Name_AttributeType</param-name>
      <param-value>displayname</param-value>
    </init-param>
    <init-param>
      <param-name>Description_AttributeType</param-name>
      <param-value>displayname</param-value>
    </init-param>
<!--
    <init-param>
      <param-name>VTLDAP_VALIDATOR</param-name>
      <param-value>ConnectLdapValidator|CompareLdapValidator</param-value>
    </init-param>
    <init-param>
      <param-name>VTLDAP_VALIDATOR_COMPARE_DN</param-name>
      <param-value>ou=People,dc=vt,dc=edu</param-value>
    </init-param>
    <init-param>
      <param-name>VTLDAP_VALIDATOR_COMPARE_SEARCH_FILTER_STRING</param-name>
      <param-value>ou=People</param-value>
    </init-param>
-->    
    /// Scope Values can be: OBJECT_SCOPE, ONELEVEL_SCOPE, SUBTREE_SCOPE 
    /// For filter use 
    
    <search>
        <searchType>searchSubject</searchType>
        <param>
            <param-name>filter</param-name>
            <param-value>
                (&amp; (employeeid=%TERM%) (objectclass=user))
            </param-value>
        </param>
        <param>
            <param-name>scope</param-name>
            <param-value>
                SUBTREE_SCOPE            
            </param-value>
        </param>
        <param>
            <param-name>base</param-name>
            <param-value>
                cn=users,dc=uncanet,dc=unca,dc=edu
            </param-value>
        </param>
         
    </search>
    <search>
        <searchType>searchSubjectByIdentifier</searchType>
        <param>
            <param-name>filter</param-name>
            <param-value>
                (&amp; (cn=%TERM%) (objectclass=user))
            </param-value>
        </param>
        <param>
            <param-name>scope</param-name>
            <param-value>
                SUBTREE_SCOPE            
            </param-value>
        </param>
        <param>
            <param-name>base</param-name>
            <param-value>
                cn=users,dc=uncanet,dc=unca,dc=edu
            </param-value>
        </param>
    </search>
    
    <search>
       <searchType>search</searchType>
         <param>
            <param-name>filter</param-name>
            <param-value>
                (&amp; (|(samaccountname=%TERM%)(cn=*%TERM%*)(employeeid=%TERM%)(distinguishedName=%TERM%)(mail=%TERM%))(objectclass=user))
            </param-value>
        </param>
        <param>
            <param-name>scope</param-name>
            <param-value>
                SUBTREE_SCOPE            
            </param-value>
        </param>
         <param>
            <param-name>base</param-name>
            <param-value>
                cn=users,dc=uncanet,dc=unca,dc=edu
            </param-value>
        </param>
    </search>
    <init-param>
      <param-name>subjectVirtualAttribute_0_searchAttribute0</param-name>
      <param-value>${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('samaccountname'), "")},${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('cn'), "")},${subjectUtils.defaultIfBlank(subject.getAttributeValueOrCommaSeparated('employeeid'), "")}</param-value>
    </init-param>
    <init-param>
      <param-name>sortAttribute0</param-name>
      <param-value>cn</param-value>
    </init-param>
    <init-param>
      <param-name>searchAttribute0</param-name>
      <param-value>searchAttribute0</param-value>
    </init-param>

     <!-- ##########################  STATUS SECTION for searches to filter out inactives and allow
                                                     the user to filter by status with e.g. status=all
                                                     this is optional, and advanced - -> 
     <!- - column or attribute which represents the status - - >
     <!- -
     <init-param>
       <param-name>statusDatastoreFieldName</param-name>
       <param-value>status</param-value>
     </init-param> - - >
     <!- - search string from user which represents the status.  e.g. status=active - - >
     <!- -
     <init-param>
       <param-name>statusLabel</param-name>
       <param-value>status</param-value>
     </init-param> - - >
     <!- - available statuses from screen (if not specified, any will be allowed). comma separated list.
          Note, this is optional and you probably dont want to configure it, it is mostly necessary
          when you have multiple sources with statuses...  if someone types an invalid status
          and you have this configured, it will not filter by it - - >
     <!- - 
     <init-param>
       <param-name>statusesFromUser<param-name>
       <param-value>Active, Inactive, Pending, All</param-value>
     </init-param> - - >
     <!- - all label from the user - - >
     <!- -
     <init-param>
       <param-name>statusAllFromUser</param-name>
       <param-value>All</param-value>
     </init-param> - - >
     <!- - if no status is specified, this will be used (e.g. for active only).  Note, the value should be of the
          form the user would type in - - >
     <!- - 
     <init-param>
       <param-name>statusSearchDefault</param-name>
       <param-value>status=active</param-value>
     </init-param> - - >
     <!- - translate between screen values of status, and the data store value.  Increment the 0 to 1, 2, etc for more translations.
          so the user could enter: status=active, and that could translate to status_col=A.  The 'user' is what the user types in,
          the 'datastore' is what is in the datastore.  The user part is not case-sensitive.  Note, this could be a many to one - - >
     <!- -
     <init-param>
       <param-name>statusTranslateUser0</param-name>
       <param-value>active</param-value>
     </init-param>
     <init-param>
       <param-name>statusTranslateDatastore0</param-name>
       <param-value>A</param-value>
     </init-param> - - >
     <!- - ########################## END STATUS SECTION --> 


    <internal-attribute>searchAttribute0</internal-attribute>

    ///Attributes you would like to display when doing a search 
    <attribute>displayname</attribute>
    <attribute>samaccountname</attribute>
    <attribute>cn</attribute>
    <attribute>department</attribute>
    <attribute>employeeid</attribute>
    <attribute>mail</attribute>

    <!-- subject identifier to store in grouper's member table - - >
    <init-param>
      <param-name>subjectIdentifierAttribute0</param-name>
      <param-value>guid</param-value>
    </init-param>
    -->
   
  </source>

The grouper-loader.properties configuration (sanitized):
#################################
## LDAP connections
#################################
# specify the ldap connection with user, pass, url
# the string after "ldap." is the ID of the connection, and it should not have
# spaces or other special chars in it.  In this case is it "personLdap"

#note the URL should start with ldap: or ldaps: if it is SSL.  
#It should contain the server and port (optional if not default), and baseDn, 

# load this vt-ldap config file before the configs here.  load from classpath
#ldap.personLdap.configFileFromClasspath = ldap.personLdap.properties

#optional, if authenticated
ldap.uncanet.user = 

#optional, if authenticated, note the password can be stored encrypted in an external file
ldap.uncanet.pass = 

#optional, if you are using tls, set this to true.  Generally you will not be using an SSL URL to use TLS...
#ldap.personLdap.tls = false

#optional, if using sasl
#ldap.personLdap.saslAuthorizationId = 
#ldap.personLdap.saslRealm = 

#optional (note, time limit is for search operations, timeout is for connection timeouts), 
#most of these default to vt-ldap defaults.  times are in millis
#validateOnCheckout defaults to true if all other validate methods are false
#ldap.personLdap.batchSize = 
#ldap.personLdap.countLimit = 
#ldap.personLdap.timeLimit = 
#ldap.personLdap.timeout = 
#ldap.personLdap.minPoolSize = 
#ldap.personLdap.maxPoolSize = 
#ldap.personLdap.validateOnCheckIn = 
#ldap.personLdap.validateOnCheckOut = 
#ldap.personLdap.validatePeriodically = 
#ldap.personLdap.validateTimerPeriod = 
#ldap.personLdap.pruneTimerPeriod = 
# if there is a max size limit on ldap server, then this will retrieve results in pages
ldap.uncanet.pagedResultsSize = 1000
# set to 'follow' if using AD and using paged results size and need this for some reason (generally you shouldnt)
ldap.uncanet.referral = follow

##################################
## LDAP loader settings
##################################

# el classes to add to the el context for the EL to calculate subejct ids or group names etc.  
# Comma-separated fully qualified classnamesm will be registered by the non-fully qualified
# uncapitalized classname.  So you register a.b.SomeClass, it will be available by variable: someClass
loader.ldap.el.classes = ldapGroupUserConverter.LdapGroupUserConverter


# by default the top folder for an ldap group of groups is the folder where the config group lives.
# set to false if you want to be able to provision groups to anywhere
loader.ldap.requireTopStemAsStemFromConfigGroup = false



Am I missing something in the configuration for the ldapGroupUserConverter to convert to the DN to something other than itself?

Thanks in advance for the assistance.

Tim Watts
--------------------------------------------
Director of Auxiliary Services
Information Technology
UNC at Asheville
Office: 828.250.3869

"Well done is better than well said." - Benjamin Franklin


  • [grouper-users] ldapGroupUserConverter Not Converting DNs to Subject Identifiers, Tim Watts, 05/07/2018

Archive powered by MHonArc 2.6.19.

Top of Page