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
75 changes: 75 additions & 0 deletions api/proto/teleport/legacy/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,13 @@ message UserCreate {

// Connector is the connector used to create the user.
string Connector = 5 [(gogoproto.jsontag) = "connector"];

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

// UserDelete is emitted when a user gets deleted
Expand All @@ -1304,6 +1311,13 @@ message UserDelete {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// UserPasswordChange is emitted when the user changes their own password.
Expand All @@ -1321,6 +1335,13 @@ message UserPasswordChange {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// AccessRequestCreate is emitted when access request has been created or updated
Expand Down Expand Up @@ -1900,6 +1921,13 @@ message RoleCreate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// RoleDelete is emitted when a role is deleted
Expand All @@ -1924,6 +1952,13 @@ message RoleDelete {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// TrustedClusterCreate is the event for creating a trusted cluster.
Expand All @@ -1948,6 +1983,13 @@ message TrustedClusterCreate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// TrustedClusterDelete is the event for removing a trusted cluster.
Expand All @@ -1972,6 +2014,13 @@ message TrustedClusterDelete {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// ProvisionTokenCreate event is emitted when a provisioning token (a.k.a. join
Expand Down Expand Up @@ -2055,6 +2104,13 @@ message GithubConnectorCreate {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// GithubConnectorDelete fires when a Github connector is deleted.
Expand All @@ -2079,6 +2135,13 @@ message GithubConnectorDelete {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];

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

// OIDCConnectorCreate fires when OIDC connector is created/updated.
Expand Down Expand Up @@ -2988,6 +3051,12 @@ message MFADeviceAdd {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
// ConnectionMetadata holds information about the connection
ConnectionMetadata Connection = 4 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// MFADeviceDelete is emitted when a user deletes an MFA device.
Expand All @@ -3010,6 +3079,12 @@ message MFADeviceDelete {
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
// ConnectionMetadata holds information about the connection
ConnectionMetadata Connection = 4 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// BillingInformationUpdate is emitted when a user updates the billing information.
Expand Down
2,319 changes: 1,419 additions & 900 deletions api/types/events/events.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions lib/auth/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func (a *Server) UpsertRole(ctx context.Context, role types.Role) error {
ResourceMetadata: apievents.ResourceMetadata{
Name: role.GetName(),
},
ConnectionMetadata: authz.ConnectionMetadata(ctx),
}); err != nil {
log.WithError(err).Warnf("Failed to emit role create event.")
}
Expand Down Expand Up @@ -132,6 +133,7 @@ func (a *Server) DeleteRole(ctx context.Context, name string) error {
ResourceMetadata: apievents.ResourceMetadata{
Name: name,
},
ConnectionMetadata: authz.ConnectionMetadata(ctx),
}); err != nil {
log.WithError(err).Warnf("Failed to emit role delete event.")
}
Expand Down
17 changes: 12 additions & 5 deletions lib/auth/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package auth

import (
"context"
"net"
"testing"
"time"

Expand All @@ -28,12 +29,14 @@ import (
"github.com/gravitational/teleport/api/types/accesslist"
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/api/types/header"
"github.com/gravitational/teleport/lib/authz"
"github.com/gravitational/teleport/lib/events"
)

func TestUpsertDeleteRoleEventsEmitted(t *testing.T) {
t.Parallel()
ctx := context.Background()
clientAddr := &net.TCPAddr{IP: net.IPv4(10, 255, 0, 0)}
ctx := authz.ContextWithClientSrcAddr(context.Background(), clientAddr)
p, err := newTestPack(ctx, t.TempDir())
require.NoError(t, err)

Expand All @@ -47,8 +50,10 @@ func TestUpsertDeleteRoleEventsEmitted(t *testing.T) {
// Creating a role should emit a RoleCreatedEvent.
err = p.a.UpsertRole(ctx, role)
require.NoError(t, err)
require.Equal(t, p.mockEmitter.LastEvent().GetType(), events.RoleCreatedEvent)
require.Equal(t, p.mockEmitter.LastEvent().(*apievents.RoleCreate).Name, role.GetName())
require.Equal(t, events.RoleCreatedEvent, p.mockEmitter.LastEvent().GetType())
createEvt := p.mockEmitter.LastEvent().(*apievents.RoleCreate)
require.Equal(t, role.GetName(), createEvt.Name)
require.Equal(t, clientAddr.String(), createEvt.ConnectionMetadata.RemoteAddr)
p.mockEmitter.Reset()

// Updating a role should emit a RoleCreatedEvent.
Expand All @@ -61,8 +66,10 @@ func TestUpsertDeleteRoleEventsEmitted(t *testing.T) {
// Deleting a role should emit a RoleDeletedEvent.
err = p.a.DeleteRole(ctx, role.GetName())
require.NoError(t, err)
require.Equal(t, p.mockEmitter.LastEvent().GetType(), events.RoleDeletedEvent)
require.Equal(t, p.mockEmitter.LastEvent().(*apievents.RoleDelete).Name, role.GetName())
require.Equal(t, events.RoleDeletedEvent, p.mockEmitter.LastEvent().GetType())
deleteEvt := p.mockEmitter.LastEvent().(*apievents.RoleDelete)
require.Equal(t, role.GetName(), deleteEvt.Name)
require.Equal(t, clientAddr.String(), deleteEvt.ConnectionMetadata.RemoteAddr)
p.mockEmitter.Reset()

// When deleting a nonexistent role, no event should be emitted.
Expand Down
10 changes: 6 additions & 4 deletions lib/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -3223,8 +3223,9 @@ func (a *Server) deleteMFADeviceSafely(ctx context.Context, user, deviceName str
Code: events.MFADeviceDeleteEventCode,
ClusterName: clusterName.GetClusterName(),
},
UserMetadata: authz.ClientUserMetadataWithUser(ctx, user),
MFADeviceMetadata: mfaDeviceEventMetadata(deviceToDelete),
UserMetadata: authz.ClientUserMetadataWithUser(ctx, user),
MFADeviceMetadata: mfaDeviceEventMetadata(deviceToDelete),
ConnectionMetadata: authz.ConnectionMetadata(ctx),
}); err != nil {
return nil, trace.Wrap(err)
}
Expand Down Expand Up @@ -3324,8 +3325,9 @@ func (a *Server) verifyMFARespAndAddDevice(ctx context.Context, req *newMFADevic
Code: events.MFADeviceAddEventCode,
ClusterName: clusterName.GetClusterName(),
},
UserMetadata: authz.ClientUserMetadataWithUser(ctx, req.username),
MFADeviceMetadata: mfaDeviceEventMetadata(dev),
UserMetadata: authz.ClientUserMetadataWithUser(ctx, req.username),
MFADeviceMetadata: mfaDeviceEventMetadata(dev),
ConnectionMetadata: authz.ConnectionMetadata(ctx),
}); err != nil {
log.WithError(err).Warn("Failed to emit add mfa device event.")
}
Expand Down
29 changes: 23 additions & 6 deletions lib/auth/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"errors"
"fmt"
mathrand "math/rand"
"net"
"os"
"sort"
"strings"
Expand Down Expand Up @@ -767,7 +768,8 @@ func TestTrustedClusterCRUDEventEmitted(t *testing.T) {
t.Parallel()
s := newAuthSuite(t)

ctx := context.Background()
clientAddr := &net.TCPAddr{IP: net.IPv4(10, 255, 0, 0)}
ctx := authz.ContextWithClientSrcAddr(context.Background(), clientAddr)
s.a.emitter = s.mockEmitter

// set up existing cluster to bypass switch cases that
Expand Down Expand Up @@ -795,6 +797,8 @@ func TestTrustedClusterCRUDEventEmitted(t *testing.T) {
_, err = s.a.UpsertTrustedCluster(ctx, tc)
require.NoError(t, err)
require.Equal(t, s.mockEmitter.LastEvent().GetType(), events.TrustedClusterCreateEvent)
require.Equal(t, events.TrustedClusterCreateEvent, s.mockEmitter.LastEvent().GetType())
require.Equal(t, clientAddr.String(), s.mockEmitter.LastEvent().(*apievents.TrustedClusterCreate).ConnectionMetadata.RemoteAddr)
s.mockEmitter.Reset()

// test create event for switch case: when tc exists but enabled is true
Expand All @@ -803,19 +807,24 @@ func TestTrustedClusterCRUDEventEmitted(t *testing.T) {
_, err = s.a.UpsertTrustedCluster(ctx, tc)
require.NoError(t, err)
require.Equal(t, s.mockEmitter.LastEvent().GetType(), events.TrustedClusterCreateEvent)
require.Equal(t, events.TrustedClusterCreateEvent, s.mockEmitter.LastEvent().GetType())
require.Equal(t, clientAddr.String(), s.mockEmitter.LastEvent().(*apievents.TrustedClusterCreate).ConnectionMetadata.RemoteAddr)
s.mockEmitter.Reset()

// test delete event
err = s.a.DeleteTrustedCluster(ctx, "test")
require.NoError(t, err)
require.Equal(t, s.mockEmitter.LastEvent().GetType(), events.TrustedClusterDeleteEvent)
require.Equal(t, events.TrustedClusterDeleteEvent, s.mockEmitter.LastEvent().GetType())
require.Equal(t, clientAddr.String(), s.mockEmitter.LastEvent().(*apievents.TrustedClusterDelete).ConnectionMetadata.RemoteAddr)
}

func TestGithubConnectorCRUDEventsEmitted(t *testing.T) {
t.Parallel()
s := newAuthSuite(t)

ctx := context.Background()
clientAddr := &net.TCPAddr{IP: net.IPv4(10, 255, 0, 0)}
ctx := authz.ContextWithClientSrcAddr(context.Background(), clientAddr)
// test github create event
github, err := types.NewGithubConnector("test", types.GithubConnectorSpecV3{
TeamsToLogins: []types.TeamMapping{
Expand All @@ -830,21 +839,25 @@ func TestGithubConnectorCRUDEventsEmitted(t *testing.T) {
err = s.a.upsertGithubConnector(ctx, github)
require.NoError(t, err)
require.IsType(t, &apievents.GithubConnectorCreate{}, s.mockEmitter.LastEvent())
require.Equal(t, s.mockEmitter.LastEvent().GetType(), events.GithubConnectorCreatedEvent)
require.Equal(t, events.GithubConnectorCreatedEvent, s.mockEmitter.LastEvent().GetType())
require.Equal(t, clientAddr.String(), s.mockEmitter.LastEvent().(*apievents.GithubConnectorCreate).ConnectionMetadata.RemoteAddr)
s.mockEmitter.Reset()

// test github update event
err = s.a.upsertGithubConnector(ctx, github)
require.NoError(t, err)
require.IsType(t, &apievents.GithubConnectorCreate{}, s.mockEmitter.LastEvent())
require.Equal(t, s.mockEmitter.LastEvent().GetType(), events.GithubConnectorCreatedEvent)
require.Equal(t, events.GithubConnectorCreatedEvent, s.mockEmitter.LastEvent().GetType())
require.Equal(t, clientAddr.String(), s.mockEmitter.LastEvent().(*apievents.GithubConnectorCreate).ConnectionMetadata.RemoteAddr)
s.mockEmitter.Reset()

// test github delete event
err = s.a.deleteGithubConnector(ctx, "test")
require.NoError(t, err)
require.IsType(t, &apievents.GithubConnectorDelete{}, s.mockEmitter.LastEvent())
require.Equal(t, s.mockEmitter.LastEvent().GetType(), events.GithubConnectorDeletedEvent)
require.Equal(t, events.GithubConnectorDeletedEvent, s.mockEmitter.LastEvent().GetType())
require.Equal(t, clientAddr.String(), s.mockEmitter.LastEvent().(*apievents.GithubConnectorDelete).ConnectionMetadata.RemoteAddr)
}

func TestOIDCConnectorCRUDEventsEmitted(t *testing.T) {
Expand Down Expand Up @@ -2064,7 +2077,8 @@ func TestDeleteMFADeviceSync(t *testing.T) {
mockEmitter := &eventstest.MockRecorderEmitter{}
authServer.emitter = mockEmitter

ctx := context.Background()
clientAddr := &net.TCPAddr{IP: net.IPv4(10, 255, 0, 0)}
ctx := authz.ContextWithClientSrcAddr(context.Background(), clientAddr)

username := "llama@goteleport.com"
_, _, err := CreateUserAndRole(authServer, username, []string{username}, nil /* allowRules */)
Expand Down Expand Up @@ -2150,6 +2164,7 @@ func TestDeleteMFADeviceSync(t *testing.T) {
require.IsType(t, &apievents.MFADeviceDelete{}, event, "underlying event type")
deleteEvent := event.(*apievents.MFADeviceDelete) // asserted above
assert.Equal(t, username, deleteEvent.User, "event.User")
assert.Equal(t, clientAddr.String(), deleteEvent.ConnectionMetadata.RemoteAddr)
})
}
}
Expand Down Expand Up @@ -2499,7 +2514,9 @@ func TestAddMFADeviceSync(t *testing.T) {
event := mockEmitter.LastEvent()
require.Equal(t, events.MFADeviceAddEvent, event.GetType())
require.Equal(t, events.MFADeviceAddEventCode, event.GetCode())
require.Equal(t, event.(*apievents.MFADeviceAdd).UserMetadata.User, u.username)
addEvt := event.(*apievents.MFADeviceAdd)
require.Equal(t, u.username, addEvt.UserMetadata.User)
assert.Contains(t, addEvt.ConnectionMetadata.RemoteAddr, "127.0.0.1", "client remote addr must be localhost")

// Check it's been added.
res, err := clt.GetMFADevices(ctx, &proto.GetMFADevicesRequest{})
Expand Down
Loading