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

GitHub proxy part 7: audit events #49923

Merged
merged 3 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
67 changes: 67 additions & 0 deletions api/proto/teleport/legacy/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -4707,6 +4707,7 @@ message OneOf {
events.WorkloadIdentityCreate WorkloadIdentityCreate = 194;
events.WorkloadIdentityUpdate WorkloadIdentityUpdate = 195;
events.WorkloadIdentityDelete WorkloadIdentityDelete = 196;
events.GitCommand GitCommand = 197;
}
}

Expand Down Expand Up @@ -7800,3 +7801,69 @@ message WorkloadIdentityDelete {
(gogoproto.jsontag) = ""
];
}

// GitCommand is emitted when a user performance a Git fetch or push command.
greedy52 marked this conversation as resolved.
Show resolved Hide resolved
message GitCommand {
// Metadata is a common event metadata
Metadata Metadata = 1 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// User is a common user event metadata
UserMetadata User = 2 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// ConnectionMetadata holds information about the connection
ConnectionMetadata Connection = 3 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// SessionMetadata is a common event session metadata
SessionMetadata Session = 4 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// ServerMetadata is a common server metadata
ServerMetadata Server = 5 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// CommandMetadata is a common command metadata
CommandMetadata Command = 6 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

// Service is the type of the git request like git-upload-pack or
// git-receive-pack.
string service = 8 [(gogoproto.jsontag) = "service"];
// Path is the Git repo path, usually <org>/<repo>.
string path = 9 [(gogoproto.jsontag) = "path"];

// Actions defines details for a Git push.
repeated GitCommandAction actions = 10 [(gogoproto.jsontag) = "actions,omitempty"];
}

// GitCommandAction defines details for a Git push.
message GitCommandAction {
// Action type like create or update.
string Action = 1 [(gogoproto.jsontag) = "action,omitempty"];
// Reference name like ref/main/my_branch.
string Reference = 2 [(gogoproto.jsontag) = "reference,omitempty"];
// Old is the old hash.
string Old = 3 [(gogoproto.jsontag) = "old,omitempty"];
// New is the new hash.
string New = 4 [(gogoproto.jsontag) = "new,omitempty"];
}
4 changes: 4 additions & 0 deletions api/types/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2402,3 +2402,7 @@ func (m *WorkloadIdentityUpdate) TrimToMaxSize(maxSize int) AuditEvent {
func (m *WorkloadIdentityDelete) TrimToMaxSize(_ int) AuditEvent {
return m
}

func (m *GitCommand) TrimToMaxSize(_ int) AuditEvent {
return m
}
5,765 changes: 3,365 additions & 2,400 deletions api/types/events/events.pb.go

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions api/types/events/oneof.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,10 @@ func ToOneOf(in AuditEvent) (*OneOf, error) {
out.Event = &OneOf_WorkloadIdentityDelete{
WorkloadIdentityDelete: e,
}
case *GitCommand:
out.Event = &OneOf_GitCommand{
GitCommand: e,
}
default:
slog.ErrorContext(context.Background(), "Attempted to convert dynamic event of unknown type into protobuf event.", "event_type", in.GetType())
unknown := &Unknown{}
Expand Down
3 changes: 3 additions & 0 deletions lib/events/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,9 @@ const (
WorkloadIdentityUpdateEvent = "workload_identity.update"
// WorkloadIdentityDeleteEvent is emitted when a WorkloadIdentity resource is deleted.
WorkloadIdentityDeleteEvent = "workload_identity.delete"

// GitCommandEvent is emitted when a Git command is executed.
GitCommandEvent = "git.command"
)

// Add an entry to eventsMap in lib/events/events_test.go when you add
Expand Down
5 changes: 5 additions & 0 deletions lib/events/codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,11 @@ const (
// WorkloadIdentityDeleteCode is the workload identity delete event code.
WorkloadIdentityDeleteCode = "WID003I"

// GitCommandCode is the git command event code
GitCommandCode = "TGIT001I"
// GitCommandFailureCode is the git command feature event code.
GitCommandFailureCode = "TGIT001E"

// UnknownCode is used when an event of unknown type is encountered.
UnknownCode = apievents.UnknownCode
)
Expand Down
2 changes: 2 additions & 0 deletions web/packages/teleport/src/Audit/EventList/EventTypeCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ const EventIconMap: Record<EventCode, any> = {
[eventCodes.CONTACT_CREATE]: Icons.Info,
[eventCodes.CONTACT_DELETE]: Icons.Info,
[eventCodes.UNKNOWN]: Icons.Question,
[eventCodes.GIT_COMMAND]: Icons.GitHub,
[eventCodes.GIT_COMMAND_FAILURE]: Icons.GitHub,
};

export default function renderTypeCell(event: Event) {
Expand Down
35 changes: 35 additions & 0 deletions web/packages/teleport/src/Audit/fixtures/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3709,6 +3709,41 @@ export const events = [
user: '30a6b2e1-3b61-4965-92cf-b4f84e9dc683.lenix',
user_kind: 1,
},
{
code: 'TGIT001E',
event: 'git.command',
time: '2024-12-07T11:11:11.111Z',
uid: '7699b806-e717-4821-85a5-d2f41acbe373',
user: 'Linus.Torvalds',
service: 'git-upload-pack',
exitError: 'some-error',
path: 'my-org/my-repo',
},
{
code: 'TGIT001I',
event: 'git.command',
time: '2024-12-07T11:11:11.112Z',
uid: '7699b806-e717-4821-85a5-d2f41acbe373',
user: 'Linus.Torvalds',
service: 'git-upload-pack',
path: 'my-org/my-repo',
},
{
code: 'TGIT001I',
event: 'git.command',
time: '2024-12-07T11:11:11.112Z',
uid: '7699b806-e717-4821-85a5-d2f41acbe373',
user: 'Linus.Torvalds',
service: 'git-receive-pack',
path: 'my-org/my-repo',
actions: [
{
action: 'update',
reference: 'refs/heads/my-branch',
new: 'd3adb33f1234567890abcdef1234567890abcdef',
},
],
},
].map(makeEvent);

// Do not add new events to this array, add it to `events` list.
Expand Down
35 changes: 35 additions & 0 deletions web/packages/teleport/src/services/audit/makeEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1893,6 +1893,41 @@ export const formatters: Formatters = {
format: ({ unknown_type, unknown_code }) =>
`Unknown '${unknown_type}' event (${unknown_code})`,
},
[eventCodes.GIT_COMMAND]: {
type: 'git.command',
desc: 'Git Command',
format: ({ user, service, path, actions }) => {
// "git-upload-pack" are fetches like "git fetch", "git pull".
if (service === 'git-upload-pack') {
return `User [${user}] has fetched from [${path}]`;
}
// "git-receive-pack" are pushes. Usually it should have one action.
if (service === 'git-receive-pack') {
if (actions && actions.length == 1) {
switch (actions[0].action) {
case 'delete':
return `User [${user}] has deleted [${actions[0].reference}] from [${path}]`;
case 'create':
return `User [${user}] has created [${actions[0].reference}] on [${path}]`;
case 'update':
return `User [${user}] has updated [${actions[0].reference}] to [${actions[0].new.substring(0, 7)}] on [${path}]`;
}
}
return `User [${user}] has attempted a push to [${path}]`;
}
if (service && path) {
return `User [${user}] has executed a Git Command [${service}] at [${path}]`;
}
return `User [${user}] has executed a Git Command`;
},
},
[eventCodes.GIT_COMMAND_FAILURE]: {
type: 'git.command',
desc: 'Git Command Failed',
format: ({ user, exitError, service, path }) => {
return `User [${user}] Git Command [${service}] at [${path}] failed [${exitError}]`;
},
},
};

const unknownFormatter = {
Expand Down
23 changes: 23 additions & 0 deletions web/packages/teleport/src/services/audit/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ export const eventCodes = {
PLUGIN_DELETE: 'PG003I',
CONTACT_CREATE: 'TCTC001I',
CONTACT_DELETE: 'TCTC002I',
GIT_COMMAND: 'TGIT001I',
GIT_COMMAND_FAILURE: 'TGIT001E',
} as const;

/**
Expand Down Expand Up @@ -1738,6 +1740,27 @@ export type RawEvents = {
contact_type: number;
}
>;
[eventCodes.GIT_COMMAND]: RawEvent<
typeof eventCodes.GIT_COMMAND,
{
service: string;
path: string;
actions?: {
action: string;
reference: string;
new?: string;
old?: string;
}[];
}
>;
[eventCodes.GIT_COMMAND_FAILURE]: RawEvent<
typeof eventCodes.GIT_COMMAND_FAILURE,
{
service: string;
path: string;
exitError: string;
}
>;
};

/**
Expand Down
Loading