package api import ( "testing" "buf.build/go/protovalidate" "github.com/stretchr/testify/assert" auditV1 "dev.azure.com/schwarzit/schwarzit.stackit-public/audit-go.git/gen/go/audit/v1" pkgAuditCommon "dev.azure.com/schwarzit/schwarzit.stackit-public/audit-go.git/pkg/audit/common" ) func Test_RoutableAuditEvent(t *testing.T) { validator, err := protovalidate.New() assert.NoError(t, err) newEvent := func() auditV1.RoutableAuditEvent { return auditV1.RoutableAuditEvent{ OperationName: "stackit.resource-manager.v1.organizations.create", Visibility: auditV1.Visibility_VISIBILITY_PUBLIC, ObjectIdentifier: &auditV1.ObjectIdentifier{ Identifier: "14f7aa86-77ba-4d77-a091-a2cf3395a221", Type: string(pkgAuditCommon.ObjectTypeProject), }, Data: &auditV1.RoutableAuditEvent_UnencryptedData{UnencryptedData: &auditV1.UnencryptedData{ Data: []byte("data"), ProtobufType: "audit.v1.AuditLogEntry", }}} } t.Run("valid event", func(t *testing.T) { event := newEvent() err := validator.Validate(&event) assert.NoError(t, err) }) t.Run("empty operation name", func(t *testing.T) { event := newEvent() event.OperationName = "" err := validator.Validate(&event) assert.EqualError(t, err, "validation error: operation_name: value is required") }) t.Run("invalid operation name", func(t *testing.T) { event := newEvent() event.OperationName = "stackit.resource-manager.v1.INVALID.organizations.create" err := validator.Validate(&event) assert.EqualError(t, err, "validation error: operation_name: value does not match regex pattern `^stackit\\.[a-z0-9-]+\\.(?:v[0-9]+\\.)?(?:[a-z0-9-.]+\\.)?[a-z0-9-]+$`") }) t.Run("visibility invalid", func(t *testing.T) { event := newEvent() event.Visibility = -1 err := validator.Validate(&event) assert.EqualError(t, err, "validation error: visibility: value must be one of the defined enum values") }) t.Run("visibility unspecified", func(t *testing.T) { event := newEvent() event.Visibility = auditV1.Visibility_VISIBILITY_UNSPECIFIED err := validator.Validate(&event) assert.EqualError(t, err, "validation error: visibility: value is required") }) t.Run("object identifier nil", func(t *testing.T) { event := newEvent() event.ObjectIdentifier = nil err := validator.Validate(&event) assert.EqualError(t, err, "validation error: object_identifier: value is required") }) t.Run("object identifier id empty", func(t *testing.T) { event := newEvent() event.ObjectIdentifier.Identifier = "" err := validator.Validate(&event) assert.EqualError(t, err, "validation error: object_identifier.identifier: value is required") }) t.Run("object identifier id not uuid", func(t *testing.T) { event := newEvent() event.ObjectIdentifier.Identifier = "invalid" err := validator.Validate(&event) assert.EqualError(t, err, "validation error: object_identifier.identifier: value must be a valid UUID") }) t.Run("object identifier type empty", func(t *testing.T) { event := newEvent() event.ObjectIdentifier.Type = "" err := validator.Validate(&event) assert.EqualError(t, err, "validation error: object_identifier.type: value is required") }) t.Run("data nil", func(t *testing.T) { event := newEvent() event.Data = nil err := validator.Validate(&event) assert.EqualError(t, err, "validation error: data: exactly one field is required in oneof") }) t.Run("data empty", func(t *testing.T) { event := newEvent() event.Data = &auditV1.RoutableAuditEvent_UnencryptedData{UnencryptedData: &auditV1.UnencryptedData{ Data: []byte{}, ProtobufType: "audit.v1.AuditLogEntry", }} err := validator.Validate(&event) assert.EqualError(t, err, "validation error: unencrypted_data.data: value is required") }) t.Run("data protobuf type empty", func(t *testing.T) { event := newEvent() event.Data = &auditV1.RoutableAuditEvent_UnencryptedData{UnencryptedData: &auditV1.UnencryptedData{ Data: []byte("data"), ProtobufType: "", }} err := validator.Validate(&event) assert.EqualError(t, err, "validation error: unencrypted_data.protobuf_type: value is required") }) } func Test_AuthenticationInfo(t *testing.T) { validator, err := protovalidate.New() assert.NoError(t, err) email := "x@x.x" newEvent := func() auditV1.AuthenticationInfo { return auditV1.AuthenticationInfo{ PrincipalId: "1234567890", PrincipalEmail: &email, ServiceAccountName: nil, ServiceAccountDelegationInfo: nil, } } t.Run("valid event", func(t *testing.T) { event := newEvent() err := validator.Validate(&event) assert.NoError(t, err) }) t.Run("valid event without email", func(t *testing.T) { event := newEvent() event.PrincipalEmail = nil err := validator.Validate(&event) assert.NoError(t, err) }) t.Run("principal id contains only whitespace", func(t *testing.T) { event := newEvent() event.PrincipalId = " " err := validator.Validate(&event) assert.EqualError(t, err, "validation error: principal_id: value does not match regex pattern `.*\\S.*`") }) t.Run("principal email contains only whitespace", func(t *testing.T) { event := newEvent() whitespaceEmail := " " event.PrincipalEmail = &whitespaceEmail err := validator.Validate(&event) assert.EqualError(t, err, "validation error: principal_email: value must be a valid email address") }) t.Run("missing host in email", func(t *testing.T) { event := newEvent() invalidEmail := "@test.com" event.PrincipalEmail = &invalidEmail err := validator.Validate(&event) assert.EqualError(t, err, "validation error: principal_email: value must be a valid email address") }) }