Dashboard
Platform

User Authentication via SAML and Okta

Gremlin supports several different authentication systems, including password-based (default), Google, OAuth, and SAML. Additionally, you can set certain parameters for different systems, such as requiring MFA during password-based login, or requiring a claim be present during SAML logins. This page provides the necessary instructions for setting up different authentication systems.

Configuring Authentication Preferences

Company Admins and Owners can control which authentication methods are enabled for their users via our Authentication Preferences settings under the Security tab. Here you can enable or disable each of our authentication methods—password, Google, OAuth and SAML—and set extra controls for each one.

Authenticating users with multi-factor authentication (MFA)

Users can enable a multi factor authentication for password based logins in Gremlin Company Settings under the Security tab. Currently, Time-based Token (Time-based One Time Passwords, TOTP) MFA is supported. An example of a compatible authenticator is the Google Authenticator, available on the Apple App Store and Google Play.

MFA can be forced for users across the entire company. When <span class="code-class-custom">MFA Required</span> is enabled via the Authentication Preferences, all users who authenticate without MFA will be provided with a secret key and QR barcode to setup their authenticator. Certain user roles also have the ability to disable MFA for individual users within their company, useful in cases where a user loses their authenticator.

When logging in with SSO, you will not be prompted to use MFA; even if it is enabled for your account. We defer to the SSO provider to enforce MFA.

Authenticating users with SAML

Gremlin supports Security Assertion Markup Language (SAML) via a compatible Identity Provider (IDP). When using SAML, Gremlin forwards authentication requests to your IDP, which performs authentication according to your company's specifications. If a user is authenticated successfully, the IDP returns details such as their email address to Gremlin, and they're granted access. Details and authentication requests are delivered securely.

In order to configure SAML in Gremlin, you must have either the <span class="code-class-custom">Owner</span> or <span class="code-class-custom">Admin</span> company roles.

Here's an overview of the steps required to authenticate using SAML:

  1. Gather the Gremlin Service Provider (SP) metadata.
  2. Gather the fields necessary for configuring SAML.
  3. Configure SAML claims.
  4. Integrate with your IDP.

1. Gathering the Gremlin Service Provider (SP) metadata

In order to configure your IDP for SAML, you'll need our Service Provider (SP) metadata. You can retrieve our Service Provider (SP) metadata with the following command:

BASH

curl https://api.gremlin.com/v1/users/auth/saml/metadata

2. Gathering the fields necessary for configuring SAML

The following fields are necessary for configuring your Identity Provider (IDP):

Field NameDescriptionValue
Assertion Consumer Service URLThe URL that will validate your IDP's SAML assertion.https://api.gremlin.com/v1/users/auth/saml/acs
Service Provider Entity IDUnique identifier for the Gremlin SPSPID.http://api.gremlin.com/saml
RelayStateHow to relay users once they're authenticated. See this footnoteRelayState for details.CompanyName|||https://app.gremlin.com/users/sso/saml/acs|||/
NameID FormatThe format of the NameID within the SAML assertion. This must be a valid email address.urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
Signature MethodThe format we use for signing our SAML metadata and requests (sha256).http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
AuthnRequestUsed by our SP to send users to their IDP during SP-initiated logins.urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect
AuthnReponseUsed by your IDP when returning the response to our ACS.urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST

3. Configuring SAML claims

SAML claims let you define the roles and team memberships users should possess when authenticating with Gremlin. Using the information provided in the claim, Gremlin will create the user if they haven't authenticated before, or update them if they have. These claims take the form of an <span class="code-class-custom">AttributeStatement</span> which is included within the <span class="code-class-custom">Assertion</span>block that is sent in the SAML Response from your IDP. Within this <span class="code-class-custom">AttributeStatement</span> are <span class="code-class-custom">Attributes</span> defining company level roles and team memberships for the user.

Warning
These will overwrite any existing roles and team memberships that the user has. For instance, if the user currently has the COMPANY_OWNER role, and the claim only specifies COMPANY_USER, then the user will now have COMPANY_USER as their only role. The same applies for team memberships, if a user belongs to teamA and teamB, yet the claim only has an attribute specifying membership and role information for teamA, then the user will no longer be a member of teamB. If a claim is sent with no team memberships, then the user will be removed from any teams they are currently on.

Company roles attribute

This determines the Company-level roles that a user has (if any). The attribute name is <span class="code-class-custom">company:roles</span>. You can only have one company role attribute block in the SAML claim, but the block can have <span class="code-class-custom">AttributeValues</span> as long as each one contains a valid role.

The valid roles are:

  • <span class="code-class-custom">COMPANY_USER</span>
  • <span class="code-class-custom">COMPANY_COORDINATOR</span>
  • <span class="code-class-custom">COMPANY_ADMIN</span>
  • <span class="code-class-custom">COMPANY_MANAGER</span>
  • <span class="code-class-custom">COMPANY_OWNER</span>

Details on these privileges these roles have can be found here. Here is an example of what an attribute looks like for a user with both <span class="code-class-custom">COMPANY_OWNER</span> and <span class="code-class-custom">COMPANY_USER</span> roles:

XML

<saml:Attribute Name="company:roles" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
  <saml:AttributeValue xsi:type="xs:string">COMPANY_OWNER</saml:AttributeValue>
  <saml:AttributeValue xsi:type="xs:string">COMPANY_USER</saml:AttributeValue>
</saml:Attribute>

Team membership attribute

This determines the Team-level roles that a user has. The valid roles for the team attributes are:

  • <span class="code-class-custom">TEAM_USER</span>
  • <span class="code-class-custom">TEAM_VIEWER</span>
  • <span class="code-class-custom">TEAM_CREDENTIAL_MANAGER</span>
  • <span class="code-class-custom">TEAM_MANAGER</span>

For details on the privileges available for each role, see Role Based Access Control.

There are two different ways to define the team membership attribute depending on your IDP limitations:

  1. The team roles format (recommended).
  2. The team membership format.

You can use either format, but you can only use one format in your SAML claim.

Note
To access the Gremlin web app, users must belong to a company and a team. You can create a user who only exists at the company level: this approach is commonly used for API automation, where the "user" manages administrative tasks like security settings.

Team roles format

The team roles format provides a more compact way of defining per-team roles. This is the recommended format, as long as your IDP supports it. In this format, each <span class="code-class-custom">AttributeValue</span> defines both the team and the roles the user has for each team. You can define multiple roles using a comma-separated list. You can use either the team name or team ID as the identifier.

For example, here we add a user to two teams. The user will have the following permissions:

  • For <span class="code-class-custom">My Other Team: TEAM_MANAGER and TEAM_USER</span>
  • For <span class="code-class-custom">6b336d49-e8ce-5a73-976c-39000cf3d1d0: TEAM_USER</span>
XML

<saml:Attribute Name="team:roles" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
  <saml:AttributeValue xsi:type="xs:string">My Other Team;TEAM_MANAGER,TEAM_USER</saml:AttributeValue>
  <saml:AttributeValue xsi:type="xs:string">6b336d49-e8ce-5a73-976c-39000cf3d1d0;TEAM_USER</saml:AttributeValue>
</saml:Attribute>

You can find the team name and identifier by going to the team's configuration page:

Team memberships format

The team memberships format splits out each team into its own <span class="code-class-custom">Attribute</span> and defines roles as <span class="code-class-custom">AttributeValue</span>. It's more verbose than the team roles format, but may be more compatible with certain IDPs.

You define an <span class="code-class-custom">Attribute</span> per team membership for the user. Each <span class="code-class-custom">Attribute</span> name is in the format <span class="code-class-custom">team:teamId</span> or <span class="code-class-custom">team:teamName</span>. The roles the user possesses for this team are defined in the <span class="code-class-custom">AttributeValues</span> of this <span class="code-class-custom">Attribute</span>. Each <span class="code-class-custom">AttributeValue</span> can contain a singular role, e.g. <span class="code-class-custom">TEAM_USER</span>, or it can contain a comma-separated list of roles, e.g. <span class="code-class-custom">TEAM_USER,TEAM_MANAGER</span>.

Here is an example of two team memberships in the form of multiple <span class="code-class-custom">Attributes</span>. One uses the <span class="code-class-custom">team:teamId</span> attribute name with one role per <span class="code-class-custom">AttributeValue</span> and the other uses the <span class="code-class-custom">team:teamName</span> attribute name with one <span class="code-class-custom">AttributeValue</span> containing a comma-separated list of roles. Both are valid.

XML

<saml:Attribute Name="team:6b336d49-e8ce-5a73-976c-39000cf3d1d0" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
  <saml:AttributeValue xsi:type="xs:string">TEAM_MANAGER</saml:AttributeValue>
  <saml:AttributeValue xsi:type="xs:string">TEAM_USER</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="team:My Other Team" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
  <saml:AttributeValue xsi:type="xs:string">TEAM_USER,TEAM_MANAGER</saml:AttributeValue>
</saml:Attribute>

4. Integrating with your SAML IDP

The next step is adding Gremlin as a Service Provider to your Identify Provider (IDP). While there are more IDPs than we can cover in this document, we'll focus on two: Okta and ADFS.

Okta setup example

If you are using Okta as your IDP, you can utilize Gremlin's Okta Integration in Okta's Integration Network. Instructions on how to setup our integration can be found in Okta's SAML documentaion.

ADFS setup example

These instructions are for Active Directory Federation Services (ADFS).

Prerequisites:

  • An Active Directory (AD) instance where users have a specified email address.
  • A running Microsoft Server with ADFS deployed.
  • An SSL certificate to secure your ADFS endpoints.
  • Save the Service Provider (SP) metadata as a file. SP metadata is available from the metadata endpoint.
  • Open the ADFS management console and select A<span class="code-class-custom">D FS > Relying Party Trusts</span>. Right click Relying Party
    Trusts and select <span class="code-class-custom">Add Relying Party Trust</span>.
  • In the Welcome screen select the desired option for <span class="code-class-custom">Claims aware</span> or <span class="code-class-custom">Non claims aware</span>. We have selected Claims aware.
  • In the Select Data Source screen, choose <span class="code-class-custom">Import data about the relying party from a file</span>. Enter the path to the file downloaded in step 1. Note: It is possible to enter this information manually, or ask ADFS to retrieve it directly. See ADFS documentation for more information.
  • On the Specify Display Name screen enter the desired <span class="code-class-custom">Display Name</span> for this service as well as any <span class="code-class-custom">Notes</span>. You can enter anything you wish here.
  • In the Choose Access Control Policy screen select the access control policy suitable for your environment. We have chosen to <span class="code-class-custom">Permit everyone and require MFA</span>.
  • In the Ready to Add Trust screen, you can review the configuration and make any necessary changes. For more information about a particular configuration setting please consult the ADFS documentation.
  • In the Finish screen you can select <span class="code-class-custom">Configure claims issuance policy for this application</span> if desired. Click Close.

Authenticating users with OAuth

Gremlin supports OAuth authentication via custom defined OAuth providers.

OAuth features are currently only available via the API.

Configuring an OAuth provider

When configuring an OAuth provider we require the following information:

  • <span class="code-class-custom">Authoriztion URI</span>: Used to authenticate against the OAuth provider. We will redirect the user to this URL when they initate a OAuth login.
  • <span class="code-class-custom">Token URI</span>: Used to exchange an OAuth code, obtained after logging into the OAuth provider, for an access token.
  • <span class="code-class-custom">User Info URI</span>: Used to query for the email of the user..
  • <span class="code-class-custom">Client Id</span>: The public identifier obtained when registering Gremlin with your OAuth provider.
  • <span class="code-class-custom">Client Secret</span>: The secret obtained when registering Gremlin with your OAuth provider.
  • <span class="code-class-custom">Scope (optional)</span>: Define what level of access the access token will have that Gremlin obtains during the OAuth login. The default is <span class="code-class-custom">email</span>. If you change it from the default, the scope provided must be able to read the email of the user.

To configure these settings you can send the following <span class="code-class-custom">POST</span> request to our API:

BASH

curl -X POST \
    --header "Content-Type: application/json" \
    --header "Authorization: $bearertoken" \
    https://api.gremlin.com/v1/companies/$companyId/oauth/settings \
    --data '
    {
      "authorizationUri": "https://example.com/oauth/authorize",
      "tokenUri": "https://example.com/oauth/token",
      "userInfoUri": "https://example.com/user",
      "clientId": "exampleClientId",
      "clientSecret": "exampleClientSecret",
      "scope": "email"
    }'

Authenticating via OAuth

After configuring your OAuth provider, you are ready to intiate a OAuth login flow.

To illustrate the flow we have provided a commented python script that explains each step of the process. The <span class="code-class-custom">requests</span> library is a prerequisite for running this script as well as Python 3.

PYTHON

import requests

COMPANY_NAME = 'Example Company'

"""
Initiates OAuth login with Gremlin
We set `allow_redirects=false` here so we can capture
the response and extract the state cookie
"""
login_response = requests.get(
   f"https://api.gremlin.com/v1/oauth/login?companyName={COMPANY_NAME}",
   allow_redirects=False
)
assert login_response.status_code == 307

"""
Response is a 307 redirect to your OAuth provider with the URL
in the Location header as well as the OAuth state cookie.
This cookie is required to prevent against CSRF attacks,
additionally it tracks your state as the OAuth flow progresses.
You need to extract this cookie so it can be used later
when being redirected back to the Gremlin API.
"""
state_cookie = login_response.cookies['oauth_state']
oauth_provider_login_url = login_response.headers['Location']

assert state_cookie != None
assert oauth_provider_login_url != None

"""
This part is implementation specific depending on your OAuth provider.
Different OAuth providers may require different things when authenticating the user.
Also for the first time you authenticate to your OAuth provider with Gremlin,
a browser may be required so that you can grant
Gremlin access based on the scope we request.

This example is performing a simple POST request to an
example OAuth provider with the following information:

 - email: Login email for your user
 - password: Login password for your user
 - state: Value of the state cookie obtained in the previous step
 - redirectUri: URL where your provider should redirect you to after authenticating.
                It should be https://api.gremlin.com/v1/oauth/callback
 - clientId: Client Id obtained when registering Gremlin with your OAuth provider

The login specific information may vary depending on your OAuth provider,
but the state, redirectUri and clientId paramaters
are often required across all types of provider.
"""
body = {
    'email':  'test@example.com',
    'password': '*********',
    'state': state_cookie, # obtained in earlier step
    'redirectUri': 'https://api.gremlin.com/v1/oauth/callback',
    'clientId': 'exampleClientId'
}

"""
Don't follow redirect as we need to add the state cookie to the next request
"""
oauth_provider_login_response = requests.post(
   oauth_provider_login_url,
   data=body,
   allow_redirects=False
)

"""
You have now successfully authenticted with your OAuth provider,
now continue the flow by following the redirect your OAuth provider
created back to Gremlins /oauth/callback endpoint
"""
gremlin_callback_url = oauth_provider_login_response.headers['Location']
assert gremlin_callback_url != None

"""
Add the state cookie to the request and then follow the redirect
to Gremlins /oauth/callback endpoint. If the state cookie is not
added the request will fail. There is a state parameter in the
redirect URL you are following and it needs to match the
value in the cookie. This helps prevent CSRF attacks.
"""
cookie = {
    'oauth_state': state_cookie
}
gremlin_callback_response = requests.get(
   gremlin_callback_url,
   cookies=cookie
)

"""
The response from the callback endpoint will contain the `access_token` in JSON
This is the end of the OAuth specific flow. This `access_token` can
now be exchanged for a Gremlin session.
"""
assert gremlin_callback_response.status_code == 200

access_token = gremlin_callback_response.json()['access_token']
assert access_token != None

"""
We now need a valid Gremlin session which can be used to access
the authenticated portions of our API. Craft a request to /users/auth/sso
to exchange access_token for a Gremlin session
"""
body = {
    'companyName': COMPANY_NAME,
    'accessToken': access_token,
    'provider': 'oauth',
}
sso_response = requests.post(
   f"https://api.gremlin.com/v1/users/auth/sso?getCompanySession=true",
   data=body
)
assert sso_response.status_code == 200

"""
The response is a JSON representation of the session.
In this JSON response is the `header` field which contains a
Bearer token that can be used in the `Authorization` header
when making requests to the Gremlin API.
"""
bearer_token = sso_response.json()['header']
assert bearer_token != None

"""
Done!
"""

If you encounter any errors during this process or have any questions please reach out to support@gremlin.com.

OpenID Connect Claims

Gremlin supports the OpenID Connect extension to OAuth, allowing you to specify roles and team memberships for your user through the form of JSON Web Token claims.

The first claim we require is either the <span class="code-class-custom">sub</span> or <span class="code-class-custom">email</span> claim. We look at both when determining the email for the user being authenticated. At least one of these claims must be present and contain a valid email. The <span class="code-class-custom">sub</span> claim will take priority over the <span class="code-class-custom">email</span> claim if both are found to be valid emails.

Specifying the role and team memberships for the user are supported via the following two custom claims:

  • <span class="code-class-custom">company_roles</span>: A list of strings, each value is a role that the user will hold at the company level.
  • <span class="code-class-custom">team_roles</span>: A list of strings, each value represents a single team membership the user will have. The team membership is defined in the following format - <span class="code-class-custom">teamName;Role1,Role2</span>.

Here is an example of what this would look like in the JSON Web Token:

JSON

{
  "company_roles": ["COMPANY_USER"],
  "team_roles": ["Team A;TEAM_USER", "Team B;TEAM_MANAGER,TEAM_USER"]
}

In the above example, the user will be given the <span class="code-class-custom">Company User</span> role, and will have a membership in Team A with the Team User role and a membership in Team B with the <span class="code-class-custom">Team User</span> and <span class="code-class-custom">Team Manager</span> roles.

These claims are the source of truth for a user's access. Any roles and memberships they currently hold will be overwritten by what's in the claim. Referring back to the above example, if the user was originally a member of Team C, they will be removed from that team since a Team C membership is not present in the claim. If a claim is sent with no team memberships, then the user will be removed from any teams they are currently on. Additionally, if the user being authenticated does not exist in Gremlin yet, they will be created using the role and membership information present in the claim.

  • The RelayState consists of three parameters seperated by <span class="code-class-custom">|||</span>:
  • Parameter 1 is your company name. This should match your company name in Gremlin.
  • Parameter 2 is the app address, where our Assertion Consumer Service (ACS) sends the user once it is done validating.
  • Parameter 3 is where we send the user once the login is fully complete. The default destination is the Gremlin home page.
  • The Service Provider Identity ID is different from the Entity ID that you entered in your SAML configuration page at <span class="code-class-custom">/settings/security</span>. The Entity ID there is your IDP Entity ID, which is unique to your IDP. This value is Gremlin's unique SP Entity ID, which you may be required to provide to your IDP when setting up IDP initiated logins.

No items found.
Next
Previous
This is some text inside of a div block.
Compatibility
Installing the Gremlin Agent
Authenticating the Gremlin Agent
Configuring the Gremlin Agent
Managing the Gremlin Agent
User Management
Integrations
Health Checks
Notifications
Command Line Interface
Updating Gremlin
Quick Start Guide
Services and Dependencies
Detected Risks
Reliability Tests
Reliability Score
Targets
Experiments
Scenarios
GameDays
Overview
Deploying Failure Flags on AWS Lambda
Deploying Failure Flags on AWS ECS
Deploying Failure Flags on Kubernetes
Classes, methods, & attributes
API Keys
Examples
Container security
General
Linux
Windows
Chao
Helm
Glossary
Alfi
Additional Configuration for Helm
Amazon CloudWatch Health Check
AppDynamics Health Check
Application Level Fault Injection (ALFI)
Blackhole Experiment
CPU Experiment
Certificate Expiry
Custom Health Check
Custom Load Generator
DNS Experiment
Datadog Health Check
Disk Experiment
Dynatrace Health Check
Grafana Cloud Health Check
Grafana Cloud K6
IO Experiment
Install Gremlin on Kubernetes manually
Install Gremlin on OpenShift 4
Installing Gremlin on AWS - Configuring your VPC
Installing Gremlin on Kubernetes with Helm
Installing Gremlin on Windows
Installing Gremlin on a virtual machine
Installing the Failure Flags SDK
Jira
Latency Experiment
Memory Experiment
Network Tags
New Relic Health Check
Overview
Overview
Overview
Overview
Overview
Packet Loss Attack
PagerDuty Health Check
Preview: Gremlin in Kubernetes Restricted Networks
Private Network Integration Agent
Process Collection
Process Killer Experiment
Prometheus Health Check
Role Based Access Control
Running Failure Flags experiments
Scheduling Scenarios
Shared Scenarios
Shutdown Experiment
Slack
Teams
Time Travel Experiment
Troubleshooting Gremlin on OpenShift
User Authentication via SAML and Okta
Users
Webhooks
Integration Agent for Linux
Test Suites
Restricting Testing Times
Reports
Process Exhaustion Experiment
Enabling DNS collection