Replace Singular-/PluralType with ObjectType

This commit is contained in:
Christian Schaible 2024-10-15 15:09:28 +02:00
parent 03d4ae5d1b
commit f9cefe876b
18 changed files with 176 additions and 246 deletions

View file

@ -9,15 +9,14 @@ The api documentation can be found
### Supported data types for routing
The following data types are currently supported for routing.
There are `SingularType` and `PluralType` representations in the code for them.
The following data types are currently supported for routing.
| Singular-Type | Plural-Type | Routable to customer | Description |
|---------------|---------------|----------------------|----------------------|
| system | system | no | The STACKIT system |
| project | projects | yes | STACKIT project |
| organization | organizations | yes | STACKIT organization |
| folder | folders | yes | STACKIT folder |
| ObjectType | Routable to customer | Description |
|--------------|----------------------|----------------------|
| system | no | The STACKIT system |
| project | yes | STACKIT project |
| organization | yes | STACKIT organization |
| folder | yes | STACKIT folder |
### Additional API implementations

View file

@ -12,8 +12,6 @@ import (
)
type EventType string
type SingularType string
type PluralType string
const (
EventTypeAdminActivity EventType = "admin-activity"
@ -22,7 +20,61 @@ const (
EventTypeDataAccess EventType = "data-access"
)
var SystemIdentifier = &auditV1.ObjectIdentifier{Identifier: uuid.Nil.String(), Type: string(SingularTypeSystem)}
type ObjectType string
const (
ObjectTypeSystem ObjectType = "system"
ObjectTypeOrganization ObjectType = "organization"
ObjectTypeFolder ObjectType = "folder"
ObjectTypeProject ObjectType = "project"
)
func ObjectTypeFromPluralString(value string) ObjectType {
switch value {
case "organizations":
return ObjectTypeOrganization
case "folders":
return ObjectTypeFolder
case "projects":
return ObjectTypeProject
case "system":
return ObjectTypeSystem
default:
return ObjectType(value)
}
}
func (t ObjectType) IsSupportedType() error {
switch t {
case ObjectTypeOrganization:
fallthrough
case ObjectTypeFolder:
fallthrough
case ObjectTypeProject:
fallthrough
case ObjectTypeSystem:
return nil
default:
return ErrUnknownObjectType
}
}
func (t ObjectType) Plural() string {
switch t {
case ObjectTypeOrganization:
return "organizations"
case ObjectTypeFolder:
return "folders"
case ObjectTypeProject:
return "projects"
case ObjectTypeSystem:
return "system"
default:
return ""
}
}
var SystemIdentifier = &auditV1.ObjectIdentifier{Identifier: uuid.Nil.String(), Type: string(ObjectTypeSystem)}
var RoutableSystemIdentifier = NewRoutableIdentifier(SystemIdentifier)
// AuditApi is the interface to log audit events.
@ -41,19 +93,6 @@ type AuditApi interface {
// * 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
//
// 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
Log(
ctx context.Context,
event *auditV1.AuditLogEntry,
@ -72,19 +111,6 @@ type AuditApi interface {
// * 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,
@ -113,13 +139,6 @@ type AuditApi interface {
) (*CloudEvent, error)
// Send the serialized content as byte array to the audit log system.
// It may return one of the following errors:
//
// - ErrTopicNameResolverNil - if the topic name resolver is nil
// - ErrMessagingApiNil - if the messaging api is nil
// - ErrCloudEventNil - if the cloud event is nil
// - ErrObjectIdentifierNil - if the object identifier is nil
// - amqp errors - if the event couldn't be sent
Send(
ctx context.Context,
routableIdentifier *RoutableIdentifier,
@ -207,7 +226,7 @@ type TopicNameResolver interface {
type RoutableIdentifier struct {
Identifier string
Type SingularType
Type ObjectType
}
func NewRoutableIdentifier(objectIdentifier *auditV1.ObjectIdentifier) *RoutableIdentifier {
@ -216,7 +235,7 @@ func NewRoutableIdentifier(objectIdentifier *auditV1.ObjectIdentifier) *Routable
}
return &RoutableIdentifier{
Identifier: objectIdentifier.Identifier,
Type: SingularType(objectIdentifier.Type),
Type: ObjectType(objectIdentifier.Type),
}
}

View file

@ -50,11 +50,8 @@ var ErrObjectIdentifierVisibilityMismatch = errors.New("object reference visibil
// ErrTopicNameResolverNil states that the topic name resolve is nil
var ErrTopicNameResolverNil = errors.New("topic name resolver nil")
// ErrUnknownPluralType indicates that the given input is an unknown plural type
var ErrUnknownPluralType = errors.New("unknown plural type")
// ErrUnknownSingularType indicates that the given input is an unknown singular type
var ErrUnknownSingularType = errors.New("unknown singular type")
// ErrUnknownObjectType indicates that the given input is an unknown object type
var ErrUnknownObjectType = errors.New("unknown object type")
// ErrUnsupportedEventTypeDataAccess states that the event type "data-access" is currently not supported
var ErrUnsupportedEventTypeDataAccess = errors.New("unsupported event type data access")
@ -93,7 +90,7 @@ func validateAndSerializePartially(
// Check that provided identifier type is supported
if err := routableIdentifier.Type.IsSupportedType(); err != nil {
if errors.Is(err, ErrUnknownSingularType) {
if errors.Is(err, ErrUnknownObjectType) {
return nil, ErrUnsupportedRoutableType
}
return nil, err
@ -101,7 +98,7 @@ func validateAndSerializePartially(
// Check identifier consistency across event attributes
if strings.HasSuffix(event.LogName, string(EventTypeSystemEvent)) {
if !(routableIdentifier.Identifier == SystemIdentifier.Identifier && routableIdentifier.Type == SingularTypeSystem) {
if !(routableIdentifier.Identifier == SystemIdentifier.Identifier && routableIdentifier.Type == ObjectTypeSystem) {
return nil, ErrInvalidRoutableIdentifierForSystemEvent
}
// The resource name can either contain the system identifier or another resource identifier
@ -165,7 +162,7 @@ func send(
// Check that provided identifier type is supported
if err := routableIdentifier.Type.IsSupportedType(); err != nil {
if errors.Is(err, ErrUnknownSingularType) {
if errors.Is(err, ErrUnknownObjectType) {
return ErrUnsupportedRoutableType
}
return err
@ -202,7 +199,7 @@ func send(
}
func isSystemIdentifier(identifier *RoutableIdentifier) bool {
if identifier.Identifier == uuid.Nil.String() && identifier.Type == SingularTypeSystem {
if identifier.Identifier == uuid.Nil.String() && identifier.Type == ObjectTypeSystem {
return true
}
return false
@ -210,15 +207,15 @@ func isSystemIdentifier(identifier *RoutableIdentifier) bool {
func areIdentifiersIdentical(routableIdentifier *RoutableIdentifier, logName string) error {
dataType, identifier := getTypeAndIdentifierFromString(logName)
pluralType := AsPluralType(dataType)
singularType, err := pluralType.AsSingularType()
objectType := ObjectTypeFromPluralString(dataType)
err := objectType.IsSupportedType()
if err != nil {
return err
}
return areTypeAndIdentifierIdentical(routableIdentifier, singularType, identifier)
return areTypeAndIdentifierIdentical(routableIdentifier, objectType, identifier)
}
func areTypeAndIdentifierIdentical(routableIdentifier *RoutableIdentifier, dataType SingularType, identifier string) error {
func areTypeAndIdentifierIdentical(routableIdentifier *RoutableIdentifier, dataType ObjectType, identifier string) error {
if routableIdentifier.Identifier != identifier {
return ErrAttributeIdentifierInvalid
}

View file

@ -169,7 +169,7 @@ func Test_ValidateAndSerializePartially_CheckVisibility_SystemEvent(t *testing.T
t.Run("Visibility public - object identifier set", func(t *testing.T) {
_, err := validateAndSerializePartially(
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, NewRoutableIdentifier(
&auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(SingularTypeOrganization)}))
&auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(ObjectTypeOrganization)}))
assert.ErrorIs(t, err, ErrInvalidRoutableIdentifierForSystemEvent)
})
@ -186,7 +186,7 @@ func Test_ValidateAndSerializePartially_CheckVisibility_SystemEvent(t *testing.T
t.Run("Visibility private - object identifier set", func(t *testing.T) {
_, err := validateAndSerializePartially(
&validator, event, auditV1.Visibility_VISIBILITY_PRIVATE, NewRoutableIdentifier(
&auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(SingularTypeOrganization)}))
&auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(ObjectTypeOrganization)}))
assert.ErrorIs(t, err, ErrInvalidRoutableIdentifierForSystemEvent)
})

View file

@ -122,25 +122,25 @@ func convertAndSerializeIntoLegacyFormat(
// Context and event type
var messageContext *LegacyAuditEventContext
switch routableEvent.ObjectIdentifier.Type {
case string(SingularTypeProject):
case string(ObjectTypeProject):
messageContext = &LegacyAuditEventContext{
OrganizationId: nil,
FolderId: nil,
ProjectId: &routableEvent.ObjectIdentifier.Identifier,
}
case string(SingularTypeFolder):
case string(ObjectTypeFolder):
messageContext = &LegacyAuditEventContext{
OrganizationId: nil,
FolderId: &routableEvent.ObjectIdentifier.Identifier,
ProjectId: nil,
}
case string(SingularTypeOrganization):
case string(ObjectTypeOrganization):
messageContext = &LegacyAuditEventContext{
OrganizationId: &routableEvent.ObjectIdentifier.Identifier,
FolderId: nil,
ProjectId: nil,
}
case string(SingularTypeSystem):
case string(ObjectTypeSystem):
messageContext = nil
default:
return nil, ErrUnsupportedObjectIdentifierType

View file

@ -30,13 +30,13 @@ func (r *routableTopicNameResolver) Resolve(routableIdentifier *RoutableIdentifi
}
switch routableIdentifier.Type {
case SingularTypeOrganization:
case ObjectTypeOrganization:
return fmt.Sprintf("topic://%s/%s", r.organizationTopicPrefix, routableIdentifier.Identifier), nil
case SingularTypeProject:
case ObjectTypeProject:
return fmt.Sprintf("topic://%s/%s", r.projectTopicPrefix, routableIdentifier.Identifier), nil
case SingularTypeFolder:
case ObjectTypeFolder:
return fmt.Sprintf("topic://%s/%s", r.folderTopicPrefix, routableIdentifier.Identifier), nil
case SingularTypeSystem:
case ObjectTypeSystem:
return r.systemTopicName, nil
default:
return "", ErrUnsupportedObjectIdentifierType

View file

@ -1,80 +0,0 @@
package api
const (
SingularTypeSystem SingularType = "system"
SingularTypeOrganization SingularType = "organization"
SingularTypeFolder SingularType = "folder"
SingularTypeProject SingularType = "project"
PluralTypeSystem PluralType = "system"
PluralTypeOrganization PluralType = "organizations"
PluralTypeFolder PluralType = "folders"
PluralTypeProject PluralType = "projects"
)
func (t SingularType) AsPluralType() (PluralType, error) {
switch t {
case SingularTypeSystem:
return PluralTypeSystem, nil
case SingularTypeOrganization:
return PluralTypeOrganization, nil
case SingularTypeFolder:
return PluralTypeFolder, nil
case SingularTypeProject:
return PluralTypeProject, nil
}
return "unknown", ErrUnknownSingularType
}
func AsPluralType(value string) PluralType {
return PluralType(value)
}
func (t PluralType) IsSupportedType() error {
switch t {
case PluralTypeOrganization:
fallthrough
case PluralTypeFolder:
fallthrough
case PluralTypeProject:
fallthrough
case PluralTypeSystem:
return nil
default:
return ErrUnknownSingularType
}
}
func (t PluralType) AsSingularType() (SingularType, error) {
switch t {
case PluralTypeOrganization:
return SingularTypeOrganization, nil
case PluralTypeFolder:
return SingularTypeFolder, nil
case PluralTypeProject:
return SingularTypeProject, nil
case PluralTypeSystem:
return SingularTypeSystem, nil
default:
return "unknown", ErrUnknownPluralType
}
}
func AsSingularType(value string) SingularType {
return SingularType(value)
}
func (t SingularType) IsSupportedType() error {
switch t {
case SingularTypeOrganization:
fallthrough
case SingularTypeFolder:
fallthrough
case SingularTypeProject:
fallthrough
case SingularTypeSystem:
return nil
default:
return ErrUnknownSingularType
}
}

View file

@ -4,7 +4,6 @@ import (
"context"
"dev.azure.com/schwarzit/schwarzit.stackit-core-platform/audit-go.git/audit/utils"
auditV1 "dev.azure.com/schwarzit/schwarzit.stackit-core-platform/audit-go.git/gen/go/audit/v1"
"dev.azure.com/schwarzit/schwarzit.stackit-core-platform/audit-go.git/log"
"errors"
"fmt"
"github.com/google/uuid"
@ -30,7 +29,7 @@ type AuditParameters struct {
ObjectId string
// Type of the object, the audit event refers to
ObjectType SingularType
ObjectType ObjectType
ResponseBody any
@ -40,29 +39,25 @@ type AuditParameters struct {
func getObjectIdAndTypeFromAuditParams(
auditParams *AuditParameters,
) (string, *PluralType, error) {
) (string, *ObjectType, error) {
objectId := auditParams.ObjectId
if objectId == "" {
return "", nil, errors.New("object id missing")
}
var objectType *SingularType
var objectType *ObjectType
if auditParams.ObjectType != "" {
objectType = &auditParams.ObjectType
}
if objectType == nil {
return "", nil, errors.New("singular type missing")
return "", nil, errors.New("object 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)
if err := objectType.IsSupportedType(); err != nil {
return "", nil, err
}
return objectId, &plural, nil
return objectId, objectType, nil
}
// AuditLogEntryBuilder collects audit params to construct auditV1.AuditLogEntry
@ -207,7 +202,7 @@ func (builder *AuditLogEntryBuilder) WithRequiredObjectId(objectId string) *Audi
// WithRequiredObjectType adds the object type.
// May be prefilled by audit middleware (if the type can be extracted from the url path).
func (builder *AuditLogEntryBuilder) WithRequiredObjectType(objectType SingularType) *AuditLogEntryBuilder {
func (builder *AuditLogEntryBuilder) WithRequiredObjectType(objectType ObjectType) *AuditLogEntryBuilder {
builder.auditParams.ObjectType = objectType
return builder
}
@ -324,7 +319,7 @@ func (builder *AuditLogEntryBuilder) Build(ctx context.Context, sequenceNumber S
auditTime := time.Now()
builder.auditMetadata.AuditTime = &auditTime
objectId, pluralType, err := getObjectIdAndTypeFromAuditParams(&builder.auditParams)
objectId, objectType, err := getObjectIdAndTypeFromAuditParams(&builder.auditParams)
if err != nil {
return nil, err
}
@ -339,19 +334,19 @@ func (builder *AuditLogEntryBuilder) Build(ctx context.Context, sequenceNumber S
builder.auditResponse.ResponseBodyBytes = responseBytes
}
resourceName := fmt.Sprintf("%s/%s", *pluralType, objectId)
resourceName := fmt.Sprintf("%s/%s", objectType.Plural(), objectId)
var logIdentifier string
var logType PluralType
var logType ObjectType
if builder.auditParams.EventType == EventTypeSystemEvent {
logIdentifier = SystemIdentifier.Identifier
logType = PluralTypeSystem
logType = ObjectTypeSystem
} else {
logIdentifier = objectId
logType = *pluralType
logType = *objectType
}
builder.auditMetadata.AuditInsertId = NewInsertId(time.Now().UTC(), builder.location, builder.workerId, uint64(sequenceNumber))
builder.auditMetadata.AuditLogName = fmt.Sprintf("%s/%s/logs/%s", logType, logIdentifier, builder.auditParams.EventType)
builder.auditMetadata.AuditLogName = fmt.Sprintf("%s/%s/logs/%s", logType.Plural(), logIdentifier, builder.auditParams.EventType)
builder.auditMetadata.AuditResourceName = resourceName
var details *map[string]interface{} = nil
@ -488,7 +483,7 @@ func (builder *AuditEventBuilder) WithRequiredObjectId(objectId string) *AuditEv
// WithRequiredObjectType adds the object type.
// May be prefilled by audit middleware (if the type can be extracted from the url path).
func (builder *AuditEventBuilder) WithRequiredObjectType(objectType SingularType) *AuditEventBuilder {
func (builder *AuditEventBuilder) WithRequiredObjectType(objectType ObjectType) *AuditEventBuilder {
builder.auditLogEntryBuilder.WithRequiredObjectType(objectType)
return builder
}
@ -623,13 +618,13 @@ func (builder *AuditEventBuilder) Build(ctx context.Context, sequenceNumber Sequ
objectType := builder.auditLogEntryBuilder.auditParams.ObjectType
var routingIdentifier *RoutableIdentifier
if builder.auditLogEntryBuilder.auditParams.EventType == EventTypeSystemEvent {
routingIdentifier = NewAuditRoutingIdentifier(uuid.Nil.String(), SingularTypeSystem)
routingIdentifier = NewAuditRoutingIdentifier(uuid.Nil.String(), ObjectTypeSystem)
if objectId == "" {
objectId = uuid.Nil.String()
builder.WithRequiredObjectId(objectId)
}
if objectType == "" {
objectType = SingularTypeSystem
objectType = ObjectTypeSystem
builder.WithRequiredObjectType(objectType)
}
} else {

View file

@ -20,47 +20,47 @@ func Test_getObjectIdAndTypeFromAuditParams(t *testing.T) {
t.Run(
"object id empty", func(t *testing.T) {
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(&AuditParameters{})
objectId, objectType, err := getObjectIdAndTypeFromAuditParams(&AuditParameters{})
assert.EqualError(t, err, "object id missing")
assert.Equal(t, "", objectId)
assert.Nil(t, objectTypePlural)
assert.Nil(t, objectType)
},
)
t.Run(
"object type empty", func(t *testing.T) {
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(&AuditParameters{ObjectId: "value"})
assert.EqualError(t, err, "singular type missing")
objectId, objectType, err := getObjectIdAndTypeFromAuditParams(&AuditParameters{ObjectId: "value"})
assert.EqualError(t, err, "object type missing")
assert.Equal(t, "", objectId)
assert.Nil(t, objectTypePlural)
assert.Nil(t, objectType)
},
)
t.Run(
"object id and invalid type set", func(t *testing.T) {
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(
objectId, objectType, err := getObjectIdAndTypeFromAuditParams(
&AuditParameters{
ObjectId: "value",
ObjectType: AsSingularType("invalid"),
ObjectType: ObjectTypeFromPluralString("invalid"),
},
)
assert.EqualError(t, err, "unknown singular type")
assert.EqualError(t, err, "unknown object type")
assert.Equal(t, "", objectId)
assert.Nil(t, objectTypePlural)
assert.Nil(t, objectType)
},
)
t.Run(
"object id and type set", func(t *testing.T) {
objectId, objectTypePlural, err := getObjectIdAndTypeFromAuditParams(
objectId, objectType, err := getObjectIdAndTypeFromAuditParams(
&AuditParameters{
ObjectId: "value",
ObjectType: SingularTypeProject,
ObjectType: ObjectTypeProject,
},
)
assert.NoError(t, err)
assert.Equal(t, "value", objectId)
assert.Equal(t, PluralTypeProject, *objectTypePlural)
assert.Equal(t, ObjectTypeProject, *objectType)
},
)
}
@ -77,7 +77,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
t.Run("details missing", func(t *testing.T) {
logEntry, err := NewAuditLogEntryBuilder().WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
Build(context.Background(), SequenceNumber(1))
assert.NoError(t, err)
@ -94,7 +94,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
builder := NewAuditLogEntryBuilder().
WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.operation").
WithRequiredApiRequest(ApiRequest{
Body: nil,
@ -198,7 +198,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
builder := NewAuditLogEntryBuilder().
WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.operation").
WithRequiredApiRequest(ApiRequest{
Body: nil,
@ -315,7 +315,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
builder := NewAuditLogEntryBuilder().
WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.operation").
WithRequiredServiceName("demo-service").
WithRequiredWorkerId("worker-id").
@ -406,7 +406,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
builder := NewAuditLogEntryBuilder().
WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.operation").
WithRequiredApiRequest(ApiRequest{
Body: nil,
@ -472,7 +472,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
}).
WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.operation").
WithRequiredRequestClientIp("127.0.0.1").
WithRequiredServiceName("demo-service").
@ -501,7 +501,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
}).
WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.operation").
WithRequiredRequestClientIp("127.0.0.1").
WithRequiredServiceName("demo-service").
@ -538,7 +538,7 @@ func Test_AuditEventBuilder(t *testing.T) {
cloudEvent, routingIdentifier, op, err := NewAuditEventBuilder(api, sequenceNumberGenerator, tracer, "demo-service", "worker-id", "eu01").
WithRequiredObjectId("objectId").
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
Build(context.Background(), SequenceNumber(1))
assert.Error(t, err)
@ -557,7 +557,7 @@ func Test_AuditEventBuilder(t *testing.T) {
operation := "stackit.demo-service.v1.operation"
builder := NewAuditEventBuilder(api, sequenceNumberGenerator, tracer, "demo-service", "worker-id", "eu01").
WithRequiredObjectId(objectId).
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation(operation).
WithRequiredApiRequest(ApiRequest{
Body: nil,
@ -573,7 +573,7 @@ func Test_AuditEventBuilder(t *testing.T) {
}).
WithRequiredRequestClientIp("127.0.0.1")
routableIdentifier := RoutableIdentifier{Identifier: objectId, Type: SingularTypeProject}
routableIdentifier := RoutableIdentifier{Identifier: objectId, Type: ObjectTypeProject}
cloudEvent, routingIdentifier, op, err := builder.Build(context.Background(), SequenceNumber(1))
assert.NoError(t, err)
@ -693,7 +693,7 @@ func Test_AuditEventBuilder(t *testing.T) {
assert.NoError(t, err)
builder := NewAuditEventBuilder(api, sequenceNumberGenerator, tracer, "demo-service", "worker-id", "eu01").
WithRequiredObjectId(objectId).
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation(operation).
WithRequiredApiRequest(ApiRequest{
Body: nil,
@ -724,7 +724,7 @@ func Test_AuditEventBuilder(t *testing.T) {
WithStatusCode(400).
WithVisibility(auditV1.Visibility_VISIBILITY_PRIVATE)
routableIdentifier := RoutableIdentifier{Identifier: objectId, Type: SingularTypeProject}
routableIdentifier := RoutableIdentifier{Identifier: objectId, Type: ObjectTypeProject}
cloudEvent, routingIdentifier, op, err := builder.Build(context.Background(), SequenceNumber(1))
assert.NoError(t, err)
@ -843,7 +843,7 @@ func Test_AuditEventBuilder(t *testing.T) {
operation := "stackit.demo-service.v1.operation"
builder := NewAuditEventBuilder(api, sequenceNumberGenerator, tracer, "demo-service", "worker-id", "eu01").
WithRequiredObjectId(objectId).
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation(operation).
AsSystemEvent()
@ -1078,7 +1078,7 @@ func Test_AuditEventBuilder(t *testing.T) {
responseBody := map[string]interface{}{"key": "response"}
builder := NewAuditEventBuilder(api, sequenceNumberGenerator, tracer, "demo-service", "worker-id", "eu01").
WithRequiredObjectId(objectId).
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation(operation).
WithRequiredApiRequest(ApiRequest{
Body: nil,
@ -1109,7 +1109,7 @@ func Test_AuditEventBuilder(t *testing.T) {
WithStatusCode(400).
WithVisibility(auditV1.Visibility_VISIBILITY_PRIVATE)
routableIdentifier := RoutableIdentifier{Identifier: objectId, Type: SingularTypeProject}
routableIdentifier := RoutableIdentifier{Identifier: objectId, Type: ObjectTypeProject}
cloudEvent, routingIdentifier, op, err := builder.Build(context.Background(), SequenceNumber(1))
assert.NoError(t, err)

View file

@ -34,7 +34,7 @@ func Test_LogEvent(t *testing.T) {
},
}).
WithRequiredObjectId(uuid.NewString()).
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.project.update").
WithRequiredRequestClientIp("0.0.0.0").
Build(context.Background(), eventBuilder.NextSequenceNumber())
@ -60,7 +60,7 @@ func Test_LogEvent(t *testing.T) {
}).
WithRequiredLocation("eu01").
WithRequiredObjectId(object_id).
WithRequiredObjectType(SingularTypeProject).
WithRequiredObjectType(ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.project.update").
WithRequiredRequestClientIp("0.0.0.0").
WithRequiredServiceName("demo-service").
@ -74,7 +74,7 @@ func Test_LogEvent(t *testing.T) {
routableIdentifier := RoutableIdentifier{
Identifier: object_id,
Type: SingularTypeProject,
Type: ObjectTypeProject,
}
routableEvent, err := validateAndSerializePartially(&protoValidator, entry, auditV1.Visibility_VISIBILITY_PUBLIC, &routableIdentifier)

View file

@ -200,7 +200,7 @@ type AuditMetadata struct {
//
// Format: <pluralType>/<identifier>/logs/<eventType>
// Where:
// Plural-Types: One from the list of supported data types
// Plural-Types: One from the list of supported ObjectType as plural
// Event-Types: admin-activity, system-event, policy-denied, data-access
//
// Examples:
@ -251,7 +251,7 @@ type AuditMetadata struct {
//
// Format: <pluralType>/<id>[/locations/<region-zone>][/<details>]
// Where:
// Plural-Type: One from the list of supported data types
// Plural-Type: One from the list of supported ObjectType as plural
// Id: The identifier of the object
// Region-Zone: Optional region and zone id. If both, separated with a - (dash). Alternatively _ (underscore).
// Details: Optional "<key>/<id>" pairs
@ -636,11 +636,11 @@ func FilterAndMergeHeaders(headers map[string][]string) map[string]string {
}
// NewAuditRoutingIdentifier instantiates a new auditApi.RoutableIdentifier for
// the given object ID and singular type.
func NewAuditRoutingIdentifier(objectId string, singularType SingularType) *RoutableIdentifier {
// the given object ID and object type.
func NewAuditRoutingIdentifier(objectId string, objectType ObjectType) *RoutableIdentifier {
return &RoutableIdentifier{
Identifier: objectId,
Type: singularType,
Type: objectType,
}
}
@ -911,22 +911,22 @@ func OperationNameFromGrpcMethod(path string) string {
func GetObjectIdAndTypeFromUrlPath(path string) (
string,
*SingularType,
*ObjectType,
error,
) {
// Extract object id and type from request url
objectTypeIdMatches := objectTypeIdPattern.FindStringSubmatch(path)
if len(objectTypeIdMatches) > 0 {
objectTypePlural := AsPluralType(objectTypeIdMatches[1])
objectTypeSingular, err := objectTypePlural.AsSingularType()
objectType := ObjectTypeFromPluralString(objectTypeIdMatches[1])
err := objectType.IsSupportedType()
if err != nil {
return "", nil, err
}
objectType := &objectTypeSingular
objectId := objectTypeIdMatches[2]
return objectId, objectType, nil
return objectId, &objectType, nil
}
return "", nil, nil

View file

@ -872,11 +872,11 @@ func Test_NewInsertId(t *testing.T) {
func Test_NewNewAuditRoutingIdentifier(t *testing.T) {
objectId := uuid.NewString()
singularType := SingularTypeProject
objectType := ObjectTypeProject
routingIdentifier := NewAuditRoutingIdentifier(objectId, singularType)
routingIdentifier := NewAuditRoutingIdentifier(objectId, objectType)
assert.Equal(t, objectId, routingIdentifier.Identifier)
assert.Equal(t, singularType, routingIdentifier.Type)
assert.Equal(t, objectType, routingIdentifier.Type)
}
func Test_OperationNameFromUrlPath(t *testing.T) {
@ -978,24 +978,24 @@ func Test_OperationNameFromGrpcMethod(t *testing.T) {
func Test_GetObjectIdAndTypeFromUrlPath(t *testing.T) {
t.Run("object id and type not in url", func(t *testing.T) {
objectId, singularType, err := GetObjectIdAndTypeFromUrlPath("/v2/projects/audit")
objectId, objectType, err := GetObjectIdAndTypeFromUrlPath("/v2/projects/audit")
assert.NoError(t, err)
assert.Equal(t, "", objectId)
assert.Nil(t, singularType)
assert.Nil(t, objectType)
})
t.Run("object id and type in url", func(t *testing.T) {
objectId, singularType, err := GetObjectIdAndTypeFromUrlPath("/v2/projects/f17d4064-9b65-4334-b6a7-8fed96340124")
objectId, objectType, err := GetObjectIdAndTypeFromUrlPath("/v2/projects/f17d4064-9b65-4334-b6a7-8fed96340124")
assert.NoError(t, err)
assert.Equal(t, "f17d4064-9b65-4334-b6a7-8fed96340124", objectId)
assert.Equal(t, SingularTypeProject, *singularType)
assert.Equal(t, ObjectTypeProject, *objectType)
})
t.Run("multiple object ids and types in url", func(t *testing.T) {
objectId, singularType, err := GetObjectIdAndTypeFromUrlPath("/v2/organization/8ee58bec-d496-4bb9-af8d-72fda4d78b6b/projects/f17d4064-9b65-4334-b6a7-8fed96340124")
objectId, objectType, err := GetObjectIdAndTypeFromUrlPath("/v2/organization/8ee58bec-d496-4bb9-af8d-72fda4d78b6b/projects/f17d4064-9b65-4334-b6a7-8fed96340124")
assert.NoError(t, err)
assert.Equal(t, "f17d4064-9b65-4334-b6a7-8fed96340124", objectId)
assert.Equal(t, SingularTypeProject, *singularType)
assert.Equal(t, ObjectTypeProject, *objectType)
})
}
@ -1051,7 +1051,7 @@ func Test_ResponseBodyToBytes(t *testing.T) {
t.Run(
"Protobuf message", func(t *testing.T) {
protobufMessage := auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(SingularTypeProject)}
protobufMessage := auditV1.ObjectIdentifier{Identifier: uuid.NewString(), Type: string(ObjectTypeProject)}
bytes, err := ResponseBodyToBytes(&protobufMessage)
assert.Nil(t, err)

View file

@ -18,7 +18,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
Visibility: auditV1.Visibility_VISIBILITY_PUBLIC,
ObjectIdentifier: &auditV1.ObjectIdentifier{
Identifier: "14f7aa86-77ba-4d77-a091-a2cf3395a221",
Type: string(SingularTypeProject),
Type: string(ObjectTypeProject),
},
Data: &auditV1.RoutableAuditEvent_UnencryptedData{UnencryptedData: &auditV1.UnencryptedData{
Data: []byte("data"),

View file

@ -33,11 +33,11 @@ func newOrganizationAuditEvent(
labels := make(map[string]string)
labels["label1"] = "value1"
auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", PluralTypeOrganization, identifier, EventTypeAdminActivity),
LogName: fmt.Sprintf("%s/%s/logs/%s", ObjectTypeOrganization.Plural(), identifier, EventTypeAdminActivity),
ProtoPayload: &auditV1.AuditLog{
ServiceName: "resource-manager",
OperationName: "stackit.resourcemanager.v2.organization.created",
ResourceName: fmt.Sprintf("%s/%s", PluralTypeOrganization, identifier),
ResourceName: fmt.Sprintf("%s/%s", ObjectTypeOrganization.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: uuid.NewString(),
PrincipalEmail: "user@example.com",
@ -45,7 +45,7 @@ func newOrganizationAuditEvent(
ServiceAccountDelegationInfo: nil,
},
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
Resource: fmt.Sprintf("%s/%s", PluralTypeOrganization, identifier),
Resource: fmt.Sprintf("%s/%s", ObjectTypeOrganization.Plural(), identifier),
Permission: &permission,
Granted: &permissionGranted,
}},
@ -95,7 +95,7 @@ func newOrganizationAuditEvent(
objectIdentifier := &auditV1.ObjectIdentifier{
Identifier: identifier.String(),
Type: string(SingularTypeOrganization),
Type: string(ObjectTypeOrganization),
}
if customization != nil {
@ -125,11 +125,11 @@ func newFolderAuditEvent(
labels := make(map[string]string)
labels["label1"] = "value1"
auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", PluralTypeFolder, identifier, EventTypeAdminActivity),
LogName: fmt.Sprintf("%s/%s/logs/%s", ObjectTypeFolder.Plural(), identifier, EventTypeAdminActivity),
ProtoPayload: &auditV1.AuditLog{
ServiceName: "resource-manager",
OperationName: "stackit.resourcemanager.v2.folder.created",
ResourceName: fmt.Sprintf("%s/%s", PluralTypeFolder, identifier),
ResourceName: fmt.Sprintf("%s/%s", ObjectTypeFolder.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: uuid.NewString(),
PrincipalEmail: "user@example.com",
@ -137,7 +137,7 @@ func newFolderAuditEvent(
ServiceAccountDelegationInfo: nil,
},
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
Resource: fmt.Sprintf("%s/%s", PluralTypeFolder, identifier),
Resource: fmt.Sprintf("%s/%s", ObjectTypeFolder.Plural(), identifier),
Permission: &permission,
Granted: &permissionGranted,
}},
@ -187,7 +187,7 @@ func newFolderAuditEvent(
objectIdentifier := &auditV1.ObjectIdentifier{
Identifier: identifier.String(),
Type: string(SingularTypeFolder),
Type: string(ObjectTypeFolder),
}
if customization != nil {
@ -217,11 +217,11 @@ func newProjectAuditEvent(
labels := make(map[string]string)
labels["label1"] = "value1"
auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", PluralTypeProject, identifier, EventTypeAdminActivity),
LogName: fmt.Sprintf("%s/%s/logs/%s", ObjectTypeProject.Plural(), identifier, EventTypeAdminActivity),
ProtoPayload: &auditV1.AuditLog{
ServiceName: "resource-manager",
OperationName: "stackit.resourcemanager.v2.project.created",
ResourceName: fmt.Sprintf("%s/%s", PluralTypeProject, identifier),
ResourceName: fmt.Sprintf("%s/%s", ObjectTypeProject.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: uuid.NewString(),
PrincipalEmail: "user@example.com",
@ -229,7 +229,7 @@ func newProjectAuditEvent(
ServiceAccountDelegationInfo: nil,
},
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
Resource: fmt.Sprintf("%s/%s", PluralTypeProject, identifier),
Resource: fmt.Sprintf("%s/%s", ObjectTypeProject.Plural(), identifier),
Permission: &permission,
Granted: &permissionGranted,
}},
@ -279,7 +279,7 @@ func newProjectAuditEvent(
objectIdentifier := &auditV1.ObjectIdentifier{
Identifier: identifier.String(),
Type: string(SingularTypeProject),
Type: string(ObjectTypeProject),
}
if customization != nil {
@ -308,7 +308,7 @@ func newProjectSystemAuditEvent(
ProtoPayload: &auditV1.AuditLog{
ServiceName: "resource-manager",
OperationName: "stackit.resourcemanager.v2.system.changed",
ResourceName: fmt.Sprintf("%s/%s", PluralTypeProject, identifier),
ResourceName: fmt.Sprintf("%s/%s", ObjectTypeProject.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: serviceAccountId,
PrincipalEmail: "service-account@sa.stackit.cloud",
@ -316,7 +316,7 @@ func newProjectSystemAuditEvent(
ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal},
},
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
Resource: fmt.Sprintf("%s/%s", PluralTypeProject, identifier),
Resource: fmt.Sprintf("%s/%s", ObjectTypeProject.Plural(), identifier),
Permission: nil,
Granted: nil,
}},
@ -386,11 +386,11 @@ func newSystemAuditEvent(
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", PluralTypeSystem, identifier, EventTypeSystemEvent),
LogName: fmt.Sprintf("%s/%s/logs/%s", ObjectTypeSystem.Plural(), identifier, EventTypeSystemEvent),
ProtoPayload: &auditV1.AuditLog{
ServiceName: "resource-manager",
OperationName: "stackit.resourcemanager.v2.system.changed",
ResourceName: fmt.Sprintf("%s/%s", PluralTypeSystem, identifier),
ResourceName: fmt.Sprintf("%s/%s", ObjectTypeSystem.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: serviceAccountId,
PrincipalEmail: "service-account@sa.stackit.cloud",
@ -398,7 +398,7 @@ func newSystemAuditEvent(
ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal},
},
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
Resource: fmt.Sprintf("%s/%s", PluralTypeSystem, identifier),
Resource: fmt.Sprintf("%s/%s", ObjectTypeSystem.Plural(), identifier),
Permission: nil,
Granted: nil,
}},

View file

@ -190,7 +190,7 @@ type AuditLogEntry struct {
// Format: <pluralType>/<identifier>/logs/<eventType>
// Where:
//
// Plural-Types: One from the list of supported data types
// Plural-Types: One from the list of supported ObjectType as plural
// Event-Types: admin-activity, system-event, policy-denied, data-access
//
// Examples:
@ -398,7 +398,7 @@ type AuditLog struct {
// Format: <pluralType>/<id>[/<details>]
// Where:
//
// Plural-Type: One from the list of supported data types
// Plural-Type: One from the list of supported ObjectType as plural
// Id: The identifier of the object
// Details: Optional "<key>/<id>" pairs
//
@ -657,7 +657,7 @@ type AuthorizationInfo struct {
// Format: <pluralType>/<id>[/<details>]
// Where:
//
// Plural-Type: One from the list of supported data types
// Plural-Type: One from the list of supported ObjectType as plural
// Id: The identifier of the object
// Details: Optional "<key>/<id>" pairs
//

View file

@ -84,7 +84,7 @@ type ObjectIdentifier struct {
//
// Required: true
Identifier string `protobuf:"bytes,1,opt,name=identifier,proto3" json:"identifier,omitempty"`
// Entity data type relevant for routing - one of the list of supported singular types.
// Entity data type relevant for routing - one of the list of supported object types.
//
// Required: true
Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"`

View file

@ -17,7 +17,7 @@ message AuditLogEntry {
//
// Format: <pluralType>/<identifier>/logs/<eventType>
// Where:
// Plural-Types: One from the list of supported data types
// Plural-Types: One from the list of supported ObjectType as plural
// Event-Types: admin-activity, system-event, policy-denied, data-access
//
// Examples:
@ -184,7 +184,7 @@ message AuditLog {
//
// Format: <pluralType>/<id>[/<details>]
// Where:
// Plural-Type: One from the list of supported data types
// Plural-Type: One from the list of supported ObjectType as plural
// Id: The identifier of the object
// Details: Optional "<key>/<id>" pairs
//
@ -292,7 +292,7 @@ message AuthorizationInfo {
//
// Format: <pluralType>/<id>[/<details>]
// Where:
// Plural-Type: One from the list of supported data types
// Plural-Type: One from the list of supported ObjectType as plural
// Id: The identifier of the object
// Details: Optional "<key>/<id>" pairs
//

View file

@ -28,7 +28,7 @@ message ObjectIdentifier {
(buf.validate.field).string.uuid = true
];
// Entity data type relevant for routing - one of the list of supported singular types.
// Entity data type relevant for routing - one of the list of supported object types.
//
// Required: true
string type = 2 [