Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/events/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ const (
// Note: some requests (like exec into a pod) use other codes (like
// ExecCode).
KubeRequestCode = "T3009I"
// SCPDisallowedCode is the SCP disallowed event code.
SCPDisallowedCode = "T3010E"

// KubernetesClusterCreateCode is the kube.create event code.
KubernetesClusterCreateCode = "T3010I"
Expand Down Expand Up @@ -329,6 +331,7 @@ const (
SFTPSymlinkFailureCode = "TS018E"
SFTPLinkCode = "TS019I"
SFTPLinkFailureCode = "TS019E"
SFTPDisallowedCode = "TS020E"

// SessionCommandCode is a session command code.
SessionCommandCode = "T4000I"
Expand Down
20 changes: 20 additions & 0 deletions lib/srv/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,16 @@ func (e *localExec) String() string {
func (e *localExec) transformSecureCopy() error {
isSCPCmd, err := checkSCPAllowed(e.Ctx, e.GetCommand())
if err != nil {
e.Ctx.GetServer().EmitAuditEvent(context.WithoutCancel(e.Ctx.Context), &apievents.SFTP{
Metadata: apievents.Metadata{
Code: events.SCPDisallowedCode,
Type: events.SCPEvent,
Time: time.Now(),
},
UserMetadata: e.Ctx.Identity.GetUserMetadata(),
ServerMetadata: e.Ctx.GetServerMetadata(),
Error: err.Error(),
})
return trace.Wrap(err)
}
if !isSCPCmd {
Expand Down Expand Up @@ -356,6 +366,16 @@ func (e *remoteExec) SetCommand(command string) {
// ExecResult is only used to communicate an error while launching.
func (e *remoteExec) Start(ctx context.Context, ch ssh.Channel) (*ExecResult, error) {
if _, err := checkSCPAllowed(e.ctx, e.GetCommand()); err != nil {
e.ctx.GetServer().EmitAuditEvent(context.WithoutCancel(ctx), &apievents.SFTP{
Metadata: apievents.Metadata{
Code: events.SCPDisallowedCode,
Type: events.SCPEvent,
Time: time.Now(),
},
UserMetadata: e.ctx.Identity.GetUserMetadata(),
ServerMetadata: e.ctx.GetServerMetadata(),
Error: err.Error(),
})
return nil, trace.Wrap(err)
}

Expand Down
14 changes: 13 additions & 1 deletion lib/srv/forward/sshserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"strconv"
"strings"
"sync"
"time"

"github.com/google/uuid"
"github.com/gravitational/trace"
Expand Down Expand Up @@ -1369,7 +1370,18 @@ func (s *Server) handleSubsystem(ctx context.Context, ch ssh.Channel, req *ssh.R

// if SFTP was requested, check that
if subsystem.subsytemName == teleport.SFTPSubsystem {
if err := serverContext.CheckSFTPAllowed(s.sessionRegistry); err != nil {
err := serverContext.CheckSFTPAllowed(s.sessionRegistry)
if err != nil {
s.EmitAuditEvent(context.WithoutCancel(ctx), &apievents.SFTP{
Metadata: apievents.Metadata{
Code: events.SFTPDisallowedCode,
Type: events.SFTPEvent,
Time: time.Now(),
},
UserMetadata: serverContext.Identity.GetUserMetadata(),
ServerMetadata: serverContext.GetServerMetadata(),
Error: err.Error(),
})
return trace.Wrap(err)
}
}
Expand Down
12 changes: 12 additions & 0 deletions lib/srv/regular/sftp.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"io"
"os"
"os/exec"
"time"

"github.com/gogo/protobuf/jsonpb"
"github.com/gravitational/trace"
Expand All @@ -33,6 +34,7 @@ import (

"github.com/gravitational/teleport"
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/srv"
"github.com/gravitational/teleport/lib/utils"
)
Expand Down Expand Up @@ -66,6 +68,16 @@ func (s *sftpSubsys) Start(ctx context.Context,
// this connection was proxied, the proxy doesn't know if file copying
// is allowed for certain Nodes.
if !serverCtx.AllowFileCopying {
serverCtx.GetServer().EmitAuditEvent(context.WithoutCancel(ctx), &apievents.SFTP{
Metadata: apievents.Metadata{
Code: events.SFTPDisallowedCode,
Type: events.SFTPEvent,
Time: time.Now(),
},
UserMetadata: serverCtx.Identity.GetUserMetadata(),
ServerMetadata: serverCtx.GetServerMetadata(),
Error: srv.ErrNodeFileCopyingNotPermitted.Error(),
})
return srv.ErrNodeFileCopyingNotPermitted
}

Expand Down
13 changes: 12 additions & 1 deletion lib/srv/regular/sshserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2154,7 +2154,18 @@ func (s *Server) parseSubsystemRequest(req *ssh.Request, ctx *srv.ServerContext)
case r.Name == teleport.GetHomeDirSubsystem:
return newHomeDirSubsys(), nil
case r.Name == teleport.SFTPSubsystem:
if err := ctx.CheckSFTPAllowed(s.reg); err != nil {
err := ctx.CheckSFTPAllowed(s.reg)
if err != nil {
s.EmitAuditEvent(context.Background(), &apievents.SFTP{
Metadata: apievents.Metadata{
Code: events.SFTPDisallowedCode,
Type: events.SFTPEvent,
Time: time.Now(),
},
UserMetadata: ctx.Identity.GetUserMetadata(),
ServerMetadata: ctx.GetServerMetadata(),
Error: err.Error(),
})
return nil, trace.Wrap(err)
}

Expand Down
4 changes: 4 additions & 0 deletions web/packages/teleport/src/Audit/EventList/EventTypeCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const EventIconMap: Record<EventCode, any> = {
[eventCodes.SCP_DOWNLOAD]: Icons.Download,
[eventCodes.SCP_UPLOAD_FAILURE]: Icons.Upload,
[eventCodes.SCP_UPLOAD]: Icons.Upload,
[eventCodes.SCP_DISALLOWED]: Icons.FolderPlus,
[eventCodes.SFTP_OPEN_FAILURE]: Icons.FolderPlus,
[eventCodes.SFTP_OPEN]: Icons.FolderPlus,
[eventCodes.SFTP_CLOSE_FAILURE]: Icons.FolderPlus,
Expand Down Expand Up @@ -83,6 +84,9 @@ const EventIconMap: Record<EventCode, any> = {
[eventCodes.SFTP_READLINK]: Icons.FolderPlus,
[eventCodes.SFTP_SYMLINK_FAILURE]: Icons.FolderPlus,
[eventCodes.SFTP_SYMLINK]: Icons.FolderPlus,
[eventCodes.SFTP_LINK]: Icons.FolderPlus,
[eventCodes.SFTP_LINK_FAILURE]: Icons.FolderPlus,
[eventCodes.SFTP_DISALLOWED]: Icons.FolderPlus,
[eventCodes.APP_SESSION_CHUNK]: Icons.Info,
[eventCodes.APP_SESSION_START]: Icons.Info,
[eventCodes.APP_SESSION_END]: Icons.Info,
Expand Down
32 changes: 32 additions & 0 deletions web/packages/teleport/src/services/audit/makeEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,14 @@ export const formatters: Formatters = {
rest['server_hostname'] || rest['addr.local']
}] failed [${exitError}]`,
},
[eventCodes.SCP_DISALLOWED]: {
type: 'scp',
desc: 'SCP Disallowed',
format: ({ user, ...rest }) =>
`User [${user}] SCP file transfer on node [${
rest['server_hostname'] || rest['addr.local']
}] blocked`,
},
[eventCodes.SFTP_OPEN]: {
type: 'sftp',
desc: 'SFTP Open',
Expand Down Expand Up @@ -569,6 +577,30 @@ export const formatters: Formatters = {
rest['server_hostname'] || rest['addr.local']
}]: [${error}]`,
},
[eventCodes.SFTP_LINK]: {
type: 'sftp',
desc: 'SFTP Link',
format: ({ user, path, ...rest }) =>
`User [${user}] created hard link [${path}] on node [${
rest['server_hostname'] || rest['addr.local']
}]`,
},
[eventCodes.SFTP_LINK_FAILURE]: {
type: 'sftp',
desc: 'SFTP Link Failed',
format: ({ user, path, error, ...rest }) =>
`User [${user}] failed to create hard link [${path}] on node [${
rest['server_hostname'] || rest['addr.local']
}]: [${error}]`,
},
[eventCodes.SFTP_DISALLOWED]: {
type: 'sftp',
desc: 'SFTP Disallowed',
format: ({ user, ...rest }) =>
`User [${user}] was blocked from creating an SFTP session on node [${
rest['server_hostname'] || rest['addr.local']
}]`,
},
[eventCodes.SESSION_JOIN]: {
type: 'session.join',
desc: 'User Joined',
Expand Down
15 changes: 15 additions & 0 deletions web/packages/teleport/src/services/audit/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export const eventCodes = {
SCP_DOWNLOAD: 'T3004I',
SCP_UPLOAD_FAILURE: 'T3005E',
SCP_UPLOAD: 'T3005I',
SCP_DISALLOWED: 'T3010E',
SFTP_OPEN_FAILURE: 'TS001E',
SFTP_OPEN: 'TS001I',
SFTP_CLOSE_FAILURE: 'TS002E',
Expand Down Expand Up @@ -188,6 +189,9 @@ export const eventCodes = {
SFTP_READLINK: 'TS017I',
SFTP_SYMLINK_FAILURE: 'TS018E',
SFTP_SYMLINK: 'TS018I',
SFTP_LINK: 'TS019I',
SFTP_LINK_FAILURE: 'TS019E',
SFTP_DISALLOWED: 'TS020E',
SESSION_COMMAND: 'T4000I',
SESSION_DATA: 'T2006I',
SESSION_DISK: 'T4001I',
Expand Down Expand Up @@ -402,6 +406,12 @@ export type RawEvents = {
exitError: string;
}
>;
[eventCodes.SCP_DISALLOWED]: RawEvent<
typeof eventCodes.SCP_DISALLOWED,
{
user: string;
}
>;
[eventCodes.SFTP_OPEN]: RawEventSFTP<typeof eventCodes.SFTP_OPEN>;
[eventCodes.SFTP_OPEN_FAILURE]: RawEventSFTP<
typeof eventCodes.SFTP_OPEN_FAILURE
Expand Down Expand Up @@ -474,6 +484,11 @@ export type RawEvents = {
[eventCodes.SFTP_SYMLINK_FAILURE]: RawEventSFTP<
typeof eventCodes.SFTP_SYMLINK_FAILURE
>;
[eventCodes.SFTP_LINK]: RawEventSFTP<typeof eventCodes.SFTP_LINK>;
[eventCodes.SFTP_LINK_FAILURE]: RawEventSFTP<
typeof eventCodes.SFTP_LINK_FAILURE
>;
[eventCodes.SFTP_DISALLOWED]: RawEventSFTP<typeof eventCodes.SFTP_DISALLOWED>;
[eventCodes.SESSION_COMMAND]: RawEventCommand<
typeof eventCodes.SESSION_COMMAND
>;
Expand Down