mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-12 02:15:01 +00:00
added audit events for discovery config actions (#43750)
Co-authored-by: Andrew LeFevre <Andrew LeFevre>
This commit is contained in:
co-authored by
Andrew LeFevre
parent
d9bcd2e2da
commit
629f2d347f
@@ -4003,6 +4003,123 @@ message DeviceEvent2 {
|
||||
];
|
||||
}
|
||||
|
||||
// DiscoveryConfigCreate is emitted when a discovery config is created.
|
||||
message DiscoveryConfigCreate {
|
||||
// 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) = ""
|
||||
];
|
||||
|
||||
// ResourceMetadata is a common resource event metadata
|
||||
ResourceMetadata Resource = 3 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// ConnectionMetadata holds information about the connection
|
||||
ConnectionMetadata Connection = 4 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
}
|
||||
|
||||
// DiscoveryConfigUpdate is emitted when a discovery config is updated.
|
||||
message DiscoveryConfigUpdate {
|
||||
// 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) = ""
|
||||
];
|
||||
|
||||
// ResourceMetadata is a common resource event metadata
|
||||
ResourceMetadata Resource = 3 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// ConnectionMetadata holds information about the connection
|
||||
ConnectionMetadata Connection = 4 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
}
|
||||
|
||||
// DiscoveryConfigDelete is emitted when a discovery config is deleted.
|
||||
message DiscoveryConfigDelete {
|
||||
// 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) = ""
|
||||
];
|
||||
|
||||
// ResourceMetadata is a common resource event metadata
|
||||
ResourceMetadata Resource = 3 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// ConnectionMetadata holds information about the connection
|
||||
ConnectionMetadata Connection = 4 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
}
|
||||
|
||||
// DiscoveryConfigDeleteAll is emitted when all discovery configs are deleted.
|
||||
message DiscoveryConfigDeleteAll {
|
||||
// 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) = ""
|
||||
];
|
||||
}
|
||||
|
||||
// OneOf is a union of one of audit events submitted to the auth service
|
||||
message OneOf {
|
||||
// Event is one of the audit events
|
||||
@@ -4165,6 +4282,10 @@ message OneOf {
|
||||
events.AccessPathChanged AccessPathChanged = 157;
|
||||
events.SpannerRPC SpannerRPC = 158;
|
||||
events.DatabaseSessionCommandResult DatabaseSessionCommandResult = 159;
|
||||
events.DiscoveryConfigCreate DiscoveryConfigCreate = 160;
|
||||
events.DiscoveryConfigUpdate DiscoveryConfigUpdate = 161;
|
||||
events.DiscoveryConfigDelete DiscoveryConfigDelete = 162;
|
||||
events.DiscoveryConfigDeleteAll DiscoveryConfigDeleteAll = 163;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2605
-1036
File diff suppressed because it is too large
Load Diff
@@ -672,6 +672,22 @@ func ToOneOf(in AuditEvent) (*OneOf, error) {
|
||||
out.Event = &OneOf_DatabaseSessionCommandResult{
|
||||
DatabaseSessionCommandResult: e,
|
||||
}
|
||||
case *DiscoveryConfigCreate:
|
||||
out.Event = &OneOf_DiscoveryConfigCreate{
|
||||
DiscoveryConfigCreate: e,
|
||||
}
|
||||
case *DiscoveryConfigUpdate:
|
||||
out.Event = &OneOf_DiscoveryConfigUpdate{
|
||||
DiscoveryConfigUpdate: e,
|
||||
}
|
||||
case *DiscoveryConfigDelete:
|
||||
out.Event = &OneOf_DiscoveryConfigDelete{
|
||||
DiscoveryConfigDelete: e,
|
||||
}
|
||||
case *DiscoveryConfigDeleteAll:
|
||||
out.Event = &OneOf_DiscoveryConfigDeleteAll{
|
||||
DiscoveryConfigDeleteAll: e,
|
||||
}
|
||||
|
||||
default:
|
||||
slog.ErrorContext(context.Background(), "Attempted to convert dynamic event of unknown type into protobuf event.", "event_type", in.GetType())
|
||||
|
||||
@@ -31,7 +31,9 @@ import (
|
||||
"github.com/gravitational/teleport/api/types"
|
||||
"github.com/gravitational/teleport/api/types/discoveryconfig"
|
||||
conv "github.com/gravitational/teleport/api/types/discoveryconfig/convert/v1"
|
||||
apievents "github.com/gravitational/teleport/api/types/events"
|
||||
"github.com/gravitational/teleport/lib/authz"
|
||||
"github.com/gravitational/teleport/lib/events"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
)
|
||||
|
||||
@@ -48,6 +50,9 @@ type ServiceConfig struct {
|
||||
|
||||
// Clock is the clock.
|
||||
Clock clockwork.Clock
|
||||
|
||||
// Emitter emits audit events.
|
||||
Emitter apievents.Emitter
|
||||
}
|
||||
|
||||
// CheckAndSetDefaults checks the ServiceConfig fields and returns an error if
|
||||
@@ -60,6 +65,9 @@ func (s *ServiceConfig) CheckAndSetDefaults() error {
|
||||
if s.Backend == nil {
|
||||
return trace.BadParameter("backend is required")
|
||||
}
|
||||
if s.Emitter == nil {
|
||||
return trace.BadParameter("emitter is required")
|
||||
}
|
||||
|
||||
if s.Logger == nil {
|
||||
s.Logger = logrus.New().WithField(teleport.ComponentKey, "discoveryconfig_crud_service")
|
||||
@@ -80,6 +88,7 @@ type Service struct {
|
||||
authorizer authz.Authorizer
|
||||
backend services.DiscoveryConfigs
|
||||
clock clockwork.Clock
|
||||
emitter apievents.Emitter
|
||||
}
|
||||
|
||||
// NewService returns a new DiscoveryConfigs gRPC service.
|
||||
@@ -93,6 +102,7 @@ func NewService(cfg ServiceConfig) (*Service, error) {
|
||||
authorizer: cfg.Authorizer,
|
||||
backend: cfg.Backend,
|
||||
clock: cfg.Clock,
|
||||
emitter: cfg.Emitter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -167,6 +177,21 @@ func (s *Service) CreateDiscoveryConfig(ctx context.Context, req *discoveryconfi
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := s.emitter.EmitAuditEvent(ctx, &apievents.DiscoveryConfigCreate{
|
||||
Metadata: apievents.Metadata{
|
||||
Type: events.DiscoveryConfigCreateEvent,
|
||||
Code: events.DiscoveryConfigCreateCode,
|
||||
},
|
||||
UserMetadata: authCtx.GetUserMetadata(),
|
||||
ResourceMetadata: apievents.ResourceMetadata{
|
||||
Name: resp.GetName(),
|
||||
Expires: resp.Expiry(),
|
||||
},
|
||||
ConnectionMetadata: authz.ConnectionMetadata(ctx),
|
||||
}); err != nil {
|
||||
s.log.WithError(err).Warn("Failed to emit discovery config create event.")
|
||||
}
|
||||
|
||||
return conv.ToProto(resp), nil
|
||||
}
|
||||
|
||||
@@ -198,6 +223,21 @@ func (s *Service) UpdateDiscoveryConfig(ctx context.Context, req *discoveryconfi
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := s.emitter.EmitAuditEvent(ctx, &apievents.DiscoveryConfigUpdate{
|
||||
Metadata: apievents.Metadata{
|
||||
Type: events.DiscoveryConfigUpdateEvent,
|
||||
Code: events.DiscoveryConfigUpdateCode,
|
||||
},
|
||||
UserMetadata: authCtx.GetUserMetadata(),
|
||||
ResourceMetadata: apievents.ResourceMetadata{
|
||||
Name: resp.GetName(),
|
||||
Expires: resp.Expiry(),
|
||||
},
|
||||
ConnectionMetadata: authz.ConnectionMetadata(ctx),
|
||||
}); err != nil {
|
||||
s.log.WithError(err).Warn("Failed to emit discovery config update event.")
|
||||
}
|
||||
|
||||
return conv.ToProto(resp), nil
|
||||
}
|
||||
|
||||
@@ -226,6 +266,21 @@ func (s *Service) UpsertDiscoveryConfig(ctx context.Context, req *discoveryconfi
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := s.emitter.EmitAuditEvent(ctx, &apievents.DiscoveryConfigCreate{
|
||||
Metadata: apievents.Metadata{
|
||||
Type: events.DiscoveryConfigCreateEvent,
|
||||
Code: events.DiscoveryConfigCreateCode,
|
||||
},
|
||||
UserMetadata: authCtx.GetUserMetadata(),
|
||||
ResourceMetadata: apievents.ResourceMetadata{
|
||||
Name: resp.GetName(),
|
||||
Expires: resp.Expiry(),
|
||||
},
|
||||
ConnectionMetadata: authz.ConnectionMetadata(ctx),
|
||||
}); err != nil {
|
||||
s.log.WithError(err).Warn("Failed to emit discovery config create event.")
|
||||
}
|
||||
|
||||
return conv.ToProto(resp), nil
|
||||
}
|
||||
|
||||
@@ -244,6 +299,20 @@ func (s *Service) DeleteDiscoveryConfig(ctx context.Context, req *discoveryconfi
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := s.emitter.EmitAuditEvent(ctx, &apievents.DiscoveryConfigDelete{
|
||||
Metadata: apievents.Metadata{
|
||||
Type: events.DiscoveryConfigDeleteEvent,
|
||||
Code: events.DiscoveryConfigDeleteCode,
|
||||
},
|
||||
UserMetadata: authCtx.GetUserMetadata(),
|
||||
ResourceMetadata: apievents.ResourceMetadata{
|
||||
Name: req.Name,
|
||||
},
|
||||
ConnectionMetadata: authz.ConnectionMetadata(ctx),
|
||||
}); err != nil {
|
||||
s.log.WithError(err).Warn("Failed to emit discovery config delete event.")
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
@@ -262,6 +331,17 @@ func (s *Service) DeleteAllDiscoveryConfigs(ctx context.Context, _ *discoverycon
|
||||
return nil, trace.Wrap(err)
|
||||
}
|
||||
|
||||
if err := s.emitter.EmitAuditEvent(ctx, &apievents.DiscoveryConfigDeleteAll{
|
||||
Metadata: apievents.Metadata{
|
||||
Type: events.DiscoveryConfigDeleteAllEvent,
|
||||
Code: events.DiscoveryConfigDeleteAllCode,
|
||||
},
|
||||
UserMetadata: authCtx.GetUserMetadata(),
|
||||
ConnectionMetadata: authz.ConnectionMetadata(ctx),
|
||||
}); err != nil {
|
||||
s.log.WithError(err).Warn("Failed to emit discovery config delete all event.")
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/gravitational/teleport/api/types/header"
|
||||
"github.com/gravitational/teleport/lib/authz"
|
||||
"github.com/gravitational/teleport/lib/backend/memory"
|
||||
"github.com/gravitational/teleport/lib/events"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/services/local"
|
||||
"github.com/gravitational/teleport/lib/tlsca"
|
||||
@@ -430,7 +431,7 @@ func TestUpdateDiscoveryConfigStatus(t *testing.T) {
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
localCtx := authorizerForSystemRole(t, ctx, string(tc.systemRole), localClient)
|
||||
localCtx := authorizerForSystemRole(ctx, string(tc.systemRole))
|
||||
|
||||
dcName := uuid.NewString()
|
||||
if tc.setup != nil {
|
||||
@@ -468,7 +469,7 @@ func authorizerForDummyUser(t *testing.T, ctx context.Context, roleSpec types.Ro
|
||||
})
|
||||
}
|
||||
|
||||
func authorizerForSystemRole(t *testing.T, ctx context.Context, systemRole string, localClient localClient) context.Context {
|
||||
func authorizerForSystemRole(ctx context.Context, systemRole string) context.Context {
|
||||
return authz.ContextWithUser(ctx, authz.BuiltinRole{
|
||||
Username: uuid.NewString(),
|
||||
Role: types.SystemRole(systemRole),
|
||||
@@ -540,9 +541,12 @@ func initSvc(t *testing.T, clusterName string) (context.Context, localClient, *S
|
||||
localResourceService, err := local.NewDiscoveryConfigService(backend)
|
||||
require.NoError(t, err)
|
||||
|
||||
emitter := events.NewDiscardEmitter()
|
||||
|
||||
resourceSvc, err := NewService(ServiceConfig{
|
||||
Backend: localResourceService,
|
||||
Authorizer: authorizer,
|
||||
Emitter: emitter,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -5300,6 +5300,7 @@ func NewGRPCServer(cfg GRPCServerConfig) (*GRPCServer, error) {
|
||||
Authorizer: cfg.Authorizer,
|
||||
Backend: cfg.AuthServer.Services,
|
||||
Clock: cfg.AuthServer.clock,
|
||||
Emitter: cfg.Emitter,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, trace.Wrap(err)
|
||||
|
||||
@@ -770,6 +770,15 @@ const (
|
||||
AccessGraphAccessPathChangedEvent = "access_graph.access_path_changed"
|
||||
// TODO(jakule): Remove once e is updated to the new name.
|
||||
AccessGraphAccessPathChanged = AccessGraphAccessPathChangedEvent
|
||||
|
||||
// DiscoveryConfigCreatedEvent is emitted when a discovery config is created.
|
||||
DiscoveryConfigCreateEvent = "discovery_config.create"
|
||||
// DiscoveryConfigUpdatedEvent is emitted when a discovery config is updated.
|
||||
DiscoveryConfigUpdateEvent = "discovery_config.update"
|
||||
// DiscoveryConfigDeletedEvent is emitted when a discovery config is deleted.
|
||||
DiscoveryConfigDeleteEvent = "discovery_config.delete"
|
||||
// DiscoveryConfigDeletedAllEvent is emitted when all discovery configs are deleted.
|
||||
DiscoveryConfigDeleteAllEvent = "discovery_config.delete_all"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -620,6 +620,15 @@ const (
|
||||
// AccessGraphAccessPathChangedCode is the access graph access path changed event code.
|
||||
AccessGraphAccessPathChangedCode = "TAG001I"
|
||||
|
||||
// DiscoveryConfigCreateCode is the discovery config created event code.
|
||||
DiscoveryConfigCreateCode = "DC001I"
|
||||
// DiscoveryConfigUpdateCode is the discovery config updated event code.
|
||||
DiscoveryConfigUpdateCode = "DC002I"
|
||||
// DiscoveryConfigDeleteCode is the discovery config delete event code.
|
||||
DiscoveryConfigDeleteCode = "DC003I"
|
||||
// DiscoveryConfigDeleteAllCode is the discovery config delete all event code.
|
||||
DiscoveryConfigDeleteAllCode = "DC004I"
|
||||
|
||||
// UnknownCode is used when an event of unknown type is encountered.
|
||||
UnknownCode = apievents.UnknownCode
|
||||
)
|
||||
|
||||
@@ -392,6 +392,15 @@ func FromEventFields(fields EventFields) (events.AuditEvent, error) {
|
||||
case CassandraExecuteEventCode:
|
||||
e = &events.CassandraExecute{}
|
||||
|
||||
case DiscoveryConfigCreateCode:
|
||||
e = &events.DiscoveryConfigCreate{}
|
||||
case DiscoveryConfigUpdateCode:
|
||||
e = &events.DiscoveryConfigUpdate{}
|
||||
case DiscoveryConfigDeleteCode:
|
||||
e = &events.DiscoveryConfigDelete{}
|
||||
case DiscoveryConfigDeleteAllCode:
|
||||
e = &events.DiscoveryConfigDeleteAll{}
|
||||
|
||||
default:
|
||||
log.Errorf("Attempted to convert dynamic event of unknown type %q into protobuf event.", eventType)
|
||||
unknown := &events.Unknown{}
|
||||
|
||||
Reference in New Issue
Block a user