mirror of
https://dev.azure.com/schwarzit/schwarzit.stackit-public/_git/audit-go
synced 2026-02-08 17:17:25 +00:00
Fix event type mapping in legacy converter and system event handling
This commit is contained in:
parent
66773aad3d
commit
03d4ae5d1b
9 changed files with 471 additions and 65 deletions
|
|
@ -18,18 +18,25 @@ import (
|
|||
const ContentTypeCloudEventsProtobuf = "application/cloudevents+protobuf"
|
||||
const ContentTypeCloudEventsJson = "application/cloudevents+json; charset=UTF-8"
|
||||
|
||||
// ErrUnknownPluralType indicates that the given input is an unknown plural type
|
||||
var ErrUnknownPluralType = errors.New("unknown plural type")
|
||||
// ErrAttributeIdentifierInvalid indicates that the object identifier
|
||||
// and the identifier in the checked attribute do not match
|
||||
var ErrAttributeIdentifierInvalid = errors.New("attribute identifier invalid")
|
||||
|
||||
// ErrUnknownSingularType indicates that the given input is an unknown singular type
|
||||
var ErrUnknownSingularType = errors.New("unknown singular type")
|
||||
// ErrAttributeTypeInvalid indicates that an invalid type has been provided.
|
||||
var ErrAttributeTypeInvalid = errors.New("attribute type invalid")
|
||||
|
||||
// ErrUnsupportedRoutableType indicates that the given input is an unsupported routable type
|
||||
var ErrUnsupportedRoutableType = errors.New("unsupported routable type")
|
||||
// ErrCloudEventNil states that the given cloud event is nil
|
||||
var ErrCloudEventNil = errors.New("cloud event nil")
|
||||
|
||||
// ErrEventNil indicates that the event was nil
|
||||
var ErrEventNil = errors.New("event is nil")
|
||||
|
||||
// ErrInvalidRoutableIdentifierForSystemEvent states that the routable identifier is not valid for a system event
|
||||
var ErrInvalidRoutableIdentifierForSystemEvent = errors.New("invalid identifier for system event")
|
||||
|
||||
// ErrMessagingApiNil states that the messaging api is nil
|
||||
var ErrMessagingApiNil = errors.New("messaging api nil")
|
||||
|
||||
// ErrObjectIdentifierNil indicates that the object identifier was nil
|
||||
var ErrObjectIdentifierNil = errors.New("object identifier is nil")
|
||||
|
||||
|
|
@ -40,28 +47,24 @@ var ErrObjectIdentifierNil = errors.New("object identifier is nil")
|
|||
// * Visibility: Private, ObjectIdentifier: <type | system>
|
||||
var ErrObjectIdentifierVisibilityMismatch = errors.New("object reference visibility mismatch")
|
||||
|
||||
// ErrUnsupportedObjectIdentifierType indicates that an unsupported object identifier type has been provided.
|
||||
var ErrUnsupportedObjectIdentifierType = errors.New("unsupported object identifier type")
|
||||
|
||||
// ErrAttributeTypeInvalid indicates that an invalid type has been provided.
|
||||
var ErrAttributeTypeInvalid = errors.New("attribute type invalid")
|
||||
|
||||
// ErrAttributeIdentifierInvalid indicates that the object identifier
|
||||
// and the identifier in the checked attribute do not match
|
||||
var ErrAttributeIdentifierInvalid = errors.New("attribute identifier invalid")
|
||||
|
||||
// ErrTopicNameResolverNil states that the topic name resolve is nil
|
||||
var ErrTopicNameResolverNil = errors.New("topic name resolver nil")
|
||||
|
||||
// ErrMessagingApiNil states that the messaging api is nil
|
||||
var ErrMessagingApiNil = errors.New("messaging api nil")
|
||||
// ErrUnknownPluralType indicates that the given input is an unknown plural type
|
||||
var ErrUnknownPluralType = errors.New("unknown plural type")
|
||||
|
||||
// ErrCloudEventNil states that the given cloud event is nil
|
||||
var ErrCloudEventNil = errors.New("cloud event nil")
|
||||
// ErrUnknownSingularType indicates that the given input is an unknown singular type
|
||||
var ErrUnknownSingularType = errors.New("unknown singular type")
|
||||
|
||||
// ErrUnsupportedEventTypeDataAccess states that the event type "data-access" is currently not supported
|
||||
var ErrUnsupportedEventTypeDataAccess = errors.New("unsupported event type data access")
|
||||
|
||||
// ErrUnsupportedObjectIdentifierType indicates that an unsupported object identifier type has been provided.
|
||||
var ErrUnsupportedObjectIdentifierType = errors.New("unsupported object identifier type")
|
||||
|
||||
// ErrUnsupportedRoutableType indicates that the given input is an unsupported routable type
|
||||
var ErrUnsupportedRoutableType = errors.New("unsupported routable type")
|
||||
|
||||
func validateAndSerializePartially(
|
||||
validator *ProtobufValidator,
|
||||
event *auditV1.AuditLogEntry,
|
||||
|
|
@ -97,11 +100,18 @@ func validateAndSerializePartially(
|
|||
}
|
||||
|
||||
// Check identifier consistency across event attributes
|
||||
if err := areIdentifiersIdentical(routableIdentifier, event.LogName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := areIdentifiersIdentical(routableIdentifier, event.ProtoPayload.ResourceName); err != nil {
|
||||
return nil, err
|
||||
if strings.HasSuffix(event.LogName, string(EventTypeSystemEvent)) {
|
||||
if !(routableIdentifier.Identifier == SystemIdentifier.Identifier && routableIdentifier.Type == SingularTypeSystem) {
|
||||
return nil, ErrInvalidRoutableIdentifierForSystemEvent
|
||||
}
|
||||
// The resource name can either contain the system identifier or another resource identifier
|
||||
} else {
|
||||
if err := areIdentifiersIdentical(routableIdentifier, event.LogName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := areIdentifiersIdentical(routableIdentifier, event.ProtoPayload.ResourceName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Test serialization even if the data is dropped later when logging to the legacy solution
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ func Test_ValidateAndSerializePartially_CheckVisibility_SystemEvent(t *testing.T
|
|||
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, NewRoutableIdentifier(
|
||||
&auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(SingularTypeOrganization)}))
|
||||
|
||||
assert.ErrorIs(t, err, ErrAttributeIdentifierInvalid)
|
||||
assert.ErrorIs(t, err, ErrInvalidRoutableIdentifierForSystemEvent)
|
||||
})
|
||||
|
||||
t.Run("Visibility private - object identifier system", func(t *testing.T) {
|
||||
|
|
@ -188,7 +188,7 @@ func Test_ValidateAndSerializePartially_CheckVisibility_SystemEvent(t *testing.T
|
|||
&validator, event, auditV1.Visibility_VISIBILITY_PRIVATE, NewRoutableIdentifier(
|
||||
&auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(SingularTypeOrganization)}))
|
||||
|
||||
assert.ErrorIs(t, err, ErrAttributeIdentifierInvalid)
|
||||
assert.ErrorIs(t, err, ErrInvalidRoutableIdentifierForSystemEvent)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
auditV1 "dev.azure.com/schwarzit/schwarzit.stackit-core-platform/audit-go.git/gen/go/audit/v1"
|
||||
|
|
@ -19,6 +20,20 @@ func convertAndSerializeIntoLegacyFormat(
|
|||
routableEvent *auditV1.RoutableAuditEvent,
|
||||
) ([]byte, error) {
|
||||
|
||||
// Event type
|
||||
var eventType string
|
||||
if strings.HasSuffix(event.LogName, string(EventTypeAdminActivity)) {
|
||||
eventType = "ADMIN_ACTIVITY"
|
||||
} else if strings.HasSuffix(event.LogName, string(EventTypeSystemEvent)) {
|
||||
eventType = "SYSTEM_EVENT"
|
||||
} else if strings.HasSuffix(event.LogName, string(EventTypePolicyDenied)) {
|
||||
eventType = "POLICY_DENIED"
|
||||
} else if strings.HasSuffix(event.LogName, string(EventTypeDataAccess)) {
|
||||
return nil, ErrUnsupportedEventTypeDataAccess
|
||||
} else {
|
||||
return nil, errors.New("unsupported event type")
|
||||
}
|
||||
|
||||
// Source IP & User agent
|
||||
var sourceIpAddress string
|
||||
var userAgent string
|
||||
|
|
@ -106,31 +121,26 @@ func convertAndSerializeIntoLegacyFormat(
|
|||
|
||||
// Context and event type
|
||||
var messageContext *LegacyAuditEventContext
|
||||
var eventType string
|
||||
switch routableEvent.ObjectIdentifier.Type {
|
||||
case string(SingularTypeProject):
|
||||
eventType = "ADMIN_ACTIVITY"
|
||||
messageContext = &LegacyAuditEventContext{
|
||||
OrganizationId: nil,
|
||||
FolderId: nil,
|
||||
ProjectId: &routableEvent.ObjectIdentifier.Identifier,
|
||||
}
|
||||
case string(SingularTypeFolder):
|
||||
eventType = "ADMIN_ACTIVITY"
|
||||
messageContext = &LegacyAuditEventContext{
|
||||
OrganizationId: nil,
|
||||
FolderId: &routableEvent.ObjectIdentifier.Identifier,
|
||||
ProjectId: nil,
|
||||
}
|
||||
case string(SingularTypeOrganization):
|
||||
eventType = "ADMIN_ACTIVITY"
|
||||
messageContext = &LegacyAuditEventContext{
|
||||
OrganizationId: &routableEvent.ObjectIdentifier.Identifier,
|
||||
FolderId: nil,
|
||||
ProjectId: nil,
|
||||
}
|
||||
case string(SingularTypeSystem):
|
||||
eventType = "SYSTEM_EVENT"
|
||||
messageContext = nil
|
||||
default:
|
||||
return nil, ErrUnsupportedObjectIdentifierType
|
||||
|
|
|
|||
|
|
@ -314,6 +314,64 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
|
|||
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||
})
|
||||
|
||||
// Check logging of system events with identifier
|
||||
t.Run("Log private project system event", func(t *testing.T) {
|
||||
defer solaceContainer.StopOnError()
|
||||
|
||||
queueName := "project-system-event-private"
|
||||
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
||||
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
||||
|
||||
topicName := "topic://audit-log/eu01/v1/resource-manager/project-system-changed"
|
||||
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
||||
|
||||
// Instantiate audit api
|
||||
auditApi, err := NewDynamicLegacyAuditApi(
|
||||
messagingApi,
|
||||
validator,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Instantiate test data
|
||||
event := newProjectSystemAuditEvent(nil)
|
||||
|
||||
// Log the event to solace
|
||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
||||
assert.NoError(t,
|
||||
(*auditApi).LogWithTrace(
|
||||
ctx,
|
||||
event,
|
||||
visibility,
|
||||
RoutableSystemIdentifier,
|
||||
nil,
|
||||
nil,
|
||||
))
|
||||
|
||||
// Receive the event from solace
|
||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check topic name
|
||||
assert.Equal(t, topicName, *message.Properties.To)
|
||||
assert.Nil(t, message.ApplicationProperties["cloudEvents:traceparent"])
|
||||
assert.Nil(t, message.ApplicationProperties["cloudEvents:tracestate"])
|
||||
|
||||
// Check deserialized message
|
||||
var auditEvent LegacyAuditEvent
|
||||
assert.NoError(t, json.Unmarshal(message.Data[0], &auditEvent))
|
||||
|
||||
assert.Equal(t, event.ProtoPayload.ResourceName, *auditEvent.ResourceName)
|
||||
assert.Equal(t, event.ProtoPayload.OperationName, auditEvent.EventName)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.ProtoPayload.AuthenticationInfo.PrincipalId, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, "SYSTEM_EVENT", auditEvent.EventType)
|
||||
assert.Equal(t, "INFO", auditEvent.Severity)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Path, auditEvent.Request.Endpoint)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerIp, auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerSuppliedUserAgent, auditEvent.UserAgent)
|
||||
})
|
||||
|
||||
// Check logging of system events
|
||||
t.Run("Log private system event", func(t *testing.T) {
|
||||
defer solaceContainer.StopOnError()
|
||||
|
|
|
|||
|
|
@ -315,6 +315,64 @@ func TestLegacyAuditApi(t *testing.T) {
|
|||
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||
})
|
||||
|
||||
// Check logging of system events with identifier
|
||||
t.Run("Log private project system event", func(t *testing.T) {
|
||||
defer solaceContainer.StopOnError()
|
||||
|
||||
queueName := "project-system-event-private"
|
||||
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
||||
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
||||
|
||||
topicName := "topic://audit-log/eu01/v1/resource-manager/project-system-changed"
|
||||
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
||||
|
||||
// Instantiate audit api
|
||||
auditApi, err := NewLegacyAuditApi(
|
||||
messagingApi,
|
||||
LegacyTopicNameConfig{TopicName: topicName},
|
||||
validator,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Instantiate test data
|
||||
event := newProjectSystemAuditEvent(nil)
|
||||
|
||||
// Log the event to solace
|
||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||
assert.NoError(t,
|
||||
(*auditApi).LogWithTrace(
|
||||
ctx,
|
||||
event,
|
||||
visibility,
|
||||
RoutableSystemIdentifier,
|
||||
nil,
|
||||
nil,
|
||||
))
|
||||
|
||||
// Receive the event from solace
|
||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check topic name
|
||||
assert.Equal(t, topicName, *message.Properties.To)
|
||||
assert.Nil(t, message.ApplicationProperties["cloudEvents:traceparent"])
|
||||
assert.Nil(t, message.ApplicationProperties["cloudEvents:tracestate"])
|
||||
|
||||
// Check deserialized message
|
||||
var auditEvent LegacyAuditEvent
|
||||
assert.NoError(t, json.Unmarshal(message.Data[0], &auditEvent))
|
||||
|
||||
assert.Equal(t, event.ProtoPayload.ResourceName, *auditEvent.ResourceName)
|
||||
assert.Equal(t, event.ProtoPayload.OperationName, auditEvent.EventName)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.ProtoPayload.AuthenticationInfo.PrincipalId, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, "SYSTEM_EVENT", auditEvent.EventType)
|
||||
assert.Equal(t, "INFO", auditEvent.Severity)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Path, auditEvent.Request.Endpoint)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerIp, auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerSuppliedUserAgent, auditEvent.UserAgent)
|
||||
})
|
||||
|
||||
// Check logging of system events
|
||||
t.Run("Log private system event", func(t *testing.T) {
|
||||
defer solaceContainer.StopOnError()
|
||||
|
|
|
|||
|
|
@ -320,6 +320,58 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
&traceState)
|
||||
})
|
||||
|
||||
// Check logging of system events with identifier
|
||||
t.Run("Log private project system event", func(t *testing.T) {
|
||||
defer solaceContainer.StopOnError()
|
||||
|
||||
queueName := "project-system-event-private"
|
||||
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
||||
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, "system/*"))
|
||||
|
||||
// Instantiate test data
|
||||
event := newProjectSystemAuditEvent(nil)
|
||||
|
||||
// Log the event to solace
|
||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||
assert.NoError(t,
|
||||
(*auditApi).LogWithTrace(
|
||||
ctx,
|
||||
event,
|
||||
visibility,
|
||||
RoutableSystemIdentifier,
|
||||
nil,
|
||||
nil,
|
||||
))
|
||||
|
||||
// Receive the event from solace
|
||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check topic name
|
||||
assert.Equal(t, systemTopicName, *message.Properties.To)
|
||||
|
||||
// Check cloud event properties
|
||||
applicationProperties := message.ApplicationProperties
|
||||
assert.Equal(t, "1.0", applicationProperties["cloudEvents:specversion"])
|
||||
assert.Equal(t, "resource-manager", applicationProperties["cloudEvents:source"])
|
||||
_, isUuid := uuid.Parse(fmt.Sprintf("%s", applicationProperties["cloudEvents:id"]))
|
||||
assert.True(t, true, isUuid)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime().UnixMilli(), applicationProperties["cloudEvents:time"])
|
||||
assert.Equal(t, "application/cloudevents+protobuf", applicationProperties["cloudEvents:datacontenttype"])
|
||||
assert.Equal(t, "audit.v1.RoutableAuditEvent", applicationProperties["cloudEvents:type"])
|
||||
assert.Nil(t, applicationProperties["cloudEvents:traceparent"])
|
||||
assert.Nil(t, applicationProperties["cloudEvents:tracestate"])
|
||||
|
||||
// Check deserialized message
|
||||
validateRoutableEventPayload(
|
||||
t,
|
||||
message.Data[0],
|
||||
RoutableSystemIdentifier.ToObjectIdentifier(),
|
||||
event,
|
||||
"stackit.resourcemanager.v2.system.changed",
|
||||
visibility)
|
||||
})
|
||||
|
||||
// Check logging of system events
|
||||
t.Run("Log private system event", func(t *testing.T) {
|
||||
defer solaceContainer.StopOnError()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"dev.azure.com/schwarzit/schwarzit.stackit-core-platform/audit-go.git/log"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/google/uuid"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -38,13 +39,12 @@ type AuditParameters struct {
|
|||
}
|
||||
|
||||
func getObjectIdAndTypeFromAuditParams(
|
||||
ctx context.Context,
|
||||
auditParams *AuditParameters,
|
||||
) (string, *SingularType, *PluralType, error) {
|
||||
) (string, *PluralType, error) {
|
||||
|
||||
objectId := auditParams.ObjectId
|
||||
if objectId == "" {
|
||||
return "", nil, nil, errors.New("object id missing")
|
||||
return "", nil, errors.New("object id missing")
|
||||
}
|
||||
|
||||
var objectType *SingularType
|
||||
|
|
@ -53,16 +53,16 @@ func getObjectIdAndTypeFromAuditParams(
|
|||
}
|
||||
|
||||
if objectType == nil {
|
||||
return "", nil, nil, errors.New("singular type missing")
|
||||
return "", nil, errors.New("singular type missing")
|
||||
}
|
||||
|
||||
// Convert to plural type
|
||||
plural, err := objectType.AsPluralType()
|
||||
if err != nil {
|
||||
log.AuditLogger.Error("failed to convert singular type to plural type", err)
|
||||
return "", nil, nil, err
|
||||
return "", nil, err
|
||||
}
|
||||
return objectId, objectType, &plural, nil
|
||||
return objectId, &plural, nil
|
||||
}
|
||||
|
||||
// AuditLogEntryBuilder collects audit params to construct auditV1.AuditLogEntry
|
||||
|
|
@ -324,7 +324,7 @@ func (builder *AuditLogEntryBuilder) Build(ctx context.Context, sequenceNumber S
|
|||
auditTime := time.Now()
|
||||
builder.auditMetadata.AuditTime = &auditTime
|
||||
|
||||
objectId, _, pluralType, err := getObjectIdAndTypeFromAuditParams(ctx, &builder.auditParams)
|
||||
objectId, pluralType, err := getObjectIdAndTypeFromAuditParams(&builder.auditParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -340,8 +340,18 @@ func (builder *AuditLogEntryBuilder) Build(ctx context.Context, sequenceNumber S
|
|||
}
|
||||
|
||||
resourceName := fmt.Sprintf("%s/%s", *pluralType, objectId)
|
||||
var logIdentifier string
|
||||
var logType PluralType
|
||||
if builder.auditParams.EventType == EventTypeSystemEvent {
|
||||
logIdentifier = SystemIdentifier.Identifier
|
||||
logType = PluralTypeSystem
|
||||
} else {
|
||||
logIdentifier = objectId
|
||||
logType = *pluralType
|
||||
}
|
||||
|
||||
builder.auditMetadata.AuditInsertId = NewInsertId(time.Now().UTC(), builder.location, builder.workerId, uint64(sequenceNumber))
|
||||
builder.auditMetadata.AuditLogName = fmt.Sprintf("%s/%s/logs/%s", *pluralType, objectId, builder.auditParams.EventType)
|
||||
builder.auditMetadata.AuditLogName = fmt.Sprintf("%s/%s/logs/%s", logType, logIdentifier, builder.auditParams.EventType)
|
||||
builder.auditMetadata.AuditResourceName = resourceName
|
||||
|
||||
var details *map[string]interface{} = nil
|
||||
|
|
@ -608,14 +618,29 @@ func (builder *AuditEventBuilder) Build(ctx context.Context, sequenceNumber Sequ
|
|||
if builder.auditLogEntryBuilder == nil {
|
||||
return nil, nil, "", fmt.Errorf("audit log entry builder not set")
|
||||
}
|
||||
|
||||
objectId := builder.auditLogEntryBuilder.auditParams.ObjectId
|
||||
objectType := builder.auditLogEntryBuilder.auditParams.ObjectType
|
||||
var routingIdentifier *RoutableIdentifier
|
||||
if builder.auditLogEntryBuilder.auditParams.EventType == EventTypeSystemEvent {
|
||||
routingIdentifier = NewAuditRoutingIdentifier(uuid.Nil.String(), SingularTypeSystem)
|
||||
if objectId == "" {
|
||||
objectId = uuid.Nil.String()
|
||||
builder.WithRequiredObjectId(objectId)
|
||||
}
|
||||
if objectType == "" {
|
||||
objectType = SingularTypeSystem
|
||||
builder.WithRequiredObjectType(objectType)
|
||||
}
|
||||
} else {
|
||||
routingIdentifier = NewAuditRoutingIdentifier(objectId, objectType)
|
||||
}
|
||||
|
||||
auditLogEntry, err := builder.auditLogEntryBuilder.Build(ctx, sequenceNumber)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
}
|
||||
|
||||
objectId := builder.auditLogEntryBuilder.auditParams.ObjectId
|
||||
objectType := builder.auditLogEntryBuilder.auditParams.ObjectType
|
||||
|
||||
ctx, span := builder.tracer.Start(ctx, "create-audit-event")
|
||||
defer span.End()
|
||||
|
||||
|
|
@ -624,7 +649,6 @@ func (builder *AuditEventBuilder) Build(ctx context.Context, sequenceNumber Sequ
|
|||
var traceState *string = nil
|
||||
visibility := builder.visibility
|
||||
operation := auditLogEntry.ProtoPayload.OperationName
|
||||
routingIdentifier := NewAuditRoutingIdentifier(objectId, objectType)
|
||||
|
||||
// Validate and serialize the protobuf event into a cloud event
|
||||
_, validateSerializeSpan := builder.tracer.Start(ctx, "validate-and-serialize-audit-event")
|
||||
|
|
|
|||
|
|
@ -20,50 +20,46 @@ func Test_getObjectIdAndTypeFromAuditParams(t *testing.T) {
|
|||
|
||||
t.Run(
|
||||
"object id empty", func(t *testing.T) {
|
||||
objectId, objectType, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(context.Background(), &AuditParameters{})
|
||||
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(&AuditParameters{})
|
||||
assert.EqualError(t, err, "object id missing")
|
||||
assert.Equal(t, "", objectId)
|
||||
assert.Nil(t, objectType)
|
||||
assert.Nil(t, objectTypePlural)
|
||||
},
|
||||
)
|
||||
|
||||
t.Run(
|
||||
"object type empty", func(t *testing.T) {
|
||||
objectId, objectType, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(context.Background(), &AuditParameters{ObjectId: "value"})
|
||||
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(&AuditParameters{ObjectId: "value"})
|
||||
assert.EqualError(t, err, "singular type missing")
|
||||
assert.Equal(t, "", objectId)
|
||||
assert.Nil(t, objectType)
|
||||
assert.Nil(t, objectTypePlural)
|
||||
},
|
||||
)
|
||||
|
||||
t.Run(
|
||||
"object id and invalid type set", func(t *testing.T) {
|
||||
objectId, objectType, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(
|
||||
context.Background(), &AuditParameters{
|
||||
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(
|
||||
&AuditParameters{
|
||||
ObjectId: "value",
|
||||
ObjectType: AsSingularType("invalid"),
|
||||
},
|
||||
)
|
||||
assert.EqualError(t, err, "unknown singular type")
|
||||
assert.Equal(t, "", objectId)
|
||||
assert.Nil(t, objectType)
|
||||
assert.Nil(t, objectTypePlural)
|
||||
},
|
||||
)
|
||||
|
||||
t.Run(
|
||||
"object id and type set", func(t *testing.T) {
|
||||
objectId, objectType, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(
|
||||
context.Background(), &AuditParameters{
|
||||
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(
|
||||
&AuditParameters{
|
||||
ObjectId: "value",
|
||||
ObjectType: SingularTypeProject,
|
||||
},
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "value", objectId)
|
||||
assert.Equal(t, SingularTypeProject, *objectType)
|
||||
assert.Equal(t, PluralTypeProject, *objectTypePlural)
|
||||
},
|
||||
)
|
||||
|
|
@ -329,7 +325,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.NotNil(t, logEntry)
|
||||
|
||||
assert.Equal(t, "projects/1/logs/system-event", logEntry.LogName)
|
||||
assert.Equal(t, fmt.Sprintf("system/%s/logs/system-event", uuid.Nil.String()), logEntry.LogName)
|
||||
assert.Nil(t, logEntry.Labels)
|
||||
assert.Nil(t, logEntry.TraceState)
|
||||
assert.Nil(t, logEntry.TraceParent)
|
||||
|
|
@ -601,7 +597,8 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NotNil(t, cloudEvent.Data)
|
||||
assert.NoError(t, proto.Unmarshal(cloudEvent.Data, &routableAuditEvent))
|
||||
|
||||
assert.Equal(t, routableIdentifier.ToObjectIdentifier(), routableAuditEvent.ObjectIdentifier)
|
||||
assert.Equal(t, routableIdentifier.ToObjectIdentifier().Identifier, routableAuditEvent.ObjectIdentifier.Identifier)
|
||||
assert.Equal(t, routableIdentifier.ToObjectIdentifier().Type, routableAuditEvent.ObjectIdentifier.Type)
|
||||
assert.Equal(t, auditV1.Visibility_VISIBILITY_PUBLIC, routableAuditEvent.Visibility)
|
||||
assert.Equal(t, operation, routableAuditEvent.OperationName)
|
||||
|
||||
|
|
@ -714,7 +711,7 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
WithAuditPermission(permission).
|
||||
WithAuditPermissionCheckResult(permissionCheckResult).
|
||||
WithDetails(details).
|
||||
WithEventType(EventTypeSystemEvent).
|
||||
WithEventType(EventTypeAdminActivity).
|
||||
WithLabels(map[string]string{"key": "label"}).
|
||||
WithNumResponseItems(int64(10)).
|
||||
WithRequestCorrelationId("correlationId").
|
||||
|
|
@ -751,7 +748,8 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NotNil(t, cloudEvent.Data)
|
||||
assert.NoError(t, proto.Unmarshal(cloudEvent.Data, &routableAuditEvent))
|
||||
|
||||
assert.Equal(t, routableIdentifier.ToObjectIdentifier(), routableAuditEvent.ObjectIdentifier)
|
||||
assert.Equal(t, routableIdentifier.ToObjectIdentifier().Identifier, routableAuditEvent.ObjectIdentifier.Identifier)
|
||||
assert.Equal(t, routableIdentifier.ToObjectIdentifier().Type, routableAuditEvent.ObjectIdentifier.Type)
|
||||
assert.Equal(t, auditV1.Visibility_VISIBILITY_PRIVATE, routableAuditEvent.Visibility)
|
||||
assert.Equal(t, operation, routableAuditEvent.OperationName)
|
||||
|
||||
|
|
@ -759,7 +757,7 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NotNil(t, routableAuditEvent.GetUnencryptedData().Data)
|
||||
assert.NoError(t, proto.Unmarshal(routableAuditEvent.GetUnencryptedData().Data, &logEntry))
|
||||
|
||||
assert.Equal(t, fmt.Sprintf("projects/%s/logs/system-event", objectId), logEntry.LogName)
|
||||
assert.Equal(t, fmt.Sprintf("projects/%s/logs/admin-activity", objectId), logEntry.LogName)
|
||||
assert.Equal(t, map[string]string{"key": "label"}, logEntry.Labels)
|
||||
assert.Nil(t, logEntry.TraceState)
|
||||
assert.Nil(t, logEntry.TraceParent)
|
||||
|
|
@ -836,14 +834,13 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("system event", func(t *testing.T) {
|
||||
t.Run("system event with object reference", func(t *testing.T) {
|
||||
api, _ := NewMockAuditApi()
|
||||
sequenceNumberGenerator := utils.NewDefaultSequenceNumberGenerator()
|
||||
tracer := otel.Tracer("test")
|
||||
|
||||
objectId := uuid.NewString()
|
||||
operation := "stackit.demo-service.v1.operation"
|
||||
routableIdentifier := RoutableIdentifier{Identifier: objectId, Type: SingularTypeProject}
|
||||
builder := NewAuditEventBuilder(api, sequenceNumberGenerator, tracer, "demo-service", "worker-id", "eu01").
|
||||
WithRequiredObjectId(objectId).
|
||||
WithRequiredObjectType(SingularTypeProject).
|
||||
|
|
@ -854,7 +851,8 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.True(t, builder.IsBuilt())
|
||||
|
||||
assert.Equal(t, &routableIdentifier, routingIdentifier)
|
||||
assert.Equal(t, SystemIdentifier.Identifier, routingIdentifier.ToObjectIdentifier().Identifier)
|
||||
assert.Equal(t, SystemIdentifier.Type, routingIdentifier.ToObjectIdentifier().Type)
|
||||
assert.Equal(t, operation, op)
|
||||
|
||||
assert.NotNil(t, cloudEvent)
|
||||
|
|
@ -872,7 +870,8 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NotNil(t, cloudEvent.Data)
|
||||
assert.NoError(t, proto.Unmarshal(cloudEvent.Data, &routableAuditEvent))
|
||||
|
||||
assert.Equal(t, routableIdentifier.ToObjectIdentifier(), routableAuditEvent.ObjectIdentifier)
|
||||
assert.Equal(t, SystemIdentifier.Identifier, routableAuditEvent.ObjectIdentifier.Identifier)
|
||||
assert.Equal(t, SystemIdentifier.Type, routableAuditEvent.ObjectIdentifier.Type)
|
||||
assert.Equal(t, auditV1.Visibility_VISIBILITY_PRIVATE, routableAuditEvent.Visibility)
|
||||
assert.Equal(t, operation, routableAuditEvent.OperationName)
|
||||
|
||||
|
|
@ -880,7 +879,7 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NotNil(t, routableAuditEvent.GetUnencryptedData().Data)
|
||||
assert.NoError(t, proto.Unmarshal(routableAuditEvent.GetUnencryptedData().Data, &logEntry))
|
||||
|
||||
assert.Equal(t, fmt.Sprintf("projects/%s/logs/system-event", objectId), logEntry.LogName)
|
||||
assert.Equal(t, fmt.Sprintf("system/%s/logs/system-event", uuid.Nil.String()), logEntry.LogName)
|
||||
assert.Nil(t, logEntry.Labels)
|
||||
assert.Nil(t, logEntry.TraceState)
|
||||
assert.Nil(t, logEntry.TraceParent)
|
||||
|
|
@ -951,6 +950,119 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("system event", func(t *testing.T) {
|
||||
api, _ := NewMockAuditApi()
|
||||
sequenceNumberGenerator := utils.NewDefaultSequenceNumberGenerator()
|
||||
tracer := otel.Tracer("test")
|
||||
|
||||
operation := "stackit.demo-service.v1.operation"
|
||||
builder := NewAuditEventBuilder(api, sequenceNumberGenerator, tracer, "demo-service", "worker-id", "eu01").
|
||||
WithRequiredOperation(operation).
|
||||
AsSystemEvent()
|
||||
|
||||
cloudEvent, routingIdentifier, op, err := builder.Build(context.Background(), SequenceNumber(1))
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, builder.IsBuilt())
|
||||
|
||||
assert.Equal(t, SystemIdentifier.Identifier, routingIdentifier.ToObjectIdentifier().Identifier)
|
||||
assert.Equal(t, SystemIdentifier.Type, routingIdentifier.ToObjectIdentifier().Type)
|
||||
assert.Equal(t, operation, op)
|
||||
|
||||
assert.NotNil(t, cloudEvent)
|
||||
assert.Equal(t, "application/cloudevents+protobuf", cloudEvent.DataContentType)
|
||||
assert.Equal(t, "audit.v1.RoutableAuditEvent", cloudEvent.DataType)
|
||||
assert.Regexp(t, "[0-9]+/eu01/worker-id/1", cloudEvent.Id)
|
||||
assert.Equal(t, "demo-service", cloudEvent.Source)
|
||||
assert.Equal(t, "1.0", cloudEvent.SpecVersion)
|
||||
assert.Equal(t, fmt.Sprintf("system/%s", uuid.Nil.String()), cloudEvent.Subject)
|
||||
assert.NotNil(t, cloudEvent.Time)
|
||||
assert.Equal(t, "00-00000000000000000000000000000000-0000000000000000-00", *cloudEvent.TraceParent)
|
||||
assert.Nil(t, cloudEvent.TraceState)
|
||||
|
||||
var routableAuditEvent auditV1.RoutableAuditEvent
|
||||
assert.NotNil(t, cloudEvent.Data)
|
||||
assert.NoError(t, proto.Unmarshal(cloudEvent.Data, &routableAuditEvent))
|
||||
|
||||
assert.Equal(t, SystemIdentifier.Identifier, routableAuditEvent.ObjectIdentifier.Identifier)
|
||||
assert.Equal(t, SystemIdentifier.Type, routableAuditEvent.ObjectIdentifier.Type)
|
||||
assert.Equal(t, auditV1.Visibility_VISIBILITY_PRIVATE, routableAuditEvent.Visibility)
|
||||
assert.Equal(t, operation, routableAuditEvent.OperationName)
|
||||
|
||||
var logEntry auditV1.AuditLogEntry
|
||||
assert.NotNil(t, routableAuditEvent.GetUnencryptedData().Data)
|
||||
assert.NoError(t, proto.Unmarshal(routableAuditEvent.GetUnencryptedData().Data, &logEntry))
|
||||
|
||||
assert.Equal(t, fmt.Sprintf("system/%s/logs/system-event", uuid.Nil.String()), logEntry.LogName)
|
||||
assert.Nil(t, logEntry.Labels)
|
||||
assert.Nil(t, logEntry.TraceState)
|
||||
assert.Nil(t, logEntry.TraceParent)
|
||||
assert.Equal(t, auditV1.LogSeverity_LOG_SEVERITY_DEFAULT, logEntry.Severity)
|
||||
assert.NotNil(t, logEntry.Timestamp)
|
||||
assert.Nil(t, logEntry.CorrelationId)
|
||||
assert.Regexp(t, "[0-9]+/eu01/worker-id/1", logEntry.InsertId)
|
||||
|
||||
assert.NotNil(t, logEntry.ProtoPayload)
|
||||
|
||||
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
|
||||
assert.NotNil(t, authenticationInfo)
|
||||
assert.Equal(t, "do-not-reply@stackit.cloud", authenticationInfo.PrincipalEmail)
|
||||
assert.Equal(t, "none", authenticationInfo.PrincipalId)
|
||||
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
|
||||
assert.Nil(t, authenticationInfo.ServiceAccountName)
|
||||
|
||||
assert.Nil(t, logEntry.ProtoPayload.AuthorizationInfo)
|
||||
assert.Nil(t, logEntry.ProtoPayload.Metadata)
|
||||
assert.Equal(t, operation, logEntry.ProtoPayload.OperationName)
|
||||
assert.Nil(t, logEntry.ProtoPayload.Request)
|
||||
|
||||
requestMetadata := logEntry.ProtoPayload.RequestMetadata
|
||||
assert.NotNil(t, requestMetadata)
|
||||
assert.Equal(t, "0.0.0.0", requestMetadata.CallerIp)
|
||||
assert.Equal(t, "none", requestMetadata.CallerSuppliedUserAgent)
|
||||
|
||||
requestAttributes := requestMetadata.RequestAttributes
|
||||
assert.NotNil(t, requestAttributes)
|
||||
assert.Equal(t, "none", requestAttributes.Path)
|
||||
assert.NotNil(t, requestAttributes.Time)
|
||||
assert.Equal(t, "0.0.0.0", requestAttributes.Host)
|
||||
assert.Equal(t, auditV1.AttributeContext_HTTP_METHOD_OTHER, requestAttributes.Method)
|
||||
assert.Nil(t, requestAttributes.Id)
|
||||
assert.Equal(t, "none", requestAttributes.Scheme)
|
||||
assert.Equal(t, map[string]string{"user-agent": "none"}, requestAttributes.Headers)
|
||||
assert.Nil(t, requestAttributes.Query)
|
||||
assert.Equal(t, "none", requestAttributes.Protocol)
|
||||
|
||||
requestAttributesAuth := requestAttributes.Auth
|
||||
assert.NotNil(t, requestAttributesAuth)
|
||||
assert.Equal(t, "none/none", requestAttributesAuth.Principal)
|
||||
assert.Nil(t, requestAttributesAuth.Audiences)
|
||||
assert.NotNil(t, requestAttributesAuth.Claims)
|
||||
assert.Equal(t, map[string]any{}, requestAttributesAuth.Claims.AsMap())
|
||||
|
||||
assert.Equal(t, fmt.Sprintf("system/%s", uuid.Nil.String()), logEntry.ProtoPayload.ResourceName)
|
||||
assert.Nil(t, logEntry.ProtoPayload.Response)
|
||||
|
||||
responseMetadata := logEntry.ProtoPayload.ResponseMetadata
|
||||
assert.NotNil(t, responseMetadata)
|
||||
assert.Nil(t, responseMetadata.ErrorDetails)
|
||||
assert.Nil(t, responseMetadata.ErrorMessage)
|
||||
assert.Equal(t, wrapperspb.Int32(200), responseMetadata.StatusCode)
|
||||
|
||||
responseAttributes := responseMetadata.ResponseAttributes
|
||||
assert.NotNil(t, responseAttributes)
|
||||
assert.Nil(t, responseAttributes.Headers)
|
||||
assert.Nil(t, responseAttributes.NumResponseItems)
|
||||
assert.Nil(t, responseAttributes.Size)
|
||||
assert.NotNil(t, responseAttributes.Time)
|
||||
|
||||
assert.Equal(t, "demo-service", logEntry.ProtoPayload.ServiceName)
|
||||
|
||||
validator, err := protovalidate.New()
|
||||
assert.NoError(t, err)
|
||||
err = validator.Validate(&logEntry)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("with responsebody unserialized", func(t *testing.T) {
|
||||
api, _ := NewMockAuditApi()
|
||||
sequenceNumberGenerator := utils.NewDefaultSequenceNumberGenerator()
|
||||
|
|
@ -984,7 +1096,7 @@ func Test_AuditEventBuilder(t *testing.T) {
|
|||
WithAuditPermission(permission).
|
||||
WithAuditPermissionCheckResult(permissionCheckResult).
|
||||
WithDetails(details).
|
||||
WithEventType(EventTypeSystemEvent).
|
||||
WithEventType(EventTypeAdminActivity).
|
||||
WithLabels(map[string]string{"key": "label"}).
|
||||
WithNumResponseItems(int64(10)).
|
||||
WithRequestCorrelationId("correlationId").
|
||||
|
|
|
|||
|
|
@ -289,6 +289,88 @@ func newProjectAuditEvent(
|
|||
return auditEvent, objectIdentifier
|
||||
}
|
||||
|
||||
func newProjectSystemAuditEvent(
|
||||
customization *func(*auditV1.AuditLogEntry)) *auditV1.AuditLogEntry {
|
||||
|
||||
identifier := uuid.New()
|
||||
requestId := fmt.Sprintf("%s/1", identifier)
|
||||
claims, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
correlationId := "9b5a8e9b-32a0-435f-b97b-a9a42b9e016b"
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
labels := make(map[string]string)
|
||||
labels["label1"] = "value1"
|
||||
serviceAccountId := uuid.NewString()
|
||||
serviceAccountName := fmt.Sprintf("projects/%s/service-accounts/%s", identifier, serviceAccountId)
|
||||
delegationPrincipal := auditV1.ServiceAccountDelegationInfo{Authority: &auditV1.ServiceAccountDelegationInfo_SystemPrincipal_{}}
|
||||
auditEvent := &auditV1.AuditLogEntry{
|
||||
LogName: fmt.Sprintf("%s/%s/logs/%s", SystemIdentifier.Type, SystemIdentifier.Identifier, EventTypeSystemEvent),
|
||||
ProtoPayload: &auditV1.AuditLog{
|
||||
ServiceName: "resource-manager",
|
||||
OperationName: "stackit.resourcemanager.v2.system.changed",
|
||||
ResourceName: fmt.Sprintf("%s/%s", PluralTypeProject, identifier),
|
||||
AuthenticationInfo: &auditV1.AuthenticationInfo{
|
||||
PrincipalId: serviceAccountId,
|
||||
PrincipalEmail: "service-account@sa.stackit.cloud",
|
||||
ServiceAccountName: &serviceAccountName,
|
||||
ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal},
|
||||
},
|
||||
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
|
||||
Resource: fmt.Sprintf("%s/%s", PluralTypeProject, identifier),
|
||||
Permission: nil,
|
||||
Granted: nil,
|
||||
}},
|
||||
RequestMetadata: &auditV1.RequestMetadata{
|
||||
CallerIp: "127.0.0.1",
|
||||
CallerSuppliedUserAgent: "OpenAPI-Generator/ 1.0.0/ go",
|
||||
RequestAttributes: &auditV1.AttributeContext_Request{
|
||||
Id: &requestId,
|
||||
Method: auditV1.AttributeContext_HTTP_METHOD_POST,
|
||||
Headers: headers,
|
||||
Path: "/v2/projects",
|
||||
Host: "stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud",
|
||||
Scheme: "https",
|
||||
Query: nil,
|
||||
Time: timestamppb.New(time.Now().UTC()),
|
||||
Protocol: "http/1.1",
|
||||
Auth: &auditV1.AttributeContext_Auth{
|
||||
Principal: "https%3A%2F%2Faccounts.dev.stackit.cloud/stackit-resource-manager-dev",
|
||||
Audiences: []string{"https:// stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud", "stackit", "api"},
|
||||
Claims: claims,
|
||||
},
|
||||
},
|
||||
},
|
||||
Request: nil,
|
||||
ResponseMetadata: &auditV1.ResponseMetadata{
|
||||
StatusCode: wrapperspb.Int32(200),
|
||||
ErrorMessage: nil,
|
||||
ErrorDetails: nil,
|
||||
ResponseAttributes: &auditV1.AttributeContext_Response{
|
||||
NumResponseItems: nil,
|
||||
Size: nil,
|
||||
Headers: nil,
|
||||
Time: timestamppb.New(time.Now().UTC()),
|
||||
},
|
||||
},
|
||||
Response: nil,
|
||||
Metadata: nil,
|
||||
},
|
||||
InsertId: fmt.Sprintf("%d/eu01/e72182e8-0bb9-4be2-a19f-87fc0dd6e738/00000000001", time.Now().UnixNano()),
|
||||
Labels: labels,
|
||||
CorrelationId: &correlationId,
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Severity: auditV1.LogSeverity_LOG_SEVERITY_DEFAULT,
|
||||
TraceParent: nil,
|
||||
TraceState: nil,
|
||||
}
|
||||
|
||||
if customization != nil {
|
||||
(*customization)(auditEvent)
|
||||
}
|
||||
|
||||
return auditEvent
|
||||
}
|
||||
|
||||
func newSystemAuditEvent(
|
||||
customization *func(*auditV1.AuditLogEntry)) *auditV1.AuditLogEntry {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue