Compare commits

..

7 commits
v1.1.0 ... main

Author SHA1 Message Date
Christian Schaible (EXT)
80326d88a6 Merged PR 908570: feat: Update dependencies and add sonarqube configuration
- Update dependencies
- Update related code adjustments
- Add sonarqube configuration and pipeline adjustments

Security-concept-update-needed: false.

JIRA Work Item: [STACKITRMA-822](https://jira.schwarz/browse/STACKITRMA-822)
2026-01-13 09:00:27 +00:00
Christian Schaible (EXT)
b10f6797ff Merged PR 890629: feat: Update dependencies
Security-concept-update-needed: false.

JIRA Work Item: [STACKITRMA-697](https://jira.schwarz/browse/STACKITRMA-697)
2025-12-02 08:30:55 +00:00
Mathias Koehrer (EXT)
84c49f2690 Merged PR 889470: feat: Add more validation to proto schema
Made the initiator.email optional and added a new validation.
Added a new regex pattern to string fields to prevent them from consisting only of whitespace.

Security-concept-update-needed: false

JIRA Work Item: [STACKITRMA-677](https://jira.schwarz/browse/STACKITRMA-677)
2025-11-27 14:52:27 +00:00
Christian Schaible (EXT)
4c7c36c8f1 Merged PR 880350: feat: Add auditlog deprecation notice
Security-concept-update-needed: false.

JIRA Work Item: [STACKITRMA-647](https://jira.schwarz/browse/STACKITRMA-647)
2025-11-27 14:17:40 +00:00
Patrick Schmitz (EXT)
a706af62a4 Merged PR 861752: feat: Adjust azure pr template to fit with the current jira board setup
Adjust azure pr template to fit with the current jira board setup

Security-concept-update-needed: false.

JIRA Work Item: [STACKITRMA-553](https://jira.schwarz/browse/STACKITRMA-553)
2025-10-14 13:24:13 +00:00
Christian Schaible (EXT)
f2715624e9 Merged PR 843653: feat: Allow underscores in subject-claims and update dependencies
The subject claim may contain underscore characters which are not allowed by the schema yet. Therefore, an adjustment of the regex in the schema has been made to allow it.

Security-concept-update-needed: false.

JIRA Work Item: STACKITALO-437
2025-09-11 07:51:34 +00:00
Christian Schaible (EXT)
40eacfe4ad Merged PR 804853: fix: Update dependencies
Security-concept-update-needed: false.

JIRA Work Item: STACKITALO-284
2025-06-30 09:15:01 +00:00
20 changed files with 621 additions and 275 deletions

View file

@ -4,19 +4,19 @@ pool:
variables: variables:
- name: bufVersion - name: bufVersion
# go install github.com/bufbuild/buf/cmd/buf@ # go install github.com/bufbuild/buf/cmd/buf@
value: v1.55.1 value: v1.63.0
- name: golangCiLintVersion - name: golangCiLintVersion
# github.com/golangci/golangci-lint # github.com/golangci/golangci-lint
value: v2.1.6 value: v2.8.0
- name: goVersion - name: goVersion
# github.com/golang/go # github.com/golang/go
value: 1.24.0 value: 1.24.0
- name: protobufValidateVersion - name: protobufValidateVersion
# go install github.com/envoyproxy/protoc-gen-validate@ # go install github.com/envoyproxy/protoc-gen-validate@
value: v1.2.1 value: v1.3.0
- name: protobufVersion - name: protobufVersion
# go install google.golang.org/protobuf/cmd/protoc-gen-go@ # go install google.golang.org/protobuf/cmd/protoc-gen-go@
value: v1.36.6 value: v1.36.11
- name: GOPATH - name: GOPATH
value: '$(system.defaultWorkingDirectory)/gopath' value: '$(system.defaultWorkingDirectory)/gopath'

View file

@ -0,0 +1,46 @@
---
name: audit_go_main_code_analyze_$(Date:yyyy-MM-dd)_$(SourceBranchName)_$(Rev:r)
trigger:
- main
resources:
repositories:
- repository: tools
type: git
name: schwarzit.stackit-core-platform/core-platform-tools
ref: refs/tags/v1.15.0
pool:
vmImage: ubuntu-24.04
variables:
- name: reportDir
value: '$(System.DefaultWorkingDirectory)/out'
- name: goVersion
value: 1.25.5
stages:
- stage: CodeQualityScans
displayName: "Code Quality Scans"
jobs:
- template: ./.azuredevops/templates/jobs/code/code-format.yml@tools
parameters:
lintReports: true
lintReportDir: $(reportDir)
- template: ./.azuredevops/templates/jobs/code/code-test.yml@tools
parameters:
testReports: true
testReportDir: $(reportDir)
- template: ./.azuredevops/templates/jobs/code/code-quality-scans.yml@tools
parameters:
dependsOn:
- Tests
- Linter
organization: 'xx-sit-odj-stackit-public'
serviceConnection: 'xx-sit-odj-stackit-public-snyk'
sonar: true
sonarReportSourceDir: $(reportDir)
sonarServiceConnection: sonarqube-audit-go

View file

@ -6,6 +6,6 @@
[Describe how the change was tested if it needs explanation] [Describe how the change was tested if it needs explanation]
Security-concept-update-needed: true/false. Security-concept-update-needed: false.
JIRA Work Item: STACKITALO-xxx JIRA Work Item: [STACKITRMA-XXX](https://jira.schwarz/browse/STACKITRMA-XXX)

View file

@ -267,6 +267,10 @@ linters:
- wastedassign - wastedassign
- wsl - wsl
path: test_.*\.go|pkg/messaging/test/solace.go path: test_.*\.go|pkg/messaging/test/solace.go
- linters:
- prealloc
path: internal/messaging/amqp_connection_pool_test.go
text: Consider preallocating connections with capacity 5
paths: paths:
- third_party$ - third_party$
- builtin$ - builtin$

82
Makefile Normal file
View file

@ -0,0 +1,82 @@
SHELL = /bin/bash -euo pipefail
PWD = $(shell pwd)
export PATH := $(PWD)/bin:$(PATH)
# constants
GOLANGCI_VERSION = 2.8.0
all: download build ## Initializes all tools and files
all/ci: ado-git-setup all
out:
@mkdir -pv "$(@)"
build: out ## do nothing
.PHONY: build/%
build/%: out ## do nothing
download:
@go mod download
fmt:
@go fmt ./...
GOLANGCI_LINT = bin/golangci-lint-$(GOLANGCI_VERSION)
$(GOLANGCI_LINT):
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- -b bin v$(GOLANGCI_VERSION)
@mv bin/golangci-lint "$(@)"
lint: fmt $(GOLANGCI_LINT) download ## Lints all code with golangci-lint
@$(GOLANGCI_LINT) run
lint/fix: fmt $(GOLANGCI_LINT) download ## Fixes automatically fixable things like imports for the defined lint rules
@$(GOLANGCI_LINT) run --fix
lint/reports: fmt $(GOLANGCI_LINT) download ## Fixes automatically fixable things like imports for the defined lint rules
@$(GOLANGCI_LINT) run ./... --output.checkstyle.path stdout | awk '!/0 issues./' > out/lint.xml
test-clean:
@go clean -testcache
tidy:
@go mod tidy
test:
@go test ./...
coverage: out/report.json ## Displays coverage per func on cli
go tool cover -func=out/cover.out
html-coverage: out/report.json ## Displays the coverage results in the browser
go tool cover -html=out/cover.out
test-reports: out/report.json
.PHONY: out/report.json
out/report.json: out
go test -v $$(go list ./... | grep -v '/tests') -tags=unit -coverprofile=out/cover.out -json | tee "$(@)"
clean:
@rm -rf bin out
.PHONY: ado-git-setup
ado-git-setup:
# Add "dev.azure.com/schwarzit" to GOPRIVATE if not present
@priv="$$(go env GOPRIVATE)"; \
[[ "$$priv" =~ '(^|,)dev\.azure\.com(/|,|$)' ]] || go env -w "GOPRIVATE=$${priv:+$$priv,}dev.azure.com/schwarzit"
# Configure HTTPS (with PAT) or SSH access to Go import paths
@if [[ -n "$${ADO_PAT:+x}" ]]; then \
git config --global "url.https://schwarzit:$${ADO_PAT}@dev.azure.com/schwarzit/.insteadof" 'https://dev.azure.com/schwarzit/'; \
else \
git config --global 'url.git@ssh.dev.azure.com:v3/schwarzit.insteadOf' 'https://dev.azure.com/schwarzit'; \
fi
help:
@echo 'Usage: make <OPTIONS> ... <TARGETS>'
@echo ''
@echo 'Available targets are:'
@echo ''
@grep -E '^[ a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
@echo ''

View file

@ -1,3 +1,35 @@
> ## DEPRECATION NOTICE
>
> ### Discontinuation of the current audit log system
>
> The audit log system provided to date will be discontinued in its current form.
> This decision was made to pave the way for a new, more powerful audit log system that
> will be provided in the future. The new system offers extended functionalities and
> improved integration options, particularly with regard to the use and analysis of
> audit data by our customers.
>
> ### What does it mean?
> The existing audit log system will be supported until the new system is generally
> available to customers on Mai 1, 2026.
> **Services that are already sending audit log events to the existing audit log
> system must continue to do so until the new system is GA** and further information
> about the shutdown process is provided.
> **Large volumes of new audit event types must not be sent to the existing audit log
> system.**
>
> STACKIT services should start migrating to the new system now by sending data to
> the new system (**in parallel**).
> **The new audit log system may drop and does not guarantee to store events until
> it will be GA**.
> Further information on the changeover and how to use the new system can be found in the
> [developer docs](https://developers.stackit.schwarz/domains/central-services/telemetry-router/integration/).
>
> We are confident that the new audit log system will make an important contribution to
> improving the transparency, traceability, and integration for our customers.
> If you have any questions or need assistance, the
> [STACKIT Telemetry Hub](https://chat.google.com/room/AAQAf9NsX6M?cls=7) team will be
> happy to help.
## audit-go ## audit-go
The audit-go library is the core library for validation and sending of audit events. The audit-go library is the core library for validation and sending of audit events.
@ -32,13 +64,7 @@ The code can be found in the [api_routable.go](./api_routable.go) and
### Development ### Development
#### Go #### Go
The current minimum toolchain version is **go1.24.0**. The current minimum Go version is **go1.24.0**.
The toolchain version can be set as environment variable (either manually in the terminal
or in the ~/.basrc or ~/.zshrc):
```shell
export GOTOOLCHAIN=go1.24.0
```
#### Linter #### Linter
@ -46,7 +72,7 @@ The linter *golangci-lint* can either be installed via package manager (e.g. bre
by running the following command in the terminal: by running the following command in the terminal:
```shell ```shell
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.1.6 curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.8.0
``` ```
#### Schema Generation #### Schema Generation
@ -61,9 +87,9 @@ Buf and the required plugins can either be installed via package manager (e.g. b
or manually by running: or manually by running:
```shell ```shell
go install github.com/bufbuild/buf/cmd/buf@v1.55.1 #Pipeline: bufVersion go install github.com/bufbuild/buf/cmd/buf@v1.63.0 #Pipeline: bufVersion
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.6 #Pipeline: protobufVersion, go.mod: buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11 #Pipeline: protobufVersion, go.mod: buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go
go install github.com/envoyproxy/protoc-gen-validate@v1.2.1 #Pipeline: protobufValidateVersion, go.mod: google.golang.org/protobuf go install github.com/envoyproxy/protoc-gen-validate@v1.3.0 #Pipeline: protobufValidateVersion, go.mod: google.golang.org/protobuf
``` ```
Please check that the versions above match the versions in the *go.mod* file Please check that the versions above match the versions in the *go.mod* file

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.6 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc (unknown)
// source: audit/v1/audit_event.proto // source: audit/v1/audit_event.proto
@ -521,8 +521,8 @@ type AuthenticationInfo struct {
// The email address of the authenticated user. // The email address of the authenticated user.
// Service accounts have email addresses that can be used. // Service accounts have email addresses that can be used.
// //
// Required: true // Required: false
PrincipalEmail string `protobuf:"bytes,2,opt,name=principal_email,json=principalEmail,proto3" json:"principal_email,omitempty"` PrincipalEmail *string `protobuf:"bytes,2,opt,name=principal_email,json=principalEmail,proto3,oneof" json:"principal_email,omitempty"`
// The name of the service account used to create or exchange // The name of the service account used to create or exchange
// credentials for authenticating the service account making the request. // credentials for authenticating the service account making the request.
// //
@ -584,8 +584,8 @@ func (x *AuthenticationInfo) GetPrincipalId() string {
} }
func (x *AuthenticationInfo) GetPrincipalEmail() string { func (x *AuthenticationInfo) GetPrincipalEmail() string {
if x != nil { if x != nil && x.PrincipalEmail != nil {
return x.PrincipalEmail return *x.PrincipalEmail
} }
return "" return ""
} }
@ -1480,10 +1480,10 @@ const file_audit_v1_audit_event_proto_rawDesc = "" +
"\vLabelsEntry\x12\x10\n" + "\vLabelsEntry\x12\x10\n" +
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\x11\n" + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01B\x11\n" +
"\x0f_correlation_id\"\xab\x06\n" + "\x0f_correlation_id\"\xb3\x06\n" +
"\bAuditLog\x12-\n" + "\bAuditLog\x125\n" +
"\fservice_name\x18\x01 \x01(\tB\n" + "\fservice_name\x18\x01 \x01(\tB\x12\xbaH\x0f\xc8\x01\x01r\n" +
"\xbaH\a\xc8\x01\x01r\x02\x10\x01R\vserviceName\x12w\n" + "\x10\x012\x06.*\\S.*R\vserviceName\x12w\n" +
"\x0eoperation_name\x18\x02 \x01(\tBP\xbaHM\xc8\x01\x01rH\x10\x01\x18\xff\x012A^stackit\\.[a-z0-9-]+\\.(?:v[0-9]+\\.)?(?:[a-z0-9-.]+\\.)?[a-z0-9-]+$R\roperationName\x12c\n" + "\x0eoperation_name\x18\x02 \x01(\tBP\xbaHM\xc8\x01\x01rH\x10\x01\x18\xff\x012A^stackit\\.[a-z0-9-]+\\.(?:v[0-9]+\\.)?(?:[a-z0-9-.]+\\.)?[a-z0-9-]+$R\roperationName\x12c\n" +
"\rresource_name\x18\x03 \x01(\tB>\xbaH;\xc8\x01\x01r6\x10\x01\x18\xff\x012/^[a-z]+/[a-z0-9-]+(?:/[a-z0-9-]+/[a-z0-9-_]+)*$R\fresourceName\x12U\n" + "\rresource_name\x18\x03 \x01(\tB>\xbaH;\xc8\x01\x01r6\x10\x01\x18\xff\x012/^[a-z]+/[a-z0-9-]+(?:/[a-z0-9-]+/[a-z0-9-_]+)*$R\fresourceName\x12U\n" +
"\x13authentication_info\x18\x04 \x01(\v2\x1c.audit.v1.AuthenticationInfoB\x06\xbaH\x03\xc8\x01\x01R\x12authenticationInfo\x12J\n" + "\x13authentication_info\x18\x04 \x01(\v2\x1c.audit.v1.AuthenticationInfoB\x06\xbaH\x03\xc8\x01\x01R\x12authenticationInfo\x12J\n" +
@ -1497,14 +1497,14 @@ const file_audit_v1_audit_event_proto_rawDesc = "" +
"\n" + "\n" +
"\b_requestB\v\n" + "\b_requestB\v\n" +
"\t_responseB\v\n" + "\t_responseB\v\n" +
"\t_metadata\"\xf3\x02\n" + "\t_metadata\"\x93\x03\n" +
"\x12AuthenticationInfo\x12-\n" + "\x12AuthenticationInfo\x125\n" +
"\fprincipal_id\x18\x01 \x01(\tB\n" + "\fprincipal_id\x18\x01 \x01(\tB\x12\xbaH\x0f\xc8\x01\x01r\n" +
"\xbaH\a\xc8\x01\x01r\x02\x10\x01R\vprincipalId\x126\n" + "\x10\x012\x06.*\\S.*R\vprincipalId\x12:\n" +
"\x0fprincipal_email\x18\x02 \x01(\tB\r\xbaH\n" + "\x0fprincipal_email\x18\x02 \x01(\tB\f\xbaH\tr\a\x10\x05\x18\xff\x01`\x01H\x00R\x0eprincipalEmail\x88\x01\x01\x12n\n" +
"\xc8\x01\x01r\x05\x10\x01\x18\xff\x01R\x0eprincipalEmail\x12n\n" + "\x14service_account_name\x18\x03 \x01(\tB7\xbaH4r220^[a-z-]+/[a-z0-9-]+/service-accounts/[a-z0-9-]+$H\x01R\x12serviceAccountName\x88\x01\x01\x12m\n" +
"\x14service_account_name\x18\x03 \x01(\tB7\xbaH4r220^[a-z-]+/[a-z0-9-]+/service-accounts/[a-z0-9-]+$H\x00R\x12serviceAccountName\x88\x01\x01\x12m\n" + "\x1fservice_account_delegation_info\x18\x04 \x03(\v2&.audit.v1.ServiceAccountDelegationInfoR\x1cserviceAccountDelegationInfoB\x12\n" +
"\x1fservice_account_delegation_info\x18\x04 \x03(\v2&.audit.v1.ServiceAccountDelegationInfoR\x1cserviceAccountDelegationInfoB\x17\n" + "\x10_principal_emailB\x17\n" +
"\x15_service_account_name\"\xf2\x01\n" + "\x15_service_account_name\"\xf2\x01\n" +
"\x11AuthorizationInfo\x12U\n" + "\x11AuthorizationInfo\x12U\n" +
"\bresource\x18\x01 \x01(\tB9\xbaH6\xc8\x01\x01r12/^[a-z]+/[a-z0-9-]+(?:/[a-z0-9-]+/[a-z0-9-_]+)*$R\bresource\x12L\n" + "\bresource\x18\x01 \x01(\tB9\xbaH6\xc8\x01\x01r12/^[a-z]+/[a-z0-9-]+(?:/[a-z0-9-]+/[a-z0-9-_]+)*$R\bresource\x12L\n" +
@ -1514,26 +1514,25 @@ const file_audit_v1_audit_event_proto_rawDesc = "" +
"\agranted\x18\x03 \x01(\bH\x01R\agranted\x88\x01\x01B\r\n" + "\agranted\x18\x03 \x01(\bH\x01R\agranted\x88\x01\x01B\r\n" +
"\v_permissionB\n" + "\v_permissionB\n" +
"\n" + "\n" +
"\b_granted\"\x89\v\n" + "\b_granted\"\xaa\v\n" +
"\x10AttributeContext\x1a\xa8\x01\n" + "\x10AttributeContext\x1a\xa9\x01\n" +
"\x04Auth\x12I\n" + "\x04Auth\x12J\n" +
"\tprincipal\x18\x01 \x01(\tB+\xbaH(\xc8\x01\x01r#2!^[a-zA-Z0-9-%.]+/[a-zA-Z0-9-%.]+$R\tprincipal\x12\x1c\n" + "\tprincipal\x18\x01 \x01(\tB,\xbaH)\xc8\x01\x01r$2\"^[a-zA-Z0-9-%._]+/[a-zA-Z0-9-%.]+$R\tprincipal\x12\x1c\n" +
"\taudiences\x18\x02 \x03(\tR\taudiences\x127\n" + "\taudiences\x18\x02 \x03(\tR\taudiences\x127\n" +
"\x06claims\x18\x03 \x01(\v2\x17.google.protobuf.StructB\x06\xbaH\x03\xc8\x01\x01R\x06claims\x1a\xae\x04\n" + "\x06claims\x18\x03 \x01(\v2\x17.google.protobuf.StructB\x06\xbaH\x03\xc8\x01\x01R\x06claims\x1a\xce\x04\n" +
"\aRequest\x12\x13\n" + "\aRequest\x12\x13\n" +
"\x02id\x18\x01 \x01(\tH\x00R\x02id\x88\x01\x01\x12J\n" + "\x02id\x18\x01 \x01(\tH\x00R\x02id\x88\x01\x01\x12J\n" +
"\x06method\x18\x02 \x01(\x0e2%.audit.v1.AttributeContext.HttpMethodB\v\xbaH\b\xc8\x01\x01\x82\x01\x02\x10\x01R\x06method\x12Q\n" + "\x06method\x18\x02 \x01(\x0e2%.audit.v1.AttributeContext.HttpMethodB\v\xbaH\b\xc8\x01\x01\x82\x01\x02\x10\x01R\x06method\x12Q\n" +
"\aheaders\x18\x03 \x03(\v2/.audit.v1.AttributeContext.Request.HeadersEntryB\x06\xbaH\x03\xc8\x01\x01R\aheaders\x12!\n" + "\aheaders\x18\x03 \x03(\v2/.audit.v1.AttributeContext.Request.HeadersEntryB\x06\xbaH\x03\xc8\x01\x01R\aheaders\x12)\n" +
"\x04path\x18\x04 \x01(\tB\r\xbaH\n" + "\x04path\x18\x04 \x01(\tB\x15\xbaH\x12\xc8\x01\x01r\r\x10\x01\x18\xff\x012\x06.*\\S.*R\x04path\x12&\n" +
"\xc8\x01\x01r\x05\x10\x01\x18\xff\x01R\x04path\x12\x1e\n" + "\x04host\x18\x05 \x01(\tB\x12\xbaH\x0f\xc8\x01\x01r\n" +
"\x04host\x18\x05 \x01(\tB\n" + "\x10\x012\x06.*\\S.*R\x04host\x12*\n" +
"\xbaH\a\xc8\x01\x01r\x02\x10\x01R\x04host\x12\"\n" + "\x06scheme\x18\x06 \x01(\tB\x12\xbaH\x0f\xc8\x01\x01r\n" +
"\x06scheme\x18\x06 \x01(\tB\n" + "\x10\x012\x06.*\\S.*R\x06scheme\x12\x19\n" +
"\xbaH\a\xc8\x01\x01r\x02\x10\x01R\x06scheme\x12\x19\n" +
"\x05query\x18\a \x01(\tH\x01R\x05query\x88\x01\x01\x12;\n" + "\x05query\x18\a \x01(\tH\x01R\x05query\x88\x01\x01\x12;\n" +
"\x04time\x18\b \x01(\v2\x1a.google.protobuf.TimestampB\v\xbaH\b\xc8\x01\x01\xb2\x01\x028\x01R\x04time\x12&\n" + "\x04time\x18\b \x01(\v2\x1a.google.protobuf.TimestampB\v\xbaH\b\xc8\x01\x01\xb2\x01\x028\x01R\x04time\x12.\n" +
"\bprotocol\x18\t \x01(\tB\n" + "\bprotocol\x18\t \x01(\tB\x12\xbaH\x0f\xc8\x01\x01r\n" +
"\xbaH\a\xc8\x01\x01r\x02\x10\x01R\bprotocol\x12;\n" + "\x10\x012\x06.*\\S.*R\bprotocol\x12;\n" +
"\x04auth\x18\n" + "\x04auth\x18\n" +
" \x01(\v2\x1f.audit.v1.AttributeContext.AuthB\x06\xbaH\x03\xc8\x01\x01R\x04auth\x1a:\n" + " \x01(\v2\x1f.audit.v1.AttributeContext.AuthB\x06\xbaH\x03\xc8\x01\x01R\x04auth\x1a:\n" +
"\fHeadersEntry\x12\x10\n" + "\fHeadersEntry\x12\x10\n" +
@ -1564,12 +1563,11 @@ const file_audit_v1_audit_event_proto_rawDesc = "" +
"\x13HTTP_METHOD_OPTIONS\x10\b\x12\x15\n" + "\x13HTTP_METHOD_OPTIONS\x10\b\x12\x15\n" +
"\x11HTTP_METHOD_TRACE\x10\t\x12\x15\n" + "\x11HTTP_METHOD_TRACE\x10\t\x12\x15\n" +
"\x11HTTP_METHOD_PATCH\x10\n" + "\x11HTTP_METHOD_PATCH\x10\n" +
"\"\xe1\x01\n" + "\"\xe9\x01\n" +
"\x0fRequestMetadata\x12'\n" + "\x0fRequestMetadata\x12'\n" +
"\tcaller_ip\x18\x01 \x01(\tB\n" + "\tcaller_ip\x18\x01 \x01(\tB\n" +
"\xbaH\a\xc8\x01\x01r\x02p\x01R\bcallerIp\x12J\n" + "\xbaH\a\xc8\x01\x01r\x02p\x01R\bcallerIp\x12R\n" +
"\x1acaller_supplied_user_agent\x18\x02 \x01(\tB\r\xbaH\n" + "\x1acaller_supplied_user_agent\x18\x02 \x01(\tB\x15\xbaH\x12\xc8\x01\x01r\r\x10\x01\x18\xff\x012\x06.*\\S.*R\x17callerSuppliedUserAgent\x12Y\n" +
"\xc8\x01\x01r\x05\x10\x01\x18\xff\x01R\x17callerSuppliedUserAgent\x12Y\n" +
"\x12request_attributes\x18\x03 \x01(\v2\".audit.v1.AttributeContext.RequestB\x06\xbaH\x03\xc8\x01\x01R\x11requestAttributes\"\xb4\x02\n" + "\x12request_attributes\x18\x03 \x01(\v2\".audit.v1.AttributeContext.RequestB\x06\xbaH\x03\xc8\x01\x01R\x11requestAttributes\"\xb4\x02\n" +
"\x10ResponseMetadata\x12H\n" + "\x10ResponseMetadata\x12H\n" +
"\vstatus_code\x18\x01 \x01(\v2\x1b.google.protobuf.Int32ValueB\n" + "\vstatus_code\x18\x01 \x01(\v2\x1b.google.protobuf.Int32ValueB\n" +
@ -1578,18 +1576,17 @@ const file_audit_v1_audit_event_proto_rawDesc = "" +
"\rerror_message\x18\x02 \x01(\tH\x00R\ferrorMessage\x88\x01\x01\x12<\n" + "\rerror_message\x18\x02 \x01(\tH\x00R\ferrorMessage\x88\x01\x01\x12<\n" +
"\rerror_details\x18\x03 \x03(\v2\x17.google.protobuf.StructR\ferrorDetails\x12\\\n" + "\rerror_details\x18\x03 \x03(\v2\x17.google.protobuf.StructR\ferrorDetails\x12\\\n" +
"\x13response_attributes\x18\x04 \x01(\v2#.audit.v1.AttributeContext.ResponseB\x06\xbaH\x03\xc8\x01\x01R\x12responseAttributesB\x10\n" + "\x13response_attributes\x18\x04 \x01(\v2#.audit.v1.AttributeContext.ResponseB\x06\xbaH\x03\xc8\x01\x01R\x12responseAttributesB\x10\n" +
"\x0e_error_message\"\xba\x04\n" + "\x0e_error_message\"\xca\x04\n" +
"\x1cServiceAccountDelegationInfo\x12c\n" + "\x1cServiceAccountDelegationInfo\x12c\n" +
"\x10system_principal\x18\x01 \x01(\v26.audit.v1.ServiceAccountDelegationInfo.SystemPrincipalH\x00R\x0fsystemPrincipal\x12Z\n" + "\x10system_principal\x18\x01 \x01(\v26.audit.v1.ServiceAccountDelegationInfo.SystemPrincipalH\x00R\x0fsystemPrincipal\x12Z\n" +
"\ridp_principal\x18\x02 \x01(\v23.audit.v1.ServiceAccountDelegationInfo.IdpPrincipalH\x00R\fidpPrincipal\x1ao\n" + "\ridp_principal\x18\x02 \x01(\v23.audit.v1.ServiceAccountDelegationInfo.IdpPrincipalH\x00R\fidpPrincipal\x1ao\n" +
"\x0fSystemPrincipal\x12G\n" + "\x0fSystemPrincipal\x12G\n" +
"\x10service_metadata\x18\x01 \x01(\v2\x17.google.protobuf.StructH\x00R\x0fserviceMetadata\x88\x01\x01B\x13\n" + "\x10service_metadata\x18\x01 \x01(\v2\x17.google.protobuf.StructH\x00R\x0fserviceMetadata\x88\x01\x01B\x13\n" +
"\x11_service_metadata\x1a\xd3\x01\n" + "\x11_service_metadata\x1a\xe3\x01\n" +
"\fIdpPrincipal\x12-\n" + "\fIdpPrincipal\x125\n" +
"\fprincipal_id\x18\x01 \x01(\tB\n" + "\fprincipal_id\x18\x01 \x01(\tB\x12\xbaH\x0f\xc8\x01\x01r\n" +
"\xbaH\a\xc8\x01\x01r\x02\x10\x01R\vprincipalId\x126\n" + "\x10\x012\x06.*\\S.*R\vprincipalId\x12>\n" +
"\x0fprincipal_email\x18\x02 \x01(\tB\r\xbaH\n" + "\x0fprincipal_email\x18\x02 \x01(\tB\x15\xbaH\x12\xc8\x01\x01r\r\x10\x01\x18\xff\x012\x06.*\\S.*R\x0eprincipalEmail\x12G\n" +
"\xc8\x01\x01r\x05\x10\x01\x18\xff\x01R\x0eprincipalEmail\x12G\n" +
"\x10service_metadata\x18\x03 \x01(\v2\x17.google.protobuf.StructH\x00R\x0fserviceMetadata\x88\x01\x01B\x13\n" + "\x10service_metadata\x18\x03 \x01(\v2\x17.google.protobuf.StructH\x00R\x0fserviceMetadata\x88\x01\x01B\x13\n" +
"\x11_service_metadataB\x12\n" + "\x11_service_metadataB\x12\n" +
"\tauthority\x12\x05\xbaH\x02\b\x01*\x96\x02\n" + "\tauthority\x12\x05\xbaH\x02\b\x01*\x96\x02\n" +

View file

@ -554,8 +554,6 @@ func (m *AuthenticationInfo) validate(all bool) error {
// no validation rules for PrincipalId // no validation rules for PrincipalId
// no validation rules for PrincipalEmail
for idx, item := range m.GetServiceAccountDelegationInfo() { for idx, item := range m.GetServiceAccountDelegationInfo() {
_, _ = idx, item _, _ = idx, item
@ -590,6 +588,10 @@ func (m *AuthenticationInfo) validate(all bool) error {
} }
if m.PrincipalEmail != nil {
// no validation rules for PrincipalEmail
}
if m.ServiceAccountName != nil { if m.ServiceAccountName != nil {
// no validation rules for ServiceAccountName // no validation rules for ServiceAccountName
} }

View file

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.36.6 // protoc-gen-go v1.36.11
// protoc (unknown) // protoc (unknown)
// source: audit/v1/routable_event.proto // source: audit/v1/routable_event.proto

71
go.mod
View file

@ -3,27 +3,28 @@ module dev.azure.com/schwarzit/schwarzit.stackit-public/audit-go.git
go 1.24.0 go 1.24.0
require ( require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1 buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1
buf.build/go/protovalidate v0.13.1 buf.build/go/protovalidate v1.1.0
github.com/Azure/go-amqp v1.4.0 github.com/Azure/go-amqp v1.5.1
github.com/docker/docker v28.2.2+incompatible github.com/docker/docker v28.5.2+incompatible
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/lestrrat-go/jwx/v2 v2.1.6 github.com/lestrrat-go/jwx/v2 v2.1.6
github.com/rs/zerolog v1.34.0 github.com/rs/zerolog v1.34.0
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.11.1
github.com/testcontainers/testcontainers-go v0.37.0 github.com/testcontainers/testcontainers-go v0.40.0
go.opentelemetry.io/otel v1.36.0 go.opentelemetry.io/otel v1.39.0
go.opentelemetry.io/otel/trace v1.36.0 go.opentelemetry.io/otel/trace v1.39.0
google.golang.org/protobuf v1.36.6 google.golang.org/protobuf v1.36.11
) )
require ( require (
cel.dev/expr v0.24.0 // indirect cel.dev/expr v0.25.1 // indirect
dario.cat/mergo v1.0.2 // indirect dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect
@ -32,60 +33,56 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
github.com/distribution/reference v0.6.0 // indirect github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect
github.com/ebitengine/purego v0.8.4 // indirect github.com/ebitengine/purego v0.9.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect github.com/goccy/go-json v0.10.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/google/cel-go v0.26.1 // indirect
github.com/google/cel-go v0.25.0 // indirect github.com/klauspost/compress v1.18.2 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/lestrrat-go/blackmagic v1.0.4 // indirect github.com/lestrrat-go/blackmagic v1.0.4 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc v1.0.6 // indirect github.com/lestrrat-go/httprc v1.0.6 // indirect
github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect github.com/lestrrat-go/option v1.0.1 // indirect
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect
github.com/magiconair/properties v1.8.10 // indirect github.com/magiconair/properties v1.8.10 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.1.0 // indirect github.com/moby/go-archive v0.2.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect github.com/moby/term v0.5.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/segmentio/asm v1.2.0 // indirect github.com/segmentio/asm v1.2.1 // indirect
github.com/shirou/gopsutil/v4 v4.25.5 // indirect github.com/shirou/gopsutil/v4 v4.25.12 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/stoewer/go-strcase v1.3.1 // indirect github.com/stoewer/go-strcase v1.3.1 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.3 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.10.0 // indirect github.com/tklauser/numcpus v0.11.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect go.opentelemetry.io/otel/metric v1.39.0 // indirect
golang.org/x/crypto v0.39.0 // indirect golang.org/x/crypto v0.46.0 // indirect
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.40.0 // indirect
golang.org/x/text v0.26.0 // indirect golang.org/x/text v0.33.0 // indirect
golang.org/x/time v0.12.0 // indirect golang.org/x/time v0.14.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
google.golang.org/grpc v1.73.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

209
go.sum
View file

@ -1,25 +1,29 @@
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1 h1:AUL6VF5YWL01j/1H/DQbPUSDkEwYqwVCNw7yhbpOxSQ= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1 h1:j9yeqTWEFrtimt8Nng2MIeRrpoCvQzM9/g25XTvqUGg=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.6-20250613105001-9f2d3c737feb.1/go.mod h1:avRlCjnFzl98VPaeCtJ24RrV/wwHFzB8sWXhj26+n/U= buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.11-20251209175733-2a1774d88802.1/go.mod h1:tvtbpgaVXZX4g6Pn+AnzFycuRK3MOz5HJfEGeEllXYM=
buf.build/go/protovalidate v0.13.1 h1:6loHDTWdY/1qmqmt1MijBIKeN4T9Eajrqb9isT1W1s8= buf.build/go/protovalidate v1.1.0 h1:pQqEQRpOo4SqS60qkvmhLTTQU9JwzEvdyiqAtXa5SeY=
buf.build/go/protovalidate v0.13.1/go.mod h1:C/QcOn/CjXRn5udUwYBiLs8y1TGy7RS+GOSKqjS77aU= buf.build/go/protovalidate v1.1.0/go.mod h1:bGZcPiAQDC3ErCHK3t74jSoJDFOs2JH3d7LWuTEIdss=
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/Azure/go-amqp v1.4.0 h1:Xj3caqi4comOF/L1Uc5iuBxR/pB6KumejC01YQOqOR4= github.com/Azure/go-amqp v1.5.1 h1:WyiPTz2C3zVvDL7RLAqwWdeoYhMtX62MZzQoP09fzsU=
github.com/Azure/go-amqp v1.4.0/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE= github.com/Azure/go-amqp v1.5.1/go.mod h1:vZAogwdrkbyK3Mla8m/CxSc/aKdnTZ4IbPxl51Y5WZE=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4=
github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
@ -40,14 +44,14 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvw
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/docker v28.2.2+incompatible h1:CjwRSksz8Yo4+RmQ339Dp/D2tGO5JxwYeqtMOEe0LDw= github.com/docker/docker v28.5.2+incompatible h1:DBX0Y0zAjZbSrm1uzOkdr1onVghKaftjlSWt4AFexzM=
github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v28.5.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw= github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
@ -63,20 +67,16 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/google/cel-go v0.26.1 h1:iPbVVEdkhTX++hpe3lzSk7D3G3QSYqLGoHOcEio+UXQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/cel-go v0.26.1/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY=
github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0 h1:+epNPbD5EqgpEMm5wrl4Hqts3jZt8+kYaqUisuuIGTk= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.0/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90= github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -93,8 +93,8 @@ github.com/lestrrat-go/jwx/v2 v2.1.6 h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVf
github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU= github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 h1:PwQumkgq4/acIiZhtifTV5OUqqiP82UAl0h87xj/l9k=
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@ -106,8 +106,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo= github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw= github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
@ -120,8 +120,8 @@ github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ= github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc= github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.1.0 h1:vBBl0pUnvi/Je71dsRrhMBtreIqNMYErSAbEeb8jrXQ=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/morikuni/aec v1.1.0/go.mod h1:xDRgiq/iw5l+zkao76YTKzKttOp2cwPEne25HDkJnBw=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
@ -132,15 +132,17 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rodaine/protogofakeit v0.1.1 h1:ZKouljuRM3A+TArppfBqnH8tGZHOwM/pjvtXe9DaXH8=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rodaine/protogofakeit v0.1.1/go.mod h1:pXn/AstBYMaSfc1/RqH3N82pBuxtWgejz1AlYpY1mI0=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc= github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY=
github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs= github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
@ -148,67 +150,50 @@ github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8w
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg= github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU=
github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY=
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 h1:ssfIgGNANqpVFCndZvcuyKbl0g+UAVcbBcqGkG28H0Y=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0/go.mod h1:GQ/474YrbE4Jx8gZ4q5I4hrhUzM6UPzyrqJYV2AqPoQ=
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg= go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 h1:dNzwXjZKpMpE2JhmO+9HsPl42NIXFIFSUSSs0fiqra0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0/go.mod h1:90PoxvaEB5n6AOdZvi+yWJQoE95U8Dhhw2bSyRqnTD0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 h1:nRVXXvf78e00EwY6Wp0YII8ww2JVWshZ20HfTlE11AM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0/go.mod h1:r49hO7CgrxY9Voaj3Xe8pANWtr0Oq916d0XAmOoCZAQ= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU=
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE= go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs= go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis= go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w= go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -216,32 +201,22 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b h1:uA40e2M6fYRBf0+8uN5mLlqUtV192iiksiICIBkYJ1E=
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= google.golang.org/genproto/googleapis/api v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:Xa7le7qx2vmqB/SzWUBa7KdMjpdpAHlh5QCSnjessQk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 h1:oWVWY3NzT7KJppx2UKhKmzPq4SRe0LdCijVRwvGeikY=
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822/go.mod h1:h3c4v36UTKzUiuaOKQ6gr3S+0hovBtUrXzTG/i3+XEc=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View file

@ -74,7 +74,7 @@ func Test_ValidateAndSerializePartially_AuditEventValidationFailed(t *testing.T)
_, err := ValidateAndSerializePartially( _, err := ValidateAndSerializePartially(
validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, pkgAuditCommon.NewRoutableIdentifier(objectIdentifier)) validator, event, auditV1.Visibility_VISIBILITY_PUBLIC, pkgAuditCommon.NewRoutableIdentifier(objectIdentifier))
assert.EqualError(t, err, "validation error:\n - log_name: value is required [required]") assert.EqualError(t, err, "validation error: log_name: value is required")
} }
func Test_ValidateAndSerializePartially_RoutableEventValidationFailed(t *testing.T) { func Test_ValidateAndSerializePartially_RoutableEventValidationFailed(t *testing.T) {
@ -83,7 +83,7 @@ func Test_ValidateAndSerializePartially_RoutableEventValidationFailed(t *testing
event, objectIdentifier := NewOrganizationAuditEvent(nil) event, objectIdentifier := NewOrganizationAuditEvent(nil)
_, err := ValidateAndSerializePartially(validator, event, 3, pkgAuditCommon.NewRoutableIdentifier(objectIdentifier)) _, err := ValidateAndSerializePartially(validator, event, 3, pkgAuditCommon.NewRoutableIdentifier(objectIdentifier))
assert.EqualError(t, err, "validation error:\n - visibility: value must be one of the defined enum values [enum.defined_only]") assert.EqualError(t, err, "validation error: visibility: value must be one of the defined enum values")
} }
func Test_ValidateAndSerializePartially_CheckVisibility_Event(t *testing.T) { func Test_ValidateAndSerializePartially_CheckVisibility_Event(t *testing.T) {

View file

@ -202,7 +202,7 @@ func ConvertAndSerializeIntoLegacyFormat(
UserAgent: userAgent, UserAgent: userAgent,
Initiator: LegacyAuditEventPrincipal{ Initiator: LegacyAuditEventPrincipal{
Id: event.ProtoPayload.AuthenticationInfo.PrincipalId, Id: event.ProtoPayload.AuthenticationInfo.PrincipalId,
Email: &event.ProtoPayload.AuthenticationInfo.PrincipalEmail, Email: event.ProtoPayload.AuthenticationInfo.PrincipalEmail,
}, },
ServiceAccountDelegationInfo: serviceAccountDelegationInfo, ServiceAccountDelegationInfo: serviceAccountDelegationInfo,
Request: request, Request: request,

View file

@ -558,7 +558,7 @@ func AuditAttributesFromAuthorizationHeader(request *pkgAuditCommon.ApiRequest)
var authenticationPrincipal = "none/none" var authenticationPrincipal = "none/none"
var principalId = "none" var principalId = "none"
var principalEmail = EmailAddressDoNotReplyAtStackItDotCloud var principalEmail *string
emptyClaims, err := structpb.NewStruct(make(map[string]interface{})) emptyClaims, err := structpb.NewStruct(make(map[string]interface{}))
if err != nil { if err != nil {
return nil, authenticationPrincipal, nil, nil, err return nil, authenticationPrincipal, nil, nil, err
@ -741,14 +741,15 @@ func extractSubjectAndEmailFromActClaims(actClaim map[string]interface{}) (strin
return principalId, principalEmail return principalId, principalEmail
} }
func extractSubjectAndEmail(token jwt.Token) (string, string) { func extractSubjectAndEmail(token jwt.Token) (string, *string) {
var principalEmail string var principalEmail *string
principalId := token.Subject() principalId := token.Subject()
emailClaim, hasEmail := token.Get("email") emailClaim, hasEmail := token.Get("email")
if !hasEmail { if hasEmail {
principalEmail = EmailAddressDoNotReplyAtStackItDotCloud trimmedEmail := strings.TrimSpace(fmt.Sprintf("%s", emailClaim))
} else { if trimmedEmail != "" {
principalEmail = fmt.Sprintf("%s", emailClaim) principalEmail = &trimmedEmail
}
} }
return principalId, principalEmail return principalId, principalEmail
} }

View file

@ -404,7 +404,7 @@ func Test_AuditAttributesFromAuthorizationHeader(t *testing.T) {
assert.Equal(t, []string{"stackit-resource-manager-dev"}, audiences) assert.Equal(t, []string{"stackit-resource-manager-dev"}, audiences)
assert.Equal(t, "stackit-resource-manager-dev", authenticationInfo.PrincipalId) assert.Equal(t, "stackit-resource-manager-dev", authenticationInfo.PrincipalId)
assert.Equal(t, "do-not-reply@stackit.cloud", authenticationInfo.PrincipalEmail) assert.Nil(t, authenticationInfo.PrincipalEmail)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
@ -442,7 +442,47 @@ func Test_AuditAttributesFromAuthorizationHeader(t *testing.T) {
assert.Equal(t, []string{"stackit", "api"}, audiences) assert.Equal(t, []string{"stackit", "api"}, audiences)
assert.Equal(t, "10f38b01-534b-47bb-a03a-e294ca2be4de", authenticationInfo.PrincipalId) assert.Equal(t, "10f38b01-534b-47bb-a03a-e294ca2be4de", authenticationInfo.PrincipalId)
assert.Equal(t, "my-service-yifc9e1@sa.stackit.cloud", authenticationInfo.PrincipalEmail) assert.Equal(t, "my-service-yifc9e1@sa.stackit.cloud", *authenticationInfo.PrincipalEmail)
assert.Equal(t,
"projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/10f38b01-534b-47bb-a03a-e294ca2be4de",
*authenticationInfo.ServiceAccountName)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
})
t.Run("service account access token with underscore in subject", func(t *testing.T) {
headers := make(map[string][]string)
headers["Authorization"] = []string{serviceAccountTokenUnderscoreSubject}
request := pkgAuditCommon.ApiRequest{Header: headers}
auditClaims, authenticationPrincipal, audiences, authenticationInfo, err :=
AuditAttributesFromAuthorizationHeader(&request)
assert.Nil(t, err)
auditClaimsMap := auditClaims.AsMap()
assert.Len(t, auditClaimsMap, 12)
assert.Equal(t, []interface{}{"stackit", "api"}, auditClaimsMap["aud"])
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", auditClaimsMap["azp"])
assert.Equal(t, "my-service-yifc9e1@sa.stackit.cloud", auditClaimsMap["email"])
assert.Equal(t, "2024-08-03 07:15:43 +0000 UTC", auditClaimsMap["exp"])
assert.Equal(t, "2024-08-02 07:15:43 +0000 UTC", auditClaimsMap["iat"])
assert.Equal(t, "stackit/serviceaccount", auditClaimsMap["iss"])
assert.Equal(t, "84c30a46-1001-436f-859f-89c0ba19be1e", auditClaimsMap["jti"])
assert.Equal(t, "api", auditClaimsMap["stackit/serviceaccount/namespace"])
assert.Equal(t, "10f38b01-534b-47bb-a03a-e294ca2be4de", auditClaimsMap[TokenClaimStackitServiceAccountId])
assert.Equal(t, "legacy", auditClaimsMap["stackit/serviceaccount/token.source"])
assert.Equal(t, "dacc7830-843e-4c5e-86ff-aa0fb51d636f", auditClaimsMap[TokenClaimStackitProjectId])
assert.Equal(t, "10f38b01_534b_47bb_a03a_e294ca2be4de", auditClaimsMap["sub"])
principal := fmt.Sprintf("%s/%s",
url.QueryEscape("10f38b01_534b_47bb_a03a_e294ca2be4de"),
url.QueryEscape("stackit/serviceaccount"))
assert.Equal(t, principal, authenticationPrincipal)
assert.Equal(t, []string{"stackit", "api"}, audiences)
assert.Equal(t, "10f38b01_534b_47bb_a03a_e294ca2be4de", authenticationInfo.PrincipalId)
assert.Equal(t, "my-service-yifc9e1@sa.stackit.cloud", *authenticationInfo.PrincipalEmail)
assert.Equal(t, assert.Equal(t,
"projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/10f38b01-534b-47bb-a03a-e294ca2be4de", "projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/10f38b01-534b-47bb-a03a-e294ca2be4de",
@ -486,7 +526,7 @@ func Test_AuditAttributesFromAuthorizationHeader(t *testing.T) {
assert.Equal(t, []string{"stackit", "api"}, audiences) assert.Equal(t, []string{"stackit", "api"}, audiences)
assert.Equal(t, "f45009b2-6433-43c1-b6c7-618c44359e71", authenticationInfo.PrincipalId) assert.Equal(t, "f45009b2-6433-43c1-b6c7-618c44359e71", authenticationInfo.PrincipalId)
assert.Equal(t, "service-account-2-tj9srt1@sa.stackit.cloud", authenticationInfo.PrincipalEmail) assert.Equal(t, "service-account-2-tj9srt1@sa.stackit.cloud", *authenticationInfo.PrincipalEmail)
assert.Equal(t, assert.Equal(t,
"projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/f45009b2-6433-43c1-b6c7-618c44359e71", "projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/f45009b2-6433-43c1-b6c7-618c44359e71",
@ -537,7 +577,7 @@ func Test_AuditAttributesFromAuthorizationHeader(t *testing.T) {
assert.Equal(t, []string{"stackit", "api"}, audiences) assert.Equal(t, []string{"stackit", "api"}, audiences)
assert.Equal(t, "1734b4b6-1d5e-4819-9b50-29917a1b9ad5", authenticationInfo.PrincipalId) assert.Equal(t, "1734b4b6-1d5e-4819-9b50-29917a1b9ad5", authenticationInfo.PrincipalId)
assert.Equal(t, "service-account-3-fghsxw1@sa.stackit.cloud", authenticationInfo.PrincipalEmail) assert.Equal(t, "service-account-3-fghsxw1@sa.stackit.cloud", *authenticationInfo.PrincipalEmail)
assert.Equal(t, assert.Equal(t,
"projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/1734b4b6-1d5e-4819-9b50-29917a1b9ad5", "projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/1734b4b6-1d5e-4819-9b50-29917a1b9ad5",
@ -582,7 +622,7 @@ func Test_AuditAttributesFromAuthorizationHeader(t *testing.T) {
assert.Equal(t, []string{"stackit-portal-login-dev-client-id"}, audiences) assert.Equal(t, []string{"stackit-portal-login-dev-client-id"}, audiences)
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId) assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId)
assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", authenticationInfo.PrincipalEmail) assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", *authenticationInfo.PrincipalEmail)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
@ -617,7 +657,7 @@ func Test_AuditAttributesFromAuthorizationHeader(t *testing.T) {
assert.Equal(t, []string{"https://stackit-service-account-dev.apps.01.cf.eu01.stackit.cloud"}, audiences) assert.Equal(t, []string{"https://stackit-service-account-dev.apps.01.cf.eu01.stackit.cloud"}, audiences)
assert.Equal(t, "5e426aed-c487-4c48-af25-87f69cf9cdd4", authenticationInfo.PrincipalId) assert.Equal(t, "5e426aed-c487-4c48-af25-87f69cf9cdd4", authenticationInfo.PrincipalId)
assert.Equal(t, "Lukas.Schmitt@stackit.cloud", authenticationInfo.PrincipalEmail) assert.Equal(t, "Lukas.Schmitt@stackit.cloud", *authenticationInfo.PrincipalEmail)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
@ -716,7 +756,7 @@ func Test_NewAuditLogEntry(t *testing.T) {
authenticationInfo := payload.AuthenticationInfo authenticationInfo := payload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId) assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId)
assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", authenticationInfo.PrincipalEmail) assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", *authenticationInfo.PrincipalEmail)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
@ -849,7 +889,7 @@ func Test_NewAuditLogEntry(t *testing.T) {
authenticationInfo := payload.AuthenticationInfo authenticationInfo := payload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId) assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId)
assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", authenticationInfo.PrincipalEmail) assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", *authenticationInfo.PrincipalEmail)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)

View file

@ -40,7 +40,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.OperationName = "" event.OperationName = ""
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - operation_name: value is required [required]") assert.EqualError(t, err, "validation error: operation_name: value is required")
}) })
t.Run("invalid operation name", func(t *testing.T) { t.Run("invalid operation name", func(t *testing.T) {
@ -48,7 +48,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.OperationName = "stackit.resource-manager.v1.INVALID.organizations.create" event.OperationName = "stackit.resource-manager.v1.INVALID.organizations.create"
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - operation_name: value does not match regex pattern `^stackit\\.[a-z0-9-]+\\.(?:v[0-9]+\\.)?(?:[a-z0-9-.]+\\.)?[a-z0-9-]+$` [string.pattern]") assert.EqualError(t, err, "validation error: operation_name: value does not match regex pattern `^stackit\\.[a-z0-9-]+\\.(?:v[0-9]+\\.)?(?:[a-z0-9-.]+\\.)?[a-z0-9-]+$`")
}) })
t.Run("visibility invalid", func(t *testing.T) { t.Run("visibility invalid", func(t *testing.T) {
@ -56,7 +56,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.Visibility = -1 event.Visibility = -1
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - visibility: value must be one of the defined enum values [enum.defined_only]") assert.EqualError(t, err, "validation error: visibility: value must be one of the defined enum values")
}) })
t.Run("visibility unspecified", func(t *testing.T) { t.Run("visibility unspecified", func(t *testing.T) {
@ -64,7 +64,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.Visibility = auditV1.Visibility_VISIBILITY_UNSPECIFIED event.Visibility = auditV1.Visibility_VISIBILITY_UNSPECIFIED
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - visibility: value is required [required]") assert.EqualError(t, err, "validation error: visibility: value is required")
}) })
t.Run("object identifier nil", func(t *testing.T) { t.Run("object identifier nil", func(t *testing.T) {
@ -72,7 +72,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.ObjectIdentifier = nil event.ObjectIdentifier = nil
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - object_identifier: value is required [required]") assert.EqualError(t, err, "validation error: object_identifier: value is required")
}) })
t.Run("object identifier id empty", func(t *testing.T) { t.Run("object identifier id empty", func(t *testing.T) {
@ -80,7 +80,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.ObjectIdentifier.Identifier = "" event.ObjectIdentifier.Identifier = ""
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - object_identifier.identifier: value is required [required]") assert.EqualError(t, err, "validation error: object_identifier.identifier: value is required")
}) })
t.Run("object identifier id not uuid", func(t *testing.T) { t.Run("object identifier id not uuid", func(t *testing.T) {
@ -88,7 +88,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.ObjectIdentifier.Identifier = "invalid" event.ObjectIdentifier.Identifier = "invalid"
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - object_identifier.identifier: value must be a valid UUID [string.uuid]") assert.EqualError(t, err, "validation error: object_identifier.identifier: value must be a valid UUID")
}) })
t.Run("object identifier type empty", func(t *testing.T) { t.Run("object identifier type empty", func(t *testing.T) {
@ -96,7 +96,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.ObjectIdentifier.Type = "" event.ObjectIdentifier.Type = ""
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - object_identifier.type: value is required [required]") assert.EqualError(t, err, "validation error: object_identifier.type: value is required")
}) })
t.Run("data nil", func(t *testing.T) { t.Run("data nil", func(t *testing.T) {
@ -104,7 +104,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
event.Data = nil event.Data = nil
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - data: exactly one field is required in oneof [required]") assert.EqualError(t, err, "validation error: data: exactly one field is required in oneof")
}) })
t.Run("data empty", func(t *testing.T) { t.Run("data empty", func(t *testing.T) {
@ -115,7 +115,7 @@ func Test_RoutableAuditEvent(t *testing.T) {
}} }}
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - unencrypted_data.data: value is required [required]") assert.EqualError(t, err, "validation error: unencrypted_data.data: value is required")
}) })
t.Run("data protobuf type empty", func(t *testing.T) { t.Run("data protobuf type empty", func(t *testing.T) {
@ -126,6 +126,59 @@ func Test_RoutableAuditEvent(t *testing.T) {
}} }}
err := validator.Validate(&event) err := validator.Validate(&event)
assert.EqualError(t, err, "validation error:\n - unencrypted_data.protobuf_type: value is required [required]") assert.EqualError(t, err, "validation error: unencrypted_data.protobuf_type: value is required")
}) })
} }
func Test_AuthenticationInfo(t *testing.T) {
validator, err := protovalidate.New()
assert.NoError(t, err)
email := "x@x.x"
newEvent := func() auditV1.AuthenticationInfo {
return auditV1.AuthenticationInfo{
PrincipalId: "1234567890",
PrincipalEmail: &email,
ServiceAccountName: nil,
ServiceAccountDelegationInfo: nil,
}
}
t.Run("valid event", func(t *testing.T) {
event := newEvent()
err := validator.Validate(&event)
assert.NoError(t, err)
})
t.Run("valid event without email", func(t *testing.T) {
event := newEvent()
event.PrincipalEmail = nil
err := validator.Validate(&event)
assert.NoError(t, err)
})
t.Run("principal id contains only whitespace", func(t *testing.T) {
event := newEvent()
event.PrincipalId = " "
err := validator.Validate(&event)
assert.EqualError(t, err, "validation error: principal_id: value does not match regex pattern `.*\\S.*`")
})
t.Run("principal email contains only whitespace", func(t *testing.T) {
event := newEvent()
whitespaceEmail := " "
event.PrincipalEmail = &whitespaceEmail
err := validator.Validate(&event)
assert.EqualError(t, err, "validation error: principal_email: value must be a valid email address")
})
t.Run("missing host in email", func(t *testing.T) {
event := newEvent()
invalidEmail := "@test.com"
event.PrincipalEmail = &invalidEmail
err := validator.Validate(&event)
assert.EqualError(t, err, "validation error: principal_email: value must be a valid email address")
})
}

View file

@ -14,6 +14,7 @@ import (
) )
const clientCredentialsToken = "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOGJlZjc1LWRmY2QtNGE3My1hMzkxLTU0YTdhZjU3YTdkNiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic3RhY2tpdC1yZXNvdXJjZS1tYW5hZ2VyLWRldiJdLCJjbGllbnRfaWQiOiJzdGFja2l0LXJlc291cmNlLW1hbmFnZXItZGV2IiwiZXhwIjoxNzI0NDA1MzI2LCJpYXQiOjE3MjQ0MDQ0MjYsImlzcyI6Imh0dHBzOi8vYWNjb3VudHMuZGV2LnN0YWNraXQuY2xvdWQiLCJqdGkiOiJlNDZlYmEzOC1kZWRiLTQ1NDEtOTRmMy00OWY5N2E5MzRkNTgiLCJuYmYiOjE3MjQ0MDQ0MjYsInNjb3BlIjoidWFhLm5vbmUiLCJzdWIiOiJzdGFja2l0LXJlc291cmNlLW1hbmFnZXItZGV2In0.JP5Uy7AMdK4ukzQ6aOYzbVwEmq0Tp2ppQGRqGOhuVQgbqs6yJ33GKXo7RPsJVLw3FR7XAxENIVqNvzGotbDXr0NjBGdzyxIHzrOaUqM4w1iLzD1KF51dXFwkoigqDdD7Ze9eI_Uo3tSn8FwGLTSoO-ONQYpnceCiGut2Gc6VIL8HOLdh8dzlRENGQtgYd-3Y5zqpoLrsR2Bd-0sv15sF-5aI0CqcC8gE70JPImKf2u_IYI-TYMDNk86YSCtaYO5-alOrHXXWwgzSoH-r2s5qoOhPbei9myV_P4fdcKXxMqfap9hImXPUooVhpdUr1AabZw3MtW7rION8tJAiauhMQA" const clientCredentialsToken = "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOGJlZjc1LWRmY2QtNGE3My1hMzkxLTU0YTdhZjU3YTdkNiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsic3RhY2tpdC1yZXNvdXJjZS1tYW5hZ2VyLWRldiJdLCJjbGllbnRfaWQiOiJzdGFja2l0LXJlc291cmNlLW1hbmFnZXItZGV2IiwiZXhwIjoxNzI0NDA1MzI2LCJpYXQiOjE3MjQ0MDQ0MjYsImlzcyI6Imh0dHBzOi8vYWNjb3VudHMuZGV2LnN0YWNraXQuY2xvdWQiLCJqdGkiOiJlNDZlYmEzOC1kZWRiLTQ1NDEtOTRmMy00OWY5N2E5MzRkNTgiLCJuYmYiOjE3MjQ0MDQ0MjYsInNjb3BlIjoidWFhLm5vbmUiLCJzdWIiOiJzdGFja2l0LXJlc291cmNlLW1hbmFnZXItZGV2In0.JP5Uy7AMdK4ukzQ6aOYzbVwEmq0Tp2ppQGRqGOhuVQgbqs6yJ33GKXo7RPsJVLw3FR7XAxENIVqNvzGotbDXr0NjBGdzyxIHzrOaUqM4w1iLzD1KF51dXFwkoigqDdD7Ze9eI_Uo3tSn8FwGLTSoO-ONQYpnceCiGut2Gc6VIL8HOLdh8dzlRENGQtgYd-3Y5zqpoLrsR2Bd-0sv15sF-5aI0CqcC8gE70JPImKf2u_IYI-TYMDNk86YSCtaYO5-alOrHXXWwgzSoH-r2s5qoOhPbei9myV_P4fdcKXxMqfap9hImXPUooVhpdUr1AabZw3MtW7rION8tJAiauhMQA"
const serviceAccountTokenUnderscoreSubject = "Bearer eyJraWQiOiJaVFJqWlRNek5tSmlNRGt3TldJMU5USTRZVGxpT1RjMllUWXlZVE16WldNIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiIxMGYzOGIwMV81MzRiXzQ3YmJfYTAzYV9lMjk0Y2EyYmU0ZGUiLCJhdWQiOlsic3RhY2tpdCIsImFwaSJdLCJzdGFja2l0L3NlcnZpY2VhY2NvdW50L3Rva2VuLnNvdXJjZSI6ImxlZ2FjeSIsInN0YWNraXQvc2VydmljZWFjY291bnQvbmFtZXNwYWNlIjoiYXBpIiwic3RhY2tpdC9wcm9qZWN0L3Byb2plY3QuaWQiOiJkYWNjNzgzMC04NDNlLTRjNWUtODZmZi1hYTBmYjUxZDYzNmYiLCJhenAiOiJjZDk0ZjAxYS1kZjJlLTQ0NTYtOTAyZS00OGY1ZTU3ZjBiNjMiLCJpc3MiOiJzdGFja2l0L3NlcnZpY2VhY2NvdW50Iiwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMTBmMzhiMDEtNTM0Yi00N2JiLWEwM2EtZTI5NGNhMmJlNGRlIiwiZXhwIjoxNzIyNjY5MzQzLCJpYXQiOjE3MjI1ODI5NDMsImVtYWlsIjoibXktc2VydmljZS15aWZjOWUxQHNhLnN0YWNraXQuY2xvdWQiLCJqdGkiOiI4NGMzMGE0Ni0xMDAxLTQzNmYtODU5Zi04OWMwYmExOWJlMWUifQ.bfD2TxfioqaKbqFJvnV_gq5zY_aoKVD2qzySMQjubaLQ5Vx_Tj95HU0q7gdNczNgcT0tBRyUp0pE4g4bwaPpB2MtYtUUunzpwG8sOX_OBchkorhcC4N50cdF5TR2pg0SMp3L6QBo3coHVbjHvaipshCj1NvyXYzARb4dSR0adrsIGnqy3IaScty1A2XQ7PN6SX_OVmxO5swpL0I-afKvCOffnChI3qmFAL5t6sFxm8PoaCWLIrkoxdtqxw5ZqsPPOJ0qDhssTuc3nE4JrQnzX8fZH5FiBVVHGT76KUNgPFd26UsVzbGqBXK20pn3pbIQHwbRiVOh6qanjr9kvHBXpQ"
const serviceAccountTokenRepeatedlyImpersonated = "Bearer eyJraWQiOiJaVFJqWlRNek5tSmlNRGt3TldJMU5USTRZVGxpT1RjMllUWXlZVE16WldNIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiIxNzM0YjRiNi0xZDVlLTQ4MTktOWI1MC0yOTkxN2ExYjlhZDUiLCJpc3MiOiJzdGFja2l0L3NlcnZpY2VhY2NvdW50IiwiYXVkIjpbInN0YWNraXQiLCJhcGkiXSwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC90b2tlbi5zb3VyY2UiOiJvYXV0aDIiLCJhY3QiOnsic3ViIjoiZjQ1MDA5YjItNjQzMy00M2MxLWI2YzctNjE4YzQ0MzU5ZTcxIiwiYWN0Ijp7InN1YiI6IjAyYWVmNTE2LTMxN2YtNGVjMS1hMWRmLTFhY2JkNGQ0OWZlMyJ9fSwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJhcGkiLCJzdGFja2l0L3Byb2plY3QvcHJvamVjdC5pZCI6ImRhY2M3ODMwLTg0M2UtNGM1ZS04NmZmLWFhMGZiNTFkNjM2ZiIsImF6cCI6ImY0NTAwOWIyLTY0MzMtNDNjMS1iNmM3LTYxOGM0NDM1OWU3MSIsInN0YWNraXQvc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjE3MzRiNGI2LTFkNWUtNDgxOS05YjUwLTI5OTE3YTFiOWFkNSIsImV4cCI6MTcyNDA2Mjk2MywiaWF0IjoxNzI0MDU5MzYzLCJlbWFpbCI6InNlcnZpY2UtYWNjb3VudC0zLWZnaHN4dzFAc2Euc3RhY2tpdC5jbG91ZCIsImp0aSI6IjFmN2YxZWZjLTMzNDktNDExYS1hNWQ3LTIyNTVlMGE1YThhZSJ9.c1ae17bAtyOdmwXQbK37W-NTyOxo7iER5aHS_C0fU1qKl2BjOz708GLjH-_vxx9eKPeYznfI21_xlTaAvuG4Aco9f5YDK7fooTVHnDaOSSggqcEaDzDPrNXhhKEDxotJeq9zRMVCEStcbirjTounnLbuULRbO5GSY5jo-8n2UKxSZ2j5G_SjFHajdJwmzwvOttp08tdL8ck1uDdgVNBfcm0VIdb6WmgrCIUq5rmoa-cRPkdEurNtIEgEB_9U0Xh-SpmmsvFsWWeNIKz0e_5RCIyJonm_wMkGmblGegemkYL76ypeMNXTQsly1RozDIePfzHuZOWbySHSCd-vKQa2kw" const serviceAccountTokenRepeatedlyImpersonated = "Bearer eyJraWQiOiJaVFJqWlRNek5tSmlNRGt3TldJMU5USTRZVGxpT1RjMllUWXlZVE16WldNIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiIxNzM0YjRiNi0xZDVlLTQ4MTktOWI1MC0yOTkxN2ExYjlhZDUiLCJpc3MiOiJzdGFja2l0L3NlcnZpY2VhY2NvdW50IiwiYXVkIjpbInN0YWNraXQiLCJhcGkiXSwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC90b2tlbi5zb3VyY2UiOiJvYXV0aDIiLCJhY3QiOnsic3ViIjoiZjQ1MDA5YjItNjQzMy00M2MxLWI2YzctNjE4YzQ0MzU5ZTcxIiwiYWN0Ijp7InN1YiI6IjAyYWVmNTE2LTMxN2YtNGVjMS1hMWRmLTFhY2JkNGQ0OWZlMyJ9fSwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJhcGkiLCJzdGFja2l0L3Byb2plY3QvcHJvamVjdC5pZCI6ImRhY2M3ODMwLTg0M2UtNGM1ZS04NmZmLWFhMGZiNTFkNjM2ZiIsImF6cCI6ImY0NTAwOWIyLTY0MzMtNDNjMS1iNmM3LTYxOGM0NDM1OWU3MSIsInN0YWNraXQvc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjE3MzRiNGI2LTFkNWUtNDgxOS05YjUwLTI5OTE3YTFiOWFkNSIsImV4cCI6MTcyNDA2Mjk2MywiaWF0IjoxNzI0MDU5MzYzLCJlbWFpbCI6InNlcnZpY2UtYWNjb3VudC0zLWZnaHN4dzFAc2Euc3RhY2tpdC5jbG91ZCIsImp0aSI6IjFmN2YxZWZjLTMzNDktNDExYS1hNWQ3LTIyNTVlMGE1YThhZSJ9.c1ae17bAtyOdmwXQbK37W-NTyOxo7iER5aHS_C0fU1qKl2BjOz708GLjH-_vxx9eKPeYznfI21_xlTaAvuG4Aco9f5YDK7fooTVHnDaOSSggqcEaDzDPrNXhhKEDxotJeq9zRMVCEStcbirjTounnLbuULRbO5GSY5jo-8n2UKxSZ2j5G_SjFHajdJwmzwvOttp08tdL8ck1uDdgVNBfcm0VIdb6WmgrCIUq5rmoa-cRPkdEurNtIEgEB_9U0Xh-SpmmsvFsWWeNIKz0e_5RCIyJonm_wMkGmblGegemkYL76ypeMNXTQsly1RozDIePfzHuZOWbySHSCd-vKQa2kw"
const serviceAccountTokenImpersonated = "Bearer eyJraWQiOiJaVFJqWlRNek5tSmlNRGt3TldJMU5USTRZVGxpT1RjMllUWXlZVE16WldNIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiJmNDUwMDliMi02NDMzLTQzYzEtYjZjNy02MThjNDQzNTllNzEiLCJpc3MiOiJzdGFja2l0L3NlcnZpY2VhY2NvdW50IiwiYXVkIjpbInN0YWNraXQiLCJhcGkiXSwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC90b2tlbi5zb3VyY2UiOiJvYXV0aDIiLCJhY3QiOnsic3ViIjoiMDJhZWY1MTYtMzE3Zi00ZWMxLWExZGYtMWFjYmQ0ZDQ5ZmUzIn0sInN0YWNraXQvc2VydmljZWFjY291bnQvbmFtZXNwYWNlIjoiYXBpIiwic3RhY2tpdC9wcm9qZWN0L3Byb2plY3QuaWQiOiJkYWNjNzgzMC04NDNlLTRjNWUtODZmZi1hYTBmYjUxZDYzNmYiLCJhenAiOiIwMmFlZjUxNi0zMTdmLTRlYzEtYTFkZi0xYWNiZDRkNDlmZTMiLCJzdGFja2l0L3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmNDUwMDliMi02NDMzLTQzYzEtYjZjNy02MThjNDQzNTllNzEiLCJleHAiOjE3MjQwNjI5MDcsImlhdCI6MTcyNDA1OTMwNywiZW1haWwiOiJzZXJ2aWNlLWFjY291bnQtMi10ajlzcnQxQHNhLnN0YWNraXQuY2xvdWQiLCJqdGkiOiIzNzU1NTE4My0wMWI5LTQyNzAtYmRjMS02OWI0ZmNmZDVlZTkifQ.auBvvsIesFMAlWOCPCPC77DrrHF7gSKZwKs_Zry5KFvu2bpZZC1BcSXOc8b9eh0SzANI9M9aGJBhOzOm39-ZZ5XOQ-6_y1aWuEenYQ6kT5D3GzCUTMDzSi1lcZ4IG5nFMa_AAlVEN_7AMv7LHGtz49bWLJnAgeTo1cvof-OgP4mCQ5O6E0iyAq-5u8V8NJL7HIZy7BDe4J1mjfYhwKagrN7QFWu4fhN4TNS7d922X_6V489BhjRFRYjLW_qDnv912JorbGRz_XwNy_dPA81EkdMyKE0BJUezguJUEKEG2_JEi9O64Flcoi6x8cFHYhaDuMMSLipzePaHdyk2lQtH7Q" const serviceAccountTokenImpersonated = "Bearer eyJraWQiOiJaVFJqWlRNek5tSmlNRGt3TldJMU5USTRZVGxpT1RjMllUWXlZVE16WldNIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiJmNDUwMDliMi02NDMzLTQzYzEtYjZjNy02MThjNDQzNTllNzEiLCJpc3MiOiJzdGFja2l0L3NlcnZpY2VhY2NvdW50IiwiYXVkIjpbInN0YWNraXQiLCJhcGkiXSwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC90b2tlbi5zb3VyY2UiOiJvYXV0aDIiLCJhY3QiOnsic3ViIjoiMDJhZWY1MTYtMzE3Zi00ZWMxLWExZGYtMWFjYmQ0ZDQ5ZmUzIn0sInN0YWNraXQvc2VydmljZWFjY291bnQvbmFtZXNwYWNlIjoiYXBpIiwic3RhY2tpdC9wcm9qZWN0L3Byb2plY3QuaWQiOiJkYWNjNzgzMC04NDNlLTRjNWUtODZmZi1hYTBmYjUxZDYzNmYiLCJhenAiOiIwMmFlZjUxNi0zMTdmLTRlYzEtYTFkZi0xYWNiZDRkNDlmZTMiLCJzdGFja2l0L3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJmNDUwMDliMi02NDMzLTQzYzEtYjZjNy02MThjNDQzNTllNzEiLCJleHAiOjE3MjQwNjI5MDcsImlhdCI6MTcyNDA1OTMwNywiZW1haWwiOiJzZXJ2aWNlLWFjY291bnQtMi10ajlzcnQxQHNhLnN0YWNraXQuY2xvdWQiLCJqdGkiOiIzNzU1NTE4My0wMWI5LTQyNzAtYmRjMS02OWI0ZmNmZDVlZTkifQ.auBvvsIesFMAlWOCPCPC77DrrHF7gSKZwKs_Zry5KFvu2bpZZC1BcSXOc8b9eh0SzANI9M9aGJBhOzOm39-ZZ5XOQ-6_y1aWuEenYQ6kT5D3GzCUTMDzSi1lcZ4IG5nFMa_AAlVEN_7AMv7LHGtz49bWLJnAgeTo1cvof-OgP4mCQ5O6E0iyAq-5u8V8NJL7HIZy7BDe4J1mjfYhwKagrN7QFWu4fhN4TNS7d922X_6V489BhjRFRYjLW_qDnv912JorbGRz_XwNy_dPA81EkdMyKE0BJUezguJUEKEG2_JEi9O64Flcoi6x8cFHYhaDuMMSLipzePaHdyk2lQtH7Q"
const serviceAccountToken = "Bearer eyJraWQiOiJaVFJqWlRNek5tSmlNRGt3TldJMU5USTRZVGxpT1RjMllUWXlZVE16WldNIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiIxMGYzOGIwMS01MzRiLTQ3YmItYTAzYS1lMjk0Y2EyYmU0ZGUiLCJhdWQiOlsic3RhY2tpdCIsImFwaSJdLCJzdGFja2l0L3NlcnZpY2VhY2NvdW50L3Rva2VuLnNvdXJjZSI6ImxlZ2FjeSIsInN0YWNraXQvc2VydmljZWFjY291bnQvbmFtZXNwYWNlIjoiYXBpIiwic3RhY2tpdC9wcm9qZWN0L3Byb2plY3QuaWQiOiJkYWNjNzgzMC04NDNlLTRjNWUtODZmZi1hYTBmYjUxZDYzNmYiLCJhenAiOiJjZDk0ZjAxYS1kZjJlLTQ0NTYtOTAyZS00OGY1ZTU3ZjBiNjMiLCJpc3MiOiJzdGFja2l0L3NlcnZpY2VhY2NvdW50Iiwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMTBmMzhiMDEtNTM0Yi00N2JiLWEwM2EtZTI5NGNhMmJlNGRlIiwiZXhwIjoxNzIyNjY5MzQzLCJpYXQiOjE3MjI1ODI5NDMsImVtYWlsIjoibXktc2VydmljZS15aWZjOWUxQHNhLnN0YWNraXQuY2xvdWQiLCJqdGkiOiI4NGMzMGE0Ni0xMDAxLTQzNmYtODU5Zi04OWMwYmExOWJlMWUifQ.hb8X9VKc9xViHgNMyFHT9ePj_lyEwTV1D2es8E278WtoCJ9-4GPPQGjhcLGGrigjnvpRYV2LKzNqpQslerT5lFT_pHACsryaAE0ImYjmoe-nutA7BBpYuM_JN6pk5VIjVFLTqRKeIvFexPacqS2Vo3YoK1GvxPB8WPWBbGIsBtMl-PTm8OTwwzooBOoCRhhMR-E1lFbAymLsc1JI4yDQKLLomvhEopgmocCnQ-P1QkiKMqdkNxiD_YYLLYTOApg6d62BhqpH66ziqx493AStdZ8d5Kjvf3e1knDhaxVwNCghQj7lSo2kNAqZe__g2tiXpiZNTXBFJ_5HgQMLh67wng" const serviceAccountToken = "Bearer eyJraWQiOiJaVFJqWlRNek5tSmlNRGt3TldJMU5USTRZVGxpT1RjMllUWXlZVE16WldNIiwiYWxnIjoiUlM1MTIifQ.eyJzdWIiOiIxMGYzOGIwMS01MzRiLTQ3YmItYTAzYS1lMjk0Y2EyYmU0ZGUiLCJhdWQiOlsic3RhY2tpdCIsImFwaSJdLCJzdGFja2l0L3NlcnZpY2VhY2NvdW50L3Rva2VuLnNvdXJjZSI6ImxlZ2FjeSIsInN0YWNraXQvc2VydmljZWFjY291bnQvbmFtZXNwYWNlIjoiYXBpIiwic3RhY2tpdC9wcm9qZWN0L3Byb2plY3QuaWQiOiJkYWNjNzgzMC04NDNlLTRjNWUtODZmZi1hYTBmYjUxZDYzNmYiLCJhenAiOiJjZDk0ZjAxYS1kZjJlLTQ0NTYtOTAyZS00OGY1ZTU3ZjBiNjMiLCJpc3MiOiJzdGFja2l0L3NlcnZpY2VhY2NvdW50Iiwic3RhY2tpdC9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiMTBmMzhiMDEtNTM0Yi00N2JiLWEwM2EtZTI5NGNhMmJlNGRlIiwiZXhwIjoxNzIyNjY5MzQzLCJpYXQiOjE3MjI1ODI5NDMsImVtYWlsIjoibXktc2VydmljZS15aWZjOWUxQHNhLnN0YWNraXQuY2xvdWQiLCJqdGkiOiI4NGMzMGE0Ni0xMDAxLTQzNmYtODU5Zi04OWMwYmExOWJlMWUifQ.hb8X9VKc9xViHgNMyFHT9ePj_lyEwTV1D2es8E278WtoCJ9-4GPPQGjhcLGGrigjnvpRYV2LKzNqpQslerT5lFT_pHACsryaAE0ImYjmoe-nutA7BBpYuM_JN6pk5VIjVFLTqRKeIvFexPacqS2Vo3YoK1GvxPB8WPWBbGIsBtMl-PTm8OTwwzooBOoCRhhMR-E1lFbAymLsc1JI4yDQKLLomvhEopgmocCnQ-P1QkiKMqdkNxiD_YYLLYTOApg6d62BhqpH66ziqx493AStdZ8d5Kjvf3e1knDhaxVwNCghQj7lSo2kNAqZe__g2tiXpiZNTXBFJ_5HgQMLh67wng"
@ -21,6 +22,7 @@ const userToken = "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOGJlZjc1LWRmY2QtNGE3My
const userTokenWithSimpleAudience = "Bearer eyJhbGciOiJSUzUxMiIsImtpZCI6InNlcnZpY2UtYWNjb3VudC1mMDdiZjZhOC02MjA3LTRmOGItYjNlOS03M2VkMGJlYjg4ZjUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL3N0YWNraXQtc2VydmljZS1hY2NvdW50LWRldi5hcHBzLjAxLmNmLmV1MDEuc3RhY2tpdC5jbG91ZCIsImVtYWlsIjoiTHVrYXMuU2NobWl0dEBzdGFja2l0LmNsb3VkIiwiZXhwIjoxNzMyMTgyMDM1LCJpYXQiOjE3MzIxNzg0MzUsImlzcyI6Imh0dHBzOi8vYXBpLmRldi5zdGFja2l0LmNsb3VkIiwianRpIjoiYzJiZTE2NTEtMWU1NC00ZTZlLWJhYzMtZWYwNzJiM2YwMTQ5IiwibmJmIjoxNzMyMTc4NDE4LCJyb2xlcyI6bnVsbCwic2NvcGUiOiJvcGVuaWQgZW1haWwgcG9ydGFsLWJmZiIsInN1YiI6IjVlNDI2YWVkLWM0ODctNGM0OC1hZjI1LTg3ZjY5Y2Y5Y2RkNCIsInVzZXJfaWQiOiIiLCJ4X2NsaWVudF9pZCI6IiIsInppZCI6IiJ9.notavailable" const userTokenWithSimpleAudience = "Bearer eyJhbGciOiJSUzUxMiIsImtpZCI6InNlcnZpY2UtYWNjb3VudC1mMDdiZjZhOC02MjA3LTRmOGItYjNlOS03M2VkMGJlYjg4ZjUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL3N0YWNraXQtc2VydmljZS1hY2NvdW50LWRldi5hcHBzLjAxLmNmLmV1MDEuc3RhY2tpdC5jbG91ZCIsImVtYWlsIjoiTHVrYXMuU2NobWl0dEBzdGFja2l0LmNsb3VkIiwiZXhwIjoxNzMyMTgyMDM1LCJpYXQiOjE3MzIxNzg0MzUsImlzcyI6Imh0dHBzOi8vYXBpLmRldi5zdGFja2l0LmNsb3VkIiwianRpIjoiYzJiZTE2NTEtMWU1NC00ZTZlLWJhYzMtZWYwNzJiM2YwMTQ5IiwibmJmIjoxNzMyMTc4NDE4LCJyb2xlcyI6bnVsbCwic2NvcGUiOiJvcGVuaWQgZW1haWwgcG9ydGFsLWJmZiIsInN1YiI6IjVlNDI2YWVkLWM0ODctNGM0OC1hZjI1LTg3ZjY5Y2Y5Y2RkNCIsInVzZXJfaWQiOiIiLCJ4X2NsaWVudF9pZCI6IiIsInppZCI6IiJ9.notavailable"
var TestHeaders = map[string][]string{"user-agent": {"custom"}, "authorization": {userToken}} var TestHeaders = map[string][]string{"user-agent": {"custom"}, "authorization": {userToken}}
var TestHeadersSa = map[string][]string{"user-agent": {"custom"}, "authorization": {serviceAccountTokenUnderscoreSubject}}
func NewOrganizationAuditEvent( func NewOrganizationAuditEvent(
customization *func( customization *func(
@ -41,6 +43,7 @@ func NewOrganizationAuditEvent(
headers["Content-Type"] = "application/json" headers["Content-Type"] = "application/json"
labels := make(map[string]string) labels := make(map[string]string)
labels["label1"] = "value1" labels["label1"] = "value1"
email := "user@example.com"
auditEvent := &auditV1.AuditLogEntry{ auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeOrganization.Plural(), identifier, pkgAuditCommon.EventTypeAdminActivity), LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeOrganization.Plural(), identifier, pkgAuditCommon.EventTypeAdminActivity),
ProtoPayload: &auditV1.AuditLog{ ProtoPayload: &auditV1.AuditLog{
@ -49,7 +52,7 @@ func NewOrganizationAuditEvent(
ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeOrganization.Plural(), identifier), ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeOrganization.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{ AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: uuid.NewString(), PrincipalId: uuid.NewString(),
PrincipalEmail: "user@example.com", PrincipalEmail: &email,
ServiceAccountName: nil, ServiceAccountName: nil,
ServiceAccountDelegationInfo: nil, ServiceAccountDelegationInfo: nil,
}, },
@ -131,6 +134,7 @@ func NewFolderAuditEvent(
headers["Content-Type"] = "application/json" headers["Content-Type"] = "application/json"
labels := make(map[string]string) labels := make(map[string]string)
labels["label1"] = "value1" labels["label1"] = "value1"
email := "user@example.com"
auditEvent := &auditV1.AuditLogEntry{ auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeFolder.Plural(), identifier, pkgAuditCommon.EventTypeAdminActivity), LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeFolder.Plural(), identifier, pkgAuditCommon.EventTypeAdminActivity),
ProtoPayload: &auditV1.AuditLog{ ProtoPayload: &auditV1.AuditLog{
@ -139,7 +143,7 @@ func NewFolderAuditEvent(
ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeFolder.Plural(), identifier), ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeFolder.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{ AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: uuid.NewString(), PrincipalId: uuid.NewString(),
PrincipalEmail: "user@example.com", PrincipalEmail: &email,
ServiceAccountName: nil, ServiceAccountName: nil,
ServiceAccountDelegationInfo: nil, ServiceAccountDelegationInfo: nil,
}, },
@ -221,6 +225,7 @@ func NewProjectAuditEvent(
headers["Content-Type"] = "application/json" headers["Content-Type"] = "application/json"
labels := make(map[string]string) labels := make(map[string]string)
labels["label1"] = "value1" labels["label1"] = "value1"
email := "user@example.com"
auditEvent := &auditV1.AuditLogEntry{ auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeProject.Plural(), identifier, pkgAuditCommon.EventTypeAdminActivity), LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeProject.Plural(), identifier, pkgAuditCommon.EventTypeAdminActivity),
ProtoPayload: &auditV1.AuditLog{ ProtoPayload: &auditV1.AuditLog{
@ -229,7 +234,7 @@ func NewProjectAuditEvent(
ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeProject.Plural(), identifier), ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeProject.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{ AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: uuid.NewString(), PrincipalId: uuid.NewString(),
PrincipalEmail: "user@example.com", PrincipalEmail: &email,
ServiceAccountName: nil, ServiceAccountName: nil,
ServiceAccountDelegationInfo: nil, ServiceAccountDelegationInfo: nil,
}, },
@ -306,6 +311,7 @@ func NewProjectSystemAuditEvent(
serviceAccountId := uuid.NewString() serviceAccountId := uuid.NewString()
serviceAccountName := fmt.Sprintf("projects/%s/service-accounts/%s", identifier, serviceAccountId) serviceAccountName := fmt.Sprintf("projects/%s/service-accounts/%s", identifier, serviceAccountId)
delegationPrincipal := auditV1.ServiceAccountDelegationInfo{Authority: &auditV1.ServiceAccountDelegationInfo_SystemPrincipal_{}} delegationPrincipal := auditV1.ServiceAccountDelegationInfo{Authority: &auditV1.ServiceAccountDelegationInfo_SystemPrincipal_{}}
email := "service-account@sa.stackit.cloud"
auditEvent := &auditV1.AuditLogEntry{ auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.SystemIdentifier.Type, pkgAuditCommon.SystemIdentifier.Identifier, pkgAuditCommon.EventTypeSystemEvent), LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.SystemIdentifier.Type, pkgAuditCommon.SystemIdentifier.Identifier, pkgAuditCommon.EventTypeSystemEvent),
ProtoPayload: &auditV1.AuditLog{ ProtoPayload: &auditV1.AuditLog{
@ -314,7 +320,7 @@ func NewProjectSystemAuditEvent(
ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeProject.Plural(), identifier), ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeProject.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{ AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: serviceAccountId, PrincipalId: serviceAccountId,
PrincipalEmail: "service-account@sa.stackit.cloud", PrincipalEmail: &email,
ServiceAccountName: &serviceAccountName, ServiceAccountName: &serviceAccountName,
ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal}, ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal},
}, },
@ -386,6 +392,7 @@ func NewSystemAuditEvent(
serviceAccountId := uuid.NewString() serviceAccountId := uuid.NewString()
serviceAccountName := fmt.Sprintf("projects/%s/service-accounts/%s", identifier, serviceAccountId) serviceAccountName := fmt.Sprintf("projects/%s/service-accounts/%s", identifier, serviceAccountId)
delegationPrincipal := auditV1.ServiceAccountDelegationInfo{Authority: &auditV1.ServiceAccountDelegationInfo_SystemPrincipal_{}} delegationPrincipal := auditV1.ServiceAccountDelegationInfo{Authority: &auditV1.ServiceAccountDelegationInfo_SystemPrincipal_{}}
email := "service-account@sa.stackit.cloud"
auditEvent := &auditV1.AuditLogEntry{ auditEvent := &auditV1.AuditLogEntry{
LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeSystem.Plural(), identifier, pkgAuditCommon.EventTypeSystemEvent), LogName: fmt.Sprintf("%s/%s/logs/%s", pkgAuditCommon.ObjectTypeSystem.Plural(), identifier, pkgAuditCommon.EventTypeSystemEvent),
ProtoPayload: &auditV1.AuditLog{ ProtoPayload: &auditV1.AuditLog{
@ -394,7 +401,7 @@ func NewSystemAuditEvent(
ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeSystem.Plural(), identifier), ResourceName: fmt.Sprintf("%s/%s", pkgAuditCommon.ObjectTypeSystem.Plural(), identifier),
AuthenticationInfo: &auditV1.AuthenticationInfo{ AuthenticationInfo: &auditV1.AuthenticationInfo{
PrincipalId: serviceAccountId, PrincipalId: serviceAccountId,
PrincipalEmail: "service-account@sa.stackit.cloud", PrincipalEmail: &email,
ServiceAccountName: &serviceAccountName, ServiceAccountName: &serviceAccountName,
ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal}, ServiceAccountDelegationInfo: []*auditV1.ServiceAccountDelegationInfo{&delegationPrincipal},
}, },

View file

@ -90,7 +90,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
err = validator.Validate(logEntry) err = validator.Validate(logEntry)
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "validation error:\n - proto_payload.service_name: value is required [required]\n - proto_payload.operation_name: value is required [required]\n - proto_payload.request_metadata.caller_supplied_user_agent: value is required [required]\n - proto_payload.request_metadata.request_attributes.method: value is required [required]\n - proto_payload.request_metadata.request_attributes.headers: value is required [required]\n - proto_payload.request_metadata.request_attributes.path: value is required [required]\n - proto_payload.request_metadata.request_attributes.host: value is required [required]\n - proto_payload.request_metadata.request_attributes.scheme: value is required [required]\n - proto_payload.request_metadata.request_attributes.protocol: value is required [required]\n - insert_id: value does not match regex pattern `^[0-9]+/[a-z0-9-]+/[a-z0-9-]+/[0-9]+$` [string.pattern]", err.Error()) assert.Equal(t, "validation errors:\n - proto_payload.service_name: value is required\n - proto_payload.operation_name: value is required\n - proto_payload.request_metadata.caller_supplied_user_agent: value is required\n - proto_payload.request_metadata.request_attributes.method: value is required\n - proto_payload.request_metadata.request_attributes.headers: value is required\n - proto_payload.request_metadata.request_attributes.path: value is required\n - proto_payload.request_metadata.request_attributes.host: value is required\n - proto_payload.request_metadata.request_attributes.scheme: value is required\n - proto_payload.request_metadata.request_attributes.protocol: value is required\n - insert_id: value does not match regex pattern `^[0-9]+/[a-z0-9-]+/[a-z0-9-]+/[0-9]+$`", err.Error())
}) })
t.Run("required only", func(t *testing.T) { t.Run("required only", func(t *testing.T) {
@ -130,7 +130,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", authenticationInfo.PrincipalEmail) assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", *authenticationInfo.PrincipalEmail)
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId) assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
@ -246,7 +246,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", authenticationInfo.PrincipalEmail) assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", *authenticationInfo.PrincipalEmail)
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId) assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
@ -310,6 +310,100 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
}) })
t.Run("with service account token", func(t *testing.T) {
builder := NewAuditLogEntryBuilder().
WithRequiredLocation("eu01").
WithRequiredObjectId("1").
WithRequiredObjectType(pkgAuditCommon.ObjectTypeProject).
WithRequiredOperation("stackit.demo-service.v1.operation").
WithRequiredApiRequest(pkgAuditCommon.ApiRequest{
Body: nil,
Header: internalAuditApi.TestHeadersSa,
Host: "localhost",
Method: "POST",
Scheme: "https",
Proto: "HTTP/1.1",
URL: pkgAuditCommon.RequestUrl{
Path: "/",
RawQuery: nil,
},
}).
WithRequiredRequestClientIp("127.0.0.1").
WithRequiredServiceName("demo-service").
WithRequiredWorkerId("worker-id")
logEntry, err := builder.Build(context.Background(), SequenceNumber(1))
assert.NoError(t, err)
assert.NotNil(t, logEntry)
assert.Equal(t, "projects/1/logs/admin-activity", logEntry.LogName)
assert.Nil(t, logEntry.Labels)
assert.Equal(t, auditV1.LogSeverity_LOG_SEVERITY_DEFAULT, logEntry.Severity)
assert.NotNil(t, logEntry.Timestamp)
assert.Nil(t, logEntry.CorrelationId)
assert.Regexp(t, "[0-9]+/eu01/worker-id/1", logEntry.InsertId)
assert.NotNil(t, logEntry.ProtoPayload)
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo)
assert.Equal(t, "my-service-yifc9e1@sa.stackit.cloud", *authenticationInfo.PrincipalEmail)
assert.Equal(t, "10f38b01_534b_47bb_a03a_e294ca2be4de", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Equal(t, "projects/dacc7830-843e-4c5e-86ff-aa0fb51d636f/service-accounts/10f38b01-534b-47bb-a03a-e294ca2be4de", *authenticationInfo.ServiceAccountName)
assert.Nil(t, logEntry.ProtoPayload.AuthorizationInfo)
assert.Nil(t, logEntry.ProtoPayload.Metadata)
assert.Equal(t, "stackit.demo-service.v1.operation", logEntry.ProtoPayload.OperationName)
assert.Nil(t, logEntry.ProtoPayload.Request)
requestMetadata := logEntry.ProtoPayload.RequestMetadata
assert.NotNil(t, requestMetadata)
assert.Equal(t, "127.0.0.1", requestMetadata.CallerIp)
assert.Equal(t, "custom", requestMetadata.CallerSuppliedUserAgent)
requestAttributes := requestMetadata.RequestAttributes
assert.NotNil(t, requestAttributes)
assert.Equal(t, "/", requestAttributes.Path)
assert.NotNil(t, requestAttributes.Time)
assert.Equal(t, "localhost", requestAttributes.Host)
assert.Equal(t, auditV1.AttributeContext_HTTP_METHOD_POST, requestAttributes.Method)
assert.Nil(t, requestAttributes.Id)
assert.Equal(t, "https", requestAttributes.Scheme)
assert.Equal(t, map[string]string{"user-agent": "custom"}, requestAttributes.Headers)
assert.Nil(t, requestAttributes.Query)
assert.Equal(t, "HTTP/1.1", requestAttributes.Protocol)
requestAttributesAuth := requestAttributes.Auth
assert.NotNil(t, requestAttributesAuth)
assert.Equal(t, "10f38b01_534b_47bb_a03a_e294ca2be4de/stackit%2Fserviceaccount", requestAttributesAuth.Principal)
assert.Equal(t, []string{"stackit", "api"}, requestAttributesAuth.Audiences)
assert.NotNil(t, requestAttributesAuth.Claims)
assert.Equal(t, "projects/1", logEntry.ProtoPayload.ResourceName)
assert.Nil(t, logEntry.ProtoPayload.Response)
responseMetadata := logEntry.ProtoPayload.ResponseMetadata
assert.NotNil(t, responseMetadata)
assert.Nil(t, responseMetadata.ErrorDetails)
assert.Nil(t, responseMetadata.ErrorMessage)
assert.Equal(t, wrapperspb.Int32(200), responseMetadata.StatusCode)
responseAttributes := responseMetadata.ResponseAttributes
assert.NotNil(t, responseAttributes)
assert.Nil(t, responseAttributes.Headers)
assert.Nil(t, responseAttributes.NumResponseItems)
assert.Nil(t, responseAttributes.Size)
assert.NotNil(t, responseAttributes.Time)
assert.Equal(t, "demo-service", logEntry.ProtoPayload.ServiceName)
validator, err := protovalidate.New()
assert.NoError(t, err)
err = validator.Validate(logEntry)
assert.NoError(t, err)
})
t.Run("system event", func(t *testing.T) { t.Run("system event", func(t *testing.T) {
builder := NewAuditLogEntryBuilder(). builder := NewAuditLogEntryBuilder().
WithRequiredLocation("eu01"). WithRequiredLocation("eu01").
@ -335,7 +429,7 @@ func Test_AuditLogEntryBuilder(t *testing.T) {
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, internalAuditApi.EmailAddressDoNotReplyAtStackItDotCloud, authenticationInfo.PrincipalEmail) assert.Nil(t, authenticationInfo.PrincipalEmail)
assert.Equal(t, "none", authenticationInfo.PrincipalId) assert.Equal(t, "none", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
@ -664,7 +758,7 @@ func Test_AuditEventBuilder(t *testing.T) {
Build(context.Background(), SequenceNumber(1)) Build(context.Background(), SequenceNumber(1))
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "validation error:\n - log_name: value does not match regex pattern `^[a-z-]+/[a-z0-9-]+/logs/(?:admin-activity|system-event|policy-denied|data-access)$` [string.pattern]\n - proto_payload.operation_name: value is required [required]\n - proto_payload.resource_name: value does not match regex pattern `^[a-z]+/[a-z0-9-]+(?:/[a-z0-9-]+/[a-z0-9-_]+)*$` [string.pattern]\n - proto_payload.request_metadata.caller_supplied_user_agent: value is required [required]\n - proto_payload.request_metadata.request_attributes.method: value is required [required]\n - proto_payload.request_metadata.request_attributes.headers: value is required [required]\n - proto_payload.request_metadata.request_attributes.path: value is required [required]\n - proto_payload.request_metadata.request_attributes.host: value is required [required]\n - proto_payload.request_metadata.request_attributes.scheme: value is required [required]\n - proto_payload.request_metadata.request_attributes.protocol: value is required [required]", err.Error()) assert.Equal(t, "validation errors:\n - log_name: value does not match regex pattern `^[a-z-]+/[a-z0-9-]+/logs/(?:admin-activity|system-event|policy-denied|data-access)$`\n - proto_payload.operation_name: value is required\n - proto_payload.resource_name: value does not match regex pattern `^[a-z]+/[a-z0-9-]+(?:/[a-z0-9-]+/[a-z0-9-_]+)*$`\n - proto_payload.request_metadata.caller_supplied_user_agent: value is required\n - proto_payload.request_metadata.request_attributes.method: value is required\n - proto_payload.request_metadata.request_attributes.headers: value is required\n - proto_payload.request_metadata.request_attributes.path: value is required\n - proto_payload.request_metadata.request_attributes.host: value is required\n - proto_payload.request_metadata.request_attributes.scheme: value is required\n - proto_payload.request_metadata.request_attributes.protocol: value is required", err.Error())
assert.Nil(t, cloudEvent) assert.Nil(t, cloudEvent)
assert.Nil(t, routingIdentifier) assert.Nil(t, routingIdentifier)
}) })
@ -736,7 +830,7 @@ func Test_AuditEventBuilder(t *testing.T) {
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", authenticationInfo.PrincipalEmail) assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", *authenticationInfo.PrincipalEmail)
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId) assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
@ -883,7 +977,7 @@ func Test_AuditEventBuilder(t *testing.T) {
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", authenticationInfo.PrincipalEmail) assert.Equal(t, "Christian.Schaible@novatec-gmbh.de", *authenticationInfo.PrincipalEmail)
assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId) assert.Equal(t, "cd94f01a-df2e-4456-902e-48f5e57f0b63", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
@ -1001,7 +1095,7 @@ func Test_AuditEventBuilder(t *testing.T) {
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, internalAuditApi.EmailAddressDoNotReplyAtStackItDotCloud, authenticationInfo.PrincipalEmail) assert.Nil(t, authenticationInfo.PrincipalEmail)
assert.Equal(t, "none", authenticationInfo.PrincipalId) assert.Equal(t, "none", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)
@ -1110,7 +1204,7 @@ func Test_AuditEventBuilder(t *testing.T) {
authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo authenticationInfo := logEntry.ProtoPayload.AuthenticationInfo
assert.NotNil(t, authenticationInfo) assert.NotNil(t, authenticationInfo)
assert.Equal(t, internalAuditApi.EmailAddressDoNotReplyAtStackItDotCloud, authenticationInfo.PrincipalEmail) assert.Nil(t, authenticationInfo.PrincipalEmail)
assert.Equal(t, "none", authenticationInfo.PrincipalId) assert.Equal(t, "none", authenticationInfo.PrincipalId)
assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo) assert.Nil(t, authenticationInfo.ServiceAccountDelegationInfo)
assert.Nil(t, authenticationInfo.ServiceAccountName) assert.Nil(t, authenticationInfo.ServiceAccountName)

View file

@ -131,7 +131,8 @@ message AuditLog {
// Required: true // Required: true
string service_name = 1 [ string service_name = 1 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1 (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// The name of the service method or operation. // The name of the service method or operation.
@ -232,17 +233,18 @@ message AuthenticationInfo {
// Required: true // Required: true
string principal_id = 1 [ string principal_id = 1 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1 (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// The email address of the authenticated user. // The email address of the authenticated user.
// Service accounts have email addresses that can be used. // Service accounts have email addresses that can be used.
// //
// Required: true // Required: false
string principal_email = 2 [ optional string principal_email = 2 [
(buf.validate.field).required = true, (buf.validate.field).string.min_len = 5,
(buf.validate.field).string.min_len = 1, (buf.validate.field).string.max_len = 255,
(buf.validate.field).string.max_len = 255 (buf.validate.field).string.email = true
]; ];
// The name of the service account used to create or exchange // The name of the service account used to create or exchange
@ -325,7 +327,7 @@ message AttributeContext {
// Required: true // Required: true
string principal = 1 [ string principal = 1 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.pattern = "^[a-zA-Z0-9-%.]+/[a-zA-Z0-9-%.]+$" (buf.validate.field).string.pattern = "^[a-zA-Z0-9-%._]+/[a-zA-Z0-9-%.]+$"
]; ];
// The intended audience(s) for this authentication information. Reflects // The intended audience(s) for this authentication information. Reflects
@ -414,7 +416,8 @@ message AttributeContext {
string path = 4 [ string path = 4 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1, (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.max_len = 255 (buf.validate.field).string.max_len = 255,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// The HTTP request `Host` header value. // The HTTP request `Host` header value.
@ -422,7 +425,8 @@ message AttributeContext {
// Required: true // Required: true
string host = 5 [ string host = 5 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1 (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// The URL scheme, such as `http`, `https` or `gRPC`. // The URL scheme, such as `http`, `https` or `gRPC`.
@ -430,7 +434,8 @@ message AttributeContext {
// Required: true // Required: true
string scheme = 6 [ string scheme = 6 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1 (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// 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
@ -457,7 +462,8 @@ message AttributeContext {
// Required: true // Required: true
string protocol = 9 [ string protocol = 9 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1 (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// The request authentication. // The request authentication.
@ -521,7 +527,8 @@ message RequestMetadata {
string caller_supplied_user_agent = 2 [ string caller_supplied_user_agent = 2 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1, (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.max_len = 255 (buf.validate.field).string.max_len = 255,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// This field contains request attributes like request url, time, etc. // This field contains request attributes like request url, time, etc.
@ -577,7 +584,8 @@ message ServiceAccountDelegationInfo {
// Required: true // Required: true
string principal_id = 1 [ string principal_id = 1 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1 (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// The email address of the authenticated user. // The email address of the authenticated user.
@ -587,7 +595,8 @@ message ServiceAccountDelegationInfo {
string principal_email = 2 [ string principal_email = 2 [
(buf.validate.field).required = true, (buf.validate.field).required = true,
(buf.validate.field).string.min_len = 1, (buf.validate.field).string.min_len = 1,
(buf.validate.field).string.max_len = 255 (buf.validate.field).string.max_len = 255,
(buf.validate.field).string.pattern = ".*\\S.*"
]; ];
// Metadata about the service that uses the service account. // Metadata about the service that uses the service account.

13
sonar-project.properties Normal file
View file

@ -0,0 +1,13 @@
sonar.projectKey=xx-sit-odj-sec-ident:audit-go
sonar.host.url=https://sonarqube.schwarz
sonar.projectName=audit-go
sonar.sources=.
sonar.exclusions=**/*_test.go,**/vendor/**,**/mocks/**,**/*.yml,**/gen/**, **/test/solace.go
sonar.tests=.
sonar.test.inclusions=**/*_test.go
sonar.test.exclusions=**/vendor/**,**/mocks/**
sonar.issuesReport.html.enable=true
sonar.log.level=INFO
sonar.go.coverage.reportPaths=out/cover.out
sonar.go.tests.reportPaths=out/report.json
sonar.go.golangci-lint.reportPaths=out/lint.xml