mirror of
https://dev.azure.com/schwarzit/schwarzit.stackit-public/_git/audit-go
synced 2026-02-08 00:57:24 +00:00
Update schema and fix tests
This commit is contained in:
parent
da9ef5f707
commit
ed68f3c6d9
17 changed files with 1796 additions and 1453 deletions
12
README.md
12
README.md
|
|
@ -185,9 +185,11 @@ In the future related code and configurations for both additional languages (Jav
|
|||
Python) will be extracted into separate repositories.
|
||||
|
||||
### Open Issues
|
||||
- Finalizing messaging schema
|
||||
- Extraction of python / java configurations and code
|
||||
- Check TODOs in the code
|
||||
- Finalizing messaging schema
|
||||
- Check if fields and constraints are correct and compatible with expected use cases
|
||||
- Check that routing api specific parameters are independent of AuditEventLog
|
||||
- Clarify if a mutex is needed? Should we provide a MutexMessagingApi?
|
||||
- Clarify if `client.go` file can be used for licence / legal reasons
|
||||
- Clean up repo (delete main.go, etc. files)
|
||||
- Finalizing API Design
|
||||
- Decision whether serialized payload should be replaced with []byte or base64 encoded string
|
||||
- Extraction of python / java configurations and code
|
||||
- Clean up repo (delete main.go, etc. files)
|
||||
|
|
|
|||
|
|
@ -119,6 +119,24 @@ type CloudEvent struct {
|
|||
|
||||
// The serialized payload
|
||||
data []byte
|
||||
|
||||
// Optional W3C conform trace parent:
|
||||
// https://www.w3.org/TR/trace-context/#traceparent-header
|
||||
//
|
||||
// Format: <version>-<trace-id>-<parent-id>-<trace-flags>
|
||||
//
|
||||
// Examples:
|
||||
// "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
||||
traceParent *string
|
||||
|
||||
// Optional W3C conform trace state header:
|
||||
// https://www.w3.org/TR/trace-context/#tracestate-header
|
||||
//
|
||||
// Format: <key1>=<value1>[,<keyN>=<valueN>]
|
||||
//
|
||||
// Examples:
|
||||
// "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE"
|
||||
traceState *string
|
||||
}
|
||||
|
||||
// RoutingIdentifierType is an enumeration of allowed identifier types.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import (
|
|||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const ContentTypeProtobuf = "application/x-protobuf"
|
||||
// ContentTypeCloudEventsProtobuf the cloudevents protobuf content-type sent in metadata of messages
|
||||
const ContentTypeCloudEventsProtobuf = "application/cloudevents+protobuf"
|
||||
|
||||
// ErrEventNil indicates that the event was nil
|
||||
var ErrEventNil = errors.New("event is nil")
|
||||
|
|
@ -109,7 +110,7 @@ func validateAndSerializePartially(
|
|||
}
|
||||
|
||||
routableEvent := auditV1.RoutableAuditEvent{
|
||||
EventName: event.LogName,
|
||||
EventName: event.ProtoPayload.MethodName,
|
||||
Visibility: visibility,
|
||||
Data: &auditV1.RoutableAuditEvent_UnencryptedData{UnencryptedData: &payload},
|
||||
}
|
||||
|
|
@ -155,6 +156,8 @@ func send(
|
|||
return err
|
||||
}
|
||||
|
||||
// Naming according to AMQP protocol binding spec
|
||||
// https://github.com/cloudevents/spec/blob/main/cloudevents/bindings/amqp-protocol-binding.md
|
||||
applicationAttributes := make(map[string]any)
|
||||
applicationAttributes["cloudEvents:specversion"] = cloudEvent.specVersion
|
||||
applicationAttributes["cloudEvents:source"] = cloudEvent.source
|
||||
|
|
@ -163,6 +166,12 @@ func send(
|
|||
applicationAttributes["cloudEvents:datacontenttype"] = cloudEvent.dataContentType
|
||||
applicationAttributes["cloudEvents:type"] = cloudEvent.dataType
|
||||
applicationAttributes["cloudEvents:subject"] = cloudEvent.subject
|
||||
if cloudEvent.traceParent != nil {
|
||||
applicationAttributes["cloudEvents:traceparent"] = cloudEvent.traceParent
|
||||
}
|
||||
if cloudEvent.traceState != nil {
|
||||
applicationAttributes["cloudEvents:tracestate"] = cloudEvent.traceState
|
||||
}
|
||||
|
||||
return (*messagingApi).Send(
|
||||
ctx,
|
||||
|
|
|
|||
|
|
@ -2,14 +2,10 @@ package api
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/bufbuild/protovalidate-go"
|
||||
"github.com/google/uuid"
|
||||
|
|
@ -69,104 +65,16 @@ func Test_ValidateAndSerializePartially_EventNil(t *testing.T) {
|
|||
assert.ErrorIs(t, err, ErrEventNil)
|
||||
}
|
||||
|
||||
func Test_ValidateAndSerializePartially_AuditEventSequenceNumber(t *testing.T) {
|
||||
validator := NewValidator(t)
|
||||
|
||||
t.Run("Sequence number too low", func(t *testing.T) {
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEvent(nil)
|
||||
event.SequenceNumber = wrapperspb.Int64(-2)
|
||||
|
||||
_, err := validateAndSerializePartially(
|
||||
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, routingIdentifier, objectIdentifier)
|
||||
|
||||
assert.EqualError(t, err, "validation error:\n - sequence_number: value must be greater than or equal to -1 [int64.gte]")
|
||||
})
|
||||
|
||||
t.Run("Sequence number is minimum", func(t *testing.T) {
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEvent(nil)
|
||||
event.SequenceNumber = wrapperspb.Int64(-1)
|
||||
|
||||
e, err := validateAndSerializePartially(
|
||||
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, routingIdentifier, objectIdentifier)
|
||||
|
||||
assert.NoError(t, err)
|
||||
validateSequenceNumber(t, e, -1)
|
||||
})
|
||||
|
||||
t.Run("Sequence number is default", func(t *testing.T) {
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEvent(nil)
|
||||
event.SequenceNumber = wrapperspb.Int64(0)
|
||||
|
||||
e, err := validateAndSerializePartially(
|
||||
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, routingIdentifier, objectIdentifier)
|
||||
|
||||
assert.NoError(t, err)
|
||||
validateSequenceNumber(t, e, 0)
|
||||
})
|
||||
|
||||
t.Run("Sequence number is greater than default", func(t *testing.T) {
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEvent(nil)
|
||||
event.SequenceNumber = wrapperspb.Int64(1)
|
||||
|
||||
e, err := validateAndSerializePartially(
|
||||
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, routingIdentifier, objectIdentifier)
|
||||
|
||||
assert.NoError(t, err)
|
||||
validateSequenceNumber(t, e, 1)
|
||||
})
|
||||
|
||||
t.Run("Sequence number not set", func(t *testing.T) {
|
||||
event := &auditV1.AuditEvent{
|
||||
EventSource: "resource-manager",
|
||||
Region: auditV1.Region_REGION_EU01,
|
||||
EventName: "ORGANIZATION_CREATED",
|
||||
EventTimeStamp: timestamppb.New(time.Now()),
|
||||
EventTrigger: auditV1.EventTrigger_EVENT_TRIGGER_EVENT,
|
||||
Initiator: &auditV1.Principal{
|
||||
Id: uuid.NewString(),
|
||||
},
|
||||
}
|
||||
|
||||
identifier := uuid.New()
|
||||
routingIdentifier := &RoutingIdentifier{
|
||||
Identifier: identifier,
|
||||
Type: RoutingIdentifierTypeOrganization,
|
||||
}
|
||||
|
||||
objectIdentifier := &auditV1.ObjectIdentifier{
|
||||
Identifier: identifier.String(),
|
||||
Type: auditV1.ObjectType_OBJECT_TYPE_ORGANIZATION,
|
||||
}
|
||||
event.ResourceContainerReference = &auditV1.AuditEvent_ObjectIdentifier{ObjectIdentifier: objectIdentifier}
|
||||
|
||||
_, err := validateAndSerializePartially(
|
||||
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, routingIdentifier, objectIdentifier)
|
||||
|
||||
assert.EqualError(t, err, "validation error:\n - sequence_number: value is required [required]")
|
||||
})
|
||||
|
||||
}
|
||||
func validateSequenceNumber(t *testing.T, event *auditV1.RoutableAuditEvent, expectedNumber int64) {
|
||||
switch data := event.GetData().(type) {
|
||||
case *auditV1.RoutableAuditEvent_UnencryptedData:
|
||||
var auditEvent auditV1.AuditEvent
|
||||
assert.NoError(t, proto.Unmarshal(data.UnencryptedData.Data, &auditEvent))
|
||||
assert.Equal(t, expectedNumber, auditEvent.SequenceNumber.Value)
|
||||
default:
|
||||
assert.Fail(t, "expected unencrypted data")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_ValidateAndSerializePartially_AuditEventValidationFailed(t *testing.T) {
|
||||
validator := NewValidator(t)
|
||||
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEvent(nil)
|
||||
event.EventName = ""
|
||||
event.LogName = ""
|
||||
|
||||
_, err := validateAndSerializePartially(
|
||||
&validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, routingIdentifier, objectIdentifier)
|
||||
|
||||
assert.EqualError(t, err, "validation error:\n - event_name: value is required [required]")
|
||||
assert.EqualError(t, err, "validation error:\n - log_name: value is required [required]")
|
||||
}
|
||||
|
||||
func Test_ValidateAndSerializePartially_RoutableEventValidationFailed(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import (
|
|||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var ErrUnsupportedSeverity = errors.New("unsupported severity level")
|
||||
|
||||
// LegacyTopicNameResolver implements TopicNameResolver.
|
||||
// A hard-coded topic name is used, routing identifiers are ignored.
|
||||
type LegacyTopicNameResolver struct {
|
||||
|
|
@ -50,7 +52,7 @@ func NewLegacyAuditApi(
|
|||
) (*AuditApi, error) {
|
||||
|
||||
if messagingApi == nil {
|
||||
return nil, errors.New("messaging api nil")
|
||||
return nil, ErrMessagingApiNil
|
||||
}
|
||||
|
||||
// Topic resolver
|
||||
|
|
@ -115,11 +117,14 @@ func (a *LegacyAuditApi) ValidateAndSerialize(
|
|||
// TODO what is the correct id?
|
||||
id: uuid.NewString(),
|
||||
time: event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(),
|
||||
dataContentType: "application/cloudevents+protobuf",
|
||||
dataContentType: ContentTypeCloudEventsProtobuf,
|
||||
dataType: fmt.Sprintf("%v", routableEvent.ProtoReflect().Descriptor().FullName()),
|
||||
// TODO check if this is correct
|
||||
subject: event.ProtoPayload.ResourceName,
|
||||
data: legacyBytes,
|
||||
// TODO set trace fields
|
||||
traceParent: nil,
|
||||
traceState: nil,
|
||||
}
|
||||
return &message, nil
|
||||
}
|
||||
|
|
@ -160,13 +165,14 @@ func (a *LegacyAuditApi) convertAndSerializeIntoLegacyFormat(
|
|||
case *auditV1.ServiceAccountDelegationInfo_IdpPrincipal_:
|
||||
principals = append(principals, LegacyAuditEventPrincipal{
|
||||
Id: principalValue.IdpPrincipal.PrincipalId,
|
||||
Email: principalValue.IdpPrincipal.PrincipalEmail,
|
||||
Email: &principalValue.IdpPrincipal.PrincipalEmail,
|
||||
})
|
||||
case *auditV1.ServiceAccountDelegationInfo_SystemPrincipal_:
|
||||
principals = append(principals, LegacyAuditEventPrincipal{
|
||||
Id: "system",
|
||||
})
|
||||
|
||||
default:
|
||||
return nil, errors.New("unsupported principal type")
|
||||
}
|
||||
}
|
||||
serviceAccountDelegationInfo = &LegacyAuditEventServiceAccountDelegationInfo{Principals: principals}
|
||||
|
|
@ -179,11 +185,18 @@ func (a *LegacyAuditApi) convertAndSerializeIntoLegacyFormat(
|
|||
}
|
||||
} else {
|
||||
var parameters map[string]interface{} = nil
|
||||
if event.ProtoPayload.RequestMetadata.RequestAttributes.Path != "" && event.ProtoPayload.RequestMetadata.RequestAttributes.Query != "" {
|
||||
parsedUrl, err := url.Parse(fmt.Sprintf("%s?%s", event.ProtoPayload.RequestMetadata.RequestAttributes.Path, event.ProtoPayload.RequestMetadata.RequestAttributes.Query))
|
||||
if event.ProtoPayload.RequestMetadata.RequestAttributes.Path != "" &&
|
||||
event.ProtoPayload.RequestMetadata.RequestAttributes.Query != nil &&
|
||||
*event.ProtoPayload.RequestMetadata.RequestAttributes.Query != "" {
|
||||
parameters = map[string]interface{}{}
|
||||
|
||||
parsedUrl, err := url.Parse(fmt.Sprintf("%s?%s",
|
||||
event.ProtoPayload.RequestMetadata.RequestAttributes.Path,
|
||||
*event.ProtoPayload.RequestMetadata.RequestAttributes.Query))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for k, v := range parsedUrl.Query() {
|
||||
parameters[k] = v
|
||||
}
|
||||
|
|
@ -258,13 +271,38 @@ func (a *LegacyAuditApi) convertAndSerializeIntoLegacyFormat(
|
|||
// Result
|
||||
var result = event.ProtoPayload.Response.AsMap()
|
||||
|
||||
// Severity
|
||||
var severity string
|
||||
switch event.Severity {
|
||||
case auditV1.LogSeverity_DEFAULT:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_DEBUG:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_INFO:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_NOTICE:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_WARNING:
|
||||
severity = "INFO"
|
||||
case auditV1.LogSeverity_ERROR:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_CRITICAL:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_ALERT:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_EMERGENCY:
|
||||
severity = "ERROR"
|
||||
default:
|
||||
return nil, ErrUnsupportedSeverity
|
||||
}
|
||||
|
||||
// Instantiate the legacy event - missing values are filled with defaults
|
||||
legacyAuditEvent := LegacyAuditEvent{
|
||||
Severity: "INFO",
|
||||
Severity: severity,
|
||||
Visibility: visibility,
|
||||
EventType: eventType,
|
||||
EventTimeStamp: event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(),
|
||||
EventName: event.LogName,
|
||||
EventName: event.ProtoPayload.MethodName,
|
||||
SourceIpAddress: sourceIpAddress,
|
||||
UserAgent: userAgent,
|
||||
Initiator: LegacyAuditEventPrincipal{
|
||||
|
|
@ -274,11 +312,12 @@ func (a *LegacyAuditApi) convertAndSerializeIntoLegacyFormat(
|
|||
ServiceAccountDelegationInfo: serviceAccountDelegationInfo,
|
||||
Request: request,
|
||||
Context: messageContext,
|
||||
ResourceId: &event.LogName,
|
||||
ResourceName: &event.ProtoPayload.ResourceName,
|
||||
CorrelationId: &event.CorrelationId,
|
||||
Result: &result,
|
||||
Details: &details,
|
||||
// TODO clarify
|
||||
ResourceId: &event.LogName,
|
||||
ResourceName: &event.ProtoPayload.ResourceName,
|
||||
CorrelationId: event.CorrelationId,
|
||||
Result: &result,
|
||||
Details: &details,
|
||||
}
|
||||
|
||||
bytes, err := json.Marshal(legacyAuditEvent)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
|
@ -320,14 +322,14 @@ func TestLegacyAuditApi(t *testing.T) {
|
|||
var auditEvent LegacyAuditEvent
|
||||
assert.NoError(t, json.Unmarshal(message.Data[0], &auditEvent))
|
||||
|
||||
assert.Equal(t, event.EventName, auditEvent.EventName)
|
||||
assert.Equal(t, event.EventTimeStamp.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.Initiator.Id, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, event.ProtoPayload.MethodName, auditEvent.EventName)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.ProtoPayload.AuthenticationInfo.PrincipalId, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, "SYSTEM_EVENT", auditEvent.EventType)
|
||||
assert.Equal(t, "INFO", auditEvent.Severity)
|
||||
assert.Equal(t, "none", auditEvent.Request.Endpoint)
|
||||
assert.Equal(t, "0.0.0.0", auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, "none", auditEvent.UserAgent)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Path, auditEvent.Request.Endpoint)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerIp, auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerSuppliedUserAgent, auditEvent.UserAgent)
|
||||
})
|
||||
|
||||
t.Run("Log event with details", func(t *testing.T) {
|
||||
|
|
@ -350,7 +352,7 @@ func TestLegacyAuditApi(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
// Instantiate test data
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEventWithDetails()
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEvent(nil)
|
||||
|
||||
// Log the event to solace
|
||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||
|
|
@ -369,7 +371,7 @@ func TestLegacyAuditApi(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func validateSentMessage(t *testing.T, topicName string, message *amqp.Message, event *auditV1.AuditEvent) {
|
||||
func validateSentMessage(t *testing.T, topicName string, message *amqp.Message, event *auditV1.AuditLogEntry) {
|
||||
// Check topic name
|
||||
assert.Equal(t, topicName, *message.Properties.To)
|
||||
|
||||
|
|
@ -377,43 +379,88 @@ func validateSentMessage(t *testing.T, topicName string, message *amqp.Message,
|
|||
var auditEvent LegacyAuditEvent
|
||||
assert.NoError(t, json.Unmarshal(message.Data[0], &auditEvent))
|
||||
|
||||
assert.Equal(t, event.EventName, auditEvent.EventName)
|
||||
assert.Equal(t, event.EventTimeStamp.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.Initiator.Id, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, "ADMIN_ACTIVITY", auditEvent.EventType)
|
||||
assert.Equal(t, "INFO", auditEvent.Severity)
|
||||
assert.Equal(t, "none", auditEvent.Request.Endpoint)
|
||||
assert.Equal(t, "0.0.0.0", auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, "none", auditEvent.UserAgent)
|
||||
}
|
||||
|
||||
func validateSentMessageWithDetails(t *testing.T, topicName string, message *amqp.Message, event *auditV1.AuditEvent) {
|
||||
// Check topic name
|
||||
assert.Equal(t, topicName, *message.Properties.To)
|
||||
|
||||
// Check deserialized message
|
||||
var auditEvent LegacyAuditEvent
|
||||
assert.NoError(t, json.Unmarshal(message.Data[0], &auditEvent))
|
||||
|
||||
assert.Equal(t, event.EventName, auditEvent.EventName)
|
||||
assert.Equal(t, event.EventTimeStamp.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.Initiator.Id, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, "ADMIN_ACTIVITY", auditEvent.EventType)
|
||||
assert.Equal(t, "INFO", auditEvent.Severity)
|
||||
assert.Equal(t, event.Request.Endpoint, auditEvent.Request.Endpoint)
|
||||
assert.Equal(t, event.Request.SourceIpAddress, auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, *event.Request.UserAgent, auditEvent.UserAgent)
|
||||
assert.Equal(t, event.Request.Body.AsMap(), *auditEvent.Request.Body)
|
||||
assert.Equal(t, event.Request.Parameters.AsMap(), *auditEvent.Request.Parameters)
|
||||
assert.Equal(t, event.Details.AsMap(), *auditEvent.Details)
|
||||
assert.Equal(t, event.Result.AsMap(), *auditEvent.Result)
|
||||
for _, header := range event.Request.Headers {
|
||||
assert.Equal(t, header.Value, (*auditEvent.Request.Headers)[header.Key])
|
||||
var severity string
|
||||
switch event.Severity {
|
||||
case auditV1.LogSeverity_DEFAULT:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_DEBUG:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_INFO:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_NOTICE:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_WARNING:
|
||||
severity = "INFO"
|
||||
case auditV1.LogSeverity_ERROR:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_CRITICAL:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_ALERT:
|
||||
fallthrough
|
||||
case auditV1.LogSeverity_EMERGENCY:
|
||||
severity = "ERROR"
|
||||
default:
|
||||
assert.Fail(t, "unknown log severity")
|
||||
}
|
||||
|
||||
for idx := range event.Principals {
|
||||
assert.Equal(t, event.Principals[idx].Id, auditEvent.ServiceAccountDelegationInfo.Principals[idx].Id)
|
||||
assert.Equal(t, event.Principals[idx].Email, auditEvent.ServiceAccountDelegationInfo.Principals[idx].Email)
|
||||
assert.Equal(t, event.ProtoPayload.MethodName, auditEvent.EventName)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.ProtoPayload.AuthenticationInfo.PrincipalId, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, "ADMIN_ACTIVITY", auditEvent.EventType)
|
||||
assert.Equal(t, severity, auditEvent.Severity)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Path, auditEvent.Request.Endpoint)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerIp, auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerSuppliedUserAgent, auditEvent.UserAgent)
|
||||
}
|
||||
|
||||
func validateSentMessageWithDetails(t *testing.T, topicName string, message *amqp.Message, event *auditV1.AuditLogEntry) {
|
||||
// Check topic name
|
||||
assert.Equal(t, topicName, *message.Properties.To)
|
||||
|
||||
// Check deserialized message
|
||||
var auditEvent LegacyAuditEvent
|
||||
assert.NoError(t, json.Unmarshal(message.Data[0], &auditEvent))
|
||||
|
||||
assert.Equal(t, event.ProtoPayload.MethodName, auditEvent.EventName)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(), auditEvent.EventTimeStamp)
|
||||
assert.Equal(t, event.ProtoPayload.AuthenticationInfo.PrincipalId, auditEvent.Initiator.Id)
|
||||
assert.Equal(t, "ADMIN_ACTIVITY", auditEvent.EventType)
|
||||
assert.Equal(t, "INFO", auditEvent.Severity)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Path, auditEvent.Request.Endpoint)
|
||||
var parameters map[string]interface{} = nil
|
||||
if event.ProtoPayload.RequestMetadata.RequestAttributes.Path != "" &&
|
||||
event.ProtoPayload.RequestMetadata.RequestAttributes.Query != nil &&
|
||||
*event.ProtoPayload.RequestMetadata.RequestAttributes.Query != "" {
|
||||
parameters = map[string]interface{}{}
|
||||
|
||||
parsedUrl, err := url.Parse(fmt.Sprintf("%s?%s",
|
||||
event.ProtoPayload.RequestMetadata.RequestAttributes.Path,
|
||||
*event.ProtoPayload.RequestMetadata.RequestAttributes.Query))
|
||||
|
||||
assert.NoError(t, err)
|
||||
for k, v := range parsedUrl.Query() {
|
||||
parameters[k] = v
|
||||
}
|
||||
}
|
||||
assert.Equal(t, event.ProtoPayload.Request.AsMap(), *auditEvent.Request.Body)
|
||||
assert.Equal(t, parameters, *auditEvent.Request.Parameters)
|
||||
for key, value := range event.ProtoPayload.RequestMetadata.RequestAttributes.Headers {
|
||||
assert.Equal(t, value, (*auditEvent.Request.Headers)[key])
|
||||
}
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerIp, auditEvent.SourceIpAddress)
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.CallerSuppliedUserAgent, auditEvent.UserAgent)
|
||||
assert.Equal(t, event.ProtoPayload.Request.AsMap(), *auditEvent.Details)
|
||||
assert.Equal(t, event.ProtoPayload.Response.AsMap(), *auditEvent.Result)
|
||||
assert.True(t, auditEvent.Context.OrganizationId != nil || auditEvent.Context.FolderId != nil || auditEvent.Context.ProjectId != nil)
|
||||
|
||||
for idx, principal := range event.ProtoPayload.AuthenticationInfo.ServiceAccountDelegationInfo {
|
||||
switch principalValue := principal.Authority.(type) {
|
||||
case *auditV1.ServiceAccountDelegationInfo_IdpPrincipal_:
|
||||
assert.Equal(t, principalValue.IdpPrincipal.PrincipalId, auditEvent.ServiceAccountDelegationInfo.Principals[idx].Id)
|
||||
assert.Equal(t, principalValue.IdpPrincipal.PrincipalEmail, auditEvent.ServiceAccountDelegationInfo.Principals[idx].Email)
|
||||
case *auditV1.ServiceAccountDelegationInfo_SystemPrincipal_:
|
||||
assert.Equal(t, "system", auditEvent.ServiceAccountDelegationInfo.Principals[idx].Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -458,7 +505,7 @@ func TestLegacyAuditApi_Log_NilEvent(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestLegacyAuditApi_ConvertAndSerializeIntoLegacyFormatInvalidObjectIdentifierType(t *testing.T) {
|
||||
customization := func(event *auditV1.AuditEvent,
|
||||
customization := func(event *auditV1.AuditLogEntry,
|
||||
routingIdentifier *RoutingIdentifier,
|
||||
objectIdentifier *auditV1.ObjectIdentifier) {
|
||||
objectIdentifier.Type = 4
|
||||
|
|
@ -477,7 +524,7 @@ func TestLegacyAuditApi_ConvertAndSerializeIntoLegacyFormatInvalidObjectIdentifi
|
|||
func TestLegacyAuditApi_ConvertAndSerializeIntoLegacyFormat_NoResourceReference(t *testing.T) {
|
||||
event, _, _ := NewProjectAuditEvent(nil)
|
||||
routableEvent := auditV1.RoutableAuditEvent{
|
||||
EventName: event.EventName,
|
||||
EventName: event.ProtoPayload.MethodName,
|
||||
Visibility: auditV1.Visibility_VISIBILITY_PUBLIC,
|
||||
ResourceReference: nil,
|
||||
Data: nil,
|
||||
|
|
|
|||
|
|
@ -69,6 +69,9 @@ func (a *MockAuditApi) ValidateAndSerialize(
|
|||
// TODO check if this is correct
|
||||
subject: event.ProtoPayload.ResourceName,
|
||||
data: routableEventBytes,
|
||||
// TODO set trace fields
|
||||
traceParent: nil,
|
||||
traceState: nil,
|
||||
}
|
||||
|
||||
return &message, nil
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func TestMockAuditApi_Log(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
|
||||
validateRoutableEventPayload(
|
||||
t, cloudEvent.data, routingIdentifier, objectIdentifier, event, event.EventName, visibility)
|
||||
t, cloudEvent.data, routingIdentifier, objectIdentifier, event, event.ProtoPayload.MethodName, visibility)
|
||||
})
|
||||
|
||||
t.Run("ValidateAndSerialize event nil", func(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -128,11 +128,14 @@ func (a *routableAuditApi) ValidateAndSerialize(
|
|||
// TODO what is the correct id?
|
||||
id: uuid.NewString(),
|
||||
time: event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime(),
|
||||
dataContentType: "application/cloudevents+protobuf",
|
||||
dataContentType: ContentTypeCloudEventsProtobuf,
|
||||
dataType: fmt.Sprintf("%v", routableEvent.ProtoReflect().Descriptor().FullName()),
|
||||
// TODO check if this is correct
|
||||
subject: event.ProtoPayload.ResourceName,
|
||||
data: routableEventBytes,
|
||||
// TODO set trace fields
|
||||
traceParent: nil,
|
||||
traceState: nil,
|
||||
}
|
||||
|
||||
return &message, nil
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
routingIdentifier,
|
||||
objectIdentifier,
|
||||
event,
|
||||
"ORGANIZATION_CREATED",
|
||||
"stackit.resourcemanager.v2.organization.created",
|
||||
visibility)
|
||||
})
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
routingIdentifier,
|
||||
objectIdentifier,
|
||||
event,
|
||||
"ORGANIZATION_CREATED",
|
||||
"stackit.resourcemanager.v2.organization.created",
|
||||
visibility)
|
||||
})
|
||||
|
||||
|
|
@ -159,7 +159,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
routingIdentifier,
|
||||
objectIdentifier,
|
||||
event,
|
||||
"FOLDER_CREATED",
|
||||
"stackit.resourcemanager.v2.folder.created",
|
||||
visibility)
|
||||
})
|
||||
|
||||
|
|
@ -197,7 +197,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
routingIdentifier,
|
||||
objectIdentifier,
|
||||
event,
|
||||
"FOLDER_CREATED",
|
||||
"stackit.resourcemanager.v2.folder.created",
|
||||
visibility)
|
||||
})
|
||||
|
||||
|
|
@ -234,7 +234,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
routingIdentifier,
|
||||
objectIdentifier,
|
||||
event,
|
||||
"PROJECT_CREATED",
|
||||
"stackit.resourcemanager.v2.project.created",
|
||||
visibility)
|
||||
})
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
routingIdentifier,
|
||||
objectIdentifier,
|
||||
event,
|
||||
"PROJECT_CREATED",
|
||||
"stackit.resourcemanager.v2.project.created",
|
||||
visibility)
|
||||
})
|
||||
|
||||
|
|
@ -309,7 +309,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
assert.Equal(t, "resource-manager", applicationProperties["cloudEvents:source"])
|
||||
_, isUuid := uuid.Parse(fmt.Sprintf("%s", applicationProperties["cloudEvents:id"]))
|
||||
assert.True(t, true, isUuid)
|
||||
assert.Equal(t, event.EventTimeStamp.AsTime().UnixMilli(), applicationProperties["cloudEvents:time"])
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime().UnixMilli(), applicationProperties["cloudEvents:time"])
|
||||
assert.Equal(t, "application/cloudevents+protobuf", applicationProperties["cloudEvents:datacontenttype"])
|
||||
assert.Equal(t, "audit.v1.RoutableAuditEvent", applicationProperties["cloudEvents:type"])
|
||||
|
||||
|
|
@ -320,7 +320,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
nil,
|
||||
nil,
|
||||
event,
|
||||
"SYSTEM_CHANGED",
|
||||
"stackit.resourcemanager.v2.system.changed",
|
||||
visibility)
|
||||
})
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
assert.NoError(t, solaceContainer.TopicSubscriptionCreate(ctx, queueName, "org/*"))
|
||||
|
||||
// Instantiate test data
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEventWithDetails()
|
||||
event, routingIdentifier, objectIdentifier := NewOrganizationAuditEvent(nil)
|
||||
|
||||
// Log the event to solace
|
||||
visibility := auditV1.Visibility_VISIBILITY_PUBLIC
|
||||
|
|
@ -356,7 +356,7 @@ func TestRoutableAuditApi(t *testing.T) {
|
|||
routingIdentifier,
|
||||
objectIdentifier,
|
||||
event,
|
||||
"ORGANIZATION_CREATED",
|
||||
"stackit.resourcemanager.v2.organization.created",
|
||||
visibility)
|
||||
})
|
||||
}
|
||||
|
|
@ -367,7 +367,7 @@ func validateSentEvent(
|
|||
message *amqp.Message,
|
||||
routingIdentifier *RoutingIdentifier,
|
||||
objectIdentifier *auditV1.ObjectIdentifier,
|
||||
event *auditV1.AuditEvent,
|
||||
event *auditV1.AuditLogEntry,
|
||||
eventName string,
|
||||
visibility auditV1.Visibility,
|
||||
) {
|
||||
|
|
@ -383,7 +383,7 @@ func validateSentEvent(
|
|||
assert.Equal(t, "resource-manager", applicationProperties["cloudEvents:source"])
|
||||
_, isUuid := uuid.Parse(fmt.Sprintf("%s", applicationProperties["cloudEvents:id"]))
|
||||
assert.True(t, true, isUuid)
|
||||
assert.Equal(t, event.EventTimeStamp.AsTime().UnixMilli(), applicationProperties["cloudEvents:time"])
|
||||
assert.Equal(t, event.ProtoPayload.RequestMetadata.RequestAttributes.Time.AsTime().UnixMilli(), applicationProperties["cloudEvents:time"])
|
||||
assert.Equal(t, "application/cloudevents+protobuf", applicationProperties["cloudEvents:datacontenttype"])
|
||||
assert.Equal(t, "audit.v1.RoutableAuditEvent", applicationProperties["cloudEvents:type"])
|
||||
|
||||
|
|
@ -397,7 +397,7 @@ func validateRoutableEventPayload(
|
|||
payload []byte,
|
||||
routingIdentifier *RoutingIdentifier,
|
||||
objectIdentifier *auditV1.ObjectIdentifier,
|
||||
event *auditV1.AuditEvent,
|
||||
event *auditV1.AuditLogEntry,
|
||||
eventName string,
|
||||
visibility auditV1.Visibility,
|
||||
) {
|
||||
|
|
@ -432,7 +432,7 @@ func validateRoutableEventPayload(
|
|||
assert.Fail(t, "Object name not expected")
|
||||
}
|
||||
|
||||
var auditEvent auditV1.AuditEvent
|
||||
var auditEvent auditV1.AuditLogEntry
|
||||
switch data := routableAuditEvent.Data.(type) {
|
||||
case *auditV1.RoutableAuditEvent_UnencryptedData:
|
||||
assert.NoError(t, proto.Unmarshal(data.UnencryptedData.Data, &auditEvent))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
"time"
|
||||
|
||||
|
|
@ -22,19 +23,74 @@ func NewOrganizationAuditEvent(
|
|||
*auditV1.ObjectIdentifier,
|
||||
) {
|
||||
|
||||
identifier := uuid.New()
|
||||
permission := "resourcemanager.organization.edit"
|
||||
permissionGranted := true
|
||||
requestId := fmt.Sprintf("%s/1", identifier)
|
||||
claims, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
request, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
response, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
correlationId := "cad100e2-e139-43b9-8c3b-335731e032bc"
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
labels := make(map[string]string)
|
||||
labels["label1"] = "value1"
|
||||
auditEvent := &auditV1.AuditLogEntry{
|
||||
EventSource: "resource-manager",
|
||||
Region: auditV1.Region_REGION_EU01,
|
||||
SequenceNumber: wrapperspb.Int64(0),
|
||||
EventName: "ORGANIZATION_CREATED",
|
||||
EventTimeStamp: timestamppb.New(time.Now()),
|
||||
EventTrigger: auditV1.EventTrigger_EVENT_TRIGGER_EVENT,
|
||||
Initiator: &auditV1.Principal{
|
||||
Id: uuid.NewString(),
|
||||
LogName: fmt.Sprintf("organizations/%s/logs/admin-activity", identifier),
|
||||
ProtoPayload: &auditV1.AuditLog{
|
||||
ServiceName: "resource-manager",
|
||||
MethodName: "stackit.resourcemanager.v2.organization.created",
|
||||
ResourceName: fmt.Sprintf("organizations/%s", identifier),
|
||||
AuthenticationInfo: &auditV1.AuthenticationInfo{
|
||||
PrincipalId: uuid.NewString(),
|
||||
PrincipalEmail: "user@example.com",
|
||||
ServiceAccountName: nil,
|
||||
ServiceAccountDelegationInfo: nil,
|
||||
},
|
||||
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
|
||||
Resource: fmt.Sprintf("organizations/%s", identifier),
|
||||
Permission: &permission,
|
||||
Granted: &permissionGranted,
|
||||
}},
|
||||
RequestMetadata: &auditV1.RequestMetadata{
|
||||
CallerIp: "127.0.0.1",
|
||||
CallerSuppliedUserAgent: "OpenAPI-Generator/ 1.0.0/ go",
|
||||
RequestAttributes: &auditV1.AttributeContext_Request{
|
||||
Id: &requestId,
|
||||
Method: "POST",
|
||||
Headers: headers,
|
||||
Path: "/v2/organizations",
|
||||
Host: "stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud",
|
||||
Scheme: "https",
|
||||
Query: nil,
|
||||
Time: timestamppb.New(time.Now().UTC()),
|
||||
Protocol: "http/1.1",
|
||||
Auth: &auditV1.AttributeContext_Auth{
|
||||
Principal: "https%3A%2F%2Faccounts.dev.stackit.cloud/stackit-resource-manager-dev",
|
||||
Audiences: []string{"https:// stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud", "stackit", "api"},
|
||||
Claims: claims,
|
||||
},
|
||||
},
|
||||
},
|
||||
Request: request,
|
||||
Status: &auditV1.ResponseStatus{
|
||||
Code: wrapperspb.Int32(200),
|
||||
Message: nil,
|
||||
Details: nil,
|
||||
},
|
||||
NumResponseItems: nil,
|
||||
Response: response,
|
||||
Metadata: nil,
|
||||
},
|
||||
InsertId: fmt.Sprintf("%d/eu01/e72182e8-0bb9-4be2-a19f-87fc0dd6e738/00000000001", time.Now().UnixNano()),
|
||||
Labels: labels,
|
||||
CorrelationId: &correlationId,
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Severity: auditV1.LogSeverity_DEFAULT,
|
||||
TraceParent: nil,
|
||||
TraceState: nil,
|
||||
}
|
||||
|
||||
identifier := uuid.New()
|
||||
routingIdentifier := &RoutingIdentifier{
|
||||
Identifier: identifier,
|
||||
Type: RoutingIdentifierTypeOrganization,
|
||||
|
|
@ -44,7 +100,6 @@ func NewOrganizationAuditEvent(
|
|||
Identifier: identifier.String(),
|
||||
Type: auditV1.ObjectType_OBJECT_TYPE_ORGANIZATION,
|
||||
}
|
||||
auditEvent.ResourceContainerReference = &auditV1.AuditEvent_ObjectIdentifier{ObjectIdentifier: objectIdentifier}
|
||||
|
||||
if customization != nil {
|
||||
(*customization)(auditEvent, routingIdentifier, objectIdentifier)
|
||||
|
|
@ -53,51 +108,6 @@ func NewOrganizationAuditEvent(
|
|||
return auditEvent, routingIdentifier, objectIdentifier
|
||||
}
|
||||
|
||||
func NewOrganizationAuditEventWithDetails() (*auditV1.AuditLogEntry,
|
||||
*RoutingIdentifier,
|
||||
*auditV1.ObjectIdentifier) {
|
||||
customization := func(event *auditV1.AuditLogEntry,
|
||||
routingIdentifier *RoutingIdentifier,
|
||||
objectIdentifier *auditV1.ObjectIdentifier) {
|
||||
userAgent := "firefox"
|
||||
parameters, _ := structpb.NewStruct(map[string]any{"parameter1": "value"})
|
||||
body, _ := structpb.NewStruct(map[string]any{"body": "value"})
|
||||
|
||||
event.Request = &auditV1.RequestDetails{
|
||||
Endpoint: "/test",
|
||||
SourceIpAddress: "127.0.0.1",
|
||||
UserAgent: &userAgent,
|
||||
Parameters: parameters,
|
||||
Body: body,
|
||||
Headers: []*auditV1.RequestHeader{
|
||||
{
|
||||
Key: "header1",
|
||||
Value: "value",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
email := "test@example.com"
|
||||
event.Principals = []*auditV1.Principal{
|
||||
{
|
||||
Id: "id",
|
||||
Email: &email,
|
||||
},
|
||||
}
|
||||
|
||||
details, _ := structpb.NewStruct(map[string]interface{}{
|
||||
"detail": "value",
|
||||
})
|
||||
event.Details = details
|
||||
|
||||
result, _ := structpb.NewStruct(map[string]interface{}{
|
||||
"result": "value",
|
||||
})
|
||||
event.Result = result
|
||||
}
|
||||
return NewOrganizationAuditEvent(&customization)
|
||||
}
|
||||
|
||||
func NewFolderAuditEvent(
|
||||
customization *func(
|
||||
*auditV1.AuditLogEntry,
|
||||
|
|
@ -109,28 +119,83 @@ func NewFolderAuditEvent(
|
|||
*auditV1.ObjectIdentifier,
|
||||
) {
|
||||
|
||||
identifier := uuid.New()
|
||||
permission := "resourcemanager.folder.edit"
|
||||
permissionGranted := true
|
||||
requestId := fmt.Sprintf("%s/1", identifier)
|
||||
claims, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
request, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
response, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
correlationId := "9c71cedf-ca52-4f9c-a519-ed006e810cdd"
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
labels := make(map[string]string)
|
||||
labels["label1"] = "value1"
|
||||
auditEvent := &auditV1.AuditLogEntry{
|
||||
EventSource: "resource-manager",
|
||||
Region: auditV1.Region_REGION_EU01,
|
||||
SequenceNumber: wrapperspb.Int64(0),
|
||||
EventName: "FOLDER_CREATED",
|
||||
EventTimeStamp: timestamppb.New(time.Now()),
|
||||
EventTrigger: auditV1.EventTrigger_EVENT_TRIGGER_EVENT,
|
||||
Initiator: &auditV1.Principal{
|
||||
Id: uuid.NewString(),
|
||||
LogName: fmt.Sprintf("folders/%s/logs/admin-activity", identifier),
|
||||
ProtoPayload: &auditV1.AuditLog{
|
||||
ServiceName: "resource-manager",
|
||||
MethodName: "stackit.resourcemanager.v2.folder.created",
|
||||
ResourceName: fmt.Sprintf("folders/%s", identifier),
|
||||
AuthenticationInfo: &auditV1.AuthenticationInfo{
|
||||
PrincipalId: uuid.NewString(),
|
||||
PrincipalEmail: "user@example.com",
|
||||
ServiceAccountName: nil,
|
||||
ServiceAccountDelegationInfo: nil,
|
||||
},
|
||||
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
|
||||
Resource: fmt.Sprintf("folders/%s", identifier),
|
||||
Permission: &permission,
|
||||
Granted: &permissionGranted,
|
||||
}},
|
||||
RequestMetadata: &auditV1.RequestMetadata{
|
||||
CallerIp: "127.0.0.1",
|
||||
CallerSuppliedUserAgent: "OpenAPI-Generator/ 1.0.0/ go",
|
||||
RequestAttributes: &auditV1.AttributeContext_Request{
|
||||
Id: &requestId,
|
||||
Method: "POST",
|
||||
Headers: headers,
|
||||
Path: "/v2/folders",
|
||||
Host: "stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud",
|
||||
Scheme: "https",
|
||||
Query: nil,
|
||||
Time: timestamppb.New(time.Now().UTC()),
|
||||
Protocol: "http/1.1",
|
||||
Auth: &auditV1.AttributeContext_Auth{
|
||||
Principal: "https%3A%2F%2Faccounts.dev.stackit.cloud/stackit-resource-manager-dev",
|
||||
Audiences: []string{"https:// stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud", "stackit", "api"},
|
||||
Claims: claims,
|
||||
},
|
||||
},
|
||||
},
|
||||
Request: request,
|
||||
Status: &auditV1.ResponseStatus{
|
||||
Code: wrapperspb.Int32(200),
|
||||
Message: nil,
|
||||
Details: nil,
|
||||
},
|
||||
NumResponseItems: nil,
|
||||
Response: response,
|
||||
Metadata: nil,
|
||||
},
|
||||
InsertId: fmt.Sprintf("%d/eu01/e72182e8-0bb9-4be2-a19f-87fc0dd6e738/00000000001", time.Now().UnixNano()),
|
||||
Labels: labels,
|
||||
CorrelationId: &correlationId,
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Severity: auditV1.LogSeverity_DEFAULT,
|
||||
TraceParent: nil,
|
||||
TraceState: nil,
|
||||
}
|
||||
|
||||
routingIdentifier := &RoutingIdentifier{
|
||||
Identifier: uuid.New(),
|
||||
Identifier: identifier,
|
||||
Type: RoutingIdentifierTypeOrganization,
|
||||
}
|
||||
|
||||
objectIdentifier := &auditV1.ObjectIdentifier{
|
||||
Identifier: uuid.New().String(),
|
||||
Identifier: identifier.String(),
|
||||
Type: auditV1.ObjectType_OBJECT_TYPE_FOLDER,
|
||||
}
|
||||
auditEvent.ResourceContainerReference = &auditV1.AuditEvent_ObjectIdentifier{ObjectIdentifier: objectIdentifier}
|
||||
|
||||
if customization != nil {
|
||||
(*customization)(auditEvent, routingIdentifier, objectIdentifier)
|
||||
|
|
@ -150,19 +215,74 @@ func NewProjectAuditEvent(
|
|||
*auditV1.ObjectIdentifier,
|
||||
) {
|
||||
|
||||
identifier := uuid.New()
|
||||
permission := "resourcemanager.project.edit"
|
||||
permissionGranted := true
|
||||
requestId := fmt.Sprintf("%s/1", identifier)
|
||||
claims, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
request, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
response, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
correlationId := "14d5b611-ccce-4cfa-9085-9ccbfccce3cb"
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
labels := make(map[string]string)
|
||||
labels["label1"] = "value1"
|
||||
auditEvent := &auditV1.AuditLogEntry{
|
||||
EventSource: "resource-manager",
|
||||
Region: auditV1.Region_REGION_EU01,
|
||||
SequenceNumber: wrapperspb.Int64(0),
|
||||
EventName: "PROJECT_CREATED",
|
||||
EventTimeStamp: timestamppb.New(time.Now()),
|
||||
EventTrigger: auditV1.EventTrigger_EVENT_TRIGGER_EVENT,
|
||||
Initiator: &auditV1.Principal{
|
||||
Id: uuid.NewString(),
|
||||
LogName: fmt.Sprintf("projects/%s/logs/admin-activity", identifier),
|
||||
ProtoPayload: &auditV1.AuditLog{
|
||||
ServiceName: "resource-manager",
|
||||
MethodName: "stackit.resourcemanager.v2.project.created",
|
||||
ResourceName: fmt.Sprintf("projects/%s", identifier),
|
||||
AuthenticationInfo: &auditV1.AuthenticationInfo{
|
||||
PrincipalId: uuid.NewString(),
|
||||
PrincipalEmail: "user@example.com",
|
||||
ServiceAccountName: nil,
|
||||
ServiceAccountDelegationInfo: nil,
|
||||
},
|
||||
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
|
||||
Resource: fmt.Sprintf("projects/%s", identifier),
|
||||
Permission: &permission,
|
||||
Granted: &permissionGranted,
|
||||
}},
|
||||
RequestMetadata: &auditV1.RequestMetadata{
|
||||
CallerIp: "127.0.0.1",
|
||||
CallerSuppliedUserAgent: "OpenAPI-Generator/ 1.0.0/ go",
|
||||
RequestAttributes: &auditV1.AttributeContext_Request{
|
||||
Id: &requestId,
|
||||
Method: "POST",
|
||||
Headers: headers,
|
||||
Path: "/v2/projects",
|
||||
Host: "stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud",
|
||||
Scheme: "https",
|
||||
Query: nil,
|
||||
Time: timestamppb.New(time.Now().UTC()),
|
||||
Protocol: "http/1.1",
|
||||
Auth: &auditV1.AttributeContext_Auth{
|
||||
Principal: "https%3A%2F%2Faccounts.dev.stackit.cloud/stackit-resource-manager-dev",
|
||||
Audiences: []string{"https:// stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud", "stackit", "api"},
|
||||
Claims: claims,
|
||||
},
|
||||
},
|
||||
},
|
||||
Request: request,
|
||||
Status: &auditV1.ResponseStatus{
|
||||
Code: wrapperspb.Int32(200),
|
||||
Message: nil,
|
||||
Details: nil,
|
||||
},
|
||||
NumResponseItems: nil,
|
||||
Response: response,
|
||||
Metadata: nil,
|
||||
},
|
||||
InsertId: fmt.Sprintf("%d/eu01/e72182e8-0bb9-4be2-a19f-87fc0dd6e738/00000000001", time.Now().UnixNano()),
|
||||
Labels: labels,
|
||||
CorrelationId: &correlationId,
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Severity: auditV1.LogSeverity_DEFAULT,
|
||||
TraceParent: nil,
|
||||
TraceState: nil,
|
||||
}
|
||||
|
||||
identifier := uuid.New()
|
||||
routingIdentifier := &RoutingIdentifier{
|
||||
Identifier: identifier,
|
||||
Type: RoutingIdentifierTypeProject,
|
||||
|
|
@ -172,7 +292,6 @@ func NewProjectAuditEvent(
|
|||
Identifier: identifier.String(),
|
||||
Type: auditV1.ObjectType_OBJECT_TYPE_PROJECT,
|
||||
}
|
||||
auditEvent.ResourceContainerReference = &auditV1.AuditEvent_ObjectIdentifier{ObjectIdentifier: objectIdentifier}
|
||||
|
||||
if customization != nil {
|
||||
(*customization)(auditEvent, routingIdentifier, objectIdentifier)
|
||||
|
|
@ -184,19 +303,74 @@ func NewProjectAuditEvent(
|
|||
func NewSystemAuditEvent(
|
||||
customization *func(*auditV1.AuditLogEntry)) *auditV1.AuditLogEntry {
|
||||
|
||||
identifier := uuid.New()
|
||||
requestId := fmt.Sprintf("%s/1", identifier)
|
||||
claims, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
request, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
response, _ := structpb.NewStruct(map[string]interface{}{})
|
||||
correlationId := "14d5b611-ccce-4cfa-9085-9ccbfccce3cb"
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
labels := make(map[string]string)
|
||||
labels["label1"] = "value1"
|
||||
serviceAccountId := uuid.NewString()
|
||||
serviceAccountName := fmt.Sprintf("projects/%s/serviceAccounts/%s", identifier, serviceAccountId)
|
||||
delegationPrincipal := auditV1.ServiceAccountDelegationInfo{Authority: &auditV1.ServiceAccountDelegationInfo_SystemPrincipal_{}}
|
||||
auditEvent := &auditV1.AuditLogEntry{
|
||||
EventSource: "resource-manager",
|
||||
Region: auditV1.Region_REGION_EU01,
|
||||
SequenceNumber: wrapperspb.Int64(0),
|
||||
EventName: "SYSTEM_CHANGED",
|
||||
EventTimeStamp: timestamppb.New(time.Now()),
|
||||
EventTrigger: auditV1.EventTrigger_EVENT_TRIGGER_EVENT,
|
||||
Initiator: &auditV1.Principal{
|
||||
Id: uuid.NewString(),
|
||||
LogName: fmt.Sprintf("projects/%s/logs/system-event", identifier),
|
||||
ProtoPayload: &auditV1.AuditLog{
|
||||
ServiceName: "resource-manager",
|
||||
MethodName: "stackit.resourcemanager.v2.system.changed",
|
||||
ResourceName: fmt.Sprintf("projects/%s", identifier),
|
||||
AuthenticationInfo: &auditV1.AuthenticationInfo{
|
||||
PrincipalId: serviceAccountId,
|
||||
PrincipalEmail: "service-account@sa.stackit.cloud",
|
||||
ServiceAccountName: &serviceAccountName,
|
||||
ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal},
|
||||
},
|
||||
AuthorizationInfo: []*auditV1.AuthorizationInfo{{
|
||||
Resource: fmt.Sprintf("projects/%s", identifier),
|
||||
Permission: nil,
|
||||
Granted: nil,
|
||||
}},
|
||||
RequestMetadata: &auditV1.RequestMetadata{
|
||||
CallerIp: "127.0.0.1",
|
||||
CallerSuppliedUserAgent: "OpenAPI-Generator/ 1.0.0/ go",
|
||||
RequestAttributes: &auditV1.AttributeContext_Request{
|
||||
Id: &requestId,
|
||||
Method: "POST",
|
||||
Headers: headers,
|
||||
Path: "/v2/projects",
|
||||
Host: "stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud",
|
||||
Scheme: "https",
|
||||
Query: nil,
|
||||
Time: timestamppb.New(time.Now().UTC()),
|
||||
Protocol: "http/1.1",
|
||||
Auth: &auditV1.AttributeContext_Auth{
|
||||
Principal: "https%3A%2F%2Faccounts.dev.stackit.cloud/stackit-resource-manager-dev",
|
||||
Audiences: []string{"https:// stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud", "stackit", "api"},
|
||||
Claims: claims,
|
||||
},
|
||||
},
|
||||
},
|
||||
Request: request,
|
||||
Status: &auditV1.ResponseStatus{
|
||||
Code: wrapperspb.Int32(200),
|
||||
Message: nil,
|
||||
Details: nil,
|
||||
},
|
||||
NumResponseItems: nil,
|
||||
Response: response,
|
||||
Metadata: nil,
|
||||
},
|
||||
InsertId: fmt.Sprintf("%d/eu01/e72182e8-0bb9-4be2-a19f-87fc0dd6e738/00000000001", time.Now().UnixNano()),
|
||||
Labels: labels,
|
||||
CorrelationId: &correlationId,
|
||||
Timestamp: timestamppb.New(time.Now()),
|
||||
Severity: auditV1.LogSeverity_DEFAULT,
|
||||
TraceParent: nil,
|
||||
TraceState: nil,
|
||||
}
|
||||
auditEvent.ResourceContainerReference = &auditV1.AuditEvent_ObjectName{
|
||||
ObjectName: auditV1.ObjectName_OBJECT_NAME_SYSTEM}
|
||||
|
||||
if customization != nil {
|
||||
(*customization)(auditEvent)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -92,8 +92,6 @@ func (m *AuditLogEntry) validate(all bool) error {
|
|||
|
||||
// no validation rules for Labels
|
||||
|
||||
// no validation rules for CorrelationId
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetTimestamp()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
|
|
@ -125,9 +123,17 @@ func (m *AuditLogEntry) validate(all bool) error {
|
|||
|
||||
// no validation rules for Severity
|
||||
|
||||
// no validation rules for TraceParent
|
||||
if m.CorrelationId != nil {
|
||||
// no validation rules for CorrelationId
|
||||
}
|
||||
|
||||
// no validation rules for TraceState
|
||||
if m.TraceParent != nil {
|
||||
// no validation rules for TraceParent
|
||||
}
|
||||
|
||||
if m.TraceState != nil {
|
||||
// no validation rules for TraceState
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return AuditLogEntryMultiError(errors)
|
||||
|
|
@ -231,6 +237,8 @@ func (m *AuditLog) validate(all bool) error {
|
|||
|
||||
// no validation rules for ServiceName
|
||||
|
||||
// no validation rules for MethodName
|
||||
|
||||
// no validation rules for ResourceName
|
||||
|
||||
if all {
|
||||
|
|
@ -412,41 +420,70 @@ func (m *AuditLog) validate(all bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetMetadata()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, AuditLogValidationError{
|
||||
field: "Metadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, AuditLogValidationError{
|
||||
field: "Metadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return AuditLogValidationError{
|
||||
field: "Metadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if m.MethodName != nil {
|
||||
// no validation rules for MethodName
|
||||
}
|
||||
|
||||
if m.NumResponseItems != nil {
|
||||
// no validation rules for NumResponseItems
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetNumResponseItems()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, AuditLogValidationError{
|
||||
field: "NumResponseItems",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, AuditLogValidationError{
|
||||
field: "NumResponseItems",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetNumResponseItems()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return AuditLogValidationError{
|
||||
field: "NumResponseItems",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if m.Metadata != nil {
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetMetadata()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, AuditLogValidationError{
|
||||
field: "Metadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, AuditLogValidationError{
|
||||
field: "Metadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetMetadata()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return AuditLogValidationError{
|
||||
field: "Metadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
|
|
@ -694,37 +731,12 @@ func (m *AuthorizationInfo) validate(all bool) error {
|
|||
|
||||
// no validation rules for Resource
|
||||
|
||||
// no validation rules for Permission
|
||||
if m.Permission != nil {
|
||||
// no validation rules for Permission
|
||||
}
|
||||
|
||||
// no validation rules for Granted
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetResourceAttributes()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, AuthorizationInfoValidationError{
|
||||
field: "ResourceAttributes",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, AuthorizationInfoValidationError{
|
||||
field: "ResourceAttributes",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetResourceAttributes()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return AuthorizationInfoValidationError{
|
||||
field: "ResourceAttributes",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
if m.Granted != nil {
|
||||
// no validation rules for Granted
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
|
|
@ -1062,9 +1074,34 @@ func (m *ResponseStatus) validate(all bool) error {
|
|||
|
||||
var errors []error
|
||||
|
||||
// no validation rules for Code
|
||||
|
||||
// no validation rules for Message
|
||||
if all {
|
||||
switch v := interface{}(m.GetCode()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, ResponseStatusValidationError{
|
||||
field: "Code",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, ResponseStatusValidationError{
|
||||
field: "Code",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetCode()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return ResponseStatusValidationError{
|
||||
field: "Code",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for idx, item := range m.GetDetails() {
|
||||
_, _ = idx, item
|
||||
|
|
@ -1100,6 +1137,10 @@ func (m *ResponseStatus) validate(all bool) error {
|
|||
|
||||
}
|
||||
|
||||
if m.Message != nil {
|
||||
// no validation rules for Message
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return ResponseStatusMultiError(errors)
|
||||
}
|
||||
|
|
@ -1392,8 +1433,6 @@ func (m *AttributeContext_Auth) validate(all bool) error {
|
|||
|
||||
// no validation rules for Principal
|
||||
|
||||
// no validation rules for Presenter
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetClaims()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
|
|
@ -1525,8 +1564,6 @@ func (m *AttributeContext_Request) validate(all bool) error {
|
|||
|
||||
var errors []error
|
||||
|
||||
// no validation rules for Id
|
||||
|
||||
// no validation rules for Method
|
||||
|
||||
// no validation rules for Headers
|
||||
|
|
@ -1537,8 +1574,6 @@ func (m *AttributeContext_Request) validate(all bool) error {
|
|||
|
||||
// no validation rules for Scheme
|
||||
|
||||
// no validation rules for Query
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetTime()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
|
|
@ -1599,6 +1634,14 @@ func (m *AttributeContext_Request) validate(all bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
if m.Id != nil {
|
||||
// no validation rules for Id
|
||||
}
|
||||
|
||||
if m.Query != nil {
|
||||
// no validation rules for Query
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return AttributeContext_RequestMultiError(errors)
|
||||
}
|
||||
|
|
@ -1701,10 +1744,6 @@ func (m *AttributeContext_Response) validate(all bool) error {
|
|||
|
||||
var errors []error
|
||||
|
||||
// no validation rules for Code
|
||||
|
||||
// no validation rules for Size
|
||||
|
||||
// no validation rules for Headers
|
||||
|
||||
if all {
|
||||
|
|
@ -1736,6 +1775,39 @@ func (m *AttributeContext_Response) validate(all bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
if m.Size != nil {
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetSize()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, AttributeContext_ResponseValidationError{
|
||||
field: "Size",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, AttributeContext_ResponseValidationError{
|
||||
field: "Size",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetSize()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return AttributeContext_ResponseValidationError{
|
||||
field: "Size",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
return AttributeContext_ResponseMultiError(errors)
|
||||
}
|
||||
|
|
@ -1816,116 +1888,6 @@ var _ interface {
|
|||
ErrorName() string
|
||||
} = AttributeContext_ResponseValidationError{}
|
||||
|
||||
// Validate checks the field values on AttributeContext_Resource with the rules
|
||||
// defined in the proto definition for this message. If any rules are
|
||||
// violated, the first error encountered is returned, or nil if there are no violations.
|
||||
func (m *AttributeContext_Resource) Validate() error {
|
||||
return m.validate(false)
|
||||
}
|
||||
|
||||
// ValidateAll checks the field values on AttributeContext_Resource with the
|
||||
// rules defined in the proto definition for this message. If any rules are
|
||||
// violated, the result is a list of violation errors wrapped in
|
||||
// AttributeContext_ResourceMultiError, or nil if none found.
|
||||
func (m *AttributeContext_Resource) ValidateAll() error {
|
||||
return m.validate(true)
|
||||
}
|
||||
|
||||
func (m *AttributeContext_Resource) validate(all bool) error {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errors []error
|
||||
|
||||
// no validation rules for Service
|
||||
|
||||
// no validation rules for Name
|
||||
|
||||
// no validation rules for Type
|
||||
|
||||
// no validation rules for Labels
|
||||
|
||||
if len(errors) > 0 {
|
||||
return AttributeContext_ResourceMultiError(errors)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AttributeContext_ResourceMultiError is an error wrapping multiple validation
|
||||
// errors returned by AttributeContext_Resource.ValidateAll() if the
|
||||
// designated constraints aren't met.
|
||||
type AttributeContext_ResourceMultiError []error
|
||||
|
||||
// Error returns a concatenation of all the error messages it wraps.
|
||||
func (m AttributeContext_ResourceMultiError) Error() string {
|
||||
var msgs []string
|
||||
for _, err := range m {
|
||||
msgs = append(msgs, err.Error())
|
||||
}
|
||||
return strings.Join(msgs, "; ")
|
||||
}
|
||||
|
||||
// AllErrors returns a list of validation violation errors.
|
||||
func (m AttributeContext_ResourceMultiError) AllErrors() []error { return m }
|
||||
|
||||
// AttributeContext_ResourceValidationError is the validation error returned by
|
||||
// AttributeContext_Resource.Validate if the designated constraints aren't met.
|
||||
type AttributeContext_ResourceValidationError struct {
|
||||
field string
|
||||
reason string
|
||||
cause error
|
||||
key bool
|
||||
}
|
||||
|
||||
// Field function returns field value.
|
||||
func (e AttributeContext_ResourceValidationError) Field() string { return e.field }
|
||||
|
||||
// Reason function returns reason value.
|
||||
func (e AttributeContext_ResourceValidationError) Reason() string { return e.reason }
|
||||
|
||||
// Cause function returns cause value.
|
||||
func (e AttributeContext_ResourceValidationError) Cause() error { return e.cause }
|
||||
|
||||
// Key function returns key value.
|
||||
func (e AttributeContext_ResourceValidationError) Key() bool { return e.key }
|
||||
|
||||
// ErrorName returns error name.
|
||||
func (e AttributeContext_ResourceValidationError) ErrorName() string {
|
||||
return "AttributeContext_ResourceValidationError"
|
||||
}
|
||||
|
||||
// Error satisfies the builtin error interface
|
||||
func (e AttributeContext_ResourceValidationError) Error() string {
|
||||
cause := ""
|
||||
if e.cause != nil {
|
||||
cause = fmt.Sprintf(" | caused by: %v", e.cause)
|
||||
}
|
||||
|
||||
key := ""
|
||||
if e.key {
|
||||
key = "key for "
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
"invalid %sAttributeContext_Resource.%s: %s%s",
|
||||
key,
|
||||
e.field,
|
||||
e.reason,
|
||||
cause)
|
||||
}
|
||||
|
||||
var _ error = AttributeContext_ResourceValidationError{}
|
||||
|
||||
var _ interface {
|
||||
Field() string
|
||||
Reason() string
|
||||
Key() bool
|
||||
Cause() error
|
||||
ErrorName() string
|
||||
} = AttributeContext_ResourceValidationError{}
|
||||
|
||||
// Validate checks the field values on
|
||||
// ServiceAccountDelegationInfo_SystemPrincipal with the rules defined in the
|
||||
// proto definition for this message. If any rules are violated, the first
|
||||
|
|
@ -1950,33 +1912,37 @@ func (m *ServiceAccountDelegationInfo_SystemPrincipal) validate(all bool) error
|
|||
|
||||
var errors []error
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetServiceMetadata()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_SystemPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
if m.ServiceMetadata != nil {
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetServiceMetadata()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_SystemPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_SystemPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
} else if v, ok := interface{}(m.GetServiceMetadata()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_SystemPrincipalValidationError{
|
||||
return ServiceAccountDelegationInfo_SystemPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetServiceMetadata()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return ServiceAccountDelegationInfo_SystemPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
|
|
@ -2088,37 +2054,39 @@ func (m *ServiceAccountDelegationInfo_IdpPrincipal) validate(all bool) error {
|
|||
|
||||
// no validation rules for PrincipalId
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetServiceMetadata()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_IdpPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_IdpPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetServiceMetadata()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return ServiceAccountDelegationInfo_IdpPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
// no validation rules for PrincipalEmail
|
||||
|
||||
if m.ServiceMetadata != nil {
|
||||
|
||||
if all {
|
||||
switch v := interface{}(m.GetServiceMetadata()).(type) {
|
||||
case interface{ ValidateAll() error }:
|
||||
if err := v.ValidateAll(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_IdpPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
case interface{ Validate() error }:
|
||||
if err := v.Validate(); err != nil {
|
||||
errors = append(errors, ServiceAccountDelegationInfo_IdpPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else if v, ok := interface{}(m.GetServiceMetadata()).(interface{ Validate() error }); ok {
|
||||
if err := v.Validate(); err != nil {
|
||||
return ServiceAccountDelegationInfo_IdpPrincipalValidationError{
|
||||
field: "ServiceMetadata",
|
||||
reason: "embedded message failed validation",
|
||||
cause: err,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if m.PrincipalEmail != nil {
|
||||
// no validation rules for PrincipalEmail
|
||||
}
|
||||
|
||||
if len(errors) > 0 {
|
||||
|
|
|
|||
|
|
@ -380,50 +380,53 @@ var file_audit_v1_routable_event_proto_rawDesc = []byte{
|
|||
0x10, 0x01, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42,
|
||||
0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x54, 0x79, 0x70, 0x65, 0x22, 0xcb, 0x03, 0x0a, 0x12, 0x52, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x54, 0x79, 0x70, 0x65, 0x22, 0xf4, 0x03, 0x0a, 0x12, 0x52, 0x6f,
|
||||
0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x12, 0x38, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x42, 0x19, 0xba, 0x48, 0x16, 0xc8, 0x01, 0x01, 0x72, 0x11, 0x32, 0x0f,
|
||||
0x5e, 0x5b, 0x41, 0x2d, 0x5a, 0x5d, 0x2b, 0x5f, 0x5b, 0x41, 0x2d, 0x5a, 0x5d, 0x2b, 0x24, 0x52,
|
||||
0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x76, 0x69,
|
||||
0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14,
|
||||
0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69,
|
||||
0x6c, 0x69, 0x74, 0x79, 0x42, 0x0b, 0xba, 0x48, 0x08, 0xc8, 0x01, 0x01, 0x82, 0x01, 0x02, 0x10,
|
||||
0x01, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x37, 0x0a,
|
||||
0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x62,
|
||||
0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65,
|
||||
0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x49, 0x0a, 0x11, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
|
||||
0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x62, 0x6a,
|
||||
0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52,
|
||||
0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65,
|
||||
0x72, 0x12, 0x46, 0x0a, 0x10, 0x75, 0x6e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64,
|
||||
0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x75,
|
||||
0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x6e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74,
|
||||
0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x48, 0x01, 0x52, 0x0f, 0x75, 0x6e, 0x65, 0x6e, 0x63, 0x72,
|
||||
0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0e, 0x65, 0x6e, 0x63,
|
||||
0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x17, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63,
|
||||
0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x48, 0x01, 0x52, 0x0d, 0x65, 0x6e,
|
||||
0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x42, 0x1b, 0x0a, 0x12, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63,
|
||||
0x65, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x42, 0x0d, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61,
|
||||
0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x2a, 0x57, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62,
|
||||
0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c,
|
||||
0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
|
||||
0x00, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f,
|
||||
0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x49, 0x53, 0x49,
|
||||
0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x02,
|
||||
0x42, 0x84, 0x01, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x63, 0x68, 0x77, 0x61, 0x72, 0x7a,
|
||||
0x2e, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x69, 0x74, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76,
|
||||
0x31, 0x42, 0x12, 0x52, 0x6f, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x0f, 0x2e, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x74,
|
||||
0x3b, 0x61, 0x75, 0x64, 0x69, 0x74, 0x56, 0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02,
|
||||
0x08, 0x41, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x41, 0x75, 0x64, 0x69,
|
||||
0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14, 0x41, 0x75, 0x64, 0x69, 0x74, 0x5c, 0x56, 0x31, 0x5c,
|
||||
0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x41, 0x75,
|
||||
0x64, 0x69, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x12, 0x61, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x42, 0x42, 0xba, 0x48, 0x3f, 0xc8, 0x01, 0x01, 0x72, 0x3a, 0x32, 0x38,
|
||||
0x5e, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x69, 0x74, 0x5c, 0x2e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d,
|
||||
0x39, 0x5d, 0x2b, 0x5c, 0x2e, 0x76, 0x5b, 0x31, 0x2d, 0x39, 0x5d, 0x5b, 0x30, 0x2d, 0x39, 0x5d,
|
||||
0x2a, 0x5c, 0x2e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x5c, 0x2e, 0x5b, 0x61,
|
||||
0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2b, 0x24, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74,
|
||||
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x42, 0x0b, 0xba,
|
||||
0x48, 0x08, 0xc8, 0x01, 0x01, 0x82, 0x01, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69,
|
||||
0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x37, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
|
||||
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x75,
|
||||
0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x48, 0x00, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x49, 0x0a, 0x11, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
|
||||
0x66, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x75, 0x64,
|
||||
0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x49, 0x64, 0x65, 0x6e,
|
||||
0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
|
||||
0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x75, 0x6e,
|
||||
0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x55, 0x6e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x48,
|
||||
0x01, 0x52, 0x0f, 0x75, 0x6e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44, 0x61,
|
||||
0x74, 0x61, 0x12, 0x40, 0x0a, 0x0e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x5f,
|
||||
0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x75, 0x64,
|
||||
0x69, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x44,
|
||||
0x61, 0x74, 0x61, 0x48, 0x01, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64,
|
||||
0x44, 0x61, 0x74, 0x61, 0x42, 0x1b, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x5f, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08,
|
||||
0x01, 0x42, 0x0d, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01,
|
||||
0x2a, 0x57, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a,
|
||||
0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53,
|
||||
0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x49,
|
||||
0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10,
|
||||
0x01, 0x12, 0x16, 0x0a, 0x12, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f,
|
||||
0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x02, 0x42, 0x84, 0x01, 0x0a, 0x1c, 0x63, 0x6f,
|
||||
0x6d, 0x2e, 0x73, 0x63, 0x68, 0x77, 0x61, 0x72, 0x7a, 0x2e, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x69,
|
||||
0x74, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x74, 0x2e, 0x76, 0x31, 0x42, 0x12, 0x52, 0x6f, 0x75, 0x74,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01,
|
||||
0x5a, 0x0f, 0x2e, 0x2f, 0x61, 0x75, 0x64, 0x69, 0x74, 0x3b, 0x61, 0x75, 0x64, 0x69, 0x74, 0x56,
|
||||
0x31, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, 0x08, 0x41, 0x75, 0x64, 0x69, 0x74, 0x2e,
|
||||
0x56, 0x31, 0xca, 0x02, 0x08, 0x41, 0x75, 0x64, 0x69, 0x74, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14,
|
||||
0x41, 0x75, 0x64, 0x69, 0x74, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61,
|
||||
0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x41, 0x75, 0x64, 0x69, 0x74, 0x3a, 0x3a, 0x56, 0x31,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
|||
117
main.go
117
main.go
|
|
@ -1,117 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
auditV1 "dev.azure.com/schwarzit/schwarzit.stackit-core-platform/common-audit.git/gen/go/audit/v1"
|
||||
|
||||
"github.com/bufbuild/protovalidate-go"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
agent := "aaa"
|
||||
parameters, _ := structpb.NewValue(map[string]any{
|
||||
"parameter": "b",
|
||||
})
|
||||
body, _ := structpb.NewValue(map[string]any{
|
||||
"body": "b",
|
||||
})
|
||||
auditEvent := auditV1.AuditEvent{
|
||||
EventName: "XXX",
|
||||
EventTrigger: auditV1.EventTrigger_EVENT_TRIGGER_REQUEST,
|
||||
Request: &auditV1.RequestDetails{
|
||||
Endpoint: "XXX",
|
||||
SourceIpAddress: "127.0.0.1",
|
||||
UserAgent: &agent,
|
||||
Parameters: parameters.GetStructValue(),
|
||||
Body: body.GetStructValue(),
|
||||
Headers: []*auditV1.RequestHeader{
|
||||
{
|
||||
Key: "abc",
|
||||
Value: "def",
|
||||
},
|
||||
},
|
||||
},
|
||||
EventTimeStamp: nil,
|
||||
Initiator: nil,
|
||||
Principals: nil,
|
||||
ResourceId: nil,
|
||||
ResourceName: nil,
|
||||
CorrelationId: nil,
|
||||
Details: nil,
|
||||
}
|
||||
|
||||
auditEventBytes, err := proto.Marshal(&auditEvent)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
payload := auditV1.UnencryptedData{
|
||||
Data: auditEventBytes,
|
||||
ProtobufType: fmt.Sprintf("%v", auditEvent.ProtoReflect().Descriptor().FullName()),
|
||||
}
|
||||
|
||||
//var version int32 = 0
|
||||
routableEvent := auditV1.RoutableAuditEvent{
|
||||
EventName: "A_V1",
|
||||
Visibility: auditV1.Visibility_VISIBILITY_PRIVATE,
|
||||
ResourceReference: &auditV1.RoutableAuditEvent_ObjectName{ObjectName: auditV1.ObjectName_OBJECT_NAME_SYSTEM},
|
||||
Data: &auditV1.RoutableAuditEvent_UnencryptedData{UnencryptedData: &payload},
|
||||
}
|
||||
|
||||
validator, err := protovalidate.New()
|
||||
if err != nil {
|
||||
fmt.Println("failed to initialize validator:", err)
|
||||
}
|
||||
err = validator.Validate(&auditEvent)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
|
||||
err = validator.Validate(&routableEvent)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
}
|
||||
|
||||
routableEventBytes, err := proto.Marshal(&routableEvent)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var deserializedRoutableEvent auditV1.RoutableAuditEvent
|
||||
err = proto.Unmarshal(routableEventBytes, &deserializedRoutableEvent)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
if proto.Equal(&routableEvent, &deserializedRoutableEvent) {
|
||||
fmt.Println("Event Matched")
|
||||
} else {
|
||||
fmt.Println("Event Not Matched")
|
||||
}
|
||||
//fmt.Println(deserializedRoutableEvent.String())
|
||||
|
||||
protoMessage := getProto(deserializedRoutableEvent.GetUnencryptedData().ProtobufType)
|
||||
err = proto.Unmarshal(deserializedRoutableEvent.GetUnencryptedData().Data, protoMessage)
|
||||
if err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
deserializedAuditEvent, isAuditEvent := protoMessage.(*auditV1.AuditEvent)
|
||||
if isAuditEvent {
|
||||
fmt.Println(deserializedAuditEvent.String())
|
||||
}
|
||||
|
||||
fmt.Println(string(auditEventBytes))
|
||||
}
|
||||
|
||||
func getProto(dataType string) protoreflect.ProtoMessage {
|
||||
t, _ := protoregistry.GlobalTypes.FindMessageByName(protoreflect.FullName(dataType))
|
||||
m := t.New().Interface()
|
||||
return m
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import "buf/validate/validate.proto";
|
|||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
import "audit/v1/common.proto";
|
||||
|
||||
|
|
@ -13,66 +14,123 @@ option go_package = "./audit;auditV1";
|
|||
option java_multiple_files = true;
|
||||
option java_package = "com.schwarz.stackit.audit.v1";
|
||||
|
||||
// TODO update numbers of elements in messages
|
||||
// TODO decide which fields should be optional
|
||||
// TODO max attribute length
|
||||
// TODO check regex patterns
|
||||
// TODO check if gRPC, messaging ans scheduled triggered events work with the schema
|
||||
|
||||
// The audit log entry can be used to record an incident in the audit log.
|
||||
message AuditLogEntry {
|
||||
|
||||
// The resource name of the log to which this log entry belongs.
|
||||
// Example: projects/<identifier>/logs/<eventType>
|
||||
string log_name = 12;
|
||||
//
|
||||
// Format: <type>/<identifier>/logs/<eventType>
|
||||
// Where:
|
||||
// Event-Types: admin-activity, system-event, policy-denied, data-access
|
||||
//
|
||||
// Examples:
|
||||
// "projects/00b0f972-59ff-48f2-a4f9-29c57b75c2fa/logs/admin-activity"
|
||||
//
|
||||
// Required: true
|
||||
string log_name = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.pattern = "^[a-z]+/[a-z0-9-]+/logs/(?:admin-activity|system-event|policy-denied|data-access)$"
|
||||
];
|
||||
|
||||
// The log entry payload, which is always an AuditLog for STACKIT Audit Log events.
|
||||
AuditLog proto_payload = 2;
|
||||
//
|
||||
// Required: true
|
||||
AuditLog proto_payload = 2 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// TODO can we specify how the format should look like?
|
||||
// TODO Encode sequence number into it?
|
||||
// https://softwaremind.com/blog/the-unique-features-of-snowflake-id-and-its-comparison-to-uuid/
|
||||
// A unique identifier for the log entry.
|
||||
// Is generated and set by the SDK.
|
||||
// Format:
|
||||
// <timestamp>/<region>/<worker-id>/<sequence-number>
|
||||
string insert_id = 4;
|
||||
// Is used to check completeness of audit events over time.
|
||||
//
|
||||
// Format: <unix-timestamp>/<region-zone>/<worker-id>/<sequence-number>
|
||||
// Where:
|
||||
// Unix-Timestamp: A UTC unix timestamp in seconds is expected
|
||||
// Region-Zone: The region and (optional) zone id. If both, separated with a - (dash)
|
||||
// Worker-Id: The ID of the K8s Pod, Service-Instance, etc (must be unique for a sending service)
|
||||
// Sequence-Number: Increasing number, representing the message offset per Worker-Id
|
||||
// If the Worker-Id changes, the sequence-number has to be reset to 0.
|
||||
//
|
||||
// Examples:
|
||||
// "1721899117/eu01/319a7fb9-edd2-46c6-953a-a724bb377c61/8792726390909855142"
|
||||
//
|
||||
// Required: true
|
||||
string insert_id = 3[
|
||||
(buf.validate.field).required = true,
|
||||
// TODO how do worker ids look like?
|
||||
(buf.validate.field).string.pattern = "^[0-9]+/[a-z0-9]+/[a-z0-9-]+/[0-9]+$"
|
||||
];
|
||||
|
||||
// A set of user-defined (key, value) data that provides additional
|
||||
// information about the log entry.
|
||||
map<string, string> labels = 11;
|
||||
//
|
||||
// Required: true
|
||||
map<string, string> labels = 4 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// Correlate multiple audit logs by setting the same id
|
||||
string correlation_id = 15;
|
||||
//
|
||||
// Required: false
|
||||
optional string correlation_id = 5 [
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// The time the event described by the log entry occurred.
|
||||
google.protobuf.Timestamp timestamp = 9;
|
||||
//
|
||||
// Required: true
|
||||
google.protobuf.Timestamp timestamp = 6 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).timestamp.lt_now = true
|
||||
];
|
||||
|
||||
// The severity of the log entry.
|
||||
LogSeverity severity = 10;
|
||||
//
|
||||
// Required: true
|
||||
LogSeverity severity = 7 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).enum.defined_only = true
|
||||
];
|
||||
|
||||
// W3C conform trace parent header:
|
||||
// Customer set W3C conform trace parent header:
|
||||
// https://www.w3.org/TR/trace-context/#traceparent-header
|
||||
//
|
||||
// Example:
|
||||
// `00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01`
|
||||
string trace_parent = 22;
|
||||
// Format: <version>-<trace-id>-<parent-id>-<trace-flags>
|
||||
//
|
||||
// Examples:
|
||||
// "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01"
|
||||
//
|
||||
// Required: false
|
||||
optional string trace_parent = 8 [
|
||||
(buf.validate.field).string.pattern = "^[0-9]+-[a-z0-9]+-[a-z0-9]+-[0-9]+$"
|
||||
];
|
||||
|
||||
// W3C conform trace state header:
|
||||
// Customer set W3C conform trace state header:
|
||||
// https://www.w3.org/TR/trace-context/#tracestate-header
|
||||
//
|
||||
// Example:
|
||||
// `rojo=00f067aa0ba902b7,congo=t61rcWkgMzE`.
|
||||
string trace_state = 27;
|
||||
// Format: <key1>=<value1>[,<keyN>=<valueN>]
|
||||
//
|
||||
// Examples:
|
||||
// "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE"
|
||||
//
|
||||
// Required: false
|
||||
optional string trace_state = 9 [
|
||||
(buf.validate.field).string.pattern = "[a-zA-Z0-9]+=[a-zA-Z0-9]+(?:,[a-zA-Z0-9]+=[a-zA-Z0-9]+)*"
|
||||
];
|
||||
}
|
||||
|
||||
// The severity of the event described in a log entry, expressed as one of the
|
||||
// standard severity levels listed below. For your reference, the levels are
|
||||
// assigned the listed numeric values. The effect of using numeric values other
|
||||
// than those listed is undefined.
|
||||
// Copied from
|
||||
// https://github.com/googleapis/googleapis/blob/master/google/logging/type/log_severity.proto
|
||||
// standard severity levels listed below.
|
||||
enum LogSeverity {
|
||||
|
||||
// (0) The log entry has no assigned severity level.
|
||||
DEFAULT = 0;
|
||||
UNSPECIFIED = 0;
|
||||
|
||||
// (1) The log entry has no assigned severity level.
|
||||
// TODO check index
|
||||
DEFAULT = 1;
|
||||
|
||||
// (100) Debug or trace information.
|
||||
DEBUG = 100;
|
||||
|
|
@ -103,87 +161,156 @@ enum LogSeverity {
|
|||
// Common audit log format for STACKIT API operations.
|
||||
message AuditLog {
|
||||
|
||||
// The name of the API service performing the operation. For example,
|
||||
// `"resource-manager"`.
|
||||
string service_name = 7;
|
||||
// The name of the API service performing the operation.
|
||||
//
|
||||
// Examples:
|
||||
// "resource-manager"
|
||||
//
|
||||
// Required: true
|
||||
string service_name = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// TODO: Add extra field to open api spec for the method_name
|
||||
// TODO rename into operation?
|
||||
// The name of the service method or operation.
|
||||
// The format should is:
|
||||
// stackit.<product>.<version>.<object>.<operation>
|
||||
//
|
||||
// For example,
|
||||
// Format: stackit.<product>.<version>.<type>.<operation>
|
||||
//
|
||||
// "stackit.resourcemanager.v1.organization.created"
|
||||
// "stackit.authorization.v2.organization.moved"
|
||||
// "stackit.authorization.v2.folder.moved"
|
||||
optional string method_name = 8;
|
||||
// Examples:
|
||||
// "stackit.resourcemanager.v1.organization.created"
|
||||
// "stackit.authorization.v2.organization.moved"
|
||||
// "stackit.authorization.v2.folder.moved"
|
||||
//
|
||||
// Required: true
|
||||
string method_name = 2 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.pattern = "^stackit\\.[a-z0-9]+\\.v[1-9][0-9]*\\.[a-z0-9]+\\.[a-z0-9]+$"
|
||||
];
|
||||
|
||||
// The resource or collection that is the target of the operation.
|
||||
// The name is a scheme-less URI, not including the API service name.
|
||||
// For example:
|
||||
//
|
||||
// "projects/<id>/zones/<region-zone>/vms/<vm-id>"
|
||||
// "projects/<id>/zones/<region-zone>/vms/<vm-id>/ports/<port-id>"
|
||||
// "projects/<id>/zones/<region-zone>/instances/instance-20240723-184227
|
||||
string resource_name = 11;
|
||||
// Format: <type>/<id>[/locations/<region-zone>][/<details>]
|
||||
// Where:
|
||||
// Region-Zone: Optional region and zone id. If both, separated with a - (dash). Alternatively _ (underscore).
|
||||
// Details: Optional "<key>/<id>" pairs
|
||||
//
|
||||
// Examples:
|
||||
// "organizations/40ab14ad-b7b0-4b1c-be41-5bc820a968d1"
|
||||
// "projects/7046e7b6-5ae9-441c-99fe-2cd28a5078ec/locations/_/instances/instance-20240723-174217"
|
||||
// "projects/7046e7b6-5ae9-441c-99fe-2cd28a5078ec/locations/eu01/instances/instance-20240723-174217"
|
||||
// "projects/dd7d1807-54e9-4426-8994-721758b5b554/locations/eu01/vms/b6851b4e-7a9d-4973-ab0f-a80a13ee3060/ports/78f8bad4-a291-4fa3-b07f-4a1985d3dbe8"
|
||||
//
|
||||
// Required: true
|
||||
string resource_name = 3[
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.pattern = "^[a-z]+/[a-z0-9-]+(?:/locations/(?:(?:[a-z0-9]+(?:-[a-z0-9]+)?)|_))?(?:/[a-z0-9]+/[a-z0-9-]+)*$"
|
||||
];
|
||||
|
||||
// Authentication information.
|
||||
AuthenticationInfo authentication_info = 3;
|
||||
//
|
||||
// Required: true
|
||||
AuthenticationInfo authentication_info = 4 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// Authorization information. If there are multiple
|
||||
// resources or permissions involved, then there is
|
||||
// Authorization information. If there are multiple resources or permissions involved, then there is
|
||||
// one AuthorizationInfo element for each {resource, permission} tuple.
|
||||
repeated AuthorizationInfo authorization_info = 9;
|
||||
//
|
||||
// Required: false
|
||||
repeated AuthorizationInfo authorization_info = 5;
|
||||
|
||||
// Metadata about the operation.
|
||||
RequestMetadata request_metadata = 4;
|
||||
//
|
||||
// Required: true
|
||||
RequestMetadata request_metadata = 6 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// The operation request. This may not include all request parameters,
|
||||
// such as those that are too large, privacy-sensitive, or duplicated
|
||||
// elsewhere in the log record.
|
||||
// It should never include user-generated data, such as file contents.
|
||||
google.protobuf.Struct request = 16;
|
||||
//
|
||||
// Required: true
|
||||
google.protobuf.Struct request = 7 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// The status of the overall operation.
|
||||
ResponseStatus status = 2;
|
||||
//
|
||||
// Required: true
|
||||
ResponseStatus status = 8 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// The number of items returned from a List or Query API method,
|
||||
// if applicable.
|
||||
optional int64 num_response_items = 12;
|
||||
//
|
||||
// Required: false
|
||||
optional google.protobuf.Int64Value num_response_items = 9 [
|
||||
(buf.validate.field).int64.gte = 0
|
||||
];
|
||||
|
||||
// The operation response. This may not include all response elements,
|
||||
// such as those that are too large, privacy-sensitive, or duplicated
|
||||
// elsewhere in the log record.
|
||||
google.protobuf.Struct response = 17;
|
||||
//
|
||||
// Required: true
|
||||
google.protobuf.Struct response = 10 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// Other service-specific data about the request, response, and other
|
||||
// information associated with the current audited event.
|
||||
google.protobuf.Struct metadata = 18;
|
||||
//
|
||||
// Required: false
|
||||
optional google.protobuf.Struct metadata = 11;
|
||||
}
|
||||
|
||||
// Authentication information for the operation.
|
||||
message AuthenticationInfo {
|
||||
|
||||
// Principal id
|
||||
string principal_id = 1;
|
||||
// STACKIT principal id
|
||||
//
|
||||
// Required: true
|
||||
string principal_id = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// The email address of the authenticated user
|
||||
string principal_email = 2;
|
||||
// The email address of the authenticated user.
|
||||
// Service accounts have email addresses that can be used.
|
||||
//
|
||||
// Required: true
|
||||
string principal_email = 2 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1,
|
||||
(buf.validate.field).string.max_len = 255
|
||||
];
|
||||
|
||||
// The name of the service account used to create or exchange
|
||||
// credentials for authenticating the service account making the request.
|
||||
// Example:
|
||||
//
|
||||
// "projects/{PROJECT_ID}/serviceAccounts/{ACCOUNT}"
|
||||
optional string service_account_name = 5;
|
||||
// Format: projects/<id>/serviceAccounts/<account>
|
||||
//
|
||||
// Examples:
|
||||
// "projects/29b2c56f-f712-4a9c-845b-f0907158e53c/serviceAccounts/a606dc68-8b97-421b-89a9-116bcbd004df"
|
||||
//
|
||||
// Required: false
|
||||
optional string service_account_name = 3 [
|
||||
(buf.validate.field).string.pattern = "^[a-z]+/[a-z0-9-]+/serviceAccounts/[a-zA-Z0-9-]+$"
|
||||
];
|
||||
|
||||
// Identity delegation history of an authenticated service account that makes
|
||||
// the request. It contains information on the real authorities that try to
|
||||
// access STACKIT resources by delegating on a service account. When multiple
|
||||
// authorities present, they are guaranteed to be sorted based on the original
|
||||
// ordering of the identity delegation events.
|
||||
repeated ServiceAccountDelegationInfo service_account_delegation_info = 6;
|
||||
//
|
||||
// Required: false
|
||||
repeated ServiceAccountDelegationInfo service_account_delegation_info = 4;
|
||||
}
|
||||
|
||||
// Authorization information for the operation.
|
||||
|
|
@ -191,37 +318,44 @@ message AuthorizationInfo {
|
|||
|
||||
// The resource being accessed, as a REST-style string.
|
||||
//
|
||||
// For example:
|
||||
// Project scoped resource: projects/test-project-123/zones/us-central1-b/instances/instance-20240723-174217
|
||||
// Global Resource: projects/_/buckets/adfeaf
|
||||
string resource = 1;
|
||||
// Format: <type>/<id>[/locations/<region-zone>][/<details>]
|
||||
// Where:
|
||||
// Region-Zone: Optional region and zone id. If both, separated with a - (dash). Alternatively _ (underscore).
|
||||
// Details: Optional "<key>/<id>" pairs
|
||||
//
|
||||
// Examples:
|
||||
// "organizations/40ab14ad-b7b0-4b1c-be41-5bc820a968d1"
|
||||
// "projects/7046e7b6-5ae9-441c-99fe-2cd28a5078ec/locations/_/instances/instance-20240723-174217"
|
||||
// "projects/7046e7b6-5ae9-441c-99fe-2cd28a5078ec/locations/eu01/instances/instance-20240723-174217"
|
||||
// "projects/7046e7b6-5ae9-441c-99fe-2cd28a5078ec/locations/eu01/vms/b6851b4e-7a9d-4973-ab0f-a80a13ee3060/ports/78f8bad4-a291-4fa3-b07f-4a1985d3dbe8"
|
||||
//
|
||||
// Required: true
|
||||
string resource = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.pattern = "^[a-z]+/[a-z0-9-]+(?:/locations/(?:(?:[a-z0-9]+(?:-[a-z0-9]+)?)|_))?(?:/[a-z0-9]+/[a-z0-9-]+)*$"
|
||||
];
|
||||
|
||||
// The required IAM permission.
|
||||
string permission = 2;
|
||||
//
|
||||
// Examples:
|
||||
// "resourcemanager.project.edit"
|
||||
//
|
||||
// Required: false
|
||||
optional string permission = 2 [
|
||||
(buf.validate.field).string.pattern = "^[a-z-]+(?:\\.[a-z-]+)*\\.[a-z-]+$"
|
||||
];
|
||||
|
||||
// Whether or not authorization for `resource` and `permission`
|
||||
// was granted.
|
||||
bool granted = 3;
|
||||
//
|
||||
// Required: false
|
||||
optional bool granted = 3;
|
||||
}
|
||||
|
||||
// TODO check description
|
||||
// This message defines the standard attribute vocabulary for STACKIT APIs.
|
||||
//
|
||||
// An attribute is a piece of metadata that describes an activity on a network
|
||||
// service. For example, the size of an HTTP request, or the status code of
|
||||
// an HTTP response.
|
||||
//
|
||||
// Each attribute has a type and a name, which is logically defined as
|
||||
// a proto message field in `AttributeContext`. The field type becomes the
|
||||
// attribute type, and the field path becomes the attribute name. For example,
|
||||
// the attribute `source.ip` maps to field `AttributeContext.source.ip`.
|
||||
//
|
||||
// This message definition is guaranteed not to have any wire breaking change.
|
||||
// So you can use it directly for passing attributes across different systems.
|
||||
//
|
||||
// NOTE: Different system may generate different subset of attributes. Please
|
||||
// verify the system specification before relying on an attribute generated
|
||||
// a system.
|
||||
// service.
|
||||
message AttributeContext {
|
||||
|
||||
// This message defines request authentication attributes. Terminology is
|
||||
|
|
@ -229,55 +363,57 @@ message AttributeContext {
|
|||
// correlate to concepts in other standards.
|
||||
message Auth {
|
||||
|
||||
// TODO check description
|
||||
// The authenticated principal. Reflects the issuer (`iss`) and subject
|
||||
// (`sub`) claims within a JWT. The issuer and subject should be `/`
|
||||
// delimited, with `/` percent-encoded within the subject fragment. For
|
||||
// Google accounts, the principal format is:
|
||||
// "https://accounts.google.com/{id}"
|
||||
string principal = 1;
|
||||
// The authenticated principal. Reflects the issuer ("iss") and subject
|
||||
// ("sub") claims within a JWT.
|
||||
//
|
||||
// Format: <sub-claim>/<iss-claim>
|
||||
// Where:
|
||||
// Sub-Claim: Sub-Claim from JWT with `/` percent-encoded (url-encoded)
|
||||
//
|
||||
// Examples:
|
||||
// "https%3A%2F%2Faccounts.dev.stackit.cloud/stackit-resource-manager-dev"
|
||||
//
|
||||
// Required: true
|
||||
string principal = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.pattern = "^[a-zA-Z0-9-%.]+/[a-zA-Z0-9-%.]+$"
|
||||
];
|
||||
|
||||
// TODO check description
|
||||
// The intended audience(s) for this authentication information. Reflects
|
||||
// the audience (`aud`) claim within a JWT. The audience
|
||||
// value(s) depends on the `issuer`, but typically include one or more of
|
||||
// the following pieces of information:
|
||||
// the audience ("aud") claim within a JWT, typically the services intended
|
||||
// to receive the credential.
|
||||
//
|
||||
// * The services intended to receive the credential such as
|
||||
// ["pubsub.googleapis.com", "storage.googleapis.com"]
|
||||
// * A set of service-based scopes. For example,
|
||||
// ["https://www.googleapis.com/auth/cloud-platform"]
|
||||
// * The client id of an app, such as the Firebase project id for JWTs
|
||||
// from Firebase Auth.
|
||||
// Examples:
|
||||
// ["https://stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud", "stackit", "api"]
|
||||
//
|
||||
// Consult the documentation for the credential issuer to determine the
|
||||
// information provided.
|
||||
// Required: false
|
||||
repeated string audiences = 2;
|
||||
|
||||
// TODO check description
|
||||
// The authorized presenter of the credential. Reflects the optional
|
||||
// Authorized Presenter (`azp`) claim within a JWT or the
|
||||
// OAuth client id. For example, a Google Cloud Platform client id looks
|
||||
// as follows: "123456789012.apps.googleusercontent.com".
|
||||
string presenter = 3;
|
||||
|
||||
// TODO check description
|
||||
// Structured claims presented with the credential. JWTs include
|
||||
// `{key: value}` pairs for standard and private claims. The following
|
||||
// is a subset of the standard required and optional claims that would
|
||||
// typically be presented for a Google-based JWT:
|
||||
// {"key": <value>} pairs for standard and private claims.
|
||||
//
|
||||
// {'iss': 'accounts.google.com',
|
||||
// 'sub': '113289723416554971153',
|
||||
// 'aud': ['123456789012', 'pubsub.googleapis.com'],
|
||||
// 'azp': '123456789012.apps.googleusercontent.com',
|
||||
// 'email': 'jsmith@example.com',
|
||||
// 'iat': 1353601026,
|
||||
// 'exp': 1353604926}
|
||||
// The following is a subset of the standard required and optional claims that would
|
||||
// typically be presented for a STACKIT JWT:
|
||||
//
|
||||
// SAML assertions are similarly specified, but with an identity provider
|
||||
// dependent structure.
|
||||
google.protobuf.Struct claims = 4;
|
||||
// {
|
||||
// "aud": "https://stackit-resource-manager-dev.apps.01.cf.eu01.stackit.cloud",
|
||||
// "email": "max@mail.schwarz",
|
||||
// "exp": 1721905449,
|
||||
// "iat": 1721901849,
|
||||
// "iss": "https://api.dev.stackit.cloud",
|
||||
// "jti": "45a196e0-480f-4c34-a592-dc5db81c8c3a",
|
||||
// "nbf": 1721900462,
|
||||
// "roles": null,
|
||||
// "sub": "cd94f01a-df2e-4456-902f-48f5e57f0b63",
|
||||
// "user_id": "",
|
||||
// "x_client_id": "",
|
||||
// "zid": ""
|
||||
// }
|
||||
//
|
||||
// Required: true
|
||||
google.protobuf.Struct claims = 3 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
}
|
||||
|
||||
// This message defines attributes for an HTTP request. If the actual
|
||||
|
|
@ -288,62 +424,126 @@ message AttributeContext {
|
|||
// The unique ID for a request, which can be propagated to downstream
|
||||
// systems. The ID should have low probability of collision
|
||||
// within a single day for a specific service.
|
||||
string id = 1;
|
||||
//
|
||||
// More information can be found here: https://google.aip.dev/155
|
||||
//
|
||||
// Format: <idempotency-key>
|
||||
// Where:
|
||||
// Idempotency-key: Typically consists of a id + version
|
||||
//
|
||||
// Examples:
|
||||
// 5e3952a9-b628-4be6-ac61-b1c6eb4a110c/5
|
||||
//
|
||||
// Required: false
|
||||
optional string id = 1;
|
||||
|
||||
// The HTTP request method, such as `GET`, `POST`.
|
||||
string method = 2;
|
||||
//
|
||||
// Required: true
|
||||
// TODO does it make sense to define an enum?
|
||||
string method = 2 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// The HTTP request headers. If multiple headers share the same key, they
|
||||
// must be merged according to the HTTP spec. All header keys must be
|
||||
// lowercased, because HTTP header keys are case-insensitive.
|
||||
map<string, string> headers = 3;
|
||||
//
|
||||
// Required: true
|
||||
map<string, string> headers = 3 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// The HTTP URL path.
|
||||
string path = 4;
|
||||
//
|
||||
// Required: true
|
||||
string path = 4 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// The HTTP request `Host` header value.
|
||||
string host = 5;
|
||||
//
|
||||
// Required: true
|
||||
string host = 5 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// The HTTP URL scheme, such as `http` and `https`.
|
||||
string scheme = 6;
|
||||
//
|
||||
// Required: true
|
||||
string scheme = 6 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// The HTTP URL query in the format of `name1=value1&name2=value2`, as it
|
||||
// The HTTP URL query in the format of "name1=value1&name2=value2", as it
|
||||
// appears in the first line of the HTTP request. No decoding is performed.
|
||||
string query = 7;
|
||||
//
|
||||
// Required: false
|
||||
optional string query = 7 [
|
||||
(buf.validate.field).string.pattern = "^[a-zA-Z0-9]+=[a-zA-Z0-9]+(?:&[a-zA-Z0-9]+=[a-zA-Z0-9]+)*$"
|
||||
];
|
||||
|
||||
// The timestamp when the `destination` service receives the first byte of
|
||||
// the request.
|
||||
google.protobuf.Timestamp time = 9;
|
||||
//
|
||||
// Required: true
|
||||
google.protobuf.Timestamp time = 8 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).timestamp.lt_now = true
|
||||
];
|
||||
|
||||
// The network protocol used with the request, such as "http/1.1",
|
||||
// "spdy/3", "h2", "h2c", "webrtc", "tcp", "udp", "quic". See
|
||||
// https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids
|
||||
// for details.
|
||||
string protocol = 11;
|
||||
//
|
||||
// Required: true
|
||||
string protocol = 9 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// The request authentication. May be absent for unauthenticated requests.
|
||||
// Derived from the HTTP request `Authorization` header or equivalent.
|
||||
Auth auth = 13;
|
||||
// The request authentication.
|
||||
//
|
||||
// Required: true
|
||||
Auth auth = 10 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
}
|
||||
|
||||
// This message defines attributes for a typical network response. It
|
||||
// generally models semantics of an HTTP response.
|
||||
// TODO do we need another status code attribute in the Response?
|
||||
message Response {
|
||||
|
||||
// The HTTP response status code, such as `200` and `404`.
|
||||
int64 code = 1;
|
||||
|
||||
// The HTTP response size in bytes. If unknown, it must be -1.
|
||||
int64 size = 2;
|
||||
// The HTTP response size in bytes.
|
||||
//
|
||||
// Required: false
|
||||
optional google.protobuf.Int64Value size = 1 [
|
||||
(buf.validate.field).int64.gte = 0
|
||||
];
|
||||
|
||||
// The HTTP response headers. If multiple headers share the same key, they
|
||||
// must be merged according to HTTP spec. All header keys must be
|
||||
// lowercased, because HTTP header keys are case-insensitive.
|
||||
map<string, string> headers = 3;
|
||||
//
|
||||
// Required: true
|
||||
map<string, string> headers = 2 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
|
||||
// The timestamp when the `destination` service generates the first byte of
|
||||
// The timestamp when the "destination" service generates the first byte of
|
||||
// the response.
|
||||
google.protobuf.Timestamp time = 4;
|
||||
//
|
||||
// Required: true
|
||||
google.protobuf.Timestamp time = 3 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).timestamp.lt_now = true
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -352,33 +552,34 @@ message RequestMetadata {
|
|||
|
||||
// The IP address of the caller.
|
||||
// For caller from internet, this will be public IPv4 or IPv6 address.
|
||||
// For caller from a VM / K8s Service / etc, this
|
||||
// will be the SIT proxy's IPv4 address.
|
||||
string caller_ip = 1;
|
||||
// For caller from a VM / K8s Service / etc, this will be the SIT proxy's IPv4 address.
|
||||
//
|
||||
// Required: true
|
||||
string caller_ip = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.ip = true
|
||||
];
|
||||
|
||||
// TODO check description
|
||||
// The user agent of the caller.
|
||||
// This information is not authenticated and should be treated accordingly.
|
||||
// For example:
|
||||
//
|
||||
// + `google-api-python-client/1.4.0`:
|
||||
// The request was made by the Google API client for Python.
|
||||
// + `Cloud SDK Command Line Tool apitools-client/1.0 gcloud/0.9.62`:
|
||||
// The request was made by the Google Cloud SDK CLI (gcloud).
|
||||
// + `AppEngine-Google; (+http://code.google.com/appengine; appid:
|
||||
// s~my-project`:
|
||||
// The request was made from the `my-project` App Engine app.
|
||||
string caller_supplied_user_agent = 2;
|
||||
// Examples:
|
||||
// "OpenAPI-Generator/1.0.0/go"
|
||||
// -> The request was made by the STACKIT SDK GO client or STACKIT CLI
|
||||
// "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
|
||||
// -> The request was made by a web browser.
|
||||
//
|
||||
// Required: true
|
||||
string caller_supplied_user_agent = 2 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// TODO check description
|
||||
// Request attributes used in IAM condition evaluation. This field contains
|
||||
// request attributes like request time and access levels associated with
|
||||
// the request.
|
||||
// This field contains request attributes like request url, time, etc.
|
||||
//
|
||||
// To get the whole view of the attributes used in IAM
|
||||
// condition evaluation, the user must also look into
|
||||
// `AuditLog.authentication_info.resource_attributes`.
|
||||
AttributeContext.Request request_attributes = 7;
|
||||
// Required: true
|
||||
AttributeContext.Request request_attributes = 3 [
|
||||
(buf.validate.field).required = true
|
||||
];
|
||||
}
|
||||
|
||||
// The `Status` type defines a logical error model that is suitable for
|
||||
|
|
@ -388,12 +589,25 @@ message RequestMetadata {
|
|||
message ResponseStatus {
|
||||
|
||||
// The http or gRPC status code.
|
||||
int32 code = 1;
|
||||
//
|
||||
// Examples:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
|
||||
// https://grpc.github.io/grpc/core/md_doc_statuscodes.html
|
||||
//
|
||||
// Required: true
|
||||
google.protobuf.Int32Value code = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).int32.gte = 0
|
||||
];
|
||||
|
||||
// Short description of the error
|
||||
string message = 2;
|
||||
//
|
||||
// Required: false
|
||||
optional string message = 2;
|
||||
|
||||
// Error details
|
||||
//
|
||||
// Required: false
|
||||
repeated google.protobuf.Struct details = 3;
|
||||
}
|
||||
|
||||
|
|
@ -404,25 +618,42 @@ message ServiceAccountDelegationInfo {
|
|||
message SystemPrincipal {
|
||||
|
||||
// Metadata about the service that uses the service account.
|
||||
google.protobuf.Struct service_metadata = 3;
|
||||
//
|
||||
// Required: false
|
||||
optional google.protobuf.Struct service_metadata = 1;
|
||||
}
|
||||
|
||||
// STACKIT idp principal.
|
||||
message IdpPrincipal {
|
||||
|
||||
// STACKIT principal id
|
||||
string principal_id = 1;
|
||||
//
|
||||
// Required: true
|
||||
string principal_id = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1
|
||||
];
|
||||
|
||||
// Optional email address
|
||||
optional string principal_email = 2;
|
||||
// The email address of the authenticated user.
|
||||
// Service accounts have email addresses that can be used.
|
||||
//
|
||||
// Required: true
|
||||
string principal_email = 2 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.min_len = 1,
|
||||
(buf.validate.field).string.max_len = 255
|
||||
];
|
||||
|
||||
// Metadata about the service that uses the service account.
|
||||
google.protobuf.Struct service_metadata = 3;
|
||||
//
|
||||
// Required: false
|
||||
optional google.protobuf.Struct service_metadata = 3;
|
||||
}
|
||||
|
||||
// Entity that creates credentials for service account and assumes its
|
||||
// identity for authentication.
|
||||
oneof Authority {
|
||||
option (buf.validate.oneof).required = true;
|
||||
|
||||
// System identity
|
||||
SystemPrincipal system_principal = 1;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,10 @@ message RoutableAuditEvent {
|
|||
|
||||
// Functional event name with pattern <TYPE>_<ACTION>, e.g. ORGANIZATION_CREATED
|
||||
// Will be copied over by the SDK from the AuditEvent
|
||||
string event_name = 1 [(buf.validate.field).required = true, (buf.validate.field).string.pattern = "^[A-Z]+_[A-Z]+$"];
|
||||
string event_name = 1 [
|
||||
(buf.validate.field).required = true,
|
||||
(buf.validate.field).string.pattern = "^stackit\\.[a-z0-9]+\\.v[1-9][0-9]*\\.[a-z0-9]+\\.[a-z0-9]+$"
|
||||
];
|
||||
|
||||
// Visibility relevant for differentiating between internal and public events
|
||||
Visibility visibility = 2 [(buf.validate.field).required = true, (buf.validate.field).enum.defined_only = true];
|
||||
|
|
|
|||
Loading…
Reference in a new issue