Merged PR 752362: feat: Apply stricter linter rules

Security-concept-update-needed: false.

JIRA Work Item: STACKITALO-184
This commit is contained in:
Christian Schaible (EXT) 2025-03-25 08:40:27 +00:00
parent 68cec628e0
commit 618be58a26
15 changed files with 388 additions and 125 deletions

272
.golangci.yml Normal file
View file

@ -0,0 +1,272 @@
linters-settings:
errcheck:
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: true
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
# default is false: such cases aren't reported by default.
check-blank: true
exhaustive:
# Presence of "default" case in switch statements satisfies exhaustiveness,
# even if all enum members are not listed.
default-signifies-exhaustive: true
funlen:
lines: 100
statements: 50
gocyclo:
min-complexity: 45
gocognit:
min-complexity: 45
dupl:
threshold: 150
goconst:
min-len: 3
min-occurrences: 5
govet:
enable-all: true
disable:
- fieldalignment
lll:
line-length: 180
tab-width: 1
cyclop:
# the maximal code complexity to report
max-complexity: 45
# the maximal average package complexity. If it's higher than 0.0 (float) the check is enabled (default 0.0)
package-average: 0.0
unused:
# treat code as a program (not a library) and report unused exported identifiers; default is false.
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
unparam:
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
nakedret:
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
max-func-lines: 5
prealloc:
# XXX: we don't recommend using this linter before doing performance profiling.
# For most programs usage of prealloc will be a premature optimization.
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
# True by default.
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: true # Report preallocation suggestions on for loops, false by default
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
disabled-checks:
- dupImport # https://github.com/go-critic/go-critic/issues/845
- octalLiteral
- unnamedResult
# Settings passed to gocritic.
# The settings key is the name of a supported gocritic checker.
# The list of supported checkers can be find in https://go-critic.github.io/overview.
settings:
hugeParam:
# Size in bytes that makes the warning trigger.
# Default: 80
sizeThreshold: 121
dogsled:
# checks assignments with too many blank identifiers; default is 2
max-blank-identifiers: 2
whitespace:
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
gomoddirectives:
# List of allowed `replace` directives. Default is empty.
# Add your allowed `replace` targets here, this rule is so you don't accidentally commit replacements you added for testing
replace-allow-list: []
nolintlint:
allow-leading-space: false # require machine-readable nolint directives (i.e. with no leading space)
allow-unused: false # report any unused nolint directives
require-explanation: true # require an explanation for nolint directives
require-specific: true # require nolint directives to be specific about which linter is being skipped
nlreturn:
# Size of the block (including return statement that is still "OK")
# so no return split required.
block-size: 5
stylecheck:
initialisms: ["ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS"]
revive:
rules:
- name: context-keys-type
disabled: false
- name: time-naming
disabled: false
- name: var-declaration
disabled: false
- name: unexported-return
disabled: false
- name: errorf
disabled: false
- name: blank-imports
disabled: false
- name: context-as-argument
disabled: false
- name: dot-imports
disabled: false
- name: error-return
disabled: false
- name: error-strings
disabled: false
- name: error-naming
disabled: false
- name: exported
disabled: false
- name: increment-decrement
disabled: false
- name: var-naming
disabled: true
- name: package-comments
disabled: false
- name: range
disabled: false
- name: receiver-naming
disabled: false
- name: indent-error-flow
disabled: false
nestif:
min-complexity: 10
linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
disable-all: true
enable:
- dogsled
- dupl
- copyloopvar
- exhaustive
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goprintffuncname
- gosec
- govet
- ineffassign
- lll
- gosimple
- misspell
- nakedret
- nolintlint
- revive
- staticcheck
- typecheck
- unconvert
- unused
- gochecknoglobals
- prealloc
- asciicheck
- nestif
- bodyclose
- cyclop
- durationcheck
- errcheck
- errorlint
- forbidigo
- forcetypeassert
- gocognit
- gomoddirectives
- gomodguard
- importas
- makezero
- nilerr
- noctx
- predeclared
- promlinter
- rowserrcheck
- sqlclosecheck
- tparallel
- unparam
- wastedassign
issues:
# Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules:
- path: audit/api/api_common.go
text: 'context-as-argument'
- path: audit/api/api.go|log/log.go|audit/api/model.go|telemetry/telemetry.go
linters:
- gochecknoglobals
- path: audit/api/api_.*.go
linters:
- dupl
- path: audit/api/model.go
text: 'exported: type name will be used as api.ApiRequest by other packages'
- path: audit/api/model_test.go|audit/api/model.go
text: 'G115'
- path: audit/api/test_data.go
linters:
- gosec
- path: _test\.go
linters:
- gochecknoglobals
- noctx
- forcetypeassert
- dogsled
- goconst
- unparam
- dupl
- errcheck
- forbidigo
- lll
- gocritic
- nestif
- revive
- gocognit
- unconvert
- unparam
- wsl
- gosimple
- ineffassign
- nakedret
- nlreturn
- staticcheck
- wastedassign
- text: 'declaration of "err" shadows declaration'
linters:
- govet
- path: test_.*\.go|audit/messaging/solace.go
linters:
- gochecknoglobals
- noctx
- forcetypeassert
- dogsled
- goconst
- unparam
- dupl
- errcheck
- forbidigo
- lll
- gocritic
- nestif
- revive
- gocognit
- unconvert
- unparam
- wsl
- gosimple
- ineffassign
- nakedret
- nlreturn
- staticcheck
- wastedassign
max-same-issues: 0
max-issues-per-linter: 0
run:
timeout: 10m
issues-exit-code: 1
tests: true

View file

@ -47,13 +47,7 @@ func ObjectTypeFromPluralString(value string) ObjectType {
func (t ObjectType) IsSupportedType() error { func (t ObjectType) IsSupportedType() error {
switch t { switch t {
case ObjectTypeOrganization: case ObjectTypeOrganization, ObjectTypeFolder, ObjectTypeProject, ObjectTypeSystem:
fallthrough
case ObjectTypeFolder:
fallthrough
case ObjectTypeProject:
fallthrough
case ObjectTypeSystem:
return nil return nil
default: default:
return ErrUnknownObjectType return ErrUnknownObjectType

View file

@ -22,15 +22,16 @@ func convertAndSerializeIntoLegacyFormat(
// Event type // Event type
var eventType string var eventType string
if strings.HasSuffix(event.LogName, string(EventTypeAdminActivity)) { switch {
case strings.HasSuffix(event.LogName, string(EventTypeAdminActivity)):
eventType = "ADMIN_ACTIVITY" eventType = "ADMIN_ACTIVITY"
} else if strings.HasSuffix(event.LogName, string(EventTypeSystemEvent)) { case strings.HasSuffix(event.LogName, string(EventTypeSystemEvent)):
eventType = "SYSTEM_EVENT" eventType = "SYSTEM_EVENT"
} else if strings.HasSuffix(event.LogName, string(EventTypePolicyDenied)) { case strings.HasSuffix(event.LogName, string(EventTypePolicyDenied)):
eventType = "POLICY_DENIED" eventType = "POLICY_DENIED"
} else if strings.HasSuffix(event.LogName, string(EventTypeDataAccess)) { case strings.HasSuffix(event.LogName, string(EventTypeDataAccess)):
return nil, ErrUnsupportedEventTypeDataAccess return nil, ErrUnsupportedEventTypeDataAccess
} else { default:
return nil, errors.New("unsupported event type") return nil, errors.New("unsupported event type")
} }
@ -46,7 +47,7 @@ func convertAndSerializeIntoLegacyFormat(
} }
// Principals // Principals
var serviceAccountDelegationInfo *LegacyAuditEventServiceAccountDelegationInfo = nil var serviceAccountDelegationInfo *LegacyAuditEventServiceAccountDelegationInfo
if len(event.ProtoPayload.AuthenticationInfo.ServiceAccountDelegationInfo) > 0 { if len(event.ProtoPayload.AuthenticationInfo.ServiceAccountDelegationInfo) > 0 {
var principals []LegacyAuditEventPrincipal var principals []LegacyAuditEventPrincipal
for _, principal := range event.ProtoPayload.AuthenticationInfo.ServiceAccountDelegationInfo { for _, principal := range event.ProtoPayload.AuthenticationInfo.ServiceAccountDelegationInfo {
@ -73,7 +74,7 @@ func convertAndSerializeIntoLegacyFormat(
Endpoint: "none", Endpoint: "none",
} }
} else { } else {
var parameters map[string]interface{} = nil var parameters map[string]interface{}
if event.ProtoPayload.RequestMetadata.RequestAttributes.Path != "" && if event.ProtoPayload.RequestMetadata.RequestAttributes.Path != "" &&
event.ProtoPayload.RequestMetadata.RequestAttributes.Query != nil && event.ProtoPayload.RequestMetadata.RequestAttributes.Query != nil &&
*event.ProtoPayload.RequestMetadata.RequestAttributes.Query != "" { *event.ProtoPayload.RequestMetadata.RequestAttributes.Query != "" {
@ -95,11 +96,11 @@ func convertAndSerializeIntoLegacyFormat(
} }
} }
var body map[string]interface{} = nil var body map[string]interface{}
if event.ProtoPayload.Request != nil { if event.ProtoPayload.Request != nil {
body = event.ProtoPayload.Request.AsMap() body = event.ProtoPayload.Request.AsMap()
} }
var headers map[string]interface{} = nil var headers map[string]interface{}
if event.ProtoPayload.RequestMetadata.RequestAttributes.Headers != nil { if event.ProtoPayload.RequestMetadata.RequestAttributes.Headers != nil {
headers = map[string]interface{}{} headers = map[string]interface{}{}
for key, value := range event.ProtoPayload.RequestMetadata.RequestAttributes.Headers { for key, value := range event.ProtoPayload.RequestMetadata.RequestAttributes.Headers {
@ -152,6 +153,8 @@ func convertAndSerializeIntoLegacyFormat(
visibility = "PUBLIC" visibility = "PUBLIC"
case auditV1.Visibility_VISIBILITY_PRIVATE: case auditV1.Visibility_VISIBILITY_PRIVATE:
visibility = "PRIVATE" visibility = "PRIVATE"
case auditV1.Visibility_VISIBILITY_UNSPECIFIED:
visibility = ""
} }
// Details // Details
@ -171,23 +174,16 @@ func convertAndSerializeIntoLegacyFormat(
// Severity // Severity
var severity string var severity string
switch event.Severity { switch event.Severity {
case auditV1.LogSeverity_LOG_SEVERITY_DEFAULT: case auditV1.LogSeverity_LOG_SEVERITY_DEFAULT,
fallthrough auditV1.LogSeverity_LOG_SEVERITY_DEBUG,
case auditV1.LogSeverity_LOG_SEVERITY_DEBUG: auditV1.LogSeverity_LOG_SEVERITY_INFO,
fallthrough auditV1.LogSeverity_LOG_SEVERITY_NOTICE,
case auditV1.LogSeverity_LOG_SEVERITY_INFO: auditV1.LogSeverity_LOG_SEVERITY_WARNING:
fallthrough
case auditV1.LogSeverity_LOG_SEVERITY_NOTICE:
fallthrough
case auditV1.LogSeverity_LOG_SEVERITY_WARNING:
severity = "INFO" severity = "INFO"
case auditV1.LogSeverity_LOG_SEVERITY_ERROR: case auditV1.LogSeverity_LOG_SEVERITY_ERROR,
fallthrough auditV1.LogSeverity_LOG_SEVERITY_CRITICAL,
case auditV1.LogSeverity_LOG_SEVERITY_CRITICAL: auditV1.LogSeverity_LOG_SEVERITY_ALERT,
fallthrough auditV1.LogSeverity_LOG_SEVERITY_EMERGENCY:
case auditV1.LogSeverity_LOG_SEVERITY_ALERT:
fallthrough
case auditV1.LogSeverity_LOG_SEVERITY_EMERGENCY:
severity = "ERROR" severity = "ERROR"
default: default:
return nil, ErrUnsupportedSeverity return nil, ErrUnsupportedSeverity

View file

@ -135,7 +135,7 @@ func (a *DynamicLegacyAuditApi) Send(
return ErrNoTopicNameProvided return ErrNoTopicNameProvided
} }
topicName := fmt.Sprintf("%s", rawTopicName) topicName := fmt.Sprintf("%s", rawTopicName)
if len(topicName) == 0 { if topicName == "" {
return ErrTopicNameEmpty return ErrTopicNameEmpty
} }

View file

@ -69,9 +69,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PUBLIC visibility := auditV1.Visibility_VISIBILITY_PUBLIC
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.ErrorIs(t, auditApi.Log( assert.ErrorIs(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),
@ -102,9 +102,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PUBLIC visibility := auditV1.Visibility_VISIBILITY_PUBLIC
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, auditApi.Log( assert.NoError(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),
@ -139,9 +139,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PRIVATE visibility := auditV1.Visibility_VISIBILITY_PRIVATE
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, auditApi.Log( assert.NoError(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),
@ -177,9 +177,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PUBLIC visibility := auditV1.Visibility_VISIBILITY_PUBLIC
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, auditApi.Log( assert.NoError(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),
@ -214,9 +214,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PRIVATE visibility := auditV1.Visibility_VISIBILITY_PRIVATE
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, auditApi.Log( assert.NoError(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),
@ -252,9 +252,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PUBLIC visibility := auditV1.Visibility_VISIBILITY_PUBLIC
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, auditApi.Log( assert.NoError(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),
@ -289,9 +289,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PRIVATE visibility := auditV1.Visibility_VISIBILITY_PRIVATE
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, auditApi.Log( assert.NoError(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),
@ -326,10 +326,10 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PRIVATE visibility := auditV1.Visibility_VISIBILITY_PRIVATE
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, assert.NoError(t,
auditApi.Log( auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
RoutableSystemIdentifier, RoutableSystemIdentifier,
@ -382,10 +382,10 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PRIVATE visibility := auditV1.Visibility_VISIBILITY_PRIVATE
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, assert.NoError(t,
auditApi.Log( auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
RoutableSystemIdentifier, RoutableSystemIdentifier,
@ -439,9 +439,9 @@ func TestDynamicLegacyAuditApi(t *testing.T) {
// Log the event to solace // Log the event to solace
visibility := auditV1.Visibility_VISIBILITY_PUBLIC visibility := auditV1.Visibility_VISIBILITY_PUBLIC
ctx := context.WithValue(ctx, ContextKeyTopic, topicName) ctxWithTopic := context.WithValue(ctx, ContextKeyTopic, topicName)
assert.NoError(t, auditApi.Log( assert.NoError(t, auditApi.Log(
ctx, ctxWithTopic,
event, event,
visibility, visibility,
NewRoutableIdentifier(objectIdentifier), NewRoutableIdentifier(objectIdentifier),

View file

@ -26,12 +26,12 @@ func TestMockAuditApi_Log(t *testing.T) {
}) })
t.Run("reject data access event", func(t *testing.T) { t.Run("reject data access event", func(t *testing.T) {
event, objectIdentifier := newOrganizationAuditEvent(nil) orgEvent, objIdentifier := newOrganizationAuditEvent(nil)
event.LogName = strings.Replace(event.LogName, string(EventTypeAdminActivity), string(EventTypeDataAccess), 1) orgEvent.LogName = strings.Replace(orgEvent.LogName, string(EventTypeAdminActivity), string(EventTypeDataAccess), 1)
routableObjectIdentifier := NewRoutableIdentifier(objectIdentifier) rtIdentifier := NewRoutableIdentifier(objIdentifier)
assert.ErrorIs(t, auditApi.Log( assert.ErrorIs(t, auditApi.Log(
context.Background(), event, auditV1.Visibility_VISIBILITY_PUBLIC, routableObjectIdentifier), context.Background(), orgEvent, auditV1.Visibility_VISIBILITY_PUBLIC, rtIdentifier),
ErrUnsupportedEventTypeDataAccess) ErrUnsupportedEventTypeDataAccess)
}) })

View file

@ -41,7 +41,7 @@ func ToBase64(
} }
base64Str := base64.StdEncoding.EncodeToString(serializedEvent) base64Str := base64.StdEncoding.EncodeToString(serializedEvent)
base64Str = base64Str + base64AuditEventV1 base64Str += base64AuditEventV1
return &base64Str, nil return &base64Str, nil
} }

View file

@ -296,7 +296,7 @@ func (builder *AuditLogEntryBuilder) WithResponseBody(responseBody any) *AuditLo
} }
// WithResponseBodyBytes adds the response body as bytes (serialized json or protobuf message expected) // WithResponseBodyBytes adds the response body as bytes (serialized json or protobuf message expected)
func (builder *AuditLogEntryBuilder) WithResponseBodyBytes(responseBody *[]byte) *AuditLogEntryBuilder { func (builder *AuditLogEntryBuilder) WithResponseBodyBytes(responseBody []byte) *AuditLogEntryBuilder {
builder.auditResponse.ResponseBodyBytes = responseBody builder.auditResponse.ResponseBodyBytes = responseBody
return builder return builder
} }
@ -359,9 +359,9 @@ func (builder *AuditLogEntryBuilder) Build(ctx context.Context, sequenceNumber S
builder.auditMetadata.AuditLogName = fmt.Sprintf("%s/%s/logs/%s", logType.Plural(), logIdentifier, builder.auditParams.EventType) builder.auditMetadata.AuditLogName = fmt.Sprintf("%s/%s/logs/%s", logType.Plural(), logIdentifier, builder.auditParams.EventType)
builder.auditMetadata.AuditResourceName = resourceName builder.auditMetadata.AuditResourceName = resourceName
var details *map[string]interface{} = nil var details map[string]interface{}
if len(builder.auditParams.Details) > 0 { if len(builder.auditParams.Details) > 0 {
details = &builder.auditParams.Details details = builder.auditParams.Details
} }
// Instantiate the audit event // Instantiate the audit event
@ -575,7 +575,7 @@ func (builder *AuditEventBuilder) WithResponseBody(responseBody any) *AuditEvent
} }
// WithResponseBodyBytes adds the response body as bytes (serialized json or protobuf message expected) // WithResponseBodyBytes adds the response body as bytes (serialized json or protobuf message expected)
func (builder *AuditEventBuilder) WithResponseBodyBytes(responseBody *[]byte) *AuditEventBuilder { func (builder *AuditEventBuilder) WithResponseBodyBytes(responseBody []byte) *AuditEventBuilder {
builder.auditLogEntryBuilder.WithResponseBodyBytes(responseBody) builder.auditLogEntryBuilder.WithResponseBodyBytes(responseBody)
return builder return builder
} }

View file

@ -31,14 +31,14 @@ var ErrInvalidAuthorizationHeaderValue = errors.New("invalid authorization heade
var ErrInvalidBearerToken = errors.New("invalid bearer token") var ErrInvalidBearerToken = errors.New("invalid bearer token")
var ErrTokenIsNotBearerToken = errors.New("token is not a bearer token") var ErrTokenIsNotBearerToken = errors.New("token is not a bearer token")
var objectTypeIdPattern, _ = regexp.Compile(".*/(projects|folders|organizations)/([0-9a-fA-F-]{36})(?:/.*)?") var objectTypeIdPattern = regexp.MustCompile(".*/(projects|folders|organizations)/([0-9a-fA-F-]{36})(?:/.*)?")
type ApiRequest struct { type ApiRequest struct {
// Body // Body
// //
// Required: false // Required: false
Body *[]byte Body []byte
// The (HTTP) request headers / gRPC metadata. // The (HTTP) request headers / gRPC metadata.
// //
@ -145,7 +145,7 @@ type AuditResponse struct {
// elsewhere in the log record. // elsewhere in the log record.
// //
// Required: false // Required: false
ResponseBodyBytes *[]byte ResponseBodyBytes []byte
// The http or gRPC status code. // The http or gRPC status code.
// //
@ -294,7 +294,7 @@ func NewAuditLogEntry(
auditResponse AuditResponse, auditResponse AuditResponse,
// Optional map that is added as "details" to the message // Optional map that is added as "details" to the message
eventMetadata *map[string]interface{}, eventMetadata map[string]interface{},
// Required metadata // Required metadata
auditMetadata AuditMetadata, auditMetadata AuditMetadata,
@ -309,9 +309,9 @@ func NewAuditLogEntry(
if err != nil { if err != nil {
return nil, errors.Join(err, ErrInvalidResponse) return nil, errors.Join(err, ErrInvalidResponse)
} }
var responseLength *int64 = nil var responseLength *int64
if responseBody != nil { if responseBody != nil {
length := int64(len(*auditResponse.ResponseBodyBytes)) length := int64(len(auditResponse.ResponseBodyBytes))
responseLength = &length responseLength = &length
} }
@ -332,7 +332,7 @@ func NewAuditLogEntry(
scheme := auditRequest.Request.Scheme scheme := auditRequest.Request.Scheme
// Initialize authorization info if available // Initialize authorization info if available
var authorizationInfo []*auditV1.AuthorizationInfo = nil var authorizationInfo []*auditV1.AuthorizationInfo
if auditMetadata.AuditPermission != nil && auditMetadata.AuditPermissionGranted != nil { if auditMetadata.AuditPermission != nil && auditMetadata.AuditPermissionGranted != nil {
authorizationInfo = []*auditV1.AuthorizationInfo{ authorizationInfo = []*auditV1.AuthorizationInfo{
NewAuthorizationInfo( NewAuthorizationInfo(
@ -342,15 +342,15 @@ func NewAuditLogEntry(
} }
// Initialize labels if available // Initialize labels if available
var labels map[string]string = nil var labels map[string]string
if auditMetadata.AuditLabels != nil { if auditMetadata.AuditLabels != nil {
labels = *auditMetadata.AuditLabels labels = *auditMetadata.AuditLabels
} }
// Initialize metadata/details // Initialize metadata/details
var metadata *structpb.Struct = nil var metadata *structpb.Struct
if eventMetadata != nil { if eventMetadata != nil {
metadataStruct, err := structpb.NewStruct(*eventMetadata) metadataStruct, err := structpb.NewStruct(eventMetadata)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -480,7 +480,7 @@ func NewRequestAttributes(
) *auditV1.AttributeContext_Request { ) *auditV1.AttributeContext_Request {
rawQuery := request.URL.RawQuery rawQuery := request.URL.RawQuery
var query *string = nil var query *string
if rawQuery != nil && *rawQuery != "" { if rawQuery != nil && *rawQuery != "" {
escapedQuery := url.QueryEscape(*rawQuery) escapedQuery := url.QueryEscape(*rawQuery)
query = &escapedQuery query = &escapedQuery
@ -505,7 +505,7 @@ func NewRequestAttributes(
} }
// NewAuthorizationInfo returns protobuf AuthorizationInfo for the given parameters. // NewAuthorizationInfo returns protobuf AuthorizationInfo for the given parameters.
func NewAuthorizationInfo(resourceName string, permission string, granted bool) *auditV1.AuthorizationInfo { func NewAuthorizationInfo(resourceName, permission string, granted bool) *auditV1.AuthorizationInfo {
return &auditV1.AuthorizationInfo{ return &auditV1.AuthorizationInfo{
Resource: resourceName, Resource: resourceName,
Permission: &permission, Permission: &permission,
@ -514,14 +514,14 @@ func NewAuthorizationInfo(resourceName string, permission string, granted bool)
} }
// NewInsertId returns a correctly formatted insert id. // NewInsertId returns a correctly formatted insert id.
func NewInsertId(insertTime time.Time, location string, workerId string, eventSequenceNumber uint64) string { func NewInsertId(insertTime time.Time, location, workerId string, eventSequenceNumber uint64) string {
return fmt.Sprintf("%d/%s/%s/%d", insertTime.UnixNano(), location, workerId, eventSequenceNumber) return fmt.Sprintf("%d/%s/%s/%d", insertTime.UnixNano(), location, workerId, eventSequenceNumber)
} }
// NewResponseMetadata returns protobuf response status with status code and short message. // NewResponseMetadata returns protobuf response status with status code and short message.
func NewResponseMetadata(statusCode int, numResponseItems *int64, responseSize *int64, headers map[string]string, responseTime time.Time) *auditV1.ResponseMetadata { func NewResponseMetadata(statusCode int, numResponseItems, responseSize *int64, headers map[string]string, responseTime time.Time) *auditV1.ResponseMetadata {
var message *string = nil var message *string
if statusCode >= 400 && statusCode < 500 { if statusCode >= 400 && statusCode < 500 {
text := "Client error" text := "Client error"
message = &text message = &text
@ -530,7 +530,7 @@ func NewResponseMetadata(statusCode int, numResponseItems *int64, responseSize *
message = &text message = &text
} }
var size *wrapperspb.Int64Value = nil var size *wrapperspb.Int64Value
if responseSize != nil { if responseSize != nil {
size = wrapperspb.Int64(*responseSize) size = wrapperspb.Int64(*responseSize)
} }
@ -548,26 +548,26 @@ func NewResponseMetadata(statusCode int, numResponseItems *int64, responseSize *
} }
// NewResponseBody converts the JSON byte response into a protobuf struct. // NewResponseBody converts the JSON byte response into a protobuf struct.
func NewResponseBody(response *[]byte) (*structpb.Struct, error) { func NewResponseBody(response []byte) (*structpb.Struct, error) {
// Return if nil // Return if nil
if response == nil || len(*response) == 0 { if len(response) == 0 {
return nil, nil return nil, nil
} }
// Convert to protobuf struct // Convert to protobuf struct
return byteArrayToPbStruct(*response) return byteArrayToPbStruct(response)
} }
// NewRequestBody converts the request body into a protobuf struct. // NewRequestBody converts the request body into a protobuf struct.
func NewRequestBody(request *ApiRequest) (*structpb.Struct, error) { func NewRequestBody(request *ApiRequest) (*structpb.Struct, error) {
if request.Body == nil || len(*request.Body) == 0 { if len(request.Body) == 0 {
return nil, nil return nil, nil
} }
// Convert to protobuf struct // Convert to protobuf struct
return byteArrayToPbStruct(*request.Body) return byteArrayToPbStruct(request.Body)
} }
// byteArrayToPbStruct converts a given json byte array into a protobuf struct. // byteArrayToPbStruct converts a given json byte array into a protobuf struct.
@ -636,14 +636,17 @@ func AuditAttributesFromAuthorizationHeader(request *ApiRequest) (
error, error,
) { ) {
var authenticationPrincipal = "none/none"
var principalId = "none" var principalId = "none"
var principalEmail = EmailAddressDoNotReplyAtStackItDotCloud var principalEmail = EmailAddressDoNotReplyAtStackItDotCloud
emptyClaims, _ := structpb.NewStruct(make(map[string]interface{})) emptyClaims, err := structpb.NewStruct(make(map[string]interface{}))
if err != nil {
return nil, authenticationPrincipal, nil, nil, err
}
var auditClaims = emptyClaims var auditClaims = emptyClaims
var authenticationPrincipal = "none/none" var serviceAccountName *string
var serviceAccountName *string = nil
audiences := make([]string, 0) audiences := make([]string, 0)
var delegationInfo []*auditV1.ServiceAccountDelegationInfo = nil var delegationInfo []*auditV1.ServiceAccountDelegationInfo
authorizationHeaders := request.Header["Authorization"] authorizationHeaders := request.Header["Authorization"]
if len(authorizationHeaders) == 0 { if len(authorizationHeaders) == 0 {
@ -652,7 +655,7 @@ func AuditAttributesFromAuthorizationHeader(request *ApiRequest) (
} }
authorizationHeader := strings.Join(authorizationHeaders, ",") authorizationHeader := strings.Join(authorizationHeaders, ",")
trimmedAuthorizationHeader := strings.TrimSpace(authorizationHeader) trimmedAuthorizationHeader := strings.TrimSpace(authorizationHeader)
if len(trimmedAuthorizationHeader) > 0 { if trimmedAuthorizationHeader != "" {
// Parse claims // Parse claims
token, err := parseToken(trimmedAuthorizationHeader) token, err := parseToken(trimmedAuthorizationHeader)
@ -712,9 +715,8 @@ func getTokenClaim(token jwt.Token, claimName string) *string {
if claimExists { if claimExists {
claimString := fmt.Sprintf("%s", claim) claimString := fmt.Sprintf("%s", claim)
return &claimString return &claimString
} else {
return nil
} }
return nil
} }
func extractAuthenticationPrincipal(token jwt.Token) string { func extractAuthenticationPrincipal(token jwt.Token) string {
@ -792,9 +794,8 @@ func extractServiceAccountDelegationInfoDetails(actClaims map[string]interface{}
nestedDelegations := extractServiceAccountDelegationInfo(actClaims) nestedDelegations := extractServiceAccountDelegationInfo(actClaims)
if len(nestedDelegations) > 0 { if len(nestedDelegations) > 0 {
return append(delegations, nestedDelegations...) return append(delegations, nestedDelegations...)
} else {
return delegations
} }
return delegations
} }
func extractServiceAccountDelegationInfo(claims map[string]interface{}) []*auditV1.ServiceAccountDelegationInfo { func extractServiceAccountDelegationInfo(claims map[string]interface{}) []*auditV1.ServiceAccountDelegationInfo {
@ -840,7 +841,7 @@ func extractSubjectAndEmail(token jwt.Token) (string, string) {
// - PATCH - update // - PATCH - update
// - DELETE - delete // - DELETE - delete
// - others - read // - others - read
func OperationNameFromUrlPath(path string, requestMethod string) string { func OperationNameFromUrlPath(path, requestMethod string) string {
queryIdx := strings.Index(path, "?") queryIdx := strings.Index(path, "?")
if queryIdx != -1 { if queryIdx != -1 {
path = path[:queryIdx] path = path[:queryIdx]
@ -862,13 +863,12 @@ func OperationNameFromUrlPath(path string, requestMethod string) string {
operation = strings.ReplaceAll(operation, "/", ".") operation = strings.ReplaceAll(operation, "/", ".")
operation = strings.TrimPrefix(operation, ".") operation = strings.TrimPrefix(operation, ".")
operation = strings.ToLower(operation) operation = strings.ToLower(operation)
if len(operation) > 0 { if operation != "" {
method := StringToHttpMethod(requestMethod) method := StringToHttpMethod(requestMethod)
var action string var action string
switch method { switch method {
case auditV1.AttributeContext_HTTP_METHOD_PUT: case auditV1.AttributeContext_HTTP_METHOD_PUT,
fallthrough auditV1.AttributeContext_HTTP_METHOD_PATCH:
case auditV1.AttributeContext_HTTP_METHOD_PATCH:
action = "update" action = "update"
case auditV1.AttributeContext_HTTP_METHOD_POST: case auditV1.AttributeContext_HTTP_METHOD_POST:
action = "create" action = "create"
@ -936,14 +936,14 @@ func StringAttributeFromMetadata(metadata map[string][]string, name string) stri
} }
// ResponseBodyToBytes converts a JSON or Protobuf response into a byte array // ResponseBodyToBytes converts a JSON or Protobuf response into a byte array
func ResponseBodyToBytes(response any) (*[]byte, error) { func ResponseBodyToBytes(response any) ([]byte, error) {
if response == nil { if response == nil {
return nil, nil return nil, nil
} }
responseBytes, isBytes := response.([]byte) responseBytes, isBytes := response.([]byte)
if isBytes { if isBytes {
return &responseBytes, nil return responseBytes, nil
} }
responseProtoMessage, isProtoMessage := response.(proto.Message) responseProtoMessage, isProtoMessage := response.(proto.Message)
@ -952,12 +952,13 @@ func ResponseBodyToBytes(response any) (*[]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &responseJson, nil return responseJson, nil
} else {
responseJson, err := json.Marshal(response)
if err != nil {
return nil, err
}
return &responseJson, nil
} }
responseJson, err := json.Marshal(response)
if err != nil {
return nil, err
}
return responseJson, nil
} }

View file

@ -787,7 +787,7 @@ func Test_NewAuditLogEntry(t *testing.T) {
Proto: "HTTP/1.1", Proto: "HTTP/1.1",
Scheme: "http", Scheme: "http",
Header: requestHeaders, Header: requestHeaders,
Body: &requestBodyBytes, Body: requestBodyBytes,
} }
clientIp := "127.0.0.1" clientIp := "127.0.0.1"
@ -814,7 +814,7 @@ func Test_NewAuditLogEntry(t *testing.T) {
responseTime := time.Now().UTC() responseTime := time.Now().UTC()
auditResponse := AuditResponse{ auditResponse := AuditResponse{
ResponseBodyBytes: &responseBody, ResponseBodyBytes: responseBody,
ResponseStatusCode: responseStatusCode, ResponseStatusCode: responseStatusCode,
ResponseHeaders: responseHeader, ResponseHeaders: responseHeader,
ResponseNumItems: &responseNumItems, ResponseNumItems: &responseNumItems,
@ -853,7 +853,7 @@ func Test_NewAuditLogEntry(t *testing.T) {
logEntry, _ := NewAuditLogEntry( logEntry, _ := NewAuditLogEntry(
auditRequest, auditRequest,
auditResponse, auditResponse,
&eventMetadata, eventMetadata,
auditMetadata) auditMetadata)
assert.Equal(t, logName, logEntry.LogName) assert.Equal(t, logName, logEntry.LogName)
@ -1104,7 +1104,7 @@ func Test_ResponseBodyToBytes(t *testing.T) {
responseBody := []byte("data") responseBody := []byte("data")
bytes, err := ResponseBodyToBytes(responseBody) bytes, err := ResponseBodyToBytes(responseBody)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, &responseBody, bytes) assert.Equal(t, responseBody, bytes)
}, },
) )
@ -1116,7 +1116,7 @@ func Test_ResponseBodyToBytes(t *testing.T) {
expected, err := protojson.Marshal(&protobufMessage) expected, err := protojson.Marshal(&protobufMessage)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, &expected, bytes) assert.Equal(t, expected, bytes)
}, },
) )
@ -1132,7 +1132,7 @@ func Test_ResponseBodyToBytes(t *testing.T) {
expected, err := json.Marshal(responseBody) expected, err := json.Marshal(responseBody)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, &expected, bytes) assert.Equal(t, expected, bytes)
}, },
) )
@ -1145,7 +1145,7 @@ func Test_ResponseBodyToBytes(t *testing.T) {
expected, err := json.Marshal(responseBody) expected, err := json.Marshal(responseBody)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, &expected, bytes) assert.Equal(t, expected, bytes)
}, },
) )
} }

View file

@ -24,7 +24,7 @@ func TraceParentAndStateFromContext(ctx context.Context) (string, string) {
} }
// AddTraceParentAndStateToContext adds trace and state related information to the given context. // AddTraceParentAndStateToContext adds trace and state related information to the given context.
func AddTraceParentAndStateToContext(ctx context.Context, traceParent string, traceState string) context.Context { func AddTraceParentAndStateToContext(ctx context.Context, traceParent, traceState string) context.Context {
mapCarrier := propagation.MapCarrier{} mapCarrier := propagation.MapCarrier{}
mapCarrier[traceParentHeader] = traceParent mapCarrier[traceParentHeader] = traceParent
mapCarrier[traceStateHeader] = traceState mapCarrier[traceStateHeader] = traceState

View file

@ -10,7 +10,7 @@ import (
"time" "time"
) )
var ConnectionClosedError = errors.New("amqp connection is closed") var ErrConnectionClosed = errors.New("amqp connection is closed")
type AmqpConnection struct { type AmqpConnection struct {
connectionName string connectionName string
@ -115,7 +115,7 @@ func (c *AmqpConnection) NewSender(ctx context.Context, topic string) (*AmqpSend
} }
if c.internalIsClosed() { if c.internalIsClosed() {
return nil, ConnectionClosedError return nil, ErrConnectionClosed
} }
c.lock.RLock() c.lock.RLock()

View file

@ -137,9 +137,9 @@ func (p *AmqpConnectionPool) NewHandle() *ConnectionPoolHandle {
defer p.lock.Unlock() defer p.lock.Unlock()
offset := p.handleOffset offset := p.handleOffset
p.handleOffset += 1 p.handleOffset++
offset = offset % p.config.PoolSize offset %= p.config.PoolSize
return &ConnectionPoolHandle{ return &ConnectionPoolHandle{
connectionOffset: offset, connectionOffset: offset,
@ -224,7 +224,6 @@ func (p *AmqpConnectionPool) nextConnectionForHandle(handle *ConnectionPoolHandl
func (p *AmqpConnectionPool) connectionIndex(handle *ConnectionPoolHandle, iteration int) int { func (p *AmqpConnectionPool) connectionIndex(handle *ConnectionPoolHandle, iteration int) int {
if iteration+handle.connectionOffset >= p.config.PoolSize { if iteration+handle.connectionOffset >= p.config.PoolSize {
return (iteration + handle.connectionOffset) % p.config.PoolSize return (iteration + handle.connectionOffset) % p.config.PoolSize
} else {
return iteration + handle.connectionOffset
} }
return iteration + handle.connectionOffset
} }

View file

@ -40,7 +40,7 @@ func (g *DefaultSequenceNumberGenerator) Next() uint64 {
var next uint64 var next uint64
if len(g.backlog) == 0 { if len(g.backlog) == 0 {
next = g.sequenceNumber next = g.sequenceNumber
g.sequenceNumber += 1 g.sequenceNumber++
} else { } else {
next = g.backlog[0] next = g.backlog[0]
g.backlog = g.backlog[1:] g.backlog = g.backlog[1:]
@ -53,7 +53,7 @@ func (g *DefaultSequenceNumberGenerator) Revert(value uint64) {
g.sequenceNumberLock.Lock() g.sequenceNumberLock.Lock()
defer g.sequenceNumberLock.Unlock() defer g.sequenceNumberLock.Unlock()
if value == g.sequenceNumber-1 { if value == g.sequenceNumber-1 {
g.sequenceNumber -= 1 g.sequenceNumber--
} else if !slices.Contains(g.backlog, value) { } else if !slices.Contains(g.backlog, value) {
g.backlog = append(g.backlog, value) g.backlog = append(g.backlog, value)
} }

View file

@ -16,11 +16,12 @@ type Logger interface {
func wrapErr(err []error) error { func wrapErr(err []error) error {
var e error var e error
if len(err) == 0 { switch {
case len(err) == 0:
e = nil e = nil
} else if len(err) == 1 { case len(err) == 1:
e = err[0] e = err[0]
} else { default:
e = errors.Join(err...) e = errors.Join(err...)
} }
return e return e