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

[v14] Add initial command to session trackers #33112

Merged
merged 1 commit into from Oct 9, 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
3 changes: 3 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Expand Up @@ -4977,6 +4977,9 @@ message SessionTrackerSpecV1 {

// TargetSubKind is the sub kind of the target server.
string TargetSubKind = 22 [(gogoproto.jsontag) = "target_sub_kind,omitempty"];

// InitialCommand is the command that was executed to start this session.
repeated string InitialCommand = 23 [(gogoproto.jsontag) = "initial_command,omitempty"];
}

// SessionTrackerPolicySet is a set of RBAC policies held by the session tracker
Expand Down
8 changes: 8 additions & 0 deletions api/types/session_tracker.go
Expand Up @@ -125,6 +125,9 @@ type SessionTracker interface {

// GetTargetSubKind returns the sub kind of the target server.
GetTargetSubKind() string

// GetCommand returns the command that initiated the session.
GetCommand() []string
}

func NewSessionTracker(spec SessionTrackerSpecV1) (SessionTracker, error) {
Expand Down Expand Up @@ -344,6 +347,11 @@ func (s *SessionTrackerV1) GetTargetSubKind() string {
return s.Spec.TargetSubKind
}

// GetCommand returns command that intiated the session.
func (s *SessionTrackerV1) GetCommand() []string {
return s.Spec.InitialCommand
}

// Match checks if a given session tracker matches this filter.
func (f *SessionTrackerFilter) Match(s SessionTracker) bool {
if f.Kind != "" && string(s.GetSessionKind()) != f.Kind {
Expand Down
2,970 changes: 1,511 additions & 1,459 deletions api/types/types.pb.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions lib/kube/proxy/sess.go
Expand Up @@ -1206,6 +1206,7 @@ func (s *session) trackSession(p *party, policySet []*types.SessionTrackerPolicy
Reason: s.reason,
Invited: s.invitedUsers,
HostID: s.forwarder.cfg.HostID,
InitialCommand: s.req.URL.Query()["command"],
}

s.log.Debug("Creating session tracker")
Expand Down
9 changes: 6 additions & 3 deletions lib/kube/proxy/sess_test.go
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"net/http"
"net/url"
"testing"

"github.com/google/uuid"
Expand Down Expand Up @@ -110,9 +111,11 @@ func Test_session_trackSession(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sess := &session{
log: logrus.New().WithField(trace.Component, "test"),
id: uuid.New(),
req: &http.Request{},
log: logrus.New().WithField(trace.Component, "test"),
id: uuid.New(),
req: &http.Request{
URL: &url.URL{},
},
podName: "podName",
accessEvaluator: auth.NewSessionAccessEvaluator(tt.args.policies, types.KubernetesSessionKind, "username"),
ctx: authContext{
Expand Down
2 changes: 2 additions & 0 deletions lib/session/session.go
Expand Up @@ -107,6 +107,8 @@ type Session struct {
Owner string `json:"owner"`
// Moderated is true if the session requires moderation (only relevant for Kind = ssh/k8s).
Moderated bool `json:"moderated"`
// Command is the command that was executed to start the session.
Command string `json:"command"`
}

// FileTransferRequestParams contain parameters for requesting a file transfer
Expand Down
9 changes: 7 additions & 2 deletions lib/srv/sess.go
Expand Up @@ -2036,6 +2036,10 @@ func (p *party) closeUnderSessionLock() error {
// on an interval until the session tracker is closed.
func (s *session) trackSession(ctx context.Context, teleportUser string, policySet []*types.SessionTrackerPolicySet, p *party) error {
s.log.Debugf("Tracking participant: %s", p.id)
var initialCommand []string
if execRequest, err := s.scx.GetExecRequest(); err == nil {
initialCommand = []string{execRequest.GetCommand()}
}
trackerSpec := types.SessionTrackerSpecV1{
SessionID: s.id.String(),
Kind: string(types.SSHSessionKind),
Expand All @@ -2056,8 +2060,9 @@ func (s *session) trackSession(ctx context.Context, teleportUser string, policyS
LastActive: s.registry.clock.Now().UTC(),
},
},
HostID: s.registry.Srv.ID(),
TargetSubKind: s.serverMeta.ServerSubKind,
HostID: s.registry.Srv.ID(),
TargetSubKind: s.serverMeta.ServerSubKind,
InitialCommand: initialCommand,
}

if s.scx.env[teleport.EnvSSHSessionInvited] != "" {
Expand Down
3 changes: 1 addition & 2 deletions lib/web/apiserver.go
Expand Up @@ -2484,7 +2484,6 @@ func (h *Handler) getSiteNamespaces(w http.ResponseWriter, r *http.Request, _ ht
}

func makeUnifiedResourceRequest(r *http.Request) (*proto.ListUnifiedResourcesRequest, error) {

values := r.URL.Query()

limit, err := queryLimitAsInt32(values, "limit", defaults.MaxIterationLimit)
Expand Down Expand Up @@ -3144,6 +3143,7 @@ func trackerToLegacySession(tracker types.SessionTracker, clusterName string) se
Moderated: accessEvaluator.IsModerated(),
DatabaseName: tracker.GetDatabaseName(),
Owner: tracker.GetHostUser(),
Command: strings.Join(tracker.GetCommand(), " "),
}
}

Expand Down Expand Up @@ -3824,7 +3824,6 @@ func consumeTokenForAPICall(ctx context.Context, proxyClient auth.ClientI, token
}

return token, nil

}

// checkTokenTTL returns true if the token is still valid.
Expand Down
13 changes: 11 additions & 2 deletions tool/tsh/common/kube.go
Expand Up @@ -575,9 +575,18 @@ func serializeKubeSessions(sessions []types.SessionTracker, format string) (stri
}

func printSessions(output io.Writer, sessions []types.SessionTracker) {
table := asciitable.MakeTable([]string{"ID", "State", "Created", "Hostname", "Address", "Login", "Reason"})
table := asciitable.MakeTable([]string{"ID", "State", "Created", "Hostname", "Address", "Login", "Reason", "Command"})
for _, s := range sessions {
table.AddRow([]string{s.GetSessionID(), s.GetState().String(), s.GetCreated().Format(time.RFC3339), s.GetHostname(), s.GetAddress(), s.GetLogin(), s.GetReason()})
table.AddRow([]string{
s.GetSessionID(),
s.GetState().String(),
s.GetCreated().Format(time.RFC3339),
s.GetHostname(),
s.GetAddress(),
s.GetLogin(),
s.GetReason(),
strings.Join(s.GetCommand(), " "),
})
}

tableOutput := table.AsBuffer().String()
Expand Down
Expand Up @@ -100,4 +100,6 @@ const session: Session = {
addr: '1.1.1.1:1111',
participantModes: ['observer', 'moderator', 'peer'],
moderated: false,
command:
'top -o command -o cpu -o boosts -o cycles -o cow -o user -o vsize -o csw -o threads -o ports -o ppid',
};
Expand Up @@ -55,6 +55,10 @@ export default function SessionList(props: Props) {
headerText: 'Users',
render: renderUsersCell,
},
{
key: 'command',
headerText: 'Command',
},
{
key: 'durationText',
altSortKey: 'created',
Expand Down