github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/session_tracker.go (about)

     1  /*
     2  Copyright 2021 Gravitational, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package types
    18  
    19  import (
    20  	"slices"
    21  	"time"
    22  
    23  	"github.com/gravitational/trace"
    24  
    25  	"github.com/gravitational/teleport/api/defaults"
    26  )
    27  
    28  const (
    29  	SSHSessionKind            SessionKind            = "ssh"
    30  	KubernetesSessionKind     SessionKind            = "k8s"
    31  	DatabaseSessionKind       SessionKind            = "db"
    32  	AppSessionKind            SessionKind            = "app"
    33  	WindowsDesktopSessionKind SessionKind            = "desktop"
    34  	SessionObserverMode       SessionParticipantMode = "observer"
    35  	SessionModeratorMode      SessionParticipantMode = "moderator"
    36  	SessionPeerMode           SessionParticipantMode = "peer"
    37  )
    38  
    39  // SessionKind is a type of session.
    40  type SessionKind string
    41  
    42  // SessionParticipantMode is the mode that determines what you can do when you join a session.
    43  type SessionParticipantMode string
    44  
    45  // SessionTracker is a resource which tracks an active session.
    46  type SessionTracker interface {
    47  	Resource
    48  
    49  	// GetSessionID returns the ID of the session.
    50  	GetSessionID() string
    51  
    52  	// GetSessionKind returns the kind of the session.
    53  	GetSessionKind() SessionKind
    54  
    55  	// GetState returns the state of the session.
    56  	GetState() SessionState
    57  
    58  	// SetState sets the state of the session.
    59  	SetState(SessionState) error
    60  
    61  	// SetCreated sets the time at which the session was created.
    62  	SetCreated(time.Time)
    63  
    64  	// GetCreated returns the time at which the session was created.
    65  	GetCreated() time.Time
    66  
    67  	// GetExpires return the time at which the session expires.
    68  	GetExpires() time.Time
    69  
    70  	// GetReason returns the reason for the session.
    71  	GetReason() string
    72  
    73  	// GetInvited returns a list of people invited to the session.
    74  	GetInvited() []string
    75  
    76  	// GetHostname returns the hostname of the session target.
    77  	GetHostname() string
    78  
    79  	// GetAddress returns the address of the session target.
    80  	GetAddress() string
    81  
    82  	// GetClusterName returns the name of the Teleport cluster.
    83  	GetClusterName() string
    84  
    85  	// GetLogin returns the target machine username used for this session.
    86  	GetLogin() string
    87  
    88  	// GetParticipants returns the list of participants in the session.
    89  	GetParticipants() []Participant
    90  
    91  	// AddParticipant adds a participant to the session tracker.
    92  	AddParticipant(Participant)
    93  
    94  	// RemoveParticipant removes a participant from the session tracker.
    95  	RemoveParticipant(string) error
    96  
    97  	// UpdatePresence updates presence timestamp of a participant.
    98  	UpdatePresence(string, time.Time) error
    99  
   100  	// GetKubeCluster returns the name of the kubernetes cluster the session is running in.
   101  	GetKubeCluster() string
   102  
   103  	// GetDesktopName returns the name of the Windows desktop the session is running in.
   104  	GetDesktopName() string
   105  
   106  	// GetAppName returns the name of the app being accessed.
   107  	GetAppName() string
   108  
   109  	// GetDatabaseName returns the name of the database being accessed.
   110  	GetDatabaseName() string
   111  
   112  	// GetHostUser fetches the user marked as the "host" of the session.
   113  	// Things like RBAC policies are determined from this user.
   114  	GetHostUser() string
   115  
   116  	// GetHostPolicySets returns a list of policy sets held by the host user at the time of session creation.
   117  	// This a subset of a role that contains some versioning and naming information in addition to the require policies
   118  	GetHostPolicySets() []*SessionTrackerPolicySet
   119  
   120  	// GetLastActive returns the time at which the session was last active (i.e used by any participant).
   121  	GetLastActive() time.Time
   122  
   123  	// HostID is the target host id that created the session tracker.
   124  	GetHostID() string
   125  
   126  	// GetTargetSubKind returns the sub kind of the target server.
   127  	GetTargetSubKind() string
   128  
   129  	// GetCommand returns the command that initiated the session.
   130  	GetCommand() []string
   131  }
   132  
   133  func NewSessionTracker(spec SessionTrackerSpecV1) (SessionTracker, error) {
   134  	session := &SessionTrackerV1{
   135  		ResourceHeader: ResourceHeader{
   136  			Metadata: Metadata{
   137  				Name: spec.SessionID,
   138  			},
   139  		},
   140  		Spec: spec,
   141  	}
   142  
   143  	if err := session.CheckAndSetDefaults(); err != nil {
   144  		return nil, trace.Wrap(err)
   145  	}
   146  
   147  	return session, nil
   148  }
   149  
   150  // setStaticFields sets static resource header and metadata fields.
   151  func (s *SessionTrackerV1) setStaticFields() {
   152  	s.Kind = KindSessionTracker
   153  	s.Version = V1
   154  }
   155  
   156  // CheckAndSetDefaults sets defaults for the session resource.
   157  func (s *SessionTrackerV1) CheckAndSetDefaults() error {
   158  	s.setStaticFields()
   159  
   160  	if err := s.Metadata.CheckAndSetDefaults(); err != nil {
   161  		return trace.Wrap(err)
   162  	}
   163  
   164  	if s.GetCreated().IsZero() {
   165  		s.SetCreated(time.Now())
   166  	}
   167  
   168  	if s.Expiry().IsZero() {
   169  		// By default, resource expiration should match session expiration.
   170  		expiry := s.GetExpires()
   171  		if expiry.IsZero() {
   172  			expiry = s.GetCreated().Add(defaults.SessionTrackerTTL)
   173  		}
   174  		s.SetExpiry(expiry)
   175  	}
   176  
   177  	return nil
   178  }
   179  
   180  // GetSessionID returns the ID of the session.
   181  func (s *SessionTrackerV1) GetSessionID() string {
   182  	return s.Spec.SessionID
   183  }
   184  
   185  // GetSessionKind returns the kind of the session.
   186  func (s *SessionTrackerV1) GetSessionKind() SessionKind {
   187  	return SessionKind(s.Spec.Kind)
   188  }
   189  
   190  // GetState returns the state of the session.
   191  func (s *SessionTrackerV1) GetState() SessionState {
   192  	return s.Spec.State
   193  }
   194  
   195  // SetState sets the state of the session.
   196  func (s *SessionTrackerV1) SetState(state SessionState) error {
   197  	switch state {
   198  	case SessionState_SessionStateRunning, SessionState_SessionStatePending, SessionState_SessionStateTerminated:
   199  		s.Spec.State = state
   200  		return nil
   201  	default:
   202  		return trace.BadParameter("invalid session state: %v", state)
   203  	}
   204  }
   205  
   206  // GetCreated returns the time at which the session was created.
   207  func (s *SessionTrackerV1) GetCreated() time.Time {
   208  	return s.Spec.Created
   209  }
   210  
   211  // SetCreated returns the time at which the session was created.
   212  func (s *SessionTrackerV1) SetCreated(created time.Time) {
   213  	s.Spec.Created = created
   214  }
   215  
   216  // GetExpires return the time at which the session expires.
   217  func (s *SessionTrackerV1) GetExpires() time.Time {
   218  	return s.Spec.Expires
   219  }
   220  
   221  // GetReason returns the reason for the session.
   222  func (s *SessionTrackerV1) GetReason() string {
   223  	return s.Spec.Reason
   224  }
   225  
   226  // GetInvited returns a list of people invited to the session.
   227  func (s *SessionTrackerV1) GetInvited() []string {
   228  	return s.Spec.Invited
   229  }
   230  
   231  // GetHostname returns the hostname of the session target.
   232  func (s *SessionTrackerV1) GetHostname() string {
   233  	return s.Spec.Hostname
   234  }
   235  
   236  // GetAddress returns the address of the session target.
   237  func (s *SessionTrackerV1) GetAddress() string {
   238  	return s.Spec.Address
   239  }
   240  
   241  // GetClustername returns the name of the cluster the session is running in.
   242  func (s *SessionTrackerV1) GetClusterName() string {
   243  	return s.Spec.ClusterName
   244  }
   245  
   246  // GetLogin returns the target machine username used for this session.
   247  func (s *SessionTrackerV1) GetLogin() string {
   248  	return s.Spec.Login
   249  }
   250  
   251  // GetParticipants returns a list of participants in the session.
   252  func (s *SessionTrackerV1) GetParticipants() []Participant {
   253  	return s.Spec.Participants
   254  }
   255  
   256  // AddParticipant adds a participant to the session tracker.
   257  func (s *SessionTrackerV1) AddParticipant(participant Participant) {
   258  	s.Spec.Participants = append(s.Spec.Participants, participant)
   259  }
   260  
   261  // RemoveParticipant removes a participant from the session tracker.
   262  func (s *SessionTrackerV1) RemoveParticipant(id string) error {
   263  	for i, participant := range s.Spec.Participants {
   264  		if participant.ID == id {
   265  			s.Spec.Participants[i], s.Spec.Participants = s.Spec.Participants[len(s.Spec.Participants)-1], s.Spec.Participants[:len(s.Spec.Participants)-1]
   266  			return nil
   267  		}
   268  	}
   269  
   270  	return trace.NotFound("participant %v not found", id)
   271  }
   272  
   273  // GetKubeCluster returns the name of the kubernetes cluster the session is running in.
   274  //
   275  // This is only valid for kubernetes sessions.
   276  func (s *SessionTrackerV1) GetKubeCluster() string {
   277  	return s.Spec.KubernetesCluster
   278  }
   279  
   280  // HostID is the target host id that created the session tracker.
   281  func (s *SessionTrackerV1) GetHostID() string {
   282  	return s.Spec.HostID
   283  }
   284  
   285  // GetDesktopName returns the name of the Windows desktop the session is running in.
   286  //
   287  // This is only valid for Windows desktop sessions.
   288  func (s *SessionTrackerV1) GetDesktopName() string {
   289  	return s.Spec.DesktopName
   290  }
   291  
   292  // GetAppName returns the name of the app being accessed in the session.
   293  //
   294  // This is only valid for app sessions.
   295  func (s *SessionTrackerV1) GetAppName() string {
   296  	return s.Spec.AppName
   297  }
   298  
   299  // GetDatabaseName returns the name of the database being accessed in the session.
   300  //
   301  // This is only valid for database sessions.
   302  func (s *SessionTrackerV1) GetDatabaseName() string {
   303  	return s.Spec.DatabaseName
   304  }
   305  
   306  // GetHostUser fetches the user marked as the "host" of the session.
   307  // Things like RBAC policies are determined from this user.
   308  func (s *SessionTrackerV1) GetHostUser() string {
   309  	return s.Spec.HostUser
   310  }
   311  
   312  // UpdatePresence updates presence timestamp of a participant.
   313  func (s *SessionTrackerV1) UpdatePresence(user string, t time.Time) error {
   314  	idx := slices.IndexFunc(s.Spec.Participants, func(participant Participant) bool {
   315  		return participant.User == user
   316  	})
   317  
   318  	if idx < 0 {
   319  		return trace.NotFound("participant %v not found", user)
   320  	}
   321  
   322  	s.Spec.Participants[idx].LastActive = t
   323  	return nil
   324  }
   325  
   326  // GetHostPolicySets returns a list of policy sets held by the host user at the time of session creation.
   327  // This a subset of a role that contains some versioning and naming information in addition to the require policies
   328  func (s *SessionTrackerV1) GetHostPolicySets() []*SessionTrackerPolicySet {
   329  	return s.Spec.HostPolicies
   330  }
   331  
   332  // GetLastActive returns the time at which the session was last active (i.e used by any participant).
   333  func (s *SessionTrackerV1) GetLastActive() time.Time {
   334  	var last time.Time
   335  
   336  	for _, participant := range s.Spec.Participants {
   337  		if participant.LastActive.After(last) {
   338  			last = participant.LastActive
   339  		}
   340  	}
   341  
   342  	return last
   343  }
   344  
   345  // GetTargetSubKind returns the sub kind of the target server.
   346  func (s *SessionTrackerV1) GetTargetSubKind() string {
   347  	return s.Spec.TargetSubKind
   348  }
   349  
   350  // GetCommand returns command that intiated the session.
   351  func (s *SessionTrackerV1) GetCommand() []string {
   352  	return s.Spec.InitialCommand
   353  }
   354  
   355  // Match checks if a given session tracker matches this filter.
   356  func (f *SessionTrackerFilter) Match(s SessionTracker) bool {
   357  	if f.Kind != "" && string(s.GetSessionKind()) != f.Kind {
   358  		return false
   359  	}
   360  	if f.State != nil && s.GetState() != f.State.State {
   361  		return false
   362  	}
   363  	if f.DesktopName != "" && s.GetDesktopName() != f.DesktopName {
   364  		return false
   365  	}
   366  	return true
   367  }