SAML-based Single Sign-On¶
This section will describe how to enable and use SAML single sign-on.
API Access for SAML¶
In dr-provision versions 4.8.0 and later, the DRP server provides the following endpoints for SAML Single Sign-On.
| Endpoint | Purpose |
|---|---|
/login |
Starts the SP-initiated SAML flow and returns a DRP token |
/logout |
Clears the local SAML session cookie |
/saml/list |
Lists the configured Identity Providers |
/saml/metadata |
Serves the DRP Service Provider metadata |
/saml/acs |
Assertion Consumer Service; receives the IDP's SAML response |
Login¶
By pointing a browser at https://drp-ip:api-port/login, the server will redirect the user to the identity provider for
authentication. Once this is complete, the login page will return a token and info structure by default.
Additionally, the login endpoint uses two query parameters to provide additional customizations.
- SAML-IDP=
- The IDP is the name of one of the configured Identity Providers. - redirect=
- The redirect option takes a base64 encoded URL that should be redirected to upon success. A DRP token is appended to the URL as a query parameter.
List¶
By pointing a browser at https://drp-ip:api-port/saml/list, a list of SAML Identity Providers is returned. This is a
smaller list from the Identity Provider objects. The object contains:
- Name - the name of the IDP to use in the SAML-IDP query parameter
- DisplayName - A display name to use for presenting to the user.
- LogoPath - A path or URL to a logo image. If the PATH is a full URL, this will be an image. If the PATH is relative, the file is served from DRP files directory.
These fields map directly to the Identity Provider fields.
The response is a JSON array sorted by Name, served with the content type application/samllist+json.
Only Identity Providers whose metadata was successfully loaded appear in this list. An IDP whose metadata could not be fetched or parsed is omitted (see Troubleshooting Tips).
Logout¶
https://drp-ip:api-port/logout deletes the local SAML session cookie and returns 200.
Logout is local to DRP only
/logout does not perform SAML Single Logout. The DRP Service Provider metadata advertises a
SingleLogoutService endpoint, but the server does not implement it. Configuring Single Logout at
the Identity Provider will not sign the user out of DRP, and /logout will not sign the user out of
the Identity Provider. Any DRP token already issued remains valid until it expires or until that
user's next SAML login regenerates their secret (see User Provisioning).
Service Provider Behavior and Limits¶
The DRP Service Provider is configured by the server and is not tunable through the Identity Provider object. These constraints affect how you configure the IDP side.
| Behavior | Value | Implication for IDP configuration |
|---|---|---|
| Signed authentication requests | Disabled | Do not require a signed AuthnRequest at the IDP |
| Forced re-authentication | Disabled | DRP never sets ForceAuthn |
| Encrypted assertions | Supported | Optional; DRP publishes an encryption key in its metadata |
| IDP-initiated SSO | Not allowed | Users must start at /login; IDP dashboard tiles and app links return 403 |
| SAML Single Logout | Not implemented | See the warning above |
| DRP token lifetime | 1 hour | Not configurable; independent of the IDP session lifetime |
DRP only accepts service-provider-initiated logins. Testing an application by clicking its tile in an
Identity Provider's dashboard is an IDP-initiated login, and the assertion is rejected with 403 at
/saml/acs. Always begin at https://drp-ip:api-port/login?SAML-IDP=<IDP> or use the IDP button on the
DRP UX login page.
The SAML-IDP value must name a loaded Identity Provider. If it does not match one, DRP redirects to an
arbitrarily chosen Identity Provider instead of reporting an error, so verify the name against
/saml/list when a login goes somewhere unexpected.
UX Access by SAML¶
The UX login page presents the standard authentication page. If Identity Providers have been configured and functional, the UX login page will have additional buttons for each of IDP. The UX will redirect the user to the SAML page for authentication. Upon completion, the UX is redirected to the UX system with a DRP token for normal operations.
Identity Provider Configuration¶
To enable SAML-based Single Sign-On, the system must have ONE or more Identity Provider configured. This configuration requires configuring the IDP with the DRP server's metadata and vice versa.
The SAML Single Sign-On uses the API server's certificate and key for identity. If this certificate/key pair is changed, the metadata at the IDP must be updated.
Register DRP with IDP¶
The DRP server must be registered with the IDP. Registration requires two distinct values, and DRP derives them from separate precedence chains. Setting only one of them is the most common cause of SAML login failures.
The identity (entityID) of the DRP server is the first configured value in order:
| Order | Source | Environment variable |
|---|---|---|
| 1 | Server Host Name | RS_SERVER_HOSTNAME |
| 2 | HA Id | RS_HA_ID |
| 3 | DRP Id | RS_DRP_ID |
The host name used to build the endpoint URLs (the ACS URL and the metadata URL) is the first configured value in order:
| Order | Source | Environment variable |
|---|---|---|
| 1 | Server Host Name | RS_SERVER_HOSTNAME |
| 2 | HA Virtual Address | none |
| 3 | Server listen address | none |
| 4 | localhost |
none |
Set RS_SERVER_HOSTNAME
RS_SERVER_HOSTNAME is the only value that appears at the top of both chains, so setting it makes
the entityID and the endpoint URLs agree. Without it, the entityID falls back to an HA or DRP Id
while the URLs fall back to an IP address, and the two will not match what you register at the IDP.
See Customizing the server at launch time.
The virtual and listen addresses affect only the endpoint URLs. They are never used as the entityID.
IPv6 listen addresses
Colons in the host name are replaced with - when the endpoint URLs are built. If DRP falls back to
an IPv6 listen address, the resulting URLs will not be usable. Set RS_SERVER_HOSTNAME in IPv6
deployments.
With the identity established, registration can be done one of two ways.
For some IDPs, they can be given a URL to get the metadata automatically. The metadata URL
is https://drp-ip:api-port/saml/metadata. Entering this URL into the IDP will cause the IDP to query the DRP Server
for the required certificate and identity information.
The other is to save the metadata into a file. This file will be XML data that can be upload to your identity provider.
This metadata.xml file can be upload to your identity provider. The file can be reused for all Identity Providers.
Register IDP with DRP¶
This requires creating an Identity Provider in the DRP system. This can be either done through the UX or the CLI.
The required fields for the IDP are:
- Name - this is the short name of the IDP.
- DisplayName - this is the displayed name for us in the UX
- LogoPath - this is an optional URL or relative file path into the DRP server. It presents an image for display.
- MetaDataUrl - This the URL to the IDP's metadata.
- MetaDataBlob - This is the XML file from the IDP stored as a string on the object.
All Identity Provider metadata is reloaded at server startup and again whenever any Identity Provider is
created, updated, or removed, including by a content pack load. MetaDataBlob is parsed in place;
MetaDataUrl is fetched from the DRP server at that time.
MetaDataUrl takes precedence. If both fields are set, MetaDataBlob is ignored. Set exactly one.
Unreachable metadata fails silently
If a MetaDataUrl cannot be fetched, or metadata cannot be parsed, that Identity Provider is skipped
and the failure is recorded only in the server log. The Identity Provider object itself shows no
error, and the IDP simply does not appear in /saml/list or on the UX login page. Check the server
log for Failed to get metadata or Failed to parse metadata blob when a configured IDP does not
appear. Because the DRP server performs this fetch, the metadata URL must be reachable from the DRP
server, not just from your browser.
Once both steps are done, SAML can be used for authentication.
Additional Customization¶
Each Identity Provider in DRP will also define the access control path for the authenticated users.
There are two attributes that are delivered by the SAML Assertions. The first attribute is used to define the username.
This is the UserAttribute field. This maps the SAML IDP identity into the Name of a User. This is usually an email for
ease of use, but is not required. If the attribute carries more than one value, only the first is used.
Which attribute identifier to use
UserAttribute and GroupAttribute are matched against each assertion attribute's FriendlyName
when the IDP supplies one, and against its Name otherwise.
The second attribute is used to define groups that should apply to the user. This is the GroupAttribute field.
Groups must be a multi-valued attribute
The IDP must emit the group attribute as a multi-valued SAML attribute, with one group name per attribute value. DRP reads the attribute's values directly and does not split them on any delimiter.
The Identity Provider has three additional fields that control what access the user should have.
- DenyIfNoGroups - If no groups are present or none match, access is denied that user.
- DefaultRole - This is the default role that should be given to the User if no groups match. The DenyIfNoGroups overrides this.
- GroupToRoles - This is a map of group names to lists of roles. It is a key value pair, where the key is the group name and the value is a list of roles to apply.
A user receives the union of the Roles mapped from all of their matching groups.
User Provisioning¶
DRP creates and maintains a User object for each SAML identity automatically. On every successful SAML login, DRP builds a User object from the assertion and writes it, creating the User if it does not already exist.
The written object contains only the name taken from UserAttribute, the Roles resolved from
GroupToRoles (or DefaultRole), and the Meta keys listed below. It replaces the stored User rather
than merging into it.
SAML login overwrites the whole User object
Because the object is replaced, every login discards any other state on that User.
Do not reuse a name that already belongs to a local password user as a SAML UserAttribute value.
The Meta keys written on each login are useful for auditing and troubleshooting:
| Meta key | Contents |
|---|---|
auth-method |
Always saml for SAML logins |
saml-auth |
Name of the Identity Provider that authenticated the user |
auth-groups |
Comma-joined list of groups received in the assertion |
auth-last |
Unix timestamp of the most recent SAML login |
auth-groups records the groups as they arrived, which makes it the quickest way to confirm whether the
IDP is sending the group names you expect.
Every Role named in GroupToRoles and DefaultRole must already exist in DRP. Writing the User fails if
any resolved Role is undefined, and the login fails with it.
Identity Provider Examples¶
AWS¶
An example yaml file for AWS:
---
DefaultRole: "superuser"
DenyIfNoGroups: false
DisplayName: AWS IAM
GroupAttribute: "groups"
GroupToRoles:
role1:
- operator
role2:
- superuser
MetaDataUrl: https://portal.sso.us-west-2.amazonaws.com/saml/metadata/Nzg0NDI0NjE0NTk2X2lucy03MjJmMGU0NjQ5OTRiNzNk
Name: aws-west-2
UserAttribute: "username"
Google¶
For Google, you will need to use go to your Google Workspace Admin page. Navigate to App -> Web and mobile apps.
You will need to "Add app -> Add custom SAML app". You will need to specify an app name, this can be anything along with a description.
At this point, you can download metadata. The contents of this file will need to be added to your IDP object as a MetadataBlob.
With that set, the next pieces to fill in are the ACS URL and the Entity ID. This can be found by selecting Download Metadata in the DRP UX. This file contains the EntityID. This is the value can be found here or the order is defined above. The ACS URL is specified near the end of the line. It looks like this:
<AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://webhook.rackn.io:8092/saml/acs" index="1"></AssertionConsumerService>
The URL is usually <https://><server name or ip>:<api port>/saml/acs. If the ServerHostname is specified, it will be
used. Otherwise, it will be the IP address of the DRP endpoint.
Specify the Name ID format as email. This must be specified, but isn't really used. The registered attributes in the next section as used for group matching.
Add Mapping attributes for the username. Click Add Mapping, select primary email and name the attribute email. Add Mapping attributes for group memberships. Select the groups you want to map to the groups attribute in the bottom section.
Click Finish.
In DRP, create an IDP object for Google. It would look like this:
DefaultRole: ''
DenyIfNoGroups: true
DisplayName: RackN Google Auth
GroupAttribute: groups
GroupToRoles:
Engineering:
- superuser
LogoPath: https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/240px-Google_%22G%22_Logo.svg.png
MetaDataBlob: blob from google
Name: GoogleAuth
UserAttribute: email
Note that UserAttribute matches the attribute containing the email of the user. Note that GroupAttribute matches the attributing containing groups list.
There are some issues with this integration. You will have to clear current google token/auth cookies to get new enabled cookies from Google. Additionally, if you have multiple google accounts, you may have to log out of the accounts that you don't want to use to login. Using an incognito window can help this.
Okta¶
First collect the DRP entityID and ACS URL, because Okta needs both and they must match exactly. Download the Service Provider metadata and read the values from it:
The entityID is the attribute on the root EntityDescriptor element. The ACS URL is the Location
attribute of the AssertionConsumerService element, normally
https://<server name or ip>:<api port>/saml/acs.
In the Okta Admin Console, create an app integration with the following settings:
| Okta field | Value |
|---|---|
| Single sign-on URL | The ACS URL from the DRP metadata |
| Audience URI (SP Entity ID) | The entityID from the DRP metadata |
| Name ID format | EmailAddress |
| Application username | Email |
Name ID must be set, but DRP does not use it for identity. The attributes configured below are what determine the username and groups.
Under Attribute Statements, add the attribute DRP will read as the username:
| Name | Name format | Value |
|---|---|---|
email |
Unspecified | user.email |
Under Group Attribute Statements, add the attribute DRP will read as group memberships. Use a filter that matches the groups you intend to map:
| Name | Name format | Filter |
|---|---|---|
groups |
Unspecified | Matches regex with .* |
A Group Attribute Statement emits one attribute value per group, which is the multi-valued form DRP requires. Narrow the regex if you do not want every Okta group sent in the assertion.
Leave request signing off. DRP does not sign authentication requests, so do not enable a signature requirement on the Okta side. Encrypted assertions are supported and may be enabled if your policy requires them.
Finish the wizard, then assign the app to the users and groups that should have DRP access. On the app's Sign On tab, use the SAML setup instructions or the metadata link to obtain the Okta IDP metadata URL.
In DRP, create the Identity Provider object:
---
DefaultRole: ''
DenyIfNoGroups: true
DisplayName: Okta
GroupAttribute: groups
GroupToRoles:
drp-admins:
- superuser
drp-operators:
- my-operator-role
LogoPath: ''
MetaDataUrl: https://<your-org>.okta.com/app/<app-label>/<app-id>/sso/saml/metadata
Name: okta
UserAttribute: email
DRP ships only two built-in Roles, superuser and discovery. my-operator-role above stands in for a
Role you have already created (see Role). Mapping a group to a Role that does
not exist causes the login to fail.
Take the MetaDataUrl value from the app's Sign On tab rather than assembling it by hand; the path
includes both the app label and the app ID.
UserAttribute and GroupAttribute must match the attribute names configured in the Okta app, not
the Okta source fields. Okta does not send a FriendlyName, so the configured name is what DRP matches on.
The keys under GroupToRoles are Okta group names as they appear in the assertion, and every Role they
map to must already exist in DRP.
Do not test by clicking the app tile in the Okta dashboard or End-User Portal. That is an IDP-initiated
login, which DRP rejects. Test from the DRP UX login page, or by browsing directly to
https://drp-ip:api-port/login?SAML-IDP=okta. See Service Provider Behavior and Limits.
Troubleshooting Tips¶
Troubleshooting issues with the SAML configuration requires some special tools. The RackN support team finds SAML Tracer very useful. It is a plugin for Firefox and Chrome that will allow an operator to debug the payloads coming and going from the Identity Provider and the Service Provider (dr-provision).
The most common problem the RackN support team encounters with customers trying to use SAML is the entityID in the Service Provider metadata not matching what is entered into the Identity Provider. This must match or the browser will end up in a loop unable to log in. The best way to set the entityID of the dr-provision Service Provider is to set the RS_SERVER_HOSTNAME environment variable in the systemd config files.
Example:
cat /etc/systemd/system/dr-provision.service.d/user.conf
[Service]
Restart=always
User=root
Group=root
Environment=RS_BASE_ROOT=/var/lib/dr-provision
Environment=RS_SERVER_HOSTNAME=MY_HOST_NAME
Always confirm the value DRP is actually publishing rather than assuming it, since the entityID and the endpoint URLs are derived from different fallback chains: