diff --git a/README.md b/README.md index 83aec4f..34d8bc8 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/audit/api/api.go b/audit/api/api.go index 33550ac..dd9d4a3 100644 --- a/audit/api/api.go +++ b/audit/api/api.go @@ -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), } } diff --git a/audit/api/api_common.go b/audit/api/api_common.go index 95224b2..7753731 100644 --- a/audit/api/api_common.go +++ b/audit/api/api_common.go @@ -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 } diff --git a/audit/api/api_common_test.go b/audit/api/api_common_test.go index 30205e6..d71d5e4 100644 --- a/audit/api/api_common_test.go +++ b/audit/api/api_common_test.go @@ -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) }) diff --git a/audit/api/api_legacy_converter.go b/audit/api/api_legacy_converter.go index 43b086b..9938297 100644 --- a/audit/api/api_legacy_converter.go +++ b/audit/api/api_legacy_converter.go @@ -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 diff --git a/audit/api/api_routable.go b/audit/api/api_routable.go index eafe9de..4438f70 100644 --- a/audit/api/api_routable.go +++ b/audit/api/api_routable.go @@ -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 diff --git a/audit/api/api_routable_types.go b/audit/api/api_routable_types.go deleted file mode 100644 index 6b99ce3..0000000 --- a/audit/api/api_routable_types.go +++ /dev/null @@ -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 - } -} diff --git a/audit/api/builder.go b/audit/api/builder.go index 869a932..18cffad 100644 --- a/audit/api/builder.go +++ b/audit/api/builder.go @@ -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 { diff --git a/audit/api/builder_test.go b/audit/api/builder_test.go index 8cdba9b..7abd69f 100644 --- a/audit/api/builder_test.go +++ b/audit/api/builder_test.go @@ -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) diff --git a/audit/api/log_test.go b/audit/api/log_test.go index 502dd0e..8034678 100644 --- a/audit/api/log_test.go +++ b/audit/api/log_test.go @@ -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) diff --git a/audit/api/model.go b/audit/api/model.go index af40d7d..dd7f138 100644 --- a/audit/api/model.go +++ b/audit/api/model.go @@ -200,7 +200,7 @@ type AuditMetadata struct { // // Format: //logs/ // 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: /[/locations/][/
] // 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 "/" 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 diff --git a/audit/api/model_test.go b/audit/api/model_test.go index 2f00ba3..cf5f14f 100644 --- a/audit/api/model_test.go +++ b/audit/api/model_test.go @@ -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) diff --git a/audit/api/schema_validation_test.go b/audit/api/schema_validation_test.go index 05e92f2..4fdafde 100644 --- a/audit/api/schema_validation_test.go +++ b/audit/api/schema_validation_test.go @@ -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"), diff --git a/audit/api/test_data.go b/audit/api/test_data.go index 0ff5db0..67f4cd7 100644 --- a/audit/api/test_data.go +++ b/audit/api/test_data.go @@ -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, }}, diff --git a/gen/go/audit/v1/audit_event.pb.go b/gen/go/audit/v1/audit_event.pb.go index 149fea5..b98d031 100644 --- a/gen/go/audit/v1/audit_event.pb.go +++ b/gen/go/audit/v1/audit_event.pb.go @@ -190,7 +190,7 @@ type AuditLogEntry struct { // Format: //logs/ // 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: /[/
] // 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 "/" pairs // @@ -657,7 +657,7 @@ type AuthorizationInfo struct { // Format: /[/
] // 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 "/" pairs // diff --git a/gen/go/audit/v1/routable_event.pb.go b/gen/go/audit/v1/routable_event.pb.go index 1cc9be1..8ad7bda 100644 --- a/gen/go/audit/v1/routable_event.pb.go +++ b/gen/go/audit/v1/routable_event.pb.go @@ -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"` diff --git a/proto/audit/v1/audit_event.proto b/proto/audit/v1/audit_event.proto index 8676b27..0d395d4 100644 --- a/proto/audit/v1/audit_event.proto +++ b/proto/audit/v1/audit_event.proto @@ -17,7 +17,7 @@ message AuditLogEntry { // // Format: //logs/ // 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: /[/
] // 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 "/" pairs // @@ -292,7 +292,7 @@ message AuthorizationInfo { // // Format: /[/
] // 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 "/" pairs // diff --git a/proto/audit/v1/routable_event.proto b/proto/audit/v1/routable_event.proto index 6b12c66..81016ff 100644 --- a/proto/audit/v1/routable_event.proto +++ b/proto/audit/v1/routable_event.proto @@ -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 [