mirror of
https://dev.azure.com/schwarzit/schwarzit.stackit-public/_git/audit-go
synced 2026-02-08 09:07:26 +00:00
184 lines
5.9 KiB
Go
184 lines
5.9 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"dev.azure.com/schwarzit/schwarzit.stackit-core-platform/common-audit.git/audit/messaging"
|
|
auditV1 "dev.azure.com/schwarzit/schwarzit.stackit-core-platform/common-audit.git/gen/go/audit/v1"
|
|
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
const ContentTypeProtobuf = "application/x-protobuf"
|
|
|
|
// ErrEventNil indicates that the event was nil
|
|
var ErrEventNil = errors.New("event is nil")
|
|
|
|
// ErrObjectIdentifierVisibilityMismatch indicates that a reference mismatch was detected.
|
|
//
|
|
// Valid combinations are:
|
|
// * Visibility: Public, ObjectIdentifier: <value>
|
|
// * Visibility: Private, ObjectIdentifier: <value | nil> -> If ObjectIdentifier is nil,
|
|
// the ObjectReference in the message will be ObjectName_OBJECT_NAME_SYSTEM
|
|
var ErrObjectIdentifierVisibilityMismatch = errors.New("object reference visibility mismatch")
|
|
|
|
// ErrRoutableIdentifierMissing indicates that a routable identifier is expected for the constellation of data.
|
|
var ErrRoutableIdentifierMissing = errors.New("routable identifier expected")
|
|
|
|
// ErrRoutableIdentifierMismatch indicates that a routable identifier (uuid) does not match.
|
|
var ErrRoutableIdentifierMismatch = errors.New("routable identifier type does not match")
|
|
|
|
// ErrRoutableIdentifierTypeMismatch indicates that a routable identifier type does not match the expected type.
|
|
var ErrRoutableIdentifierTypeMismatch = errors.New("routable identifier type does not match")
|
|
|
|
// ErrUnsupportedObjectIdentifierType indicates that an unsupported object identifier type has been provided.
|
|
var ErrUnsupportedObjectIdentifierType = errors.New("unsupported object identifier type")
|
|
|
|
// ErrUnsupportedResourceReferenceType indicates that an unsupported reference type has been provided.
|
|
var ErrUnsupportedResourceReferenceType = errors.New("unsupported resource reference type")
|
|
|
|
// 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")
|
|
|
|
// ErrSerializedPayloadNil states that the give serialized payload is nil
|
|
var ErrSerializedPayloadNil = errors.New("serialized payload nil")
|
|
|
|
func validateAndSerializePartially(
|
|
validator *ProtobufValidator,
|
|
event *auditV1.AuditEvent,
|
|
visibility auditV1.Visibility,
|
|
routingIdentifier *RoutingIdentifier,
|
|
objectIdentifier *auditV1.ObjectIdentifier,
|
|
) (*auditV1.RoutableAuditEvent, error) {
|
|
|
|
// Return error if the given event is nil
|
|
if event == nil {
|
|
return nil, ErrEventNil
|
|
}
|
|
|
|
// Validate the actual event
|
|
err := (*validator).Validate(event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Ensure that an object identifier is set if the event is public
|
|
if objectIdentifier == nil && visibility == auditV1.Visibility_VISIBILITY_PUBLIC {
|
|
return nil, ErrObjectIdentifierVisibilityMismatch
|
|
}
|
|
|
|
// Routing identifier not set but object identifier with routable identifier
|
|
if routingIdentifier == nil && objectIdentifier != nil &&
|
|
visibility != auditV1.Visibility_VISIBILITY_PRIVATE {
|
|
|
|
return nil, ErrRoutableIdentifierMissing
|
|
}
|
|
|
|
// Routing identifier type and object identifier types are not compatible
|
|
if routingIdentifier != nil &&
|
|
objectIdentifier != nil &&
|
|
objectIdentifier.Type == auditV1.ObjectType_OBJECT_TYPE_FOLDER &&
|
|
routingIdentifier.Type != RoutingIdentifierTypeOrganization {
|
|
|
|
return nil, ErrRoutableIdentifierTypeMismatch
|
|
}
|
|
|
|
// Routing identifier type and object identifier do not match
|
|
if routingIdentifier != nil &&
|
|
objectIdentifier != nil &&
|
|
objectIdentifier.Type != auditV1.ObjectType_OBJECT_TYPE_FOLDER &&
|
|
routingIdentifier.Identifier.String() != objectIdentifier.Identifier {
|
|
|
|
return nil, ErrRoutableIdentifierMismatch
|
|
}
|
|
|
|
// Test serialization even if the data is dropped later while logging to the legacy solution
|
|
auditEventBytes, err := proto.Marshal(event)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
payload := auditV1.UnencryptedData{
|
|
Data: auditEventBytes,
|
|
ProtobufType: fmt.Sprintf("%v", event.ProtoReflect().Descriptor().FullName()),
|
|
}
|
|
|
|
routableEvent := auditV1.RoutableAuditEvent{
|
|
EventName: event.EventName,
|
|
Visibility: visibility,
|
|
Data: &auditV1.RoutableAuditEvent_UnencryptedData{UnencryptedData: &payload},
|
|
}
|
|
|
|
// Set oneof protobuf fields after creation of the object
|
|
if objectIdentifier == nil {
|
|
routableEvent.ResourceReference = &auditV1.RoutableAuditEvent_ObjectName{
|
|
ObjectName: auditV1.ObjectName_OBJECT_NAME_SYSTEM}
|
|
} else {
|
|
routableEvent.ResourceReference = &auditV1.RoutableAuditEvent_ObjectIdentifier{
|
|
ObjectIdentifier: objectIdentifier}
|
|
}
|
|
|
|
err = (*validator).Validate(&routableEvent)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &routableEvent, nil
|
|
}
|
|
|
|
func serializeToProtobufMessage(routableEvent *auditV1.RoutableAuditEvent) (SerializedPayload, error) {
|
|
// Serialize routable event
|
|
routableEventBytes, err := proto.Marshal(routableEvent)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Package the routable event with information about the type in a message
|
|
message := auditV1.ProtobufMessage{
|
|
Value: routableEventBytes,
|
|
ProtobufType: fmt.Sprintf("%v", routableEvent.ProtoReflect().Descriptor().FullName()),
|
|
}
|
|
|
|
// Serialize message
|
|
messageBytes, err := proto.Marshal(&message)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &routablePayload{
|
|
payload: messageBytes,
|
|
contentType: ContentTypeProtobuf,
|
|
}, nil
|
|
}
|
|
|
|
// Send implements AuditApi.Send
|
|
func send(
|
|
topicNameResolver *TopicNameResolver,
|
|
messagingApi *messaging.MessagingApi,
|
|
ctx context.Context,
|
|
routingIdentifier *RoutingIdentifier,
|
|
serializedPayload *SerializedPayload,
|
|
) error {
|
|
|
|
if topicNameResolver == nil {
|
|
return ErrTopicNameResolverNil
|
|
}
|
|
if messagingApi == nil {
|
|
return ErrMessagingApiNil
|
|
}
|
|
if serializedPayload == nil {
|
|
return ErrSerializedPayloadNil
|
|
}
|
|
|
|
topic, err := (*topicNameResolver).Resolve(routingIdentifier)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return (*messagingApi).Send(ctx, topic, (*serializedPayload).GetPayload(), (*serializedPayload).GetContentType())
|
|
}
|