PlantUML | ||||
---|---|---|---|---|
| ||||
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)" 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) deactivate G B->E: POST(idp-login-ui) note right: Browser follows redirect activate E E-->B: ok(idp-login-ui) note right: BrowserSAML IdP followspresents redirect login form activateto idpuser cli <-- idp: ok200(form) deactivate E B->E: POST(idp-login-ui,credentials) note right: SAML User provides credentials to IdP presentsvia login form to user deactivate idp cli -> idp: /login.POST(username,password.\nSAML IdP validates credentials. activate E E-->B: redirect(knox-sso,saml-assertion) note right: UserIdP providesredirects credentialsback to IdP via login form.\nSAML IdP validates credentials. activate idp cli <-- idp: redirect302(knox-origin-url,saml-bearer-token) knox-origin-url with SAML assertion\nin form POST deactivate E B->G: POST(knox-sso,saml-assertion) note right: IdPKnoxSSO converts redirectsSAML backassertion to knoxa KnoxSSO cookie\nand extracts ui-origin-url withfrom SAML Bearer token in headers deactivate idp cli -> sso: /login.GET(saml-beareroriginal-url cookie activate G G-->B: redirect(ui-origin-url,knox-token) note right: KnoxTS/SSOKnoxSSO convertsredirects SAMLclient Bearer Tokenback to a normalized JWT Bearer Token\nand extracts ui-origin-url with KnoxSSO cookie deactivate G B->A: GET(ui-origin-url from ,knox-origin-urltoken) activate sso cli <-- sso: redirect302(ui-origin-url,jwt-bearer-token-cookie) note note right: KnoxTS/SSOBrowser redirectsfollows client backredirect to ui-origin-url with JWT Bearer tokenToken in cookie .\nJWT Bearer deactivate sso cli -> ui: /view.GET(jwt-bearer-token-Token validated by AuthFilter in UI activate A A->B: ok(ui-cookie) note right: BrowserRequest followsprocesses redirectand to ui-origin-url with JWT Bearer Token in cookie.\nJWT Bearer Token validated by AuthFilter in UI activate ui cli <- ui: ok200(response) note right: Request processes and response returned to client. deactivate ui deactivate cli response returned to client. deactivate A @enduml |
Knox Picketlink Federation Provider
...
The following table details the configuration elements of the provider and reflects the current implementation in the master branch:
Param | Description | Default | ||
---|---|---|---|---|
identity.url | The URL to redirect incoming requests that do not contain the expected cookie and presumably to facilitate an authentication challenge. | none | ||
service.url | The URL back to the KnoxSSO endpoint for the IdP to redirect the browser after authentication. | none | ||
keystore.url | The location of the keystore with the public cert of the IdP for token validation. BUG: this is currently hardcoded to gateway.jks | gateway.jks | ||
validating.alias.key | This 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.com | none | ||
validating.alias.value | This is the alias for the actual cert to use for the idp domain - ie. server.crt | none | 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.milis | The clock skew to use during the validation of tokens | none |
...
<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>gateway-identity<<value>servercert</value>
</param>
<param>
<name>clock.skew.milis</name>
<value>2000</value>
</param>
</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> <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:
...