By: Jordan Goldman user 04 Apr 2019 at 3:47 p.m. CDT

20 Responses
Jordan Goldman gravatar
The two links in the installation instructions for multi_auth_conf are broken, and we can't seem to find a mirror of it anywhere, so we're not sure how to install it properly: https://github.com/GluuFederation/oxAuth/blob/master/Server/integrations/basic.multi_auth_conf/INSTALLATION.txt#L16 We have one ActiveDirectory server and one OpenLDAP server, and we're trying to enable authentication through both, but the custom script keeps disabling itself and we get the following error: ``` org.xdi.exception.PythonException: Failed to load python file 'java.io.ByteArrayInputStream@7f6d7c3e' at org.xdi.service.PythonService.loadPythonScript(PythonService.java:182) at org.xdi.service.PythonService$Proxy$_$$_WeldClientProxy.loadPythonScript(Unknown Source) at org.xdi.service.custom.script.CustomScriptManager.createExternalTypeFromStringWithPythonException(CustomScriptManager.java:383) at org.xdi.service.custom.script.CustomScriptManager$Proxy$_$$_WeldSubclass.createExternalTypeFromStringWithPythonException(Unknown Source) at org.xdi.service.custom.script.CustomScriptManager.createExternalType(CustomScriptManager.java:351) at org.xdi.service.custom.script.CustomScriptManager.reloadCustomScriptConfigurations(CustomScriptManager.java:261) at org.xdi.service.custom.script.CustomScriptManager.reloadImpl(CustomScriptManager.java:158) at org.xdi.service.custom.script.CustomScriptManager.reload(CustomScriptManager.java:145) at org.xdi.service.custom.script.CustomScriptManager.reloadTimerEvent(CustomScriptManager.java:121) at org.xdi.service.custom.script.CustomScriptManager$Proxy$_$$_WeldSubclass.reloadTimerEvent(Unknown Source) at sun.reflect.GeneratedMethodAccessor99.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:95) at org.jboss.weld.injection.StaticMethodInjectionPoint.invoke(StaticMethodInjectionPoint.java:85) at org.jboss.weld.injection.MethodInvocationStrategy$SimpleMethodInvocationStrategy.invoke(MethodInvocationStrategy.java:129) at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:330) at org.jboss.weld.event.ObserverMethodImpl.sendEvent(ObserverMethodImpl.java:308) at org.jboss.weld.event.ObserverMethodImpl.notify(ObserverMethodImpl.java:286) at javax.enterprise.inject.spi.ObserverMethod.notify(ObserverMethod.java:124) at org.jboss.weld.util.Observers.notify(Observers.java:166) at org.jboss.weld.event.ObserverNotifier.notifySyncObservers(ObserverNotifier.java:285) at org.jboss.weld.event.ObserverNotifier.notify(ObserverNotifier.java:273) at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:177) at org.jboss.weld.event.ObserverNotifier.fireEvent(ObserverNotifier.java:159) at org.jboss.weld.manager.BeanManagerImpl.fireEvent(BeanManagerImpl.java:632) at org.jboss.weld.util.ForwardingBeanManager.fireEvent(ForwardingBeanManager.java:104) at org.xdi.service.timer.TimerJob.execute(TimerJob.java:37) at org.xdi.service.timer.JobExecutionDelegate.execute(JobExecutionDelegate.java:29) at org.xdi.service.timer.JobExecutionDelegate$Proxy$_$$_WeldClientProxy.execute(Unknown Source) at org.quartz.core.JobRunShell.run(JobRunShell.java:202) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) Caused by: Traceback (most recent call last): File "multi_auth_conf.py", line 7, in <module> ImportError: No module named service at org.python.core.Py.ImportError(Py.java:334) at org.python.core.imp.import_logic(imp.java:913) at org.python.core.imp.import_module_level(imp.java:970) at org.python.core.imp.importName(imp.java:1057) at org.python.core.ImportFunction.__call__(__builtin__.java:1280) at org.python.core.PyObject.__call__(PyObject.java:450) at org.python.core.__builtin__.__import__(__builtin__.java:1232) at org.python.core.imp.importFromAs(imp.java:1149) at org.python.core.imp.importFrom(imp.java:1124) at org.python.pycode._pyx19.f$0(multi_auth_conf.py:21) at org.python.pycode._pyx19.call_function(multi_auth_conf.py) at org.python.core.PyTableCode.call(PyTableCode.java:171) at org.python.core.PyCode.call(PyCode.java:18) at org.python.core.Py.runCode(Py.java:1614) at org.python.util.PythonInterpreter.execfile(PythonInterpreter.java:296) at org.xdi.service.PythonService.loadPythonScript(PythonService.java:179) ... 31 more ==================Further details============================ Failed to load python file 'java.io.ByteArrayInputStream@7f6d7c3e' ``` We're currently on the community edition, but if we can get Gluu working properly to authenticate against two ldap servers, our management will likely want to upgrade to the enterprise version. Thank you!

By Mohib Zico Account Admin 04 Apr 2019 at 4:22 p.m. CDT

Mohib Zico gravatar
Hi Jordan, Please allow me to go over doc and script a bit, I'll get back to you.

By Mohib Zico Account Admin 05 Apr 2019 at 9:09 a.m. CDT

Mohib Zico gravatar
Jordan, Can you please try to use [this](https://raw.githubusercontent.com/GluuFederation/oxAuth/version_3.1.6/Server/integrations/basic.multi_auth_conf/BasicMultiAuthConfExternalAuthenticator.py) script? Seems like this is working for me: ``` 2019-04-05 14:03:23,916 INFO [oxAuthScheduler_Worker-2] [org.xdi.service.PythonService$PythonLoggerOutputStream] (PythonService.java:239) - Basic (multi auth conf). Initialization 2019-04-05 14:05:24,082 INFO [oxAuthScheduler_Worker-2] [org.xdi.service.PythonService$PythonLoggerOutputStream] (PythonService.java:239) - Basic (multi auth conf). Initialized successfully ``` I am also attaching screenshot from config, there is nothing fancy here... - Add your backend server's info like this way: ``` root@localhost:~# cat /etc/certs/multi_auth_conf.json { "ldap_configuration": [ { "configId":"ad_1", "servers":["localhost:1389"], "bindDN":"cn=directory manager", "bindPassword":"FUVOklq6JdxVsyb2aYJdaQ==", "useSSL":false, "maxConnections":3, "baseDNs":["ou=people,o=gluu"], "loginAttributes":["uid"], "localLoginAttributes":["uid"] }, { "configId":"ad_2", "servers":["localhost:2389"], "bindDN":"cn=directory manager", "bindPassword":"FUVOklq6JdxVsyb2aYJdaQ==", "useSSL":false, "maxConnections":3, "baseDNs":["ou=people,o=gluu"], "loginAttributes":["mail"], "localLoginAttributes":["mail"] } ] } root@localhost:~# ``` - Add script and configuration from oxTrust ( GUI ). Screenshot attached. - 'Enable' it.

By Jordan Goldman user 09 Apr 2019 at 5:53 p.m. CDT

Jordan Goldman gravatar
Thanks Mohib, I installed the script you attached and it is no longer throwing any errors, though I've not been able to get authentication working through the second server yet. I scheduled some time to chat with you guys next Monday, so hopefully we can get it resolved then. Thanks!

By Aliaksandr Samuseu staff 11 Apr 2019 at 11:24 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Jordan. Could you share next items we need to understand your current configuration? Could save a lot of time during the call I believe you already have arranged. Next items would be appreciated: 1. Your current `/etc/certs/multi_auth_conf.json` file; you can strip sensitive data from it (password, bind DNs etc), if needed 2. Your settings from "Manage Authentication" page (screenshot will do; fill free to censor sensitive parts as well) 3. Your settings from "Cache Refresh" page (all tabs except the last one, sreenshots again) Overall, a few things to keep in mind when using this script: 1. "bindPassword" property must not contain cleartext bind password, but instead output of this command: `# /opt/gluu/bin/encode.py YOUR_CLEARTEXT_BIND_PASSWORD` 2. In case of any issues with particular backend server, setting "useSSL" to `false` is recommended, to rule out possible issues with setting up SSL layer (certificates-related, mostly) - assuming this server allows unencrypted connections; don't forget to also change port in "servers" property in such case 3. Don't forget that your Cache Refresh configuration must mirror the one used by the script; thus if you have 2 backend directories, you must ensure CR will pull user entries in from both; the script will still check whether a locally cached entry exists for an user, and authentication will fail if it doesn't

By Jordan Goldman user 12 Apr 2019 at 12:23 p.m. CDT

Jordan Goldman gravatar
Absolutely - I went ahead and rescheduled our meeting for Wednesday at 2:30 in order to give me a bit more time to get these things over to you and make sure we're prepared. I'll try to get this to you by EOB, or Monday at the latest.

By Jordan Goldman user 15 Apr 2019 at 3:49 p.m. CDT

Jordan Goldman gravatar
Hi Aliaksandr, the requested files & screenshots are available here: http://alwaysmanaged.com/files/gluu/. The passwords, though removed, are indeed encrypted and we have SSL temporarily disabled for testing. Both the AD and LDAP server are configured in both the Cache Refresh configuration and the Authentication configuration, though we are seeing a certain number of errors on the import. I suspect the Gluu log file might also be helpful, since we're getting some errors? Let me know if you'd like me to send that over to your support email. Thanks! Jordan

By Aliaksandr Samuseu staff 15 Apr 2019 at 6:30 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Jordan. Thanks for the data. Are you sure that CR is functioning, in general? Like, can you confirm that local copies of user entries from **both** your LDAP backends are created (at least, for most of them)? I see 480 on error counter on your screenshot, for example. One thing I noticed is that you may use DNS names when specifying your LDAP backends. I would suggest to either use ip addresses everywhere instead, until you'll get working configuration, or at least make sure all those DNS names are resolvable **from inside the container** (try to ping them from inside of it). Another thing is that apparently your LDAP backends rely on different key attributes - `uid` and `samaccountname`. Though during authentication you may use a different key attribute per each backend, Cache Refresh still relies on some universally unique key attribute used to consolidate arrays of user data received from different sources into sort of one meta-array of entries. That's why it won't allow you to specify per-server "Key Attribute", instead for CR you specify it once for all backends at "Customer Backend Key / Attributes" tab - and you have "saMAccountName" there, what will not work for the other your backend server (OpenLDAP), unless you added "saMAccountName" to schema there and populated it for all user entries. Thus I suppose you may not receiving any user data from that server as nothing is returned for a search like `&(samaccountname=*)` from there (you can confirm it by searching Gluu Server's internal directory). Here is the problem: before even approaching the authentication against several backends, we first must resolve all issues with CR and ensure user entries are imported from both servers. Will be much easier to attend one issue at a time. Lastly, if you are using the script already, you don't need the same LDAP backend servers added separately at "Manage authentication" page, as they will be directly queried from the script. Though I believe in such case configuration done from web UI will be by-passed, I would still suggest to remove those 2 extra entries you added, leaving only the defaut one ("auth_ldap_server"). >I suspect the Gluu log file might also be helpful, since we're getting some errors? Let me know if you'd like me to send that over to your support email. That would help, indeed, thanks. You can send them to `alex@gluu.org`. In such case may I also ask you to visit "JSON configuration" page and make sure "loggingLevel" property is set to DEBUG for both oxTrust and oxAuth? Logs we would need are listed below: - `/opt/gluu/jetty/oxauth/logs/oxauth_script.log` - `/opt/gluu/jetty/oxauth/logs/oxauth.log` - `/opt/gluu/jetty/identity/logs/oxtrust_cache_refresh.log` Btw, do you have any CR custom scripts in use, by any chance? They may have significant impact on how imported entries are handled.

By Aliaksandr Samuseu staff 15 Apr 2019 at 6:34 p.m. CDT

Aliaksandr Samuseu gravatar
Done a few ninja-edits to my previous post, please check the updated version at support boards.

By Jordan Goldman user 15 Apr 2019 at 6:38 p.m. CDT

Jordan Goldman gravatar
Excellent, thanks Aliaksandr! I'll review all this first thing in the morning and get back to you. -Jordan

By Jordan Goldman user 16 Apr 2019 at 5:41 p.m. CDT

Jordan Goldman gravatar
Hi Aliaksandr, Cache Refresh appears to be working for the AD server, but not the LDAP server. I'm launching another VM right now and installing Gluu so I can make sure it's not something that went wrong on this particular server. I think the issue is likely with the Backend Key/Attributes -- do you mean that whichever attribute we choose as the Key Attribute has to exist in both the AD server and the LDAP server? I tried using sAMAccountName *and* uid, and then each one separately, and it didn't seem to make a difference. I noticed that 'cacheRefreshEnabled' on the JSON Configuration -> oxTrust Configuration page is set to 'false', and when I set it to true, if I refresh a few seconds later, it's set itself back to false. I'll let you know if that behavior continues on the new server I'm setting it up. Best, Jordan

By Aliaksandr Samuseu staff 16 Apr 2019 at 6:35 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Jordan. >do you mean that whichever attribute we choose as the Key Attribute has to exist in both the AD server and the LDAP server? Yes, that's it. You need to ensure there is attribute in both servers you can use as a universal key, and its values must be unique across all those servers. >I tried using sAMAccountName and uid, and then each one separately, and it didn't seem to make a difference Unless one of those exists on user entries in **both** servers, it won't work. >I noticed that 'cacheRefreshEnabled' on the JSON Configuration -> oxTrust Configuration page is set to 'false', and when I set it to true, if I refresh a few seconds later, it's set itself back to false. I'll check it out, seems strange. Still, you should enable CR using corresponding control on its own configuration page, it should be enough.

By Jordan Goldman user 17 Apr 2019 at 12:42 p.m. CDT

Jordan Goldman gravatar
Thanks Aliaksandr, I think I'm getting closer, and it appears that it's now importing from both the AD and LDAP server (it's been running for around 45 minutes), but I'm getting a lot of these: 2019-04-17 10:37:49,726 ERROR [ForkJoinPool.commonPool-worker-1] [gluu.oxtrust.ldap.cache.service.CacheRefreshTimer] (CacheRefreshTimer.java:691) - Failed to 'add' person '@!0A2E.7B75.67C6.1F70!0001!D313.6C94!0000!020B.91E9' org.gluu.site.ldap.exception.DuplicateEntryException: Entry already exists: Duplicate UID value: null There are also a lot of, what appears to be, successful adds, like the following, and the user count in o=gluu is growing: 2019-04-17 10:38:25,528 DEBUG [ForkJoinPool.commonPool-worker-1] [gluu.oxtrust.ldap.cache.service.CacheRefreshTimer] (CacheRefreshTimer.java:688) - Added new person '@!0A2E.7B75.67C6.1F70!0001!D313.6C94!0000!08BA.2DAB' I have debug logging enabled, but I'm not exactly sure what the duplicate UID value error is complaining about. How can I narrow that down a bit? Edit: usernames (uids) are the same in both AD and LDAP, so it occurs to me that it might be adding one user (from either AD or LDAP), and then throwing a duplicate error when it tries to add the same user from the other server. It's adding the AD users with the domain in front (ADNAME\uid) though, so I'm not sure what it's looking at that makes it think it's a duplicate though. I'll attach updated screenshots in a moment. Thanks! Jordan

By Jordan Goldman user 17 Apr 2019 at 1:06 p.m. CDT

Jordan Goldman gravatar
Here are screenshots of the updated configuration: http://alwaysmanaged.com/files/gluu/server2/ It's still running, but it looks like it is indeed only adding one user per uid (i.e. if it added the ADNAME\abc123 version, it doesn't add the abc123 version from LDAP, and vice versa). How can I configure it so that it won't think they're duplicates? Best, Jordan

By Jordan Goldman user 19 Apr 2019 at 11:17 a.m. CDT

Jordan Goldman gravatar
Hi Aliaksandr, I discussed with our team and our requirements changed a little bit, so I spent some time reconfiguring Gluu how we need it, and I think I have Cache Refresh & Authentication working as expected -- all the users are imported and I am able to authenticate to Gluu via both the admin user and all the imported users. My last question is about external authentication -- I'm trying to set up a linux server to authenticate through Gluu, but I realized that the OpenDJ ports (1389 and 1636) are only listening locally, so nothing can query it. How can I go about making it listen on 0.0.0.0 so that we can set up sssd, or similar software, to authenticate via our Gluu server? Or should I be going about this a different way? Is this just a matter of changing idpLdapServer in the oxTrust Configuration from localhost:1636 to 0.0.0.0:1636 and restarting Gluu? Thanks! Jordan

By Aliaksandr Samuseu staff 19 Apr 2019 at 2:45 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Jordan. Glad to know it's working now. A few comments on previous issues you mentioned, first. >It's still running, but it looks like it is indeed only adding one user per uid (i.e. if it added the ADNAME\abc123 version, it doesn't add the abc123 version from LDAP, and vice versa). How can I configure it so that it won't think they're duplicates? >usernames (uids) are the same in both AD and LDAP, so it occurs to me that it might be adding one user (from either AD or LDAP), and then throwing a duplicate error when it tries to add the same user from the other server. It's adding the AD users with the domain in front (ADNAME\uid) though, so I'm not sure what it's looking at that makes it think it's a duplicate though. Your understanding seems spot on. CR basically just consolidates users from several LDAP backends into one array of cached user entries stored locally in Gluu's internal LDAP server. You are in control of which attribute of an remote user entry will be mapped to a certain attribute of the cached local entry. The easiest way to do it is via mappings on the main tab of "Cache Refresh" page. That's why requirement about all remote directories having one common attribute with values unique across all of them exist. That attribute is called "key attribute", and it's then usually mapped to local "uid" attribute, as, by default, OpenDJ enforces uniqueness of "uid", thus it just a natural thing to do. It's not set in stone necessarily, but it's a recommended way to do it, still. It also doesn't mean you can only use "uid" for authentication later on (you can use email, or some other attribute), it's more about how CR handles its own task of creating and managing local cache of user entries. From our past experiences with projects involving several LDAP backends, we saw our customers either using attributes like UPN (User Principal Name) when all backends are AD servers from different domains (you can't use saMAccountName in this case as it's only unique within a domain, but UPN is globally unique as it's scoped), or just creating same custom attribute in all of their LDAP backends with some numeric ID value which is assigned to every user in them by some automated routine, ensuring its global uniqueness. Using email attribute usually present on user entries in every LDAP server implementation mapped to "uid" in Gluu Server was also tried, I believe. Thus actual value is not that important, until it's unique.

By Aliaksandr Samuseu staff 19 Apr 2019 at 3:33 p.m. CDT

Aliaksandr Samuseu gravatar
Regarding your last question: >I'm trying to set up a linux server to authenticate through Gluu, but I realized that the OpenDJ ports (1389 and 1636) are only listening locally, so nothing can query it. Correct, it was decided it will be more secure this way. Normally, you don't need for this server to be accessible from the outside world, so I would at least recommend to reconsider your approach to the task which requires you to open that access. We could try to suggest you an alternative, if you would provide more context on it. Specifically, this part: > I'm trying to set up a linux server to authenticate through Gluu Could you describe this use case in more details? >Or should I be going about this a different way? If I understand your use case correctly, I don't think there is another way. Frankly speaking, Gluu Server is designed to handle authentication in WWW world, i.e. it's expected it will be used in conjunction with web services, and users will interact with it via web browser. I don't think its main features will be suitable as authentication mechanism for sshd, or linux login. You can still use its internal LDAP directory as authentication mechanism, of course, but I'm not sure how it all synergizes with your previous efforts to configure authentication against external LDAP directories in Gluu Server itself. You won't be able to use this configuration to authenticate users loging in to sshd, for example, as sshd will be talking directly to OpenDJ, while what you configured on "Manage authentication" page before is implemented by oxAuth (a more high-level component, so to say) and only is engaged for web authentication flows. CR doesn't store passwords of users it imports from external LDAP servers, so you won't be able to use those locally cached entries for authentication. Answering the question, still: >How can I go about making it listen on 0.0.0.0 so that we can set up sssd, or similar software, to authenticate via our Gluu server? 1. Move into container 2. Run this command to change ip address for LDAPS listener: `# /opt/opendj/bin/dsconfig set-connection-handler-prop --hostname localhost --port 4444 --bindDN "cn=Directory Manager" --bindPassword YOUR_LDAP_ADMIN_PASS --handler-name "LDAPS Connection Handler" --set "listen-address:0.0.0.0" --trustAll --no-prompt` 3. Retrieve settings of the listener to confirm the property is changed: `# /opt/opendj/bin/dsconfig get-connection-handler-prop --hostname localhost --port 4444 --bindDN "cn=Directory Manager" --bindPassword YOUR_LDAP_ADMIN_PASS --handler-name "LDAPS Connection Handler" --trustAll --no-prompt` 4. Restart "opendj" service Don't forget to ensure that connections to TCP port 1636 on this box are not blocked by a firewall or the like.

By Aliaksandr Samuseu staff 23 Apr 2019 at 2:35 p.m. CDT

Aliaksandr Samuseu gravatar
Hi, Jordan. What other questions do you have? Do you think we can close this ticket?

By Jordan Goldman user 23 Apr 2019 at 2:42 p.m. CDT

Jordan Goldman gravatar
Hey Aliaksandr, Thanks so much for your help! I was able to get LDAP listening on 0.0.0.0 with the command you provided, and I have things set up pretty closely to how we think we'll need them. One issue I'm still having is that I've been unable to connect to OpenDJ via the default/openldap version of the ldapsearch binary -- it seems that I have to use the ldapsearch binary provided by OpenDJ/Gluu in order to establish a connection. Is that something that is known, or should I be able to use any ldapsearch binary to connect to OpenDJ? Edit: apologies, I spent a bit of time working on this and was able to get openldap's ldapsearch binary to work after some debug troubleshooting. You can go ahead and close out this ticket for now. Thank you so much for your help! Best, Jordan

By Aliaksandr Samuseu staff 23 Apr 2019 at 3:31 p.m. CDT

Aliaksandr Samuseu gravatar
I can only say that we used OpenDJ's console tools with OpenLDAP successfully before (`ldapsearch`, at least), but I doubt the other way round was tried, and as we now decided to get rid of OpenLDAP completely in our products, it's not something we would like to support as well. Is it a mandatory requirement for you, or you could proceed without it?

By Jordan Goldman user 23 Apr 2019 at 3:43 p.m. CDT

Jordan Goldman gravatar
No worries, thank you so much Aliaksandr. I edited my earlier post to say that I was able to get it to work, so I'm going to close out the ticket :) We're planning to show it all to management this week. All the best, Jordan