mirror of
https://dev.azure.com/schwarzit/schwarzit.stackit-public/_git/audit-go
synced 2026-02-08 17:17:25 +00:00
So far the SDK provided a messaging API that was not thread-safe (i.e. goroutine-safe). Additionally the SDK provided a MutexAPI which made it thread-safe at the cost of removed concurrency possibilities. The changes implemented in this commit replace both implementations with a thread-safe connection pool based solution. The api gateway is a SDK user that requires reliable high performance send capabilities with a limit amount of amqp connections. These changes in the PR try address their requirements by moving the responsibility of connection management into the SDK. From this change other SDK users will benefit as well. Security-concept-update-needed: false. JIRA Work Item: STACKITALO-62
520 lines
17 KiB
Go
520 lines
17 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"go.opentelemetry.io/otel"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"dev.azure.com/schwarzit/schwarzit.stackit-public/audit-go.git/audit/messaging"
|
|
auditV1 "dev.azure.com/schwarzit/schwarzit.stackit-public/audit-go.git/gen/go/audit/v1"
|
|
|
|
"github.com/bufbuild/protovalidate-go"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
func TestDynamicLegacyAuditApi(t *testing.T) {
|
|
|
|
// Specify test timeout
|
|
ctx, cancelFn := context.WithTimeout(context.Background(), 120*time.Second)
|
|
defer cancelFn()
|
|
|
|
// Start solace docker container
|
|
solaceContainer, err := messaging.NewSolaceContainer(context.Background())
|
|
assert.NoError(t, err)
|
|
defer solaceContainer.Stop()
|
|
|
|
// Instantiate the messaging api
|
|
messagingApi, err := messaging.NewAmqpApi(
|
|
messaging.AmqpConnectionPoolConfig{
|
|
Parameters: messaging.AmqpConnectionConfig{BrokerUrl: solaceContainer.AmqpConnectionString},
|
|
PoolSize: 1,
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
// Validator
|
|
validator, err := protovalidate.New()
|
|
assert.NoError(t, err)
|
|
|
|
topicSubscriptionTopicPattern := "audit-log/>"
|
|
|
|
// Check that event-type data-access is rejected as it is currently
|
|
// not supported by downstream services
|
|
t.Run("reject data access event", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "reject-data-access-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/organization-rejected"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newOrganizationAuditEvent(nil)
|
|
event.LogName = strings.Replace(event.LogName, string(EventTypeAdminActivity), string(EventTypeDataAccess), 1)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.ErrorIs(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
), ErrUnsupportedEventTypeDataAccess)
|
|
})
|
|
|
|
// Check logging of organization events
|
|
t.Run("Log public organization event", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "org-event-public-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/organization-created"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newOrganizationAuditEvent(nil)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
))
|
|
|
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
|
assert.NoError(t, err)
|
|
|
|
validateSentMessage(t, topicName, message, event)
|
|
})
|
|
|
|
t.Run("Log private organization event", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "org-event-private-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/organization-created"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newOrganizationAuditEvent(nil)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
))
|
|
|
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
|
assert.NoError(t, err)
|
|
|
|
validateSentMessage(t, topicName, message, event)
|
|
})
|
|
|
|
// Check logging of folder events
|
|
t.Run("Log public folder event", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "folder-event-public-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/folder-created"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newFolderAuditEvent(nil)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
))
|
|
|
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
|
assert.NoError(t, err)
|
|
|
|
validateSentMessage(t, topicName, message, event)
|
|
})
|
|
|
|
t.Run("Log private folder event", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "folder-event-private-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/folder-created"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newFolderAuditEvent(nil)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
))
|
|
|
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
|
assert.NoError(t, err)
|
|
|
|
validateSentMessage(t, topicName, message, event)
|
|
})
|
|
|
|
// Check logging of project events
|
|
t.Run("Log public project event", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "project-event-public-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/project-created"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newProjectAuditEvent(nil)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
))
|
|
|
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
|
assert.NoError(t, err)
|
|
|
|
validateSentMessage(t, topicName, message, event)
|
|
})
|
|
|
|
t.Run("Log private project event", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "project-event-private-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/project-created"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newProjectAuditEvent(nil)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
))
|
|
|
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
|
assert.NoError(t, err)
|
|
|
|
validateSentMessage(t, topicName, message, event)
|
|
})
|
|
|
|
// 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.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
RoutableSystemIdentifier,
|
|
))
|
|
|
|
// 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.Equal(t, "", message.ApplicationProperties["cloudEvents:traceparent"])
|
|
assert.Equal(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()
|
|
|
|
queueName := "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/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 := newSystemAuditEvent(nil)
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PRIVATE
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t,
|
|
auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
RoutableSystemIdentifier,
|
|
))
|
|
|
|
// 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.Equal(t, "", message.ApplicationProperties["cloudEvents:traceparent"])
|
|
assert.Equal(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.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)
|
|
})
|
|
|
|
t.Run("Log event with details", func(t *testing.T) {
|
|
defer solaceContainer.StopOnError()
|
|
|
|
// Create the queue and topic subscription in solace
|
|
queueName := "org-event-with-details-legacy"
|
|
assert.NoError(t, solaceContainer.QueueCreate(ctx, queueName))
|
|
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, topicSubscriptionTopicPattern))
|
|
|
|
topicName := "topic://audit-log/eu01/v1/resource-manager/organization-created"
|
|
assert.NoError(t, solaceContainer.ValidateTopicName(topicSubscriptionTopicPattern, topicName))
|
|
|
|
// Instantiate audit api
|
|
auditApi, err := NewDynamicLegacyAuditApi(
|
|
messagingApi,
|
|
validator,
|
|
)
|
|
assert.NoError(t, err)
|
|
|
|
// Instantiate test data
|
|
event, objectIdentifier := newOrganizationAuditEvent(nil)
|
|
escapedQuery := url.QueryEscape("param=value")
|
|
event.ProtoPayload.RequestMetadata.RequestAttributes.Query = &escapedQuery
|
|
|
|
// Log the event to solace
|
|
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
|
ctx := context.WithValue(ctx, ContextKeyTopic, topicName)
|
|
assert.NoError(t, auditApi.Log(
|
|
ctx,
|
|
event,
|
|
visibility,
|
|
NewRoutableIdentifier(objectIdentifier),
|
|
))
|
|
|
|
message, err := solaceContainer.NextMessageFromQueue(ctx, queueName, true)
|
|
assert.NoError(t, err)
|
|
|
|
validateSentMessageWithDetails(t, topicName, message, event)
|
|
})
|
|
}
|
|
|
|
func TestDynamicLegacyAuditApi_NewLegacyAuditApi_MessagingApiNil(t *testing.T) {
|
|
auditApi, err := NewDynamicLegacyAuditApi(nil, nil)
|
|
assert.Nil(t, auditApi)
|
|
assert.EqualError(t, err, "messaging api nil")
|
|
}
|
|
|
|
func TestDynamicLegacyAuditApi_ValidateAndSerialize_ValidationFailed(t *testing.T) {
|
|
expectedError := errors.New("expected error")
|
|
|
|
validator := &ProtobufValidatorMock{}
|
|
validator.On("Validate", mock.Anything).Return(expectedError)
|
|
var protobufValidator ProtobufValidator = validator
|
|
|
|
auditApi := DynamicLegacyAuditApi{
|
|
tracer: otel.Tracer("test"),
|
|
validator: protobufValidator,
|
|
}
|
|
|
|
event := newSystemAuditEvent(nil)
|
|
_, err := auditApi.ValidateAndSerialize(context.Background(), event, auditV1.Visibility_VISIBILITY_PUBLIC, RoutableSystemIdentifier)
|
|
assert.ErrorIs(t, err, expectedError)
|
|
}
|
|
|
|
func TestDynamicLegacyAuditApi_Log_ValidationFailed(t *testing.T) {
|
|
expectedError := errors.New("expected error")
|
|
|
|
validator := &ProtobufValidatorMock{}
|
|
validator.On("Validate", mock.Anything).Return(expectedError)
|
|
var protobufValidator ProtobufValidator = validator
|
|
|
|
auditApi := DynamicLegacyAuditApi{
|
|
tracer: otel.Tracer("test"),
|
|
validator: protobufValidator,
|
|
}
|
|
|
|
event := newSystemAuditEvent(nil)
|
|
err := auditApi.Log(context.Background(), event, auditV1.Visibility_VISIBILITY_PUBLIC, RoutableSystemIdentifier)
|
|
assert.ErrorIs(t, err, expectedError)
|
|
}
|
|
|
|
func TestDynamicLegacyAuditApi_Log_NilEvent(t *testing.T) {
|
|
auditApi := DynamicLegacyAuditApi{tracer: otel.Tracer("test")}
|
|
err := auditApi.Log(context.Background(), nil, auditV1.Visibility_VISIBILITY_PUBLIC, RoutableSystemIdentifier)
|
|
assert.ErrorIs(t, err, ErrEventNil)
|
|
}
|
|
|
|
func TestDynamicLegacyAuditApi_ConvertAndSerializeIntoLegacyFormatInvalidObjectIdentifierType(t *testing.T) {
|
|
customization := func(event *auditV1.AuditLogEntry,
|
|
objectIdentifier *auditV1.ObjectIdentifier) {
|
|
objectIdentifier.Type = "invalid"
|
|
}
|
|
event, objectIdentifier := newProjectAuditEvent(&customization)
|
|
|
|
validator := &ProtobufValidatorMock{}
|
|
validator.On("Validate", mock.Anything).Return(nil)
|
|
var protobufValidator ProtobufValidator = validator
|
|
|
|
auditApi := DynamicLegacyAuditApi{
|
|
tracer: otel.Tracer("test"),
|
|
validator: protobufValidator,
|
|
}
|
|
_, err := auditApi.ValidateAndSerialize(context.Background(), event, auditV1.Visibility_VISIBILITY_PUBLIC, NewRoutableIdentifier(objectIdentifier))
|
|
assert.ErrorIs(t, err, ErrUnsupportedRoutableType)
|
|
}
|