LDAP Attributes Access

I’ve seen a couple of threads (one that actually asked about the LDAP attribute I’m needing to extract) concerning accessing LDAP User Data. I’m wondering if any more capabilities have been added to the system.user.getUser function in later version to allow for extracting other data. The attribute I need to extract from the Active Directory User is the employee-ID attribute.

In the PyUser Class I see a lot of methods but nothing that screams “I can get the employee-ID data for you!”

Can this attribute’s data be gotten from this standard function?
If not, what is the suggested Python Library to import and use for this?
The Ignition version being used is 8.0.16.

Thanks.

I’m looking to grab a couple of attributes as well. Mine include the objectGUID and some custom entries. Replying here to ping this request.

This isn’t possible using Ignition’s built-in user source handling. Only the specific attributes listed in the user source’s properties will be attached to the created users.

You could theoretically come up with something via gateway scripting; the best entrypoint would probably be the LDAPHelper class. You’ll have to script the entire search process yourself, and doing so using the internal class would be officially unsupported.

If you don’t want to go down that road, I’d suggest an ideas post suggesting the ability to bring in arbitrary user properties via LDAP; we could theoretically expose some kind of configuration UI on the user sources to allow that.

Thanks for the reply. This was the road I was going down, but I thought I’d look before digging too deeply.
This has been on the Ideas list since 2015. Allow custom attributes to be pulled from the AD user source | Voters | Inductive Automation

1 Like

Ouch. I went ahead and filed an internal ticket from the ideas post; basically all that means is that it’ll get in front of the people who decide whether to implement a feature or not - so no promises, but this does seem like a reasonable thing to ask for.

Is the LDAPHelper class available as one of the pre-included modules? Or will it need to be manually installed?

It is available with the base ignition install.

ImportError: Error loading module myldap: ImportError: No module named LDAPHelper

LDAPHelper is a Java/Ignition class.
from com.inductiveautomation.ignition.gateway.authentication.impl import LDAPHelper
Would be the import path. In a gateway script execution context.

Perfect, thanks.

So, I’m trying to use the LDAPHelper class to retrieve custom LDAP attributes.
I was trying some basic stuff, but keep getting a java.lang.NullPointerException on the isUserValid() call. I was hoping someone might have a suggestion.

I’ve tried setting other properties on the instance, including auth type, referral type, etc. with the same result.

Any ideas?
Thanks.
-Shane

		from com.inductiveautomation.ignition.gateway.authentication.impl import LDAPHelper
		from com.inductiveautomation.ignition.common.util import LoggerEx
		
		builder = LoggerEx.newBuilder()
		logger = builder.build('integration.LDAP')

		instance = LDAPHelper(logger)

		instance.setLdapHost(PRIMARY_DOMAIN_CONTROLLER)
		instance.setLdapPort(DC_PORT)
		instance.setSecondaryLdapHost(SECONDARY_DOMAIN_CONTROLLER)
		instance.setSecondaryLdapPort(DC_PORT)
		instance.setUseSSL(False)

		valid = instance.isUserValid(SVC_USER, PASSWORD)

The exact NPE would help point you in the right direction.

Caused by: org.python.core.PyException: java.lang.NullPointerException: java.lang.NullPointerException

... 28 common frames omitted

Caused by: java.lang.NullPointerException: null

at com.inductiveautomation.ignition.gateway.authentication.impl.LDAPHelper.openContext(LDAPHelper.java:243)

at com.inductiveautomation.ignition.gateway.authentication.impl.LDAPHelper.isUserValid(LDAPHelper.java:315)

at jdk.internal.reflect.GeneratedMethodAccessor599.invoke(Unknown Source)

at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)

at java.base/java.lang.reflect.Method.invoke(Unknown Source)

at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:190)


Set a read timeout on your LDAPHelper instance.

Thank you so much. That got me past that hurdle. I had literally tried setting just about every other property from ‘SASL config’ to ‘Username Suffix’.

Thank you so much for your previous help. Hoping for help clearing one more hurdle:

The search() methods expect to be passed a SearchHandler. I’ve stubbed out what I think a class should look like for that handler. However, the create() method never gets called. init, beginBatch(), endBatch(), and getNoun() DO get called – although I’ve not quite puzzled out what they should be doing. The ctx they are called with appears valid, though the results list passed to endBatch() is empty.

		class mySearchHandlerClass(LDAPHelper.SearchHandler):
			def __init__(self):
				self.ctx = None
				self.result = None
				self.results = []
				return
			def create(self, ctx, result):
				self.ctx = ctx
				self.result = result
				return self
			def beginBatch(self, ctx):
				self.ctx = ctx
				return
			def endBatch(self, ctx, results):
				self.ctx = ctx
				self.results = results  # list
				return
			def getNoun(self):
				return 'foo'
		search_handler = mySearchHandlerClass()
		results = instance.search(bases, filter, filterArgs, search_handler)

create is called when the search operation produces results, and is supposed to return whatever result object you want to create. It’ll be called once per result row, so that the top level search method can return a list of whatever objects. You can set your logger to DEBUG or TRACE and see at least a confirmation that the query has started; but I suspect that create isn’t being called because something’s wrong with your query and it’s not returning any results.

Thank you for your patience and help. You were right in that something was wrong with my query.
I assumed that the bases list wanted me to split it up, ie. [ ‘DC=foo’, ‘DC=com’ ], when it wanted them as a single string, ie. [ ‘DC=foo,DC=com’ ]
Thanks so much for pointing me in the right direction. I’m getting back results now which include the custom attribute I was looking for.

1 Like

I was able to replicate this work by @ShaneH. However I had to remove beginBatch and endBatch from the mySearchHandlerClass class. Otherwise I would get an “Illegal use of nonvirtual function call” error. The LDAPHelper class also requires the setPageSize(1000) otherwise the search won’t return anything.