Fork me on GitHub
Teleport

SSH Authentication with Okta

How to use Okta as a single sign-on (SSO) provider for SSH

This guide will cover how to configure Okta to issue SSH credentials to specific groups of users. When used in combination with role based access control (RBAC), it allows SSH administrators to define policies like:

  • Only members of "DBA" group can SSH into machines running PostgreSQL.
  • Developers must never SSH into production servers.
Version Warning
This guide requires a commercial edition of Teleport. The open source edition of Teleport only supports Github as an SSO provider.

Enable SAML Authentication

First, configure Teleport auth server to use SAML authentication instead of the local user database. Update /etc/teleport.yaml as shown below and restart the teleport daemon.

auth_service:
    authentication:
        type: saml

Configure Okta

First, create a SAML 2.0 Web App in Okta configuration section

1. Switch to Classic UI

Switch to classic UI

2. Select Create New App

Select Web Platform and SAML 2.0 Sign On Method.

Create APP

Configure the App

We are going to map the Okta groups we've created above to the SAML Attribute statements (special signed metadata exposed via a SAML XML response).

GENERAL

  • Single sign on URL https://teleport-proxy.example.com:3080/v1/webapi/saml/acs
  • Audience URI (SP Entity ID)https://teleport-proxy.example.com:3080/v1/webapi/saml/acs
  • Name ID format EmailAddress
  • Application username Okta username

SINGLE ATTRIBUTE STATEMENTS

  • Name: username | Name format: Unspecified | Value: user.login

GROUP ATTRIBUTE STATEMENTS

  • Name: groups | Name format: Unspecified
  • Filter: Matches regex | .*
Configure APP

Note: RegEx requires .*

Configure APP
tip
Notice that we have set "NameID" to the email format and mapped the groups with a wildcard regex in the Group Attribute statements. We have also set the "Audience" and SSO URL to the same value.

Create & Assign Groups

Create Groups

We are going to create two groups: "okta-dev" and "okta-admin":

Create Group Devs

...and the admin:

Create Group Devs

Assign groups and people to your SAML app:

Configure APP

Make sure to download the metadata in the form of an XML document. It will be used it to configure a Teleport connector:

Download metadata

Create a SAML Connector

Now, create a SAML connector resource:

#
# Example resource for a SAML connector
# This connector can be used for SAML endpoints like Okta
#
kind: saml
version: v2
metadata:
  # the name of the connector
  name: new_saml_connector
spec:
  # connector display name that will be appended to the title of "Login with"
  # button on the cluster login screen so it will say "Login with Okta"
  display: Okta
  # SAML provider will make a callback to this URL after successful authentication
  # cluster-url is the address the cluster UI is reachable at
  acs: https://<cluster-url>/v1/webapi/saml/acs
  attributes_to_roles:
    - {name: "groups", value: "okta-admin", roles: ["admin"]}
    - {name: "groups", value: "okta-dev", roles: ["dev"]}
  # Note that the entire XML document is indented by 4 spaces. This is
  # required because the pipe symbol indicates what follows is raw text.
  # Below is an Example. Replace with your XML
  entity_descriptor: |
    <md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://www.example.com/00000000000000000000">
      <md:IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
        <md:KeyDescriptor use="signing">
          <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:X509Data>
              <ds:X509Certificate>Lu4bLZ57YSPClo5x1RHtXihqSdBfwqTU1tiPnL3i5QrHAXnyrmwscJ1VnutbfaTWCsPlICYQAVin
    vSAArSQU5WTjvZut9UeEenrYY72xDCLNe5vHimOEHFRvPeP626vx7/gkKSSL5F0Se+YYhLLCWcz8
    DYrQn41YZb72PBt5T0vIRS3FMZOYz55Ww8XbIWAwIKKmRfm00bPpMYPTD34ZCnVGTXSkHzHDCehu
    pQMug4IpWIcy45ffbi6sXoFD1ud8vG8H0RFhUk8MBFSCSsYHkrgz5cB8sbPLs0PocxN/nYIFJ2A1
    U68y2d3U/ClLfOb/kh4w3EcKvqtSwsMdLgxHjrDGtPgiAZDJhriZnpCQ0WvgBcAOYjRjsFncTRWH
    DqpTXsQzjkRa3A/KD3pA6bd5aYSF21nKAR7aVj7Aq0ogWEb4owZL5/W2lEnuwKSfGcnrz6GmJSaT
    113wKahleH/VPb1KoaGJ81h5Om1DZI3ohYuxQYC/jwDhOlPXpdECkJe11gSTp34WQ1a93uSYkGo9
    MZ/7WI2LXpD6pjGtz5YSVKR1naj2pci5jwGi86KwL2MqXX288vguvGqcGZXUwi+383Ct99WLBNgo
    9A6kIFvexILcscyeKthsoBGzu+MBipoGnSYuw+vlSa/0jIoluQqYpqYIg7ZBWoOjrKDDFdv01BtL
    nnVBFR43wCIm77obPQ5+103KYWcs42wpAxtX78HdlTav/D35D45GnGxM/fadpth65BSejgoPnd+z
    MXwMOv2W8B+fuolEcQGLrXw+mHtc2p3A7XKGhexY5A+FkSlAs3RMa0weizcylDlW2vj7ksdmZ/Ag
    AQ6EetT85DS6gV9wn3pBaWRhFU/OqFT/PezFcnxjiHVwfil+G9nhYhmjaspLqSLTkGPnyYabReZw
    ZtnSnKnWfwEr5GDqfYxHkBdZUtiofNhu/K/gs/aLTGoxWVac6F9y1xzXYnXPEPkmNsFfwn/H+LuL
    M01dKisWCfMPHCeBTxKSMB3IrixUym64cxlqkvk/rPXrUcktfvPhd/1I9jWIzQwPfbWyW9wpYzBm
    xYqZ1MocFyZhfh1UHOwaOiMlgAlOTDn6irtT1BW/a45nAkCl8jqgFKPSJ6kusj+HffSL6xDQJ0vA
    L5BGENThmToTm7euueLzYY0JDqhqo18wnha5MSCJtB3dcqKTeK+jiyF7FRHfZt/qJolXCufZyN48
    DQGrdrUjjolHvE8jmtgPkYuq9pdTciUnJIQN8vtQ/tOgk0Ui3n03FSM0YNARyaTZ0vgj+GLfGMc6
    VFKf6t/sSgFO8W4dgi2e0VwryOd8Etrq5NFul</ds:X509Certificate>
            </ds:X509Data>
          </ds:KeyInfo>
        </md:KeyDescriptor>
        <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</md:NameIDFormat>
        <md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
        <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://www.example.com/app/teleport/00000000000000000000"/>
        <md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://www.example.com/app/teleport/00000000000000000000"/>
      </md:IDPSSODescriptor>
    </md:EntityDescriptor>

Create the connector using tctl tool:

$ tctl create okta-connector.yaml

Create Teleport Roles

We are going to create 2 roles, privileged role admin who is able to login as root and is capable of administrating the cluster and non-privileged dev.

kind: role
version: v3
metadata:
  name: admin
spec:
  options:
    max_session_ttl: 24h
  allow:
    logins: [root]
    node_labels:
      "*": "*"
    rules:
      - resources: ["*"]
        verbs: ["*"]

The developer role:

kind: role
version: v3
metadata:
  name: dev
spec:
  options:
    max_session_ttl: 24h
  allow:
    logins: [ "{{email.local(external.username)}}", ubuntu ]
    node_labels:
      access: relaxed
  • Devs are only allowed to login to nodes labelled with access: relaxed label.
  • Developers can log in as ubuntu user
  • Notice {{external.username}} login. It configures Teleport to look at "username" Okta claim and use that field as an allowed login for each user. This example uses email as the username format. The email.local(external.trait) function will remove the @domain and just have the username prefix.
  • Developers also do not have any "allow rules" i.e. they will not be able to see/replay past sessions or re-configure the Teleport cluster.

Now, create both roles on the auth server:

$ tctl create admin.yaml
$ tctl create dev.yaml

Testing

The Web UI will now contain a new button: "Login with Okta". The CLI is the same as before:

$ tsh --proxy=proxy.example.com login

This command will print the SSO login URL (and will try to open it automatically in a browser).

Tip
Teleport can use multiple SAML connectors. In this case a connector name can be passed via tsh login --auth=connector_name
IMPORTANT
Teleport only supports sending party initiated flows for SAML 2.0. This means you can not initiate login from your identity provider, you have to initiate login from either the Teleport Web UI or CLI.

Troubleshooting

If you get "access denied errors" the number one place to check is the audit log on the Teleport auth server. It is located in /var/lib/teleport/log by default and it will contain the detailed reason why a user's login was denied.

Some errors (like filesystem permissions or misconfigured network) can be diagnosed using Teleport's stderr log, which is usually available via:

$ sudo journalctl -fu teleport

If you wish to increase the verbosity of Teleport's syslog, you can pass --debug flag to teleport start command.

Have a suggestion or can’t find something?
IMPROVE THE DOCS