10 Replies Latest reply on Mar 23, 2015 10:37 AM by rareddy

    Can client authentication be configured for Embedded Teiid?

    btkibler

      Following the v8.8 Embedded guide, I was able to get Teiid listening on the PG wire protocol, and accepting connections from a PostgreSQL-provided JDBC or ODBC client driver.

       

      However, I couldn't find any documentation or unit tests on how to configure authentication mechanisms (GSS-API for Kerberos, LDAP, etc.) for the socket listener transport. The code seems to support doing GSS authentication within the ODBC socket listener, but it's not clear how to configure this behavior.  I looked through all the public interfaces provided by EmbeddedConfiguration and ModelMetadata, and couldn't figure out how to inject the configuration typically done in the vdb.xml or standalone-teiid.xml configuration files.

       

      Is this technically even possible, or is it not expected to ever be possible with the embedded version?

       

      Thanks,

      Ben

        • 1. Re: Can client authentication be configured for Embedded Teiid?
          rareddy

          Question is how are configuring any security domains in the embedded scenario? In the JBoss EAP based deployment Teiid uses JAAS Login Modules supplied by the JBoss EAP platform and Teiid hooks into that for Kerberos negotiation. So, you need to configure a security domain. Take look at EmbeddedConfiguration.getSecurityHelper() and EmbeddedConfiguration.getSecurityDomain() methods. These give you option to inject the security domain and manage it.  The client side you use same configuration as Teiid documented for JBoss EAP based deployment. If everything configured correctly then you should see call into your security domain module from Teiid.

           

          Ramesh..

          1 of 1 people found this helpful
          • 2. Re: Re: Can client authentication be configured for Embedded Teiid?
            btkibler

            Thanks Ramesh, that helped, and got me started on the right track.  I have Kerberos working now (using the Postgres JDBC driver, from a Java client), but I still think I'm missing something...

             

            Steps I took:

            1. Extended SessionServiceImpl, overriding/implementing the negotiateGssLogin() method, to call LoginContext.acceptSecContext() and validate the client's Kerberos token. (source code attached)
            2. Created a basic KerberosSecurityHelper and KerberosSecurityContext to store the authenticated state in thread-local variables.

             

            However, it wasn't clear how the logic in ODBCServerRemoteImpl expected to handle the GSSResult.isAuthenticated() state returned from negotiateGssLogin().  The Postgres client driver expects the following token handshake sequence (from the Postgres driver debug logs):

             

            1. 08:16:28.101 (1)  FE=> StartupPacket(user=MYUSERID@MYDOMAIN.COM, database=test, client_encoding=UTF8, DateStyle=ISO, TimeZone=America/New_York, extra_float_digits=2)

            2. 08:16:28.143 (1) Using JSSE GSSAPI, gssapi requested by server and gsslib=sspi not forced

            3. 08:16:28.144 (1)  <=BE AuthenticationReqGSS

            4. 08:16:28.449 (1)  FE=> Password(GSS Authentication Token)

            5. 08:16:28.495 (1)  <=BE AuthenticationGSSContinue

            6. 08:16:28.514 (1)  <=BE AuthenticationOk

             

            In the log above, step 3 is the response from the server requesting GSS auth, step 4 is the client token sent to the server, step 5 is the peer response from the server (used by the client to validate the server's SPN), and step 6 is a final ACK from the server telling the client it's ready to start processing queries.

             

            However, the ODBCServerRemoteImpl class (as implemented) would only send an AuthenticationGSSContinue OR an AuthenticationOK response.  If my GSSResult.isAuthenticated() response returns TRUE, the code returns an AuthenticationOK, and the client throws an exception because it never got the server's GSSContinue response token for mutual auth.  If I send GSSResult.isAuthenticated = FALSE, the server code just sends an AuthenticationGSSContinue, and the client blocks and waits on an AuthenticationOK message, which never arrives.  Neither approach seems correct, because the client is expecting BOTH messages (GSSContinue and OK).

             

            I made the following modifications to ODBCServerRemoteImpl class:

            else if (authType.equals(AuthenticationType.GSS)) {
              byte[] serviceToken = data.readServiceToken();
              LogonResult result = this.logon.neogitiateGssLogin(this.props, serviceToken, false);
              serviceToken = (byte[])result.getProperty(ILogon.KRB5TOKEN);
              //REMOVE if (Boolean.TRUE.equals(result.getProperty(ILogon.KRB5_ESTABLISHED))) {
              info.put(ILogon.KRB5TOKEN, serviceToken);
              // if delegation is in progress, participate in it.
              if (result.getProperty(GSSCredential.class.getName()) != null) {
              info.put(GSSCredential.class.getName(), result.getProperty(GSSCredential.class.getName()));
              }
              //REMOVE }
              //REMOVE else {
              this.client.authenticationGSSContinue(serviceToken);
              //REMOVE return;            
              //REMOVE}
            } else {
              throw new AssertionError("Unsupported Authentication Type"); //$NON-NLS-1$
            }
            

             

            These modifications got it working, but I wonder if I'm doing something wrong, or missing a while (!isAuthenticated()) loop somewhere that should be processing the handshake.

            Any suggestions are welcome, and I can attach more of my sample code if needed.

             

            -Ben

            • 3. Re: Re: Can client authentication be configured for Embedded Teiid?
              shawkins

              I don't think you are missing something.  My guess would be we had different expectations from our kerberos/client setups. From http://www.postgresql.org/docs/9.1/static/protocol-flow.html what you have would certainly seem to be a valid flow.  I think we should test on our end with a similar change to verify.

               

              Thanks,

              Steve

              1 of 1 people found this helpful
              • 4. Re: Re: Re: Can client authentication be configured for Embedded Teiid?
                rareddy

                What I remember seeing is, some times the negotiation take more one trip between client and server, thus the way it is. Re-reading the link provided by Steve, I think the code should read as

                 

                else if (authType.equals(AuthenticationType.GSS)) {
                  byte[] serviceToken = data.readServiceToken();
                  LogonResult result = this.logon.neogitiateGssLogin(this.props, serviceToken, false);
                  serviceToken = (byte[])result.getProperty(ILogon.KRB5TOKEN);
                  if (Boolean.TRUE.equals(result.getProperty(ILogon.KRB5_ESTABLISHED))) {
                    info.put(ILogon.KRB5TOKEN, serviceToken);
                    // if delegation is in progress, participate in it.
                    if (result.getProperty(GSSCredential.class.getName()) != null) {
                    info.put(GSSCredential.class.getName(), result.getProperty(GSSCredential.class.getName()));
                    }
                    this.client.authenticationGSSContinue(serviceToken); // NEW LINE ADDED
                  }
                  else {
                    this.client.authenticationGSSContinue(serviceToken);
                    return;            
                  }
                } else {
                  throw new AssertionError("Unsupported Authentication Type"); //$NON-NLS-1$
                }
                

                 

                You can open a JIRA, I will apply the fix.

                 

                Ramesh..

                • 5. Re: Re: Re: Can client authentication be configured for Embedded Teiid?
                  btkibler

                  Thanks Ramesh! I applied those changes and it works in our environment, both from a standalone Java JDBC client, and from SQLWorkbench/J, using the Postgres 9.4-1201 JDBC driver.  I'll create a JIRA to request a fix.

                  • 6. Re: Re: Re: Can client authentication be configured for Embedded Teiid?
                    rareddy

                    Ben,

                     

                    Very nice. Would you be willing to write some kind of blog about your usecase, that will be superb. I am really interested to know how/why you are embedding the Teiid. There are few community members developing using embedded Teiid, it would great if we can develop some reference architecture docs/samples etc to share with others.

                     

                    Thanks

                     

                    Ramesh..

                    • 7. Re: Re: Re: Re: Can client authentication be configured for Embedded Teiid?
                      btkibler

                      This particular scenario is to provide Kerberos authentication for Amazon AWS-managed cloud databases that don't natively support LDAP or Kerberos for integrated authentication. AWS probably doesn't have much customer demand for LDAP or Kerberos integration, because typically end-users connect to a web application with SSO credentials, and then the web app server connects to the back-end database using a single database-provided local credential.  However in enterprise/legacy use cases, and some operational support use cases, we have 2-tier client/server applications that require end users to connect directly to the database, bypassing the application tier.  Rather than maintaining individual userids and passwords for every user in each of those back-end databases, we can easily pop up a small Teiid instance which proxies the user connection, authenticating the client against Kerberos, and then proxy-connect to the back-end database using a "service account" with the appropriate permissions.  All of our client desktops are Kerberos-aware and integrated with Active Directory, and the Postgres client natively supports Kerberos, so Teiid seemed like an great fit.

                       

                      We're not a "JBoss shop", and generally prefer lightweight J2SE containers over large/complex J2EE servers, so Teiid Embedded was much more attractive than running a JBoss container.  I found the embedded version easy to debug, extend via code, and unit test with minimal effort.  This use case doesn't have complex connection pooling, XA, or distributed transaction management requirements, since we're basically mapping each client connection to a single back-end DB connection, and if either end of the connection fails, the client can simply reconnect.

                       

                      Unfortunately I'm not permitted to blog or mention my employer, but you're welcome to blog about the general use case of adding Kerberos auth to non-Kerberos databases.

                       

                      Our primary use case for Teiid Embedded is probably more traditional: if an application needs to join between two disparate databases or data sources, we encourage them to embed Teiid within their application, and use the VDB model to join the data, rather than writing complex joins (hashmaps, lookups, etc.) in Java code.  This use case doesn't need Kerberos, and for most simple use cases, the configuration is done entirely in code, with no need for vdb.xml files.  The attached code is what I share with developers as an example of joining two disparate databases (or even processing small text files using SQL constructs) within Java code.

                      • 8. Re: Re: Re: Re: Can client authentication be configured for Embedded Teiid?
                        rareddy

                        Thanks for sharing, that is really cool. I have never seen somebody using Teiid for just the authentication unification before. We do say one place to manage all the user permissions for enterprise.

                        • 9. Re: Re: Re: Re: Can client authentication be configured for Embedded Teiid?
                          shawkins

                          Also there is now [TEIID-3380] Simplify Kerberos configuration with Embedded - JBoss Issue Tracker

                           

                          That will be a breaking change from an API perspective, but should better encapsulate the implementation.