mirror of
https://dev.azure.com/schwarzit/schwarzit.stackit-public/_git/audit-go
synced 2026-02-15 12:21:44 +00:00
Allow users of the library to send tracing headers with the events
This commit is contained in:
parent
23f99b0668
commit
92fb9923a7
7 changed files with 250 additions and 56 deletions
|
|
@ -60,6 +60,39 @@ type AuditApi interface {
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) error
|
) error
|
||||||
|
|
||||||
|
// LogWithTrace is a convenience method that validates, serializes and sends data over the wire.
|
||||||
|
// If the transactional outbox patter should be used, the ValidateAndSerialize method
|
||||||
|
// and Send method can be called manually.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// * ctx - the context object
|
||||||
|
// * event - the auditV1.AuditEvent
|
||||||
|
// * visibility - route the event only internally or to the customer (no routing in the legacy solution)
|
||||||
|
// * routableIdentifier - the identifier of the object
|
||||||
|
// * traceParent - optional trace parent
|
||||||
|
// * traceState - optional trace state
|
||||||
|
//
|
||||||
|
// It may return one of the following errors:
|
||||||
|
//
|
||||||
|
// - ErrUnknownSingularType - if the routableIdentifier type is unknown
|
||||||
|
// - ErrUnknownPluralType - if the routableIdentifier type is unknown
|
||||||
|
// - ErrEventNil - if event is nil
|
||||||
|
// - ErrObjectIdentifierNil - if the object identifier is nil
|
||||||
|
// - ErrObjectIdentifierVisibilityMismatch - if object identifier and visibility are not in a valid state
|
||||||
|
// - ErrUnsupportedObjectIdentifierType - if an unsupported object identifier type was provided
|
||||||
|
// - ErrAttributeIdentifierInvalid - if identifier in a checked attribute and the object identifier do not match
|
||||||
|
// - ErrAttributeTypeInvalid - if the type from checked attribute and the type from object identifier do not match
|
||||||
|
// - protovalidate.ValidationError - if schema validation errors have been detected
|
||||||
|
// - protobuf serialization errors - if the event couldn't be serialized
|
||||||
|
LogWithTrace(
|
||||||
|
ctx context.Context,
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) error
|
||||||
|
|
||||||
// ValidateAndSerialize validates and serializes the event into a byte representation.
|
// ValidateAndSerialize validates and serializes the event into a byte representation.
|
||||||
// The result has to be sent explicitly by calling the Send method.
|
// The result has to be sent explicitly by calling the Send method.
|
||||||
ValidateAndSerialize(
|
ValidateAndSerialize(
|
||||||
|
|
@ -68,6 +101,16 @@ type AuditApi interface {
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) (*CloudEvent, error)
|
) (*CloudEvent, error)
|
||||||
|
|
||||||
|
// ValidateAndSerializeWithTrace validates and serializes the event into a byte representation.
|
||||||
|
// The result has to be sent explicitly by calling the Send method.
|
||||||
|
ValidateAndSerializeWithTrace(
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) (*CloudEvent, error)
|
||||||
|
|
||||||
// Send the serialized content as byte array to the audit log system.
|
// Send the serialized content as byte array to the audit log system.
|
||||||
// It may return one of the following errors:
|
// It may return one of the following errors:
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,20 @@ func (a *LegacyAuditApi) Log(
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) error {
|
) error {
|
||||||
|
|
||||||
cloudEvent, err := a.ValidateAndSerialize(event, visibility, routableIdentifier)
|
return a.LogWithTrace(ctx, event, visibility, routableIdentifier, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogWithTrace implements AuditApi.LogWithTrace
|
||||||
|
func (a *LegacyAuditApi) LogWithTrace(
|
||||||
|
ctx context.Context,
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
cloudEvent, err := a.ValidateAndSerializeWithTrace(event, visibility, routableIdentifier, traceParent, traceState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -94,6 +107,18 @@ func (a *LegacyAuditApi) ValidateAndSerialize(
|
||||||
visibility auditV1.Visibility,
|
visibility auditV1.Visibility,
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) (*CloudEvent, error) {
|
) (*CloudEvent, error) {
|
||||||
|
return a.ValidateAndSerializeWithTrace(event, visibility, routableIdentifier, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAndSerializeWithTrace implements AuditApi.ValidateAndSerializeWithTrace.
|
||||||
|
// It serializes the event into the byte representation of the legacy audit log system.
|
||||||
|
func (a *LegacyAuditApi) ValidateAndSerializeWithTrace(
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) (*CloudEvent, error) {
|
||||||
|
|
||||||
routableEvent, err := validateAndSerializePartially(a.validator, event, visibility, routableIdentifier)
|
routableEvent, err := validateAndSerializePartially(a.validator, event, visibility, routableIdentifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -121,11 +146,10 @@ func (a *LegacyAuditApi) ValidateAndSerialize(
|
||||||
dataContentType: ContentTypeCloudEventsProtobuf,
|
dataContentType: ContentTypeCloudEventsProtobuf,
|
||||||
dataType: fmt.Sprintf("%v", routableEvent.ProtoReflect().Descriptor().FullName()),
|
dataType: fmt.Sprintf("%v", routableEvent.ProtoReflect().Descriptor().FullName()),
|
||||||
// TODO check if this is correct
|
// TODO check if this is correct
|
||||||
subject: event.ProtoPayload.ResourceName,
|
subject: event.ProtoPayload.ResourceName,
|
||||||
data: legacyBytes,
|
data: legacyBytes,
|
||||||
// TODO set trace fields
|
traceParent: traceParent,
|
||||||
traceParent: nil,
|
traceState: traceState,
|
||||||
traceState: nil,
|
|
||||||
}
|
}
|
||||||
return &message, nil
|
return &message, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,8 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
topicSubscriptionTopicPattern := "audit-log/>"
|
topicSubscriptionTopicPattern := "audit-log/>"
|
||||||
|
traceParent := "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
||||||
|
traceState := "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE"
|
||||||
|
|
||||||
// Check logging of organization events
|
// Check logging of organization events
|
||||||
t.Run("Log public organization event", func(t *testing.T) {
|
t.Run("Log public organization event", func(t *testing.T) {
|
||||||
|
|
@ -69,17 +71,19 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
validateSentMessage(t, topicName, message, event)
|
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Log private organization event", func(t *testing.T) {
|
t.Run("Log private organization event", func(t *testing.T) {
|
||||||
|
|
@ -106,17 +110,19 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
validateSentMessage(t, topicName, message, event)
|
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Check logging of folder events
|
// Check logging of folder events
|
||||||
|
|
@ -144,17 +150,19 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
validateSentMessage(t, topicName, message, event)
|
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Log private folder event", func(t *testing.T) {
|
t.Run("Log private folder event", func(t *testing.T) {
|
||||||
|
|
@ -181,17 +189,19 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
validateSentMessage(t, topicName, message, event)
|
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Check logging of project events
|
// Check logging of project events
|
||||||
|
|
@ -219,17 +229,19 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
validateSentMessage(t, topicName, message, event)
|
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Log private project event", func(t *testing.T) {
|
t.Run("Log private project event", func(t *testing.T) {
|
||||||
|
|
@ -256,17 +268,19 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
validateSentMessage(t, topicName, message, event)
|
validateSentMessage(t, topicName, message, event, &traceParent, &traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Check logging of system events
|
// Check logging of system events
|
||||||
|
|
@ -294,11 +308,13 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t,
|
assert.NoError(t,
|
||||||
(*auditApi).Log(
|
(*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
RoutableSystemIdentifier,
|
RoutableSystemIdentifier,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Receive the event from solace
|
// Receive the event from solace
|
||||||
|
|
@ -307,9 +323,8 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Check topic name
|
// Check topic name
|
||||||
assert.Equal(t, topicName, *message.Properties.To)
|
assert.Equal(t, topicName, *message.Properties.To)
|
||||||
|
assert.Nil(t, message.ApplicationProperties["cloudEvents:traceparent"])
|
||||||
// Check topic name
|
assert.Nil(t, message.ApplicationProperties["cloudEvents:tracestate"])
|
||||||
assert.Equal(t, topicName, *message.Properties.To)
|
|
||||||
|
|
||||||
// Check deserialized message
|
// Check deserialized message
|
||||||
var auditEvent LegacyAuditEvent
|
var auditEvent LegacyAuditEvent
|
||||||
|
|
@ -349,23 +364,35 @@ func TestLegacyAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
validateSentMessageWithDetails(t, topicName, message, event)
|
validateSentMessageWithDetails(t, topicName, message, event, &traceParent, &traceState)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSentMessage(t *testing.T, topicName string, message *amqp.Message, event *auditV1.AuditLogEntry) {
|
func validateSentMessage(
|
||||||
// Check topic name
|
t *testing.T,
|
||||||
|
topicName string,
|
||||||
|
message *amqp.Message,
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) {
|
||||||
|
|
||||||
|
// Check message properties
|
||||||
assert.Equal(t, topicName, *message.Properties.To)
|
assert.Equal(t, topicName, *message.Properties.To)
|
||||||
|
assert.Equal(t, *traceParent, message.ApplicationProperties["cloudEvents:traceparent"])
|
||||||
|
assert.Equal(t, *traceState, message.ApplicationProperties["cloudEvents:tracestate"])
|
||||||
|
|
||||||
// Check deserialized message
|
// Check deserialized message
|
||||||
var auditEvent LegacyAuditEvent
|
var auditEvent LegacyAuditEvent
|
||||||
|
|
@ -405,9 +432,19 @@ func validateSentMessage(t *testing.T, topicName string, message *amqp.Message,
|
||||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerSuppliedUserAgent, auditEvent.UserAgent)
|
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerSuppliedUserAgent, auditEvent.UserAgent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateSentMessageWithDetails(t *testing.T, topicName string, message *amqp.Message, event *auditV1.AuditLogEntry) {
|
func validateSentMessageWithDetails(
|
||||||
|
t *testing.T,
|
||||||
|
topicName string,
|
||||||
|
message *amqp.Message,
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) {
|
||||||
|
|
||||||
// Check topic name
|
// Check topic name
|
||||||
assert.Equal(t, topicName, *message.Properties.To)
|
assert.Equal(t, topicName, *message.Properties.To)
|
||||||
|
assert.Equal(t, *traceParent, message.ApplicationProperties["cloudEvents:traceparent"])
|
||||||
|
assert.Equal(t, *traceState, message.ApplicationProperties["cloudEvents:tracestate"])
|
||||||
|
|
||||||
// Check deserialized message
|
// Check deserialized message
|
||||||
var auditEvent LegacyAuditEvent
|
var auditEvent LegacyAuditEvent
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,27 @@ func NewMockAuditApi() (*AuditApi, error) {
|
||||||
// Log implements AuditApi.Log.
|
// Log implements AuditApi.Log.
|
||||||
// Validates and serializes the event but doesn't send it.
|
// Validates and serializes the event but doesn't send it.
|
||||||
func (a *MockAuditApi) Log(
|
func (a *MockAuditApi) Log(
|
||||||
_ context.Context,
|
ctx context.Context,
|
||||||
event *auditV1.AuditLogEntry,
|
event *auditV1.AuditLogEntry,
|
||||||
visibility auditV1.Visibility,
|
visibility auditV1.Visibility,
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) error {
|
) error {
|
||||||
|
|
||||||
_, err := a.ValidateAndSerialize(event, visibility, routableIdentifier)
|
return a.LogWithTrace(ctx, event, visibility, routableIdentifier, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogWithTrace implements AuditApi.LogWithTrace.
|
||||||
|
// Validates and serializes the event but doesn't send it.
|
||||||
|
func (a *MockAuditApi) LogWithTrace(
|
||||||
|
_ context.Context,
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
_, err := a.ValidateAndSerializeWithTrace(event, visibility, routableIdentifier, traceParent, traceState)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,6 +60,18 @@ func (a *MockAuditApi) ValidateAndSerialize(
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) (*CloudEvent, error) {
|
) (*CloudEvent, error) {
|
||||||
|
|
||||||
|
return a.ValidateAndSerializeWithTrace(event, visibility, routableIdentifier, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAndSerializeWithTrace implements AuditApi.ValidateAndSerializeWithTrace
|
||||||
|
func (a *MockAuditApi) ValidateAndSerializeWithTrace(
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) (*CloudEvent, error) {
|
||||||
|
|
||||||
routableEvent, err := validateAndSerializePartially(a.validator, event, visibility, routableIdentifier)
|
routableEvent, err := validateAndSerializePartially(a.validator, event, visibility, routableIdentifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -67,8 +93,8 @@ func (a *MockAuditApi) ValidateAndSerialize(
|
||||||
// TODO check if this is correct
|
// TODO check if this is correct
|
||||||
subject: event.ProtoPayload.ResourceName,
|
subject: event.ProtoPayload.ResourceName,
|
||||||
data: routableEventBytes,
|
data: routableEventBytes,
|
||||||
traceParent: nil,
|
traceParent: traceParent,
|
||||||
traceState: nil,
|
traceState: traceState,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &message, nil
|
return &message, nil
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,8 @@ func TestMockAuditApi_Log(t *testing.T) {
|
||||||
|
|
||||||
t.Run("ValidateAndSerialize", func(t *testing.T) {
|
t.Run("ValidateAndSerialize", func(t *testing.T) {
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
cloudEvent, err := (*auditApi).ValidateAndSerialize(
|
cloudEvent, err := (*auditApi).ValidateAndSerializeWithTrace(
|
||||||
event, visibility, routableObjectIdentifier)
|
event, visibility, routableObjectIdentifier, nil, nil)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,20 @@ func (a *routableAuditApi) Log(
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) error {
|
) error {
|
||||||
|
|
||||||
cloudEvent, err := a.ValidateAndSerialize(event, visibility, routableIdentifier)
|
return a.LogWithTrace(ctx, event, visibility, routableIdentifier, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogWithTrace implements AuditApi.LogWithTrace
|
||||||
|
func (a *routableAuditApi) LogWithTrace(
|
||||||
|
ctx context.Context,
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) error {
|
||||||
|
|
||||||
|
cloudEvent, err := a.ValidateAndSerializeWithTrace(event, visibility, routableIdentifier, traceParent, traceState)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -124,6 +137,18 @@ func (a *routableAuditApi) ValidateAndSerialize(
|
||||||
routableIdentifier *RoutableIdentifier,
|
routableIdentifier *RoutableIdentifier,
|
||||||
) (*CloudEvent, error) {
|
) (*CloudEvent, error) {
|
||||||
|
|
||||||
|
return a.ValidateAndSerializeWithTrace(event, visibility, routableIdentifier, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateAndSerializeWithTrace implements AuditApi.ValidateAndSerializeWithTrace
|
||||||
|
func (a *routableAuditApi) ValidateAndSerializeWithTrace(
|
||||||
|
event *auditV1.AuditLogEntry,
|
||||||
|
visibility auditV1.Visibility,
|
||||||
|
routableIdentifier *RoutableIdentifier,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
|
) (*CloudEvent, error) {
|
||||||
|
|
||||||
routableEvent, err := validateAndSerializePartially(
|
routableEvent, err := validateAndSerializePartially(
|
||||||
a.validator,
|
a.validator,
|
||||||
event,
|
event,
|
||||||
|
|
@ -148,11 +173,10 @@ func (a *routableAuditApi) ValidateAndSerialize(
|
||||||
dataContentType: ContentTypeCloudEventsProtobuf,
|
dataContentType: ContentTypeCloudEventsProtobuf,
|
||||||
dataType: fmt.Sprintf("%v", routableEvent.ProtoReflect().Descriptor().FullName()),
|
dataType: fmt.Sprintf("%v", routableEvent.ProtoReflect().Descriptor().FullName()),
|
||||||
// TODO check if this is correct
|
// TODO check if this is correct
|
||||||
subject: event.ProtoPayload.ResourceName,
|
subject: event.ProtoPayload.ResourceName,
|
||||||
data: routableEventBytes,
|
data: routableEventBytes,
|
||||||
// TODO set trace fields
|
traceParent: traceParent,
|
||||||
traceParent: nil,
|
traceState: traceState,
|
||||||
traceState: nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &message, nil
|
return &message, nil
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,15 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
validator, err := protovalidate.New()
|
validator, err := protovalidate.New()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
traceParent := "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
||||||
|
traceState := "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE"
|
||||||
|
|
||||||
// Instantiate the audit api
|
// Instantiate the audit api
|
||||||
organizationTopicPrefix := "org"
|
organizationTopicPrefix := "org"
|
||||||
projectTopicPrefix := "project"
|
projectTopicPrefix := "project"
|
||||||
folderTopicPrefix := "folder"
|
folderTopicPrefix := "folder"
|
||||||
systemTopicName := "topic://system/admin-events"
|
systemTopicName := "topic://system/admin-events"
|
||||||
|
|
||||||
auditApi, err := newRoutableAuditApi(
|
auditApi, err := newRoutableAuditApi(
|
||||||
messagingApi,
|
messagingApi,
|
||||||
topicNameConfig{
|
topicNameConfig{
|
||||||
|
|
@ -67,11 +71,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
|
|
@ -84,7 +90,9 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
objectIdentifier,
|
objectIdentifier,
|
||||||
event,
|
event,
|
||||||
"stackit.resourcemanager.v2.organization.created",
|
"stackit.resourcemanager.v2.organization.created",
|
||||||
visibility)
|
visibility,
|
||||||
|
&traceParent,
|
||||||
|
&traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Log private organization event", func(t *testing.T) {
|
t.Run("Log private organization event", func(t *testing.T) {
|
||||||
|
|
@ -104,11 +112,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t,
|
assert.NoError(t,
|
||||||
(*auditApi).Log(
|
(*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Receive the event from solace
|
// Receive the event from solace
|
||||||
|
|
@ -122,7 +132,9 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
objectIdentifier,
|
objectIdentifier,
|
||||||
event,
|
event,
|
||||||
"stackit.resourcemanager.v2.organization.created",
|
"stackit.resourcemanager.v2.organization.created",
|
||||||
visibility)
|
visibility,
|
||||||
|
&traceParent,
|
||||||
|
&traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Check logging of folder events
|
// Check logging of folder events
|
||||||
|
|
@ -139,11 +151,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
|
|
@ -156,7 +170,9 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
objectIdentifier,
|
objectIdentifier,
|
||||||
event,
|
event,
|
||||||
"stackit.resourcemanager.v2.folder.created",
|
"stackit.resourcemanager.v2.folder.created",
|
||||||
visibility)
|
visibility,
|
||||||
|
&traceParent,
|
||||||
|
&traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Log private folder event", func(t *testing.T) {
|
t.Run("Log private folder event", func(t *testing.T) {
|
||||||
|
|
@ -174,11 +190,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t,
|
assert.NoError(t,
|
||||||
(*auditApi).Log(
|
(*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Receive the event from solace
|
// Receive the event from solace
|
||||||
|
|
@ -192,7 +210,9 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
objectIdentifier,
|
objectIdentifier,
|
||||||
event,
|
event,
|
||||||
"stackit.resourcemanager.v2.folder.created",
|
"stackit.resourcemanager.v2.folder.created",
|
||||||
visibility)
|
visibility,
|
||||||
|
&traceParent,
|
||||||
|
&traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Check logging of project events
|
// Check logging of project events
|
||||||
|
|
@ -209,11 +229,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t,
|
assert.NoError(t,
|
||||||
(*auditApi).Log(
|
(*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Receive the event from solace
|
// Receive the event from solace
|
||||||
|
|
@ -227,7 +249,9 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
objectIdentifier,
|
objectIdentifier,
|
||||||
event,
|
event,
|
||||||
"stackit.resourcemanager.v2.project.created",
|
"stackit.resourcemanager.v2.project.created",
|
||||||
visibility)
|
visibility,
|
||||||
|
&traceParent,
|
||||||
|
&traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Log private project event", func(t *testing.T) {
|
t.Run("Log private project event", func(t *testing.T) {
|
||||||
|
|
@ -243,11 +267,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t,
|
assert.NoError(t,
|
||||||
(*auditApi).Log(
|
(*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Receive the event from solace
|
// Receive the event from solace
|
||||||
|
|
@ -261,7 +287,9 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
objectIdentifier,
|
objectIdentifier,
|
||||||
event,
|
event,
|
||||||
"stackit.resourcemanager.v2.project.created",
|
"stackit.resourcemanager.v2.project.created",
|
||||||
visibility)
|
visibility,
|
||||||
|
&traceParent,
|
||||||
|
&traceState)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Check logging of system events
|
// Check logging of system events
|
||||||
|
|
@ -278,11 +306,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
||||||
assert.NoError(t,
|
assert.NoError(t,
|
||||||
(*auditApi).Log(
|
(*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
RoutableSystemIdentifier,
|
RoutableSystemIdentifier,
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
))
|
))
|
||||||
|
|
||||||
// Receive the event from solace
|
// Receive the event from solace
|
||||||
|
|
@ -301,6 +331,8 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime().UnixMilli(), applicationProperties["cloudEvents:time"])
|
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, "application/cloudevents+protobuf", applicationProperties["cloudEvents:datacontenttype"])
|
||||||
assert.Equal(t, "audit.v1.RoutableAuditEvent", applicationProperties["cloudEvents:type"])
|
assert.Equal(t, "audit.v1.RoutableAuditEvent", applicationProperties["cloudEvents:type"])
|
||||||
|
assert.Nil(t, applicationProperties["cloudEvents:traceparent"])
|
||||||
|
assert.Nil(t, applicationProperties["cloudEvents:tracestate"])
|
||||||
|
|
||||||
// Check deserialized message
|
// Check deserialized message
|
||||||
validateRoutableEventPayload(
|
validateRoutableEventPayload(
|
||||||
|
|
@ -326,11 +358,13 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
|
|
||||||
// Log the event to solace
|
// Log the event to solace
|
||||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||||
assert.NoError(t, (*auditApi).Log(
|
assert.NoError(t, (*auditApi).LogWithTrace(
|
||||||
ctx,
|
ctx,
|
||||||
event,
|
event,
|
||||||
visibility,
|
visibility,
|
||||||
NewRoutableIdentifier(objectIdentifier),
|
NewRoutableIdentifier(objectIdentifier),
|
||||||
|
&traceParent,
|
||||||
|
&traceState,
|
||||||
))
|
))
|
||||||
|
|
||||||
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
||||||
|
|
@ -343,7 +377,9 @@ func TestRoutableAuditApi(t *testing.T) {
|
||||||
objectIdentifier,
|
objectIdentifier,
|
||||||
event,
|
event,
|
||||||
"stackit.resourcemanager.v2.organization.created",
|
"stackit.resourcemanager.v2.organization.created",
|
||||||
visibility)
|
visibility,
|
||||||
|
&traceParent,
|
||||||
|
&traceState)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,6 +391,8 @@ func validateSentEvent(
|
||||||
event *auditV1.AuditLogEntry,
|
event *auditV1.AuditLogEntry,
|
||||||
eventName string,
|
eventName string,
|
||||||
visibility auditV1.Visibility,
|
visibility auditV1.Visibility,
|
||||||
|
traceParent *string,
|
||||||
|
traceState *string,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// Check topic name
|
// Check topic name
|
||||||
|
|
@ -369,8 +407,10 @@ func validateSentEvent(
|
||||||
_, isUuid := uuid.Parse(fmt.Sprintf("%s", applicationProperties["cloudEvents:id"]))
|
_, isUuid := uuid.Parse(fmt.Sprintf("%s", applicationProperties["cloudEvents:id"]))
|
||||||
assert.True(t, true, isUuid)
|
assert.True(t, true, isUuid)
|
||||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime().UnixMilli(), applicationProperties["cloudEvents:time"])
|
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, ContentTypeCloudEventsProtobuf, applicationProperties["cloudEvents:datacontenttype"])
|
||||||
assert.Equal(t, "audit.v1.RoutableAuditEvent", applicationProperties["cloudEvents:type"])
|
assert.Equal(t, "audit.v1.RoutableAuditEvent", applicationProperties["cloudEvents:type"])
|
||||||
|
assert.Equal(t, *traceParent, applicationProperties["cloudEvents:traceparent"])
|
||||||
|
assert.Equal(t, *traceState, applicationProperties["cloudEvents:tracestate"])
|
||||||
|
|
||||||
// Check deserialized message
|
// Check deserialized message
|
||||||
validateRoutableEventPayload(
|
validateRoutableEventPayload(
|
||||||
|
|
@ -443,7 +483,7 @@ func TestRoutableAuditApi_Log_ValidationFailed(t *testing.T) {
|
||||||
auditApi := routableAuditApi{validator: &protobufValidator}
|
auditApi := routableAuditApi{validator: &protobufValidator}
|
||||||
|
|
||||||
event := NewSystemAuditEvent(nil)
|
event := NewSystemAuditEvent(nil)
|
||||||
err := auditApi.Log(context.Background(), event, auditV1.Visibility_VISIBILITY_PUBLIC, RoutableSystemIdentifier)
|
err := auditApi.LogWithTrace(context.Background(), event, auditV1.Visibility_VISIBILITY_PUBLIC, RoutableSystemIdentifier, nil, nil)
|
||||||
assert.ErrorIs(t, err, expectedError)
|
assert.ErrorIs(t, err, expectedError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue