Fork me on GitHub


Moderated Sessions



Moderated Sessions allows Teleport administrators to define requirements for other users to be present in a server or Kubernetes session. Depending on the requirements, these users can observe the session in real time, participate in the session, and terminate the session at will.

In addition, Teleport administrators can define rules that allow users to join each other's sessions from tsh and the Web UI.

Moderated Sessions requires Teleport Enterprise or Teleport Cloud.

Use cases

Moderated Sessions are useful in the following scenarios:

  • When you have stringent security requirements and need to have people watching over user-initiated sessions on a set of servers.
  • When you want to share a terminal with someone else to be able to instruct or collaborate.


Moderated Sessions makes use of RBAC policies to allow for fine grained control over who can join a session and who is required to be present to start one.

The system is based around require policies and allow policies.

Require policies define a set of conditions that must be a met for a session to start or run. A minimum of one policy from each relevant role the user has must match for the session to start.

Allow policies are used to define what sessions a user can join and under what conditions they may join a session.

Configuring Moderated Sessions



The following are required options for require_session_join:

nameStringThe name of the require policy
filterFilterAn expression that, if it evaluates to true for a given user, enables the user to be present in a Moderated Session
kinds[]Session kindThe kind of session that the policy applies to
modes[]Participant modeThe participant mode that applies to the user joining the Moderated Session under this policy
countIntegerThe number of users that need to match the filter expression to satisfy the policy

The following fields are optional for require_session_join:

on_leaveOn leaveThe action to take when the policy is no longer satisfied


The policy below specifies that the prod-access role must have a minimum of two users with the role auditor and the mode moderator present in the session to start it. The policy applies to SSH and Kubernetes sessions only.

This policy requires that at least one user with the auditor role is present as a moderator for SSH or Kubernetes sessions to start. That is applied for servers and Kubernetes resources labeled env: prod. The session will not start until the policy is fulfilled.

kind: role
  name: prod-access
version: v6
      - name: Auditor oversight
        filter: 'contains(user.spec.roles, "auditor")'
        kinds: ['k8s', 'ssh']
        modes: ['moderator']
        count: 1
    - ubuntu
    - debian
      env: prod
      env: prod
    - prod-access
    - USER
    - kind: pod
      name: '*'
      namespace: '*'

Combining Policies

The authorizer applies require policies within a role together with an OR operator and the policies from each role with an AND operator. In practice, this means that for every role with at least one require policy, one of its policies must be met before a session can be started.



The following are required options for join_sessions:

nameStringThe name of the allow policy
roles[]StringA list of names of Teleport roles whose sessions this policy applies to. Active sessions created by users with these roles can be joined under this policy.
kinds[]Session kindThe kind of session that the policy applies to
modes[]Participant modeThe participant mode that applies to the user joining the session under this policy

Joining from the UI is available for SSH sessions. Kubernetes sessions can only be joined from the CLI.

Example Moderator Role

The following allow policy attaches to the role auditor and allows one to join SSH and Kubernetes sessions started by a user with the role prod-access as a moderator or observer.

kind: role
  name: auditor
version: v6
      - name: Auditor oversight
        roles : ['prod-access']
        kinds: ['k8s', 'ssh']
        modes: ['moderator', 'observer']

Joining sessions example

Here is an example of Jeff with role prod-access connecting to a SSH server in the production environment.

Teleport > Creating session with ID: 46e2af03-62d6-4e07-a886-43fe741ca044...

Teleport > Controls

- CTRL-C: Leave the session

- t: Forcefully terminate the session (moderators only)

Teleport > User jeff joined the session.

Teleport > Waiting for required participants...

Jeff's session is paused, waiting for the required observers.

Now Alice with the auditor role joins as a moderator and the session can begin.

tsh join --mode=moderator 46e2af03-62d6-4e07-a886-43fe741ca044

Teleport > Creating session with ID: 46e2af03-62d6-4e07-a886-43fe741ca044...

Teleport > Controls

- CTRL-C: Leave the session

- t: Forcefully terminate the session (moderators only)

Teleport > User jeff joined the session.

Teleport > Waiting for required participants...

Teleport > User alice joined the session.

Teleport > Connecting to over SSH

[email protected] %

Here is an example of joining from the UI that is available for server sessions.

Join Server Session from UI


Filter expressions allow for more detailed control over the scope of an allow policy or require policy.

Require policies can specify which users they consider as valid with a filter expression. The filter context has a user object defined with the set fields roles and name.

Here is an example of a filter expression that evaluates to true if the user is Adam or if the user has the trait cs-observe:

equals(, "adam") || contains(user.spec.roles, "cs-observe")

A filter expression is a string statement used to define logic based on a set of input variables. The filter expressions follow a restricted subset of Go syntax and supports the following functions and operators:

  • contains(set, item): Returns true if the item is in the set, otherwise false. The set can be a string or an array.
  • equals(a, b): Returns true if the two values are equal, otherwise returns false.
  • ![expr]: Negates a boolean expression.
  • [expr] && [expr]: Performs a logical AND on two boolean expressions.
  • [expr] || [expr]: Performs a logical OR on two boolean expressions.

Session kinds

Require and allow policies have to specify which sessions they apply to. Valid options are ssh and k8s.

  • ssh policies apply to all SSH sessions on a node running the Teleport SSH server.
  • k8s policies apply to all Kubernetes sessions on clusters connected to Teleport.

Participant modes

A participant joining a session will always have one of three modes:

  • observer: Allows read-only access to the session. You can view output but cannot control the session in any way nor send any input.
  • moderator: Allows you to watch the session. You can view output and forcefully terminate or pause the session at any time, but can't send input.
  • peer: Allows you to collaborate in the session. You can view output and send input.

When joining a session with tsh join or tsh kube join, a user can specify a participant mode with the --mode <mode> flag , where the mode is one of peer, moderator or observer. By default, the mode is observer.

A participant may leave a session with the shortcut ^c (Control + c) while in observer or moderator mode. When in moderator mode, a participant may also forcefully terminate the session at any point in time with the shortcut t.

Require policy count

Require policies can have a variable amount of users that need to match the filter expression in order to satisfy the policy. The count field of a require policy is a positive integer value that specifies the minimum amount of users this policy requires.

On leave

The on_leave string option in require policies is used to define what happens when a moderator leaves a session, causing a policy to no longer be satisfied.

There are two possible actions to take in this scenario:

  1. Terminate the session and disconnect all participants, corresponding to the "terminate" value.
  2. Pause the session and stop any input/output streaming until the policy is satisfied again, corresponding to the "pause" value.

By default, Teleport treats an empty string in this field as the same as terminate. That is, the session is terminated instantly and all participants are disconnected.

If all require policies attached to the session owner are set to "pause", the session will instead pause but the session will remain open. This discards all input from session participants and buffers the most recent output until the session can resume.

Backwards compatibility with Server Access

Moderated Session RBAC controls were added to the role specification in version 5 (version: v5 in the YAML definition). Previously, the Teleport SSH Service did not include controls over which users can join a session. To avoid breaking functionality for users with only roles on v4 or older, RBAC access checks will only be enforced if the user has at least one v5 role.

New roles will be created as v5 by default, and older roles can by updated with tctl or from the Web UI by modifying the version field.

MFA-based presence

When per_session_mfa is set to true via role or cluster settings, Teleport enforces MFA-based presence checks for moderators. This requires that all moderators wishing to join have a configured U2F or WebAuthn MFA token.

Every 30 seconds, Teleport will issue a prompt to the user in the terminal, asking them to press their MFA token in the next 15 seconds. This will happen continuously during the session and exists so that moderators are always present and watching a given session.

If no MFA input is received within 60 seconds, the user is kicked from the session which may pause it, if RBAC policies are no longer met.

Session invites

When starting an interactive SSH or Kubernetes session using tsh ssh or tsh kube exec respectively, one may supply a --reason <reason> and/or an --invited <users> flag where <reason> is a string and <users> is a comma-separated list of usernames.

This information can be picked up by a third party integration and may for example be used to enable notifications over some external communication system.

File transfers

File transfers within moderated sessions are available via the Web UI only. When initiating a file transfer, if the current active session requires moderation, a file transfer request will automatically be sent to all current party members.

Both the session originator and the moderator(s) must be present in the Web UI during the file transfer initiation to receive the file transfer request notification. Once the file transfer has been requested, all members of the party will be notified and prompted with an Approve/Deny dialog.

Approve/Deny Prompt

If a moderator denies the file transfer request, the request is immediately removed and all party members are notified.

After enough approvals have been given to satisfy the policy (the same policy to start the session), the file transfer will automatically begin.