Skip to content

Commit 9d2d858

Browse files
committed
Implement OTEL audit logging in Admin API
- Add audit logging middleware to Admin API, capturing WHO/WHAT/WHEN for every request via `go-otel-audit` - Refactor shared `CreateOtelAuditMsg` to accept caller-specific operation description, access level, and identities (previously hardcoded to Frontend values) - Share response writer to capture status codes with frontend - Add `audit.connectSocket` config for mdsd socket connection [ARO-24628](https://issues.redhat.com/browse/ARO-24628) Signed-off-by: Gerd Oberlechner <goberlec@redhat.com>
1 parent 48168d2 commit 9d2d858

File tree

17 files changed

+382
-29
lines changed

17 files changed

+382
-29
lines changed

.yamllint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ yaml-files:
55
ignore:
66
- 'acrpull/deploy/templates/deployment.yaml'
77
- 'admin/deploy/templates/ext-authz.authorizationpolicy.yaml'
8+
- 'admin/deploy/templates/admin.deployment.yaml'
89
- 'frontend/deploy/templates/ext-authz.authorizationpolicy.yaml'
910
- 'frontend/deploy/templates/allow-ingress.authorizationpolicy.yaml'
1011
- 'frontend/deploy/templates/frontend.deployment.yaml'

admin/deploy/templates/admin.deployment.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ spec:
5858
value: "/secrets/fpa-cert/bundle"
5959
- name: FPA_CLIENT_ID
6060
value: "{{ .Values.fpa.clientId }}"
61+
- name: AUDIT_CONNECT_SOCKET
62+
value: "{{ .Values.audit.connectSocket }}"
6163
ports:
6264
- containerPort: 8443
6365
name: http
@@ -97,10 +99,20 @@ spec:
9799
- name: fpa-cert
98100
mountPath: /secrets/fpa-cert
99101
readOnly: true
102+
{{- if .Values.audit.connectSocket }}
103+
- name: mdsd-asa-run-vol
104+
mountPath: /var/run/mdsd
105+
{{- end }}
100106
volumes:
101107
- name: fpa-cert
102108
csi:
103109
driver: secrets-store.csi.k8s.io
104110
readOnly: true
105111
volumeAttributes:
106112
secretProviderClass: fpa-cert
113+
{{- if .Values.audit.connectSocket }}
114+
- name: mdsd-asa-run-vol
115+
hostPath:
116+
path: /var/run/mdsd
117+
type: Directory
118+
{{- end }}

admin/server/cmd/server/options.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ package server
1717
import (
1818
"context"
1919
"fmt"
20+
"log/slog"
2021
"net"
2122
"os"
2223
"time"
2324

25+
"github.com/go-logr/logr"
26+
"github.com/microsoft/go-otel-audit/audit/base"
2427
"github.com/prometheus/client_golang/prometheus"
2528
"github.com/spf13/cobra"
2629

@@ -31,6 +34,7 @@ import (
3134
sdk "github.com/openshift-online/ocm-sdk-go"
3235

3336
"github.com/Azure/ARO-HCP/admin/server/server"
37+
"github.com/Azure/ARO-HCP/internal/audit"
3438
"github.com/Azure/ARO-HCP/internal/database"
3539
"github.com/Azure/ARO-HCP/internal/fpa"
3640
"github.com/Azure/ARO-HCP/internal/ocm"
@@ -39,8 +43,9 @@ import (
3943

4044
func DefaultOptions() *RawOptions {
4145
return &RawOptions{
42-
Port: 8443,
43-
MetricsPort: 8444,
46+
Port: 8443,
47+
MetricsPort: 8444,
48+
AuditLogQueueSize: 2048,
4449
}
4550
}
4651

@@ -56,6 +61,8 @@ type RawOptions struct {
5661
KustoEndpoint string
5762
FpaCertBundlePath string
5863
FpaClientID string
64+
AuditLogQueueSize int
65+
AuditConnectSocket bool
5966
}
6067

6168
func (opts *RawOptions) BindOptions(cmd *cobra.Command) error {
@@ -68,6 +75,8 @@ func (opts *RawOptions) BindOptions(cmd *cobra.Command) error {
6875
cmd.Flags().StringVar(&opts.KustoEndpoint, "kusto-endpoint", getEnv("KUSTO_ENDPOINT", opts.KustoEndpoint), "Endpoint of the Kusto cluster.")
6976
cmd.Flags().StringVar(&opts.FpaClientID, "fpa-client-id", getEnv("FPA_CLIENT_ID", opts.FpaClientID), "Client ID of the FPA application.")
7077
cmd.Flags().StringVar(&opts.FpaCertBundlePath, "fpa-cert-bundle-path", getEnv("FPA_CERT_BUNDLE_PATH", opts.FpaCertBundlePath), "Path to the FPA certificate bundle.")
78+
cmd.Flags().IntVar(&opts.AuditLogQueueSize, "audit-log-queue-size", opts.AuditLogQueueSize, "Log queue size for audit logging client.")
79+
cmd.Flags().BoolVar(&opts.AuditConnectSocket, "audit-connect-socket", os.Getenv("AUDIT_CONNECT_SOCKET") == "true", "Connect to mdsd audit socket.")
7180
return nil
7281
}
7382

@@ -97,6 +106,7 @@ type completedOptions struct {
97106
ClusterServiceClient ocm.ClusterServiceClientSpec
98107
KustoClient *kusto.Client
99108
FpaCredentialRetriever fpa.FirstPartyApplicationTokenCredentialRetriever
109+
AuditClient audit.Client
100110
}
101111

102112
type Options struct {
@@ -176,6 +186,19 @@ func (o *ValidatedOptions) Complete(ctx context.Context) (*Options, error) {
176186
return nil, fmt.Errorf("failed to create the FPA token credentials: %w", err)
177187
}
178188

189+
// Create audit client
190+
logger := utils.LoggerFromContext(ctx)
191+
slogLogger := slog.New(logr.ToSlogHandler(logger))
192+
auditClient, err := audit.NewOtelAuditClient(
193+
audit.CreateConn(o.AuditConnectSocket),
194+
base.WithLogger(slogLogger),
195+
base.WithSettings(base.Settings{
196+
QueueSize: o.AuditLogQueueSize,
197+
}))
198+
if err != nil {
199+
return nil, fmt.Errorf("failed to create audit client: %w", err)
200+
}
201+
179202
return &Options{
180203
completedOptions: &completedOptions{
181204
Port: o.Port,
@@ -185,6 +208,7 @@ func (o *ValidatedOptions) Complete(ctx context.Context) (*Options, error) {
185208
ClusterServiceClient: csClient,
186209
KustoClient: kustoClient,
187210
FpaCredentialRetriever: fpaCredentialRetriever,
211+
AuditClient: auditClient,
188212
},
189213
}, nil
190214
}
@@ -213,6 +237,7 @@ func (opts *Options) Run(ctx context.Context) error {
213237
opts.ClusterServiceClient,
214238
opts.KustoClient,
215239
opts.FpaCredentialRetriever,
240+
opts.AuditClient,
216241
)
217242

218243
runErrCh := make(chan error)

admin/server/go.mod

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ require (
88
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0
99
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6 v6.2.0
1010
github.com/go-logr/logr v1.4.3
11+
github.com/microsoft/go-otel-audit v0.2.2
1112
github.com/openshift-online/ocm-sdk-go v0.1.494
1213
github.com/prometheus/client_golang v1.23.2
1314
github.com/spf13/cobra v1.10.2
15+
github.com/stretchr/testify v1.11.1
1416
)
1517

1618
require (
@@ -19,6 +21,7 @@ require (
1921
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect
2022
github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos v1.4.1 // indirect
2123
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect
24+
github.com/Azure/retry v0.0.0-20250221010952-92c9290cea0f // indirect
2225
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 // indirect
2326
github.com/aymerick/douceur v0.2.0 // indirect
2427
github.com/beorn7/perks v1.0.1 // indirect
@@ -29,19 +32,23 @@ require (
2932
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
3033
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
3134
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
35+
github.com/go-json-experiment/json v0.0.0-20250517221953-25912455fbc8 // indirect
3236
github.com/go-logr/stdr v1.2.2 // indirect
3337
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
3438
github.com/gogo/protobuf v1.3.2 // indirect
3539
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
3640
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
3741
github.com/golang/glog v1.2.5 // indirect
42+
github.com/golang/protobuf v1.5.4 // indirect
3843
github.com/google/go-cmp v0.7.0 // indirect
3944
github.com/google/uuid v1.6.0 // indirect
4045
github.com/gorilla/css v1.0.1 // indirect
4146
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
4247
github.com/inconshreveable/mousetrap v1.1.0 // indirect
48+
github.com/jedib0t/go-pretty/v6 v6.6.7 // indirect
4349
github.com/json-iterator/go v1.1.12 // indirect
4450
github.com/kylelemons/godebug v1.1.0 // indirect
51+
github.com/mattn/go-runewidth v0.0.16 // indirect
4552
github.com/microcosm-cc/bluemonday v1.0.27 // indirect
4653
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
4754
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
@@ -53,11 +60,14 @@ require (
5360
github.com/prometheus/client_model v0.6.2 // indirect
5461
github.com/prometheus/common v0.66.1 // indirect
5562
github.com/prometheus/procfs v0.17.0 // indirect
63+
github.com/rivo/uniseg v0.4.7 // indirect
5664
github.com/samber/lo v1.52.0 // indirect
65+
github.com/sanity-io/litter v1.5.8 // indirect
5766
github.com/shopspring/decimal v1.4.0 // indirect
5867
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
5968
github.com/spf13/pflag v1.0.10 // indirect
60-
github.com/stretchr/testify v1.11.1 // indirect
69+
github.com/vmihailenco/msgpack/v4 v4.3.13 // indirect
70+
github.com/vmihailenco/tagparser v0.1.2 // indirect
6171
github.com/x448/float16 v0.8.4 // indirect
6272
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
6373
go.opentelemetry.io/contrib/bridges/prometheus v0.62.0 // indirect
@@ -85,10 +95,12 @@ require (
8595
go.uber.org/mock v0.6.0 // indirect
8696
go.yaml.in/yaml/v2 v2.4.2 // indirect
8797
golang.org/x/crypto v0.46.0 // indirect
98+
golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect
8899
golang.org/x/net v0.47.0 // indirect
89100
golang.org/x/oauth2 v0.30.0 // indirect
90101
golang.org/x/sys v0.39.0 // indirect
91102
golang.org/x/text v0.32.0 // indirect
103+
google.golang.org/appengine v1.6.8 // indirect
92104
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
93105
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
94106
google.golang.org/grpc v1.76.0 // indirect

0 commit comments

Comments
 (0)