Fork me on GitHub
Teleport

Teleport Kubernetes Access Controls

Improve

Single Sign-On and Kubernetes RBAC

Teleport issues short-lived X.509 certs and updates Kubernetes clients to talk to Teleport proxy using mutual TLS. It then intercepts every request and adds impersonation headers to map users to Kubernetes users and groups.

Impersonation

Teleport's connectors configure single sign-on for OIDC, OAuth, or SAML providers. Here are examples of connectors that map SSO users to Kubernetes groups in the Teleport Open Source Edition and Teleport's roles in the Enterprise Edition:

GitHub's teams_to_logins section maps users to roles based on users' teams.

kind: github
version: v3
metadata:
  # Connector name that will be used with `tsh --auth=github login`
  name: github
spec:
  # Client ID of GitHub OAuth app
  client_id: client-id
  # Client secret of GitHub OAuth app
  client_secret: client-secret
  # This name will be shown on UI login screen
  display: GitHub
  # Change tele.example.com to your domain name
  redirect_url: https://tele.example.com:443/v1/webapi/github/callback
  # Map github teams to teleport roles
  teams_to_logins:
    - organization: octocats # GitHub organization name
      team: admin            # GitHub team name within that organization
      # keep this field as is for now
      logins: ["admin"]

OIDC and SAML connectors claims_to_roles and attributes_to_roles sections map attribute statements and claims received from identity providers to Teleport's roles.

kind: saml
version: v2
metadata:
  name: okta
spec:
  acs: https://tele.example.com/v1/webapi/saml/acs
  attributes_to_roles:
  # Any user who has SAML `groups` atrribute with value `okta-admin`
  # will be given the Teleport `kube-access` role.
  - {name: "groups", value: "okta-admin", roles: ["kube-access"]}
  entity_descriptor: |
    <?xml !!! Make sure to shift all lines in XML descriptor
    with 4 spaces, otherwise things will not work

In this example, the kube-access role uses the kubernetes_groups property to assign Teleport users to Kubernetes groups

kind: role
version: v3
metadata:
  name: kube-access
spec:
  allow:
    # If kubernetes integration is enabled, this setting configures which
    # kubernetes groups the users of this role will be assigned to.
    # Note that you can refer to a SAML/OIDC trait named 'property' via the "{{external.property}}" template variable,
    # this allows you to specify Kubernetes group membership via your identity provider:
    kubernetes_groups: ["system:masters"]

Mapping OIDC claims and SAML attributes to Kubernetes groups

Identity provider admins can assign metadata to a user, such as group membership or access permissions. Administrators configure what metadata is shared with Teleport. Teleport receives user metadata keys and values as OIDC claims or SAML attributes during single sign-on redirect flow:

# Alice has an email [email protected] Email is a standard OIDC claim.
email: "[email protected]"
# Alice is a member of groups admins and devs
groups: ["admins", "devs"]
# She can access prod and staging environments
access: {"env": ["prod", "staging"]}

Teleport's roles map OIDC claims or SAML attributes using template variables. Template variable {{external.groups}} will be substituted to the users' group list in the role definition.

kind: role
version: v5
metadata:
  name: group-member
spec:
  allow:
    # For Alice, will be substituted with the list ["admins", "devs"]
    kubernetes_groups: ["{{external.groups}}"]
    # For Alice, will be substituted with ["[email protected]"]
    kubernetes_users: ["{{external.email}}"]

When running Teleport in production, we recommend that you follow the practices below to avoid security incidents. These practices may differ from the examples used in this guide, which are intended for demo environments:

  • Avoid using sudo in production environments unless it's necessary.
  • Create new, non-root, users and use test instances for experimenting with Teleport.
  • Run Teleport's services as a non-root user unless required. Only the SSH Service requires root access. Note that you will need root permissions (or the CAP_NET_BIND_SERVICE capability) to make Teleport listen on a port numbered < 1024 (e.g. 443).
  • Follow the "Principle of Least Privilege" (PoLP). Don't give users permissive roles when giving them more restrictive roles will do instead. For example, assign users the built-in access,editor roles.
  • When joining a Teleport agent to a cluster, save the invitation token to a file. Otherwise, the token will be visible when examining the teleport command that started the agent, e.g., via the history command on a compromised system.

Create or update this role using tctl:

Log in to your Teleport cluster so you can use tctl remotely.

You can also run tctl on your Auth Service host.

tsh login --proxy=teleport.example.com --user=myuser
tctl create -f member.yaml

Assign this role to a user in OIDC or SAML connector:

kind: github
version: v3
metadata:
  # Connector name that will be used with `tsh --auth=github login`
  name: github
spec:
  # Client ID of GitHub OAuth app
  client_id: client-id
  # Client secret of GitHub OAuth app
  client_secret: client-secret
  # This name will be shown on UI login screen
  display: GitHub
  # Change tele.example.com to your domain name
  redirect_url: https://tele.example.com:443/v1/webapi/github/callback
  # Map github teams to kubernetes groups
  teams_to_logins:
    - organization: octocats # GitHub organization name
      team: admin            # GitHub team name within that organization
      # List of Kubernetes groups this GitHub team is allowed to connect to
      # Keep this field as is for now
      logins: ["admins"]
kind: oidc
version: v2
metadata:
  name: auth0
spec:
  redirect_url: https://tele.example.com/v1/webapi/oidc/callback
  client_id: client-id-here
  client_secret: client-secret-here
  issuer_url: https://idp.example.com/
  # request groups scope from OIDC provider
  # read more about scopes here https://auth0.com/docs/scopes/openid-connect-scopes
  scope: [groups]
  claims_to_roles:
    - {claim: "groups", value: "*", roles: ["group-member"]}
kind: saml
version: v2
metadata:
  name: okta
spec:
  acs: https://tele.example.com/v1/webapi/saml/acs
  attributes_to_roles:
  - {name: "groups", value: "*", roles: ["group-member"]}
  entity_descriptor: |
    <?xml !!! Make sure to indent all lines in XML descriptor
    with 4 spaces, otherwise things will not work

Local Users

Local users are mapped to Kubernetes groups using roles:

Specify `kubernetes_groups` property in a role "admins" and

create a user assigned to the role.

tctl users add joe --roles="admins"

Kubernetes labels

Label each cluster with key-value pairs describing the cluster:

Install or upgrade the agent or cluster and set labels:

helm upgrade teleport-agent teleport-kube-agent --set kubeClusterName={CLUSTER?}\ --set proxyAddr=${PROXY?} --set authToken=${TOKEN?} --create-namespace --namespace=teleport-agent\ --set labels.env=prod --set labels.region=us-west-1
kubernetes_service:
  enabled: true
  kube_cluster_name: cookie
  labels:
    env: prod
    region: us-west-1

Limit access to cluster based on the label:

kind: role
version: v5
metadata:
  name: group-member
spec:
  allow:
    # Allow access to Kubernetes clusters in the production environment
    kubernetes_labels:
      'env': 'prod'
    # Allows access to group "admins" in Kubernetes clusters
    kubernetes_groups: ["admins"]

Impersonation

Teleport uses Kubernetes impersonation to map OIDC and SAML users to Kubernetes users and groups.

Here is an example of Kubernetes ClusterRole and ClusterRoleBinding allowing Teleport's ServiceAccount to impersonate users and groups:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: teleport-impersonation
rules:
- apiGroups:
  - ""
  resources:
  - users
  - groups
  - serviceaccounts
  verbs:
  - impersonate
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
- apiGroups:
  - "authorization.k8s.io"
  resources:
  - selfsubjectaccessreviews
  verbs:
  - create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: teleport
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: teleport-impersonation
subjects:
- kind: ServiceAccount
  # this should be changed to the name of the Kubernetes ServiceAccount being used
  name: teleport-serviceaccount
  namespace: default

Take a look at the example usage in a Teleport Helm chart

Next steps

Integrate with your identity provider: