SAML 2.0

Spinnaker supports using a SAML identity provider for single sign-on authentication.

Security Assertion Markup Language (SAML) is an XML based way to implement single sign-on (SSO).

A cryptographically signed XML document (known as a “SAML Assertion”) is sent to the API gateway server (Gate) with your identifying information, such as username and group membership.

Gate verifies the XML document’s signature using a metadata file, and if successful, it associates the identifying information with the user and allows the user to proceed as authenticated.

Identity provider setup

  1. In your SAML Identity Provider (IdP), download the metadata.xml file. Some providers expose this as a URL. It may look something like this:

    1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    2. <md:EntityDescriptor
    3. xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
    4. entityID="https://accounts.google.com/o/saml2?idpid=SomeValueHere"
    5. validUntil="2021-05-16T15:17:27.000Z">
    6. <md:IDPSSODescriptor
    7. WantAuthnRequestsSigned="false"
    8. protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    9. <md:KeyDescriptor use="signing">
    10. <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    11. <ds:X509Data>
    12. <ds:X509Certificate>
    13. MIIDdDCCAlygAwIBAgIGAVS/Sw5yMA0GCSqGSIb3DQEBCwUAMHsxFDASBgNVBAoTC0dvb2dsZSBJ
    14. bmMuMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MQ8wDQYDVQQDEwZHb29nbGUxGDAWBgNVBAsTD0dv
    15. b2dsZSBGb3IgV29yazELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWEwHhcNMTYwNTE3
    16. MTUxNzI3WhcNMjEwNTE2MTUxNzI3WjB7MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEWMBQGA1UEBxMN
    17. TW91bnRhaW4gVmlldzEPMA0GA1UEAxMGR29vZ2xlMRgwFgYDVQQLEw9Hb29nbGUgRm9yIFdvcmsx
    18. CzAJBgNVBAYTblVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMIIBIjANBgkqhkiG9w0BAQEF46OCAQ8A
    19. MIIBCgKCAQEA4JsnpS0ZBzb7DtlU7Zop7l+Kgr7NzusKWcEC6MOsFa4Dlt7jxv4ScKZ/61M5WKxd
    20. 5YX0ol1rPokpNztj+Zk7OXrG8lDic0DpeDutc9pcq0+9/NYFF7WR7TDjh4B7Txnq7SerSB78fT8d
    21. 4rK7Bd+cu/cBIyAAyZ5tLeLbmTnHAk093Y9vF3mdWQnfAhx4ldOfstF6G/d2ev7I5xjSKzQuH6Ew
    22. 3bb3HLcM4uEVevOfNAlh1KoV4vQr+qzbc9UEFcPRwzuTwGa6QjfspWW7NgXKbHHC+X6a+gqJrke/
    23. 6l2VvHaQBJ7oIyt4PCdel2cnUkvuxvzHPYedh1AgrIiSP1brSQIDAQABMA0GCSqGSI34DQEBCwUA
    24. A4IBAQCPqMAIau+pRDs2NZG1nGfyEMDfs0qop6FBa/wTNis75tLvay9MUlxXkTxm9aVxgggjEyc6
    25. XtDjpV0onrH0jBnSc+vRI1GFQ48EO3owy3uBIeR1aMy13ZwAA+KVizeoOrXBJbvIUZHo0yfKRzIu
    26. gtM58j58BdAFeYo+X9ds/ysvZ8FIGTLqMl/A3oO/yBNDjXR9Izoqgm7RX0JJXGL9Y1AgmEjxyqo9
    27. MhxZAGxOHm9HZWWfVMcoe8p62mRJ2zf4lkNPBnDHrQ8MDPSsXewAuiSnRBDLxhdBgyThT/KW7Q06
    28. rGa6Dp0rntKWzZE3hGQS0AdsnuFY/OXbmkNG9WUrUg5x
    29. </ds:X509Certificate>
    30. </ds:X509Data>
    31. </ds:KeyInfo>
    32. </md:KeyDescriptor>
    33. <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
    34. <md:SingleSignOnService
    35. Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
    36. Location="https://accounts.google.com/o/saml2/idp?idpid=SomeValueHere"/>
    37. <md:SingleSignOnService
    38. Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
    39. Location="https://accounts.google.com/o/saml2/idp?idpid=SomeValueHere"/>
    40. </md:IDPSSODescriptor>
    41. </md:EntityDescriptor>
  2. Create a Spinnaker SAML application.

  3. Specify the login URL as https://localhost:8084/saml/SSO. Replace “localhost” with Gate’s address, if known.

  4. Specify a unique entity ID (we’ll use spinnaker.test in our example).

  5. Enable the users you’d like to have access to your Spinnaker instance.

  6. Generate a keystore and key in a new Java Keystore with some password:

    1. keytool -genkey -v -keystore saml.jks -alias saml -keyalg RSA -keysize 2048 -validity 10000
  7. Execute the following halyard commands and redeploy Gate:

    1. KEYSTORE_PATH= # /path/to/keystore.jks
    2. KEYSTORE_PASSWORD=hunter2
    3. METADATA_PATH= # /path/to/metadata.xml
    4. SERVICE_ADDR_URL=https://localhost:8084
    5. ISSUER_ID=spinnaker.test
    6. hal config security authn saml edit \
    7. --keystore $KEYSTORE_PATH \
    8. --keystore-alias saml \
    9. --keystore-password $KEYSTORE_PASSWORD \
    10. --metadata $METADATA_PATH \
    11. --issuer-id $ISSUER_ID \
    12. --service-address-url $SERVICE_ADDR_URL
    13. hal config security authn saml enable

Network architecture and SSL termination

During the SAML workflow , Gate makes an intelligent guess on how to assemble a URI to itself, called the Assertion Consumer Service URL. Sometimes this guess is wrong when Spinnaker is deployed in concert with other networking components, such as an SSL-terminating load balancer, or in the case of the Quickstart images, a fronting Apache instance.

To override the values to assemble the URL, use the following hal command:

  1. hal config security authn saml edit --service-address-url https://my-real-gate-address.com:8084

Please check on the SSL Documentation for more information.

For the Quickstart images, append /gate to the --service-address-url. All other configurations can omit this setting.

Workflow

The SAML workflow below reflects the process when the user navigates to Spinnaker first, is redirected to the SAML IdP for login, and redirected back to Spinnaker. Some SAML providers will allow the user login to the SAML provider first, and click a link to be taken to Spinnaker.

sequenceDiagram participant Deck participant Gate participant IdentityProvider Deck->>+Gate: GET /something/protected Gate->>-Deck: HTTP 302 to https://idp.url/?SAMLRequest=… Deck->>+IdentityProvider: GET https://idp.url/?SAMLRequest=… IdentityProvider->>-Deck: Returns login page

  1. User attempts to access a protected resource.

  2. Gate redirects to the SAML provider, passing a few query params:

    • SAMLRequest: a Gzip’ed XML authentication request.
    • SigAlg: The algorithm used to generate the Signature parameter.
    • Signature: A digest of the SAMLRequest using the SigAlg algorithm and the server’s key.

    Within the SAMLRequest is the Assertion Consumer Service URL, with is the URL to your Gate instance. See here for how to override this value.

  3. SAML provider prompts user for username & password.

    sequenceDiagram participant Deck participant Gate participant IdentityProvider Deck->>+IdentityProvider: User sends credentials IdentityProvider->>-Deck: HTTP 200 with self-submitting form to POST https://gate.url Deck->>+Gate: POST /saml/SSO with { SAMLResponse: … } Note right of Gate: User identity verified Note right of Gate: Gate extracts data based on userInfoMapping Gate->>-Deck: HTTP 302 /something/protected

  4. A SAML response must be POSTed to /saml/SSO, and most browsers won’t re-POST when given an HTTP 302. Instead, providers sometimes return a page (with HTTP 200) that has a self-submitting HTML form to POST to Gate’s /saml/SSO endpoint.

  5. Gate verifies the message’s integrity by checking its signature, and thus verifying the user’s identity information.

  6. Gate determines the username and/or email address, and optionally extracts group membership (if sent by the IdP).

  7. With the user’s identity verified, Gate redirects the user to the originally requested URL.

Next steps

Now that you’ve authenticated the user, proceed to setting up their authorization .

Troubleshooting

Last modified May 4, 2021: rest of migration (700781a)