Community Articles

Find and share helpful community-sourced technical articles.
Labels (2)
avatar

In part I of this series, we reviewed preliminaries related to SSO, including LDAP authentication for Ambari, and we set up an application in Okta that would correspond to our KnoxSSO service provider for the SAML authentication flow. We are now ready to configure Knox within Ambari.

We will replace the Form-based IdP configuration that Knox comes with out of the box with the pac4j federation provider. Pac4j is a Java security library and it is used as a federation provider within Knox to support the OAuth, CAS, SAML and OpenID Connect protocols. It must be used for SSO, in association with the KnoxSSO service (and optionally with the SSOCookieProvider for access to REST APIs).

In Ambari, we'll navigate to Knox > Config > Advanced knoxsso-topology and add XML similar to the following:

<topology>
   <gateway>
     <provider>
         <role>federation</role>
         <name>pac4j</name>
         <enabled>true</enabled>
         <param>
           <name>pac4j.callbackUrl</name>
      <value>https://sslka-123-master2-1.field.hortonworks.com:8443/gateway/knoxsso/api/v1/websso</value>
         </param>
         <param>
           <name>clientName</name>
           <value>SAML2Client</value>
         </param>

         <param>
           <name>saml.identityProviderMetadataPath</name>
           <value>https://dev-999.oktapreview.com/app/redacted/sso/saml/metadata</value>
         </param> 

         <param>
           <name>saml.serviceProviderMetadataPath</name>
           <value>/tmp/sp-metadata.xml</value>
         </param>

         <param>
           <name>saml.serviceProviderEntityId</name>
<value>https://sslka-123-master2-1.field.hortonworks.com:8443/gateway/knoxsso/api/v1/websso?pac4jCallback=true&client_name=SAML2Client</value>
         </param>
     </provider>

     <provider>
         <role>identity-assertion</role>
         <name>Default</name>
         <enabled>true</enabled>
         <param>
           <name>principal.mapping</name>
           <value>slachterman@hortonworks.com=slachterman;</value>
         </param>
     </provider>
   </gateway>

   <service>
              <role>KNOXSSO</role>
              <param>
                  <name>knoxsso.cookie.secure.only</name>
                  <value>true</value>
              </param>
              <param>
                  <name>knoxsso.token.ttl</name>
                  <value>30000</value>
              </param>
              <param>
                 <name>knoxsso.redirect.whitelist.regex</name>
                <value>^https:\/\/(knox-host-fqdn\.example\.com|localhost|127\.0\.0\.1|0:0:0:0:0:0:0:1|::1):[0-9].*$</value>
  </param>
          </service>
      </topology>


A couple of things to note here:

  • The callback URL for KnoxSSO is the WebSSO endpoint without the URL parameter
  • The identity provider metadata path points to the metadata for the Okta application you configured in part I
    • You can find this URL in Okta, within your Application configuration on the Sign On tab. See Identity Provider metadata in the screenshot below (under the View Setup Instructions button)
  • The service provider metadata path is a dummy location, this can't be NULL or you will see an exception in the current release
  • The principal mapping converts the username that Okta presents to the shortname used throughout HDP. A regex mapping is available and be more manageable for Produciton
  • Note the knoxsso.cookie.secure.only setting. It's important that the session cookie only be served for HTTPS to protect from session hijacking.
  • The knoxsso.redirect.whitelist.regex must match your environment, knox-host-fqdn.example.com is a dummy placeholder in the topology file above

42790-screen-shot-2017-11-28-at-43256-pm.png

After Knox has been configured, the last step is to configure Ambari for SSO and we'll do this from the command line. You'll need to SSH to the host where Ambari Server is running.

As a preliminary step, you'll need the public certificate for Knox. You can use this snippet, where ${knoxserver} is the host running the Knox Gateway:

openssl s_client -connect ${knoxserver}:8443 < /dev/null | openssl x509 -out /tmp/knox.crt

To configure Ambari, we'll run

sudo ambari-server setup-sso

For the provider URL, enter you callback URL

http://<KNOX_HOST>:<KNOX_PORT>/gateway/knoxsso/api/v1/websso

Then paste the public certificate without the header and footer (don't include the BEGIN CERTIFICATE or END CERTIFICATE lines).

You can accept all other defaults.

Finally, you'll need to run

sudo ambari-server restart

You should now be all set! After saving the above Knox configuration in Ambari and restarting Knox and any required services, try navigating to Ambari to test.

If everything has been set up correctly, you'll be logged in to Ambari after authenticating to Okta.

In future posts in this series, we'll take a look at the Form-based IdP that's included with KnoxSSO, setting up SSO for Ranger, and other topics!

5,722 Views
Comments
avatar
Super Collaborator

Great article!

avatar
Explorer

Hi There,

Following the below document from Hortonworks we have configured the KNOXSSO using OKTA(SAML). But, while accessing ambari web UI using Okta single sign on, the redirecturl is unable access the KNOX end point. Could you please share your thoughts on troubleshooting the issue as shown in the screenshots below.

https://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.6.3/bk_security/content/ch02s09s01.html#saml_ba...

Federation provider: pac4j

SAML IDP provider: Okta

Service provider: KnoxSSO

gateway-audit.log

error:18/06/07 17:01:39 ||2c5194ce-fb4e-4049-bdb9-dac767934214|audit|172.20.100.241|KNOXSSO||||access|uri|/gateway/knoxsso/api/v1/websso?pac4jCallback=true&client_name=SAML2Client|failure|

gateway.log :

2018-06-07 17:01:39,605 ERROR hadoop.gateway (GatewayServlet.java:service(146)) - Gateway processing failed: javax.servlet.ServletException: org.pac4j.saml.exceptions.SAMLException: Error decoding saml message javax.servlet.ServletException: org.pac4j.saml.exceptions.SAMLException: Error decoding saml message at org.apache.hadoop.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:70) at org.apache.hadoop.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:332) at org.apache.hadoop.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:232) at org.apache.hadoop.gateway.GatewayFilter.doFilter(GatewayFilter.java:139) at org.apache.hadoop.gateway.GatewayFilter.doFilter(GatewayFilter.java:91) at org.apache.hadoop.gateway.GatewayServlet.service(GatewayServlet.java:141) at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:587) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577) at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.apache.hadoop.gateway.trace.TraceHandler.handle(TraceHandler.java:51)

at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.apache.hadoop.gateway.filter.CorrelationHandler.handle(CorrelationHandler.java:39) at org.eclipse.jetty.servlets.gzip.GzipHandler.handle(GzipHandler.java:479) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.apache.hadoop.gateway.filter.PortMappingHelperHandler.handle(PortMappingHelperHandler.java:92) at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:110) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:499) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) at java.lang.Thread.run(Thread.java:745) Caused by: org.pac4j.saml.exceptions.SAMLException: Error decoding saml message at org.pac4j.saml.sso.impl.SAML2WebSSOMessageReceiver.receiveMessage(SAML2WebSSOMessageReceiver.java:43) at org.pac4j.saml.sso.impl.SAML2WebSSOProfileHandler.receive(SAML2WebSSOProfileHandler.java:35) at org.pac4j.saml.client.SAML2Client.lambda$clientInit$0(SAML2Client.java:110) at org.pac4j.core.client.BaseClient.retrieveCredentials(BaseClient.java:61) at org.pac4j.core.client.IndirectClient.getCredentials(IndirectClient.java:125) at org.pac4j.core.engine.DefaultCallbackLogic.perform(DefaultCallbackLogic.java:79) at org.pac4j.j2e.filter.CallbackFilter.internalFilter(CallbackFilter.java:77) at org.pac4j.j2e.filter.AbstractConfigFilter.doFilter(AbstractConfigFilter.java:81) at org.apache.hadoop.gateway.pac4j.filter.Pac4jDispatcherFilter.doFilter(Pac4jDispatcherFilter.java:220) at org.apache.hadoop.gateway.GatewayFilter$Holder.doFilter(GatewayFilter.java:332) at org.apache.hadoop.gateway.GatewayFilter$Chain.doFilter(GatewayFilter.java:232) at org.apache.hadoop.gateway.filter.XForwardedHeaderFilter.doFilter(XForwardedHeaderFilter.java:30) at org.apache.hadoop.gateway.filter.AbstractGatewayFilter.doFilter(AbstractGatewayFilter.java:61) ... 32 more Caused by: org.opensaml.messaging.decoder.MessageDecodingException: This message decoder only supports the HTTP POST method at org.pac4j.saml.transport.Pac4jHTTPPostDecoder.doDecode(Pac4jHTTPPostDecoder.java:57) at org.opensaml.messaging.decoder.AbstractMessageDecoder.decode(AbstractMessageDecoder.java:58) at org.pac4j.saml.sso.impl.SAML2WebSSOMessageReceiver.receiveMessage(SAML2WebSSOMessageReceiver.java:40) ... 44 more

avatar
Explorer

Knoxsso.xml

federation pac4j true

pac4j.callbackUrl https://knoxhost:8443/gateway/knoxsso/api/v1/websso clientName SAML2Client saml.identityProviderMetadataPath https://xxxxxxxx/app/exk1bs9c6clt0ttLo2p7/sso/saml/metadata saml.serviceProviderMetadataPath /tmp/sp-metadata.xml saml.serviceProviderEntityId https://knoxhost:8443/gateway/knoxsso/api/v1/websso?pac4jCallback=true&client_name=SAML2Client identity-assertion Default true principal.mappingtest1@jmfamily.com=tester,admin=admin KNOXSSO knoxsso.cookie.secure.only true knoxsso.token.ttl 30000 knoxsso.redirect.whitelist.regex ^https:\/\/xxxxx\.xxxxx\.com|localhost|127\.0\.0\.1|0:0:0:0:0:0:0:1|::1):[0-9].*{replace49}lt;/value>

avatar
New Contributor

Is it possible to enable SSO and MFA in ambari 2.6.5 without Knox being enabled? Any pointer will be appreciated.