Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
PlantUML
border1
titleWeb UI SSO Flow (SAML)
hide footbox@startuml
autonumber
 footbox off
participant "Browser" as cliB
participant "WebUI\n(eg NN UI)" as ui #limeA
participant "Knox\nTS/SSO" as sso #limeG
participant "SAML IdP\n(eg Shibboleth)"_IdP as idpE
 
activate cli
cli -> ui: /view.GET()
  
B->A: GET(ui-origin-url)
note right: User/browser makes request to UI without valid token
  activate ui
  cli <A
A-- ui>B: redirect302(SSO:/login,redirect(knox-sso+ui-origin-url)
  note right: AuthFilter in UI detectesdetects no/invalid token redirects to\nKnoxSSO KnoxTS/SSO preserving ui-origin-url
  deactivate uiA
cli -> ssoB->G: /login.GET(knox-sso+ui-origin-uilurl)
  note right: Browser follows redirect
  activate sso
  cli <G
G-- sso>B: redirect302(IdP:/login,knox-origin-url)
  redirect(idp-login-ui)
note right: KnoxTS/SSOKnoxSSO finds no/invalid token,\nredirects redirects to SAML IdP preserving knox-origin-url with encoded ui-origin-uri
  deactivate sso
cli -> idp: /login.GET(knox-origin-url)
  note right: Browser follows redirect
  activate idp
  cli <-- idp: ok200(form)
  
deactivate G
B->E: POST(idp-login-ui)
note right: Browser follows redirect
activate E
E-->B: ok(idp-login-ui)
note right: SAML IdP presents login form to user
  deactivate idpE
cli -> idpB->E: /login.POST(username,passwordidp-login-ui,credentials)
note right: User provides credentials to IdP via login form.\nSAML IdP validates credentials.
  activate idp
  cli <E
E-- idp>B: redirect302redirect(knox-origin-urlsso,saml-bearer-tokenassertion)
  note right: IdP redirects back to knox-origin-url with SAML Bearerassertion\nin tokenform in headersPOST
  deactivate idpE
cli -> ssoB->G: /login.GET(saml-bearer-token)
  POST(knox-sso,saml-assertion)
note right: KnoxTS/SSOKnoxSSO converts SAML Bearer Tokenassertion to a normalized JWT Bearer TokenKnoxSSO cookie\nand extracts ui-origin-url from knox-originoriginal-url cookie
  activate sso
  cli <G
G-- sso>B: redirect302redirect(ui-origin-url,jwt-bearerknox-token-cookie)
  note right: KnoxTS/SSOKnoxSSO redirects client back to ui-origin-url with JWT Bearer token inKnoxSSO cookie
  deactivate ssoG
cli -> uiB->A: /view.GET(jwt-bearerui-origin-url,knox-token-cookie)
note right: Browser follows redirect to ui-origin-url with JWT Bearer Token in cookie.\nJWT Bearer Token validated by AuthFilter in UI
  activate ui
  cli <- ui: ok200(response)
  A
A->B: ok(ui-cookie)
note right: Request processes and response returned to client.
  deactivate ui
deactivate cli
 deactivate A
@enduml
 

Knox Picketlink Federation Provider

The picketlink federation provider allows for the federation of an authentication event that is represented by a SAML assertion cookie/token.

It enables the flow illustrated above in the sequence diagram for SAML based authentication for Hadoop Web UIs and is based on Apache Picketlink.

It has currently been tested with shibboleth as the SAML provider.

The following table details the configuration elements of the provider and reflects the current implementation in the master branch:

ParamDescriptionDefault
identity.urlThe URL to redirect incoming requests that do not contain the expected cookie and presumably to facilitate an authentication challenge.none
service.urlThe URL back to the KnoxSSO endpoint for the IdP to redirect the browser after authentication.none
keystore.urlThe location of the keystore with the public cert of the IdP for token validation. BUG: this is currently hardcoded to gateway.jksgateway.jks
validating.alias.keyThis is the idp domain which is used as the alias for looking up the alias for the cert to validate incoming tokens with - ie. idp.example.comnone
validating.alias.valueThis is the alias for the actual cert to use for the idp domain - ie. servercert - and is used by picket link to get to the public key for the IdP in order to verify the presented token.none
clock.skew.milisThe clock skew to use during the validation of tokensnone

 

Sample Topology file: "idp.xml"

<topology>
  <gateway>
    <provider>
      <role>federation</role>
      <name>Picketlink</name>
      <enabled>true</enabled>
      <param>
        <name>identity.url</name>
        <value>https://localhost:9443/idp/profile/SAML2/POST/SSO</value>
      </param>
      <param>
        <name>service.url</name>
        <value>http://c6401.ambari.apache.org:8888/gateway/idp/knoxsso/</value>
      </param>
      <param>
         <name>keystore.url</name>
         <value>/usr/hdp/current/knox-server/data/security/keystores/gateway.jks</value>
      </param>
      <param>
        <name>validating.alias.key</name>
        <value>c6401.ambari.apache.org</value>
      </param>
      <param>
        <name>validating.alias.value</name>
        <value>servercert</value>
      </param>
      <param>
        <name>clock.skew.milis</name>
        <value>2000</value>
      </param>
    </provider>

    <provider>
      <role>identity-assertion</role>
      <name>Default</name>
      <enabled>true</enabled>
    </provider>

    <provider>
      <role>authorization</role>
      <name>AclsAuthz</name>
      <enabled>true</enabled>
    </provider>

  </gateway>

  <service>
    <role>KNOXSSO</role>
    <param>
      <name>sso.cookie.secure.only</name>
      <value>false</value>
    </param>
  </service>
</topology>

The following is an example of what the resulting picketlink.xml file should look like in the generated webapp deployments directory:

 

<?xml version="1.0" encoding="UTF-8" ?>
<PicketLink xmlns="urn:picketlink:identity-federation:config:2.1">
  <PicketLinkSP xmlns="urn:picketlink:identity-federation:config:1.0"
    ServerEnvironment="jetty"
    BindingType="POST"
    IDPUsesPostBinding="true"
    SupportsSignatures="true"
    CanonicalizationMethod="http://www.w3.org/2001/10/xml-exc-c14n#">

    <IdentityURL>https://localhost:8443/idp/profile/SAML2/POST/SSO</IdentityURL>
    <ServiceURL>http://localhost:9443/gateway/idp/knoxsso/api/v1/websso</ServiceURL>
    <KeyProvider ClassName="org.picketlink.identity.federation.core.impl.KeyStoreKeyManager">
      <Auth Key="KeyStoreURL" Value="/Users/larry/Projects/incubator-knox/install/knox-0.7.0-SNAPSHOT/data/security/keystores/gateway.jks"/>
      <Auth Key="KeyStorePass" Value="knox"/> // populated automatically to match the master secret - must be made configurable though
      <Auth Key="SigningKeyAlias" Value="gateway-identity"/> // hardcoded to be gateway identity since it assumes the gateway identity key is used to sign the token
      <Auth Key="SigningKeyPass" Value="knox"/> // populated automatically to match the master secret - must be made configurable though
      <ValidatingAlias Key="localhost" Value="localhost"/>
    </KeyProvider>
  </PicketLinkSP>

  <Handlers>
    <Handler class="org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler">
      <Option Key="NAMEID_FORMAT" Value="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"/>
      <Option Key="CLOCK_SKEW_MILIS" Value="2000"/>
      <Option Key="ASSERTION_SESSION_ATTRIBUTE_NAME" Value="org.picketlink.sp.assertion"/>
    </Handler>
    <Handler class="org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler"/>
  </Handlers>
</PicketLink>

Proof of Concept Status

The following notes reflect the CURRENT POC state for the above flow inside an Ambari managed ambari-vagrant 3 node cluster:

...

** CAVEAT: the simple hadoop-auth cookie and any subsequent JWT solution will dictate that knoxsso endpoint be in the same domain as all of the UIs. IOW - all nodes in the cluster that host UIs or will need the cookie to be available need to be in the same domain as the knoxsso endpoint.

Required Configuration for Hadoop Consoles

OBSOLETE but in the proper spirit of HADOOP-11717 (

Jira
serverASF JIRA
serverId5aa69414-a9e9-3523-82ec-879b028fb15b
keyHADOOP-11717
)

<property>
  <name>hadoop.http.authentication.simple.anonymous.allowed</name>
  <value>false</value>
</property>

...

<property>
   <name>hadoop.http.authentication.public.key.pem</name>
   <value>MIICVjCCAb+gAwIBAgIJAPPvOtuTxFeiMA0GCSqGSIb3DQEBBQUAMG0xCzAJBgNV
   BAYTAlVTMQ0wCwYDVQQIEwRUZXN0MQ0wCwYDVQQHEwRUZXN0MQ8wDQYDVQQKEwZI
   YWRvb3AxDTALBgNVBAsTBFRlc3QxIDAeBgNVBAMTF2M2NDAxLmFtYmFyaS5hcGFj
   aGUub3JnMB4XDTE1MDcxNjE4NDcyM1oXDTE2MDcxNTE4NDcyM1owbTELMAkGA1UE
   BhMCVVMxDTALBgNVBAgTBFRlc3QxDTALBgNVBAcTBFRlc3QxDzANBgNVBAoTBkhh
   ZG9vcDENMAsGA1UECxMEVGVzdDEgMB4GA1UEAxMXYzY0MDEuYW1iYXJpLmFwYWNo
   ZS5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMFs/rymbiNvg8lDhsdA
   qvh5uHP6iMtfv9IYpDleShjkS1C+IqId6bwGIEO8yhIS5BnfUR/fcnHi2ZNrXX7x
   QUtQe7M9tDIKu48w//InnZ6VpAqjGShWxcSzR6UB/YoGe5ytHS6MrXaormfBg3VW
   tDoy2MS83W8pweS6p5JnK7S5AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEANyVg6EzE
   2q84gq7wQfLt9t047nYFkxcRfzhNVL3LB8p6IkM4RUrzWq4kLA+z+bpY2OdpkTOe
   wUpEdVKzOQd4V7vRxpdANxtbG/XXrJAAcY/S+eMy1eDK73cmaVPnxPUGWmMnQXUi
   TLab+w8tBQhNbq6BOQ42aOrLxA8k/M4cV1A=</value>
</property>

Picketlink POC Server

The knoxsso endpoint at this point is represented by a simple embedded jetty server hosting a webapp with a number of filters.

...