Skip to content

Commit

Permalink
Move --reason and --invite to tsh ssh (#42365)
Browse files Browse the repository at this point in the history
These flags are part of the moderated sessions feature and are
used to update the session tracker resource. As mentioned in the
RFD, they were supposed to be added to `tsh kube exec` and `tsh ssh`.

While `tsh kube exec` works as intended, for SSH we mistakenly added
these flags to `tsh join`. As a result, these flags were effectively
no-ops for SSH sessions.

Additionally, the environment variable used to propagate session
invite information was incorrect named "JOIN_MODE" presumably due
to a copy-paste error. This has been fixed, but we will continue
to check the old env var for 1 major release to maintain backwards
compatibility.

Closes #42255
  • Loading branch information
zmb3 authored Jun 4, 2024
1 parent 5b734ec commit b267ed9
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 62 deletions.
4 changes: 2 additions & 2 deletions api/proto/teleport/legacy/types/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -5309,8 +5309,8 @@ message SessionTrackerSpecV1 {
// purpose.
string Reason = 7 [(gogoproto.jsontag) = "reason,omitempty"];

// Invited is a list of invited users, this field is interpreted by different
// clients on a best-effort basis and used for delivering notifications to invited users.
// Invited is a list of invited users, this field can be used by
// clients to deliver notifications to invited users.
repeated string Invited = 8 [(gogoproto.jsontag) = "invited,omitempty"];

// Hostname identifies the target this session is connected to.
Expand Down
4 changes: 2 additions & 2 deletions api/types/types.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,7 @@ const (
// EnvSSHSessionReason is a reason attached to started sessions meant to describe their intent.
EnvSSHSessionReason = "TELEPORT_SESSION_REASON"

// EnvSSHSessionInvited is an environment variable listning people invited to a session.
// EnvSSHSessionInvited is an environment variable listing people invited to a session.
EnvSSHSessionInvited = "TELEPORT_SESSION_JOIN_MODE"

// EnvSSHSessionDisplayParticipantRequirements is set to true or false to indicate if participant
Expand Down
107 changes: 54 additions & 53 deletions docs/pages/access-controls/guides/moderated-sessions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ keywords:
- audit
---

Moderated sessions allow you to define requirements for other users to be present
in an active server or Kubernetes session started by another user. Depending on the
requirements you specify, users who are allowed to join other users' sessions can be
Moderated sessions allow you to define requirements for other users to be present
in an active server or Kubernetes session started by another user. Depending on the
requirements you specify, users who are allowed to join other users' sessions can be
granted permission to do the following:

- Observe another user's session in real time.
Expand All @@ -24,28 +24,28 @@ The most common use cases for moderated sessions involve the following scenarios
- You want to share a terminal with someone else to be able to instruct or collaborate.
- You need the ability to pause or terminate active sessions.

Note that you can share terminal sessions using any Teleport edition. However, you must
have Teleport Enterprise or Teleport Enterprise Cloud if you want to require active
sessions to be observed or moderated.
Note that you can share terminal sessions using any Teleport edition. However,
you must have Teleport Enterprise if you want to require active sessions to be
observed or moderated.

## Require and allow policies

Moderated sessions use roles to provide fine grained control over who can join a session
Moderated sessions use roles to provide fine grained control over who can join a session
and who is required to be present to start one.

There are two types of policies you can use to control moderated sessions:

- **Require** policies define a set of conditions that must be a met for a session to
start or run. A user assigned a role with a require policy must meet the minimum
start or run. A user assigned a role with a require policy must meet the minimum
requirements of the policy to start the session that the policy applies to.
- **Allow** policies define what sessions users can join and under what conditions
- **Allow** policies define what sessions users can join and under what conditions
they can join a session.

## Configure a require policy

In Teleport Enterprise editions, you can use `require_session_join` in a role to specify
the conditions that must be a met for a session to start or run. For example, the following
policy specifies that users assigned the `prod-access` role must have a minimum of one user
In Teleport Enterprise editions, you can use `require_session_join` in a role to specify
the conditions that must be a met for a session to start or run. For example, the following
policy specifies that users assigned the `prod-access` role must have a minimum of one user
with the `auditor` role and the `moderator` mode present to start SSH or Kubernetes sessions:

```yaml
Expand Down Expand Up @@ -80,8 +80,8 @@ spec:
```
Because this sample policy requires that at least one user with the `auditor` role to be present
as a moderator to start SSH or Kubernetes sessions, a user assigned this `prod-access` role
won't be able to start any sessions until the policy requirements are fulfilled.
as a moderator to start SSH or Kubernetes sessions, a user assigned this `prod-access` role
won't be able to start any sessions until the policy requirements are fulfilled.

The `require_session_join` rules apply to all of the user's sessions, including
those that are accessible via other roles. If you do not want to require moderation
Expand All @@ -103,8 +103,8 @@ The following are required fields for `require_session_join`:
#### Filter expressions

Filter expressions allow for more detailed control over the scope of a policy.
For example, you can use a filter expression to specify which users are required
to be present in a session. The filter has a `user` object as its context that you
For example, you can use a filter expression to specify which users are required
to be present in a session. The filter has a `user` object as its context that you
can refine to match the `roles` and `name` fields you specify.

In the following example, the filter expression evaluates to true if the user's name is
Expand All @@ -126,8 +126,8 @@ Filter expressions support the following functions and operators:

#### Matching user count

You can use the `count` field in a require policy to specify the minimum number
of users matching the filter expression who must be present in a session to satisfy
You can use the `count` field in a require policy to specify the minimum number
of users matching the filter expression who must be present in a session to satisfy
the policy.

### Optional fields
Expand All @@ -138,7 +138,7 @@ The following field is optional for `require_session_join`:
|---|---|---|
|`on_leave`|String|The action to take when the policy is no longer satisfied.|

You can use the `on_leave` field in require policies to define what happens
You can use the `on_leave` field in require policies to define what happens
when a moderator leaves a session and causes the policy to no longer be satisfied.
There are two possible values for this field:

Expand All @@ -147,33 +147,33 @@ There are two possible values for this field:

By default, Teleport treats an empty string in this field the same as `terminate`.

If all require policies attached to the session owner are set to `pause`, the session
discards all input from session participants and buffers the most recent output but
If all require policies attached to the session owner are set to `pause`, the session
discards all input from session participants and buffers the most recent output but
the session remains open so it can resume.

### Combining require policies and roles

In evaluating policies and roles, all of the require policies within a role are evaluated using an
OR operator and the policies from each role are evaluated using 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
In evaluating policies and roles, all of the require policies within a role are evaluated using an
OR operator and the policies from each role are evaluated using 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 user assigned the role can start a session.

### Requiring moderated sessions in a leaf cluster

If you create a role with the `require_session_join` policy in a root cluster, only sessions started
on resources in the root cluster are required to be moderated for the users assigned that role.
If users assigned the role connect to resources in a leaf node, their sessions won't require moderation,
If users assigned the role connect to resources in a leaf node, their sessions won't require moderation,
unless the mapped leaf role also requires moderation. To require moderated sessions in the leaf cluster,
you must include the `require_session_join` policy in the mapped role defined on the leaf cluster.

For more information about configuring trust relationships and role mapping between root and leaf
For more information about configuring trust relationships and role mapping between root and leaf
clusters, see [Configure Trusted Clusters](../../management/admin/trustedclusters.mdx).

## Configure an allow policy

You can use `join_sessions` in a role to specify the sessions users can join and under what conditions
they can join a session. For example, the following policy is attached to the `auditor` role and allows
a user assigned to the auditor role to join SSH and Kubernetes sessions started by a user with the
You can use `join_sessions` in a role to specify the sessions users can join and under what conditions
they can join a session. For example, the following policy is attached to the `auditor` role and allows
a user assigned to the auditor role to join SSH and Kubernetes sessions started by a user with the
role `prod-access` and to join the session as a moderator or an observer:

```yaml
Expand All @@ -191,10 +191,10 @@ spec:
```

Users who are assigned a role with a `join_sessions` allow policy are
implicitly allowed to list the sessions that the policy gives them permission
to join. If there's a `deny` rule that prevents listing sessions, the
`join_sessions` policy overrides the `deny` rule for the sessions the
policy allows the user to join. Outside of this exception for joining
implicitly allowed to list the sessions that the policy gives them permission
to join. If there's a `deny` rule that prevents listing sessions, the
`join_sessions` policy overrides the `deny` rule for the sessions the
policy allows the user to join. Outside of this exception for joining
sessions, `deny` statements take precedent.

### Required fields
Expand Down Expand Up @@ -224,7 +224,7 @@ Teleport > Waiting for required participants...
```

Jeff's session is paused, waiting for the required observers.
When Alice, who is assigned the `auditor` role, joins the waiting session
When Alice, who is assigned the `auditor` role, joins the waiting session
as a moderator, the session can begin.
For example:

Expand All @@ -242,7 +242,7 @@ Teleport > Connecting to prod.teleport.example.com over SSH
[email protected] %
```

Because this session is an SSH session, Alice could also join from the
Because this session is an SSH session, Alice could also join from the
Teleport Web UI. For example:

![Join Server Session from UI](../../../img/webui-active-session.png)
Expand All @@ -251,9 +251,9 @@ Teleport Web UI. For example:

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
- `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
- `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.

Expand All @@ -262,18 +262,18 @@ participant mode with the `--mode <mode>` command-line option, where `<mode>` is
`moderator`, or `observer`. The default participant mode is `observer`.

You can leave a session with the shortcut `^c` (Control + c) while in observer or
moderator mode. In moderator mode, you can also forcefully terminate the session
moderator mode. In moderator mode, you can also forcefully terminate the session
at any point in time with the shortcut `t`.

### Multifactor authentication

If `per_session_mfa` is set to `true` in role or cluster settings, Teleport requires
If `per_session_mfa` is set to `true` in role or cluster settings, Teleport requires
multifactor authentication checks when starting new sessions. This requirement is
also enforced for session moderators. Therefore, moderators who want to join a session
must have configured a device for multifactor authentication.

Every 30 seconds, Teleport prompts session moderators to re-authenticate within the
next 15 seconds. This behavior continues throughout the session to ensure that
Every 30 seconds, Teleport prompts session moderators to re-authenticate within the
next 15 seconds. This behavior continues throughout the session to ensure that
moderators are always present and watching a given session.

If no MFA input is received within 60 seconds, the user is disconnected from the
Expand All @@ -288,37 +288,38 @@ 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.

Users with the `join_sessions` permission for SSH sessions can join sessions from the
command line or from the Teleport Web UI. Users with the `join_sessions` permission for
Users with the `join_sessions` permission for SSH sessions can join sessions from the
command line or from the Teleport Web UI. Users with the `join_sessions` permission for
Kubernetes sessions can only join session from the command line.

## Session invites

When starting an interactive SSH or Kubernetes session using `tsh ssh` or `tsh kube exec`
When starting an interactive SSH or Kubernetes session using `tsh ssh` or `tsh kube exec`
respectively, you can supply the `--reason <reason>` or `--invited <users>` command-line
option to specify `<reason>` as a string or `<users>` as a comma-separated list of
option to specify `<reason>` as a string or `<users>` as a comma-separated list of
user names.

You can use this information to integrate with a third party, for example, to enable
notifications over some external communication system.
This information is propagated to the `session_tracker` resource, which can be
used to with a third party, for example, to enable notifications over some
external communication system.

## File transfers

File transfers within moderated sessions are only supported when using the Teleport Web UI.
If the current active session requires moderation, file transfer requests are automatically
File transfers within moderated sessions are only supported when using the Teleport Web UI.
If the current active session requires moderation, file transfer requests are automatically
sent to all current session participants.

Both the session originator and the moderator(s) must be present in the Teleport Web UI
during the file transfer initiation to receive the file transfer request notification.
Both the session originator and the moderator(s) must be present in the Teleport Web UI
during the file transfer initiation to receive the file transfer request notification.
After the file transfer has been requested, all session participants and notified
and prompted to approve or deny the file transfer request.

![Approve/Deny Prompt](../../../img/moderated-file-transfer-dialog.png)

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

After enough approvals have been given to satisfy the policy used to start the session,
After enough approvals have been given to satisfy the policy used to start the session,
the file transfer automatically begins.

## Related documentation
Expand Down
4 changes: 2 additions & 2 deletions lib/srv/sess.go
Original file line number Diff line number Diff line change
Expand Up @@ -2135,8 +2135,8 @@ func (s *session) trackSession(ctx context.Context, teleportUser string, policyS
InitialCommand: initialCommand,
}

if s.scx.env[teleport.EnvSSHSessionInvited] != "" {
if err := json.Unmarshal([]byte(s.scx.env[teleport.EnvSSHSessionInvited]), &trackerSpec.Invited); err != nil {
if invitedUsers := s.scx.env[teleport.EnvSSHSessionInvited]; invitedUsers != "" {
if err := json.Unmarshal([]byte(invitedUsers), &trackerSpec.Invited); err != nil {
return trace.Wrap(err)
}
}
Expand Down
4 changes: 2 additions & 2 deletions tool/tsh/common/tsh.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,8 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error {
ssh.Flag("x11-untrusted", "Requests untrusted (secure) X11 forwarding for this session").Short('X').BoolVar(&cf.X11ForwardingUntrusted)
ssh.Flag("x11-trusted", "Requests trusted (insecure) X11 forwarding for this session. This can make your local machine vulnerable to attacks, use with caution").Short('Y').BoolVar(&cf.X11ForwardingTrusted)
ssh.Flag("x11-untrusted-timeout", "Sets a timeout for untrusted X11 forwarding, after which the client will reject any forwarding requests from the server").Default("10m").DurationVar((&cf.X11ForwardingTimeout))
ssh.Flag("invite", "A comma separated list of people to mark as invited for the session.").StringsVar(&cf.Invited)
ssh.Flag("reason", "The purpose of the session.").StringVar(&cf.Reason)
ssh.Flag("participant-req", "Displays a verbose list of required participants in a moderated session.").BoolVar(&cf.displayParticipantRequirements)
ssh.Flag("request-reason", "Reason for requesting access").StringVar(&cf.RequestReason)
ssh.Flag("request-mode", fmt.Sprintf("Type of automatic access request to make (%s)", strings.Join(accessRequestModes, ", "))).Envar(requestModeEnvVar).Default(accessRequestModeResource).EnumVar(&cf.RequestMode, accessRequestModes...)
Expand Down Expand Up @@ -946,8 +948,6 @@ func Run(ctx context.Context, args []string, opts ...CliOption) error {
join := app.Command("join", "Join the active SSH or Kubernetes session.")
join.Flag("cluster", clusterHelp).Short('c').StringVar(&cf.SiteName)
join.Flag("mode", "Mode of joining the session, valid modes are observer, moderator and peer.").Short('m').Default("observer").EnumVar(&cf.JoinMode, "observer", "moderator", "peer")
join.Flag("reason", "The purpose of the session.").StringVar(&cf.Reason)
join.Flag("invite", "A comma separated list of people to mark as invited for the session.").StringsVar(&cf.Invited)
join.Arg("session-id", "ID of the session to join").Required().StringVar(&cf.SessionID)
// play
play := app.Command("play", "Replay the recorded session (SSH, Kubernetes, App, DB).")
Expand Down

0 comments on commit b267ed9

Please sign in to comment.