Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v13] Fix moderated session presence checking #28456

Merged
merged 2 commits into from Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 11 additions & 8 deletions api/types/session_tracker.go
Expand Up @@ -20,6 +20,7 @@ import (
"time"

"github.com/gravitational/trace"
"golang.org/x/exp/slices"

"github.com/gravitational/teleport/api/defaults"
)
Expand Down Expand Up @@ -94,7 +95,7 @@ type SessionTracker interface {
RemoveParticipant(string) error

// UpdatePresence updates presence timestamp of a participant.
UpdatePresence(string) error
UpdatePresence(string, time.Time) error

// GetKubeCluster returns the name of the kubernetes cluster the session is running in.
GetKubeCluster() string
Expand Down Expand Up @@ -295,15 +296,17 @@ func (s *SessionTrackerV1) GetHostUser() string {
}

// UpdatePresence updates presence timestamp of a participant.
func (s *SessionTrackerV1) UpdatePresence(user string) error {
for _, participant := range s.Spec.Participants {
if participant.User == user {
participant.LastActive = time.Now().UTC()
return nil
}
func (s *SessionTrackerV1) UpdatePresence(user string, t time.Time) error {
idx := slices.IndexFunc(s.Spec.Participants, func(participant Participant) bool {
return participant.User == user
})

if idx < 0 {
return trace.NotFound("participant %v not found", user)
}

return trace.NotFound("participant %v not found", user)
s.Spec.Participants[idx].LastActive = t
return nil
}

// GetHostPolicySets returns a list of policy sets held by the host user at the time of session creation.
Expand Down
66 changes: 66 additions & 0 deletions api/types/session_tracker_test.go
@@ -0,0 +1,66 @@
// Copyright 2023 Gravitational, Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package types

import (
"testing"
"time"

"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestSessionTrackerV1_UpdatePresence(t *testing.T) {
clock := clockwork.NewFakeClock()
now := clock.Now().UTC()

s, err := NewSessionTracker(SessionTrackerSpecV1{
SessionID: "123",
Participants: []Participant{
{
ID: "1",
User: "llama",
Mode: string(SessionPeerMode),
LastActive: now,
},
{
ID: "2",
User: "fish",
Mode: string(SessionModeratorMode),
LastActive: now,
},
},
})
require.NoError(t, err)

// Presence cannot be updated for a non-existent user
err = s.UpdatePresence("alpaca", now.Add(time.Hour))
require.ErrorIs(t, err, trace.NotFound("participant alpaca not found"))

// Update presence for just the user fish
require.NoError(t, s.UpdatePresence("fish", now.Add(time.Hour)))

// Verify that llama has not been active but that fish was
for _, participant := range s.GetParticipants() {
lastActive := now
if participant.User == "fish" {
lastActive = lastActive.Add(time.Hour)
}

assert.Equal(t, lastActive, participant.LastActive)
}
}
21 changes: 14 additions & 7 deletions integration/helpers/instance.go
Expand Up @@ -1226,6 +1226,8 @@ func (i *TeleInstance) Start() error {

// ClientConfig is a client configuration
type ClientConfig struct {
// TeleportUser is Teleport username
TeleportUser string
// Login is SSH login name
Login string
// Cluster is a cluster name to connect to
Expand Down Expand Up @@ -1305,8 +1307,12 @@ func (i *TeleInstance) NewUnauthenticatedClient(cfg ClientConfig) (tc *client.Te
fwdAgentMode = client.ForwardAgentYes
}

if cfg.TeleportUser == "" {
cfg.TeleportUser = cfg.Login
}

cconf := &client.Config{
Username: cfg.Login,
Username: cfg.TeleportUser,
Host: cfg.Host,
HostPort: cfg.Port,
HostLogin: cfg.Login,
Expand Down Expand Up @@ -1537,21 +1543,22 @@ func (w *WebClient) SSH(termReq web.TerminalRequest) (*web.TerminalStream, error
return nil, trace.Wrap(err)
}

stream, err := web.NewTerminalStream(ws)
if err != nil {
return nil, trace.Wrap(err)
}

stream := web.NewTerminalStream(context.Background(), ws, utils.NewLoggerForTests())
return stream, nil
}

// AddClientCredentials adds authenticated credentials to a client.
// (server CAs and signed session key).
func (i *TeleInstance) AddClientCredentials(tc *client.TeleportClient, cfg ClientConfig) (*client.TeleportClient, error) {
login := cfg.Login
if cfg.TeleportUser != "" {
login = cfg.TeleportUser
}

// Generate certificates for the user simulating login.
creds, err := GenerateUserCreds(UserCredsRequest{
Process: i.Process,
Username: cfg.Login,
Username: login,
SourceIP: cfg.SourceIP,
})
if err != nil {
Expand Down