Arthur SSO Access Control Overview#

In on-prem installations, cluster administrators have the ability to configure their Arthur install to use a 3rd party identity provider (IdP) to manage Arthur users and access. Arthur can work with any IdP that supports the Open ID Connect (OIDC) or SAML protocols.

User and App Authentication#

Regardless of if your IdP is using OIDC or SAML, the IdP will be responsible for authenticating users and system access to Arthur. As a result, applications or downstream systems that need to authenticate with Arthur will require working with your IdP to get access. Some IdPs provide support for AppID’s or service accounts, but it will depend on the specific IdP and how your organization supports it.

Warning

Important! Arthur API keys cannot be used when SSO in enabled. Instead, users will rely on their own authentication tokens, which are validated by the IdP and enforce the custom permissions assigned to their roles.

Authorization (RBAC)#

Arthur installations with SSO are able to use custom role-based access control policies (RBAC) for users authenticated via the IdP. Arthur’s custom RBAC system uses two kinds of roles. The first kind are organization level roles, which grant a user the specified permissions within a single Arthur organization. The second kind are global roles, which grant the specified privileges across all organizations in the system. Global roles are intended for administrators, so they can perform actions like managing organizations and roles at the global level. They should not be used to grant non-admin users cross-organization access. Instead, users that need access to more than one organization should have a distinct role for each organization. Commonly, the global administrator role only has permissions to create new organizations and to manage custom roles for the platform. All model and data access should be configured using organization scoped roles. See the Custom RBAC for an overview of how to configure custom roles for your Arthur installation.

Linking IdP Groups to Arthur Roles#

Roles are the link between the IdP’s user groups and the Arthur access control system. As shown in Set Up an Identity Provider, when you configure an IdP, you will tell Arthur how to parse a user’s groups out of the IdP response. The group, or list of groups, returned from your IdP must match the names of custom roles configured in Arthur. For this reason, Arthur enforces all custom roles to have unique names, so the platform can map a user group from an external IdP to a specific set of permissions. This means all roles in the system must have unique names, even across organizations.

For example, if using OIDC and the IdP returns a JWT token of the following format, Arthur must be configured with roles that match the groups listed under the “groups” field in the token. The group names are used to look up the roles that apply for the user in Arthur. More examples of how to configure the OIDC JWT claim parsing can be found in Setting Up an OIDC IdP.

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  // this field in the token corresponds to the user's groups in the IdP
  "groups": [
    // an "idp-admin" role must be created in Arthur to match this group
    "idp-admin",
    // an "org-1-user" role must be created in Arthur to match this group
    "org-1-user"
  ]
}

Note

It is ok if the OIDC token contains extra groups that are not matched to roles in Arthur. It is not required that every group have a corresponding role, but at least one group must.

Similarly if using SAML, the SAML assertion from the IdP must contain some attribute values that contains the user’s groups in the IdP. More examples of how to configure the SAML attribute parsing can be found in Setting Up a SAML IdP.

<saml2:AttributeStatement>
    <saml2:Attribute Name="email">
        <saml2:AttributeValue>support@arthur.ai</saml2:AttributeValue>
    </saml2:Attribute>
    <saml2:Attribute Name="firstName">
        <saml2:AttributeValue>John</saml2:AttributeValue>
    </saml2:Attribute>
    <saml2:Attribute Name="lastName">
        <saml2:AttributeValue>Doe</saml2:AttributeValue>
    </saml2:Attribute>
    // this field in the assertion corresponds to the user's groups in the IdP
    <saml2:Attribute Name="groups">
        // an "idp-admin" role must be created in Arthur to match this group
        <saml2:AttributeValue>idp-admin</saml2:AttributeValue>
        // an "org-1-user" role must be created in Arthur to match this group
        <saml2:AttributeValue>org-1-user</saml2:AttributeValue>
    </saml2:Attribute>
</saml2:AttributeStatement>

Note

It is ok if the SAML assertion contains extra groups that are not matched to roles in Arthur. It is not required that every group have a corresponding role, but at least one group must.

Set Up an Identity Provider#

OIDC#

See Setting Up an OIDC IdP for the steps to configure an OIDC IdP with Arthur.

SAML#

See Setting Up a SAML IdP for the steps to configure a SAML IdP with Arthur.

Creating Custom Roles#

As mentioned above, custom roles can be used to grant either permissions within an organization or permissions across all organizations. This section will first cover how to create global roles, then it will cover how to create roles for an organization. The steps outlined here are sufficient to get SSO working. For more details about managing custom RBAC access control, please see the Custom RBAC guide.

Creating Global Roles for Managing Organizations and RBAC Policies#

Note

In order to complete this section, you must have access to the Arthur Admin Console config page.

Global roles are intended to be used by a cluster administrator to manage organizations and roles in the Arthur application. Global roles should be scoped with the minimal privileges and should be given out with caution. It is not recommended to grant model or data access with global roles as that would give access to every model in the system. Global roles can be created in the Arthur installer Admin Console configuration in the “Use a 3rd Party Global Identity Provider” section where the IdP configuration YAML is set. A list of custom global roles can be provided in the Identity Provider YAML under the globalRoleDefs key. The following example shows a global role for an Arthur cluster admin to manage organizations and RBAC for the installation:

  globalRoleDefs:
    # Here we specify a list to define multiple global roles
    - name: "idp-admin" # change the name of this role to match the cluster administrator group name in your IdP
      # this role grants a user permissions to manage organizations and RBAC policies in Arthur 
      permissions:
        custom_roles:
          - read
          - write
          - delete
        organization_global:
          - read
          - write
        organization:
          - read
          - delete

Once you add a role to your config, be sure to click “Save” at the bottom of the page and then deploy the change. After the update completes, the new global role should be created.

Creating Organization Scoped Roles for Non-admin Users#

Completing this section will require either access to the Arthur superadmin user, or access to a previously created, custom global role assumable via an IdP (see above). Additionally, only installations with SSO configured can use custom RBAC policies. If you do not have SSO configured, please see Arthur Standard Access Control Overview.

The section below assumes an organization already exists that you would like to give users access to. If you would like to create a new Arthur organization, please check out the Managing RBAC and Organizations for SSO users, then come back here to add roles to that new organization.

Using either the Arthur superadmin user or having assumed a custom RBAC role with global scope to manage RBAC, organization scoped roles can be created using the Arthur API. The following is an example of a request to create a new role in an organization. Be sure to fill in the missing values for the hostname, authorization token (must be a superadmin or your token from a custom global role), organization ID, and change the role names to match your IdP user groups. See Managing RBAC and Organizations for SSO users for an overview of role permissions and some example roles.

curl --location 'https://<YOUR ARTHUR HOST HERE>/api/v3/authorization/custom_roles' \
--header 'Arthur-Organization-ID: <YOUR ORGANIZATION ID HERE>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <YOUR AUTH TOKEN HERE>' \
--data '{
    "roles": [
        {
            "role_name": "my-idp-group-1",
            "inherited_role_names": [
                "Administrator"
            ]
        },
        {
            "role_name": "my-idp-group-2",
            "inherited_role_names": [
                "Model Owner"
            ]
        }
    ]
}'

This sample API call will create two custom roles in the <YOUR ORGANIZATION ID HERE> organization. These roles will apply to users in the “my-idp-group-1” or “my-idp-group-2” groups managed by the IdP.

Granting Users Access to Multiple Organizations#

Users can be given access to multiple organizations by creating a unique custom role in each organization, then adding them to the associated groups in the IdP. For example, if you have two organizations, org-1 and org-2, the Arthur cluster administrator will need to create a custom role in each organization. Let’s call them role-1 and role-2 respectively. As described above, these role names will need to correspond to user groups in the IdP so please name them according to your group names. With two organizations and a role created in each, the last step is to add your users to both groups in your IdP, and they will be able to access both organizations.

Note

If users have access to more than one organization, they will need to specify one to use during API calls. See the next section for more information on how to specify an organization when using the Arthur API.

API Authentication with Multiple Organization Users#

The Arthur platform separates resources logically by Arthur Organizations. When an Arthur deployment is configured with Arthur’s Standard Authentication mechanism, user access is granted to one organization at a time, so all interactions with the platform are automatically scoped with that organization.

However, when SSO is enabled, SSO tokens can grant access to one or more Arthur organizations at a time. They do this by listing multiple roles for a user within the token, each with access to a distinct organization. As a result, users can have access to more than one organization at a time, and Arthur cannot determine which organization the user intends to take an action in. Therefore, when SSO users have access to more than one organization, they must select a specific Arthur Organization in each request to the platform via the methods described in this section.

Alternatives for Selecting an Organization in the Arthur API#

  1. Request Header

  2. Session-Based Organization Tracking

  3. Arthur SDK Client

  4. Deep Linking to an Organization in the UI

Request Header#

In an API call made by an SSO-authenticated user with access to more than one organization, the platform will first check for a request header with an Arthur-Organization-ID key. If one is found, the platform will parse it and, assuming the organization exists and the calling user can access it, continue the request with the specified ID as its target organization. If the header is not found, it will fall back to one of the other methods described below. If the header is present and the user does not have access to the organization, the API will return a 404 status code.

Session-Based Organization Tracking#

If no organization-specifying request header is included in the request, the platform will then use session information to determine one.

Sessions enable users to establish a long-lived association with an organization that can be used to automatically scope all requests to a specific organization. Users can establish a session using the PUT /organizations/current endpoint. Similarly, they can retrieve the organization from their current session with the GET /organizations/current endpoint.

By calling PUT /organizations/current with a target organization specified, a user receives an _arthur_session cookie that associates future requests with the target organization. Any future calls to PUT /organizations/current will return a new _arthur_session cookie to track your new session for whichever organization is specified in the PUT call.

By calling GET /organizations/current with an _arthur_session cookie included in the request, users can retrieve the organization their current session is associated with.

Note

Sessions do not provide any access to Arthur on their own. They only keep track of the user’s association with a specific organization. Users must also have an access token to authenticate with the Arthur APIs. Since sessions do not grant any access to the Arthur platform, they expire after 30 days to prevent users from repeatedly having to specify an organization.

Arthur SDK Client#

For SSO-authenticated users with access to more than one organization working with the Arthur SDK, the SDK client allows selecting a specific organization. Note: SDK users with access to a single Arthur organization will automatically have their one organization set.

When an SDK user is instantiating the ArthurAI client , they can first specify which organization they want that client to be associated with by passing in that organization’s ID as the organization_id optional parameter.

connection = ArthurAI(organization_id=org_id: str, ...)

After the ArthurAI client has been instantiated, users can update the client’s current organization by calling the set_current_org() method.

connection.set_current_org(org_id: str)

At any point, SDK users can access their ArthurAI client’s current organization by calling the get_current_org() method.

current_org = connection.get_current_org()

Deep Linking to an Organization in the UI#

If an SSO-authenticated user has access to more than one organization, Arthur allows them to bypass manual organization selection through deep linking. A user can append the url parameter ?organization_id=<ORG-ID> to the Arthur platform host name, where <ORG-ID> is equal to one of the organization IDs to which the user has access. This will tie the users session to that organization ID upon authentication through SSO.

N.B. This will only work when appended to the platform host name. E.g. https://[Arthur hostname]/?organization_id=<ORG-ID> This will not work if you are attempting to apply the parameter to any other path on the Arthur host. E.g. https://[Arthur hostname]/login/?organization_id=<ORG-ID> will NOT work.