Skip to content

feat: enrich Check span with auth decision attributes - #670

Open
asanzgom wants to merge 2 commits into
Kuadrant:mainfrom
asanzgom:feat/check-span-enrichment
Open

feat: enrich Check span with auth decision attributes#670
asanzgom wants to merge 2 commits into
Kuadrant:mainfrom
asanzgom:feat/check-span-enrichment

Conversation

@asanzgom

@asanzgom asanzgom commented Aug 11, 2026

Copy link
Copy Markdown

Summary

Enrich the existing Check span with domain-specific auth decision attributes so traces carry actionable metadata for debugging auth flows in production.

Before: Check span only had authorino.request_id and guid:x-request-id.
After: Check span includes auth result, denial reason, AuthConfig name/namespace, and resolved identity source/type.

New span attributes

Attribute Type When set
authorino.auth.result ALLOW / DENY Always
authorino.auth.response_code gRPC code name Always
authorino.auth.denial_reason Denial message On deny only
authorino.auth_config.name AuthConfig CR name When AuthConfig found
authorino.auth_config.namespace AuthConfig CR namespace When AuthConfig found
authorino.identity.source Identity evaluator name When identity resolved
authorino.identity.type Identity evaluator type When identity resolved

Uses the authorino.* namespace, consistent with existing authorino.request_id. OTel has no general-purpose auth semantic conventions (only framework-specific aspnetcore.*), so a custom namespace avoids future collisions.

Attributes are set at every exit path in Check() (invalid request, service not found, context timeout, pipeline result) so spans always carry the decision.

Changes

  • pkg/trace/trace.go: Add 7 attribute name constants
  • pkg/service/auth.go: Set span attributes at each return path in Check(); add setAuthResultSpanAttrs helper
  • pkg/service/auth_test.go: 4 new tests verifying span attributes for allowed, denied, not-found, and invalid request scenarios

Related

Test plan

  • All 4 new span attribute tests pass (TestCheckSpanAttributes_*)
  • All 43 existing service tests pass unchanged
  • go build ./pkg/service/ compiles cleanly

Summary by CodeRabbit

  • New Features
    • Authentication and authorisation tracing now records whether requests were allowed or denied.
    • Trace data includes response codes, denial reasons, authentication configuration details, and resolved identity source and type.
    • Invalid requests, missing configuration, context errors, and evaluated results now provide consistent diagnostic attributes for improved observability.
    • Authentication outcomes can be investigated more consistently across successful, denied, invalid, and unavailable-service requests.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 736d7a38-7e84-4b19-9735-8aaa34b6b677

📥 Commits

Reviewing files that changed from the base of the PR and between a792584 and 774ec95.

📒 Files selected for processing (1)
  • pkg/service/auth_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/service/auth_test.go

📝 Walkthrough

Walkthrough

The authorisation service now enriches OpenTelemetry spans with decision, response, denial, AuthConfig, and identity attributes. Tests verify these attributes for allowed, denied, unknown-service, and invalid requests.

Changes

Authentication trace enrichment

Layer / File(s) Summary
Trace attribute contracts
pkg/trace/trace.go
Adds exported constants for authentication results, response codes, denial reasons, AuthConfig metadata, and identity metadata.
Authorisation span enrichment
pkg/service/auth.go
Records trace attributes for invalid requests, missing services, context errors, and evaluated authorisation results.
Trace attribute validation
pkg/service/auth_test.go
Adds an in-memory tracer and tests span attributes for allowed, denied, unknown-service, and invalid requests.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Poem

A rabbit watches spans appear,
ALLOW and DENY are clear.
Config and identity leave their mark,
Reasons shine within the dark.
Trace the hops from burrow to spark.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements the Check span enrichment but does not include the linked issue's required authorino.auth.denial_code attribute [#669]. Add authorino.auth.denial_code to denied spans and add test coverage for the result code.
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding authentication decision attributes to the Check span.
Out of Scope Changes check ✅ Passed The changes remain within the linked issue's Check span enrichment scope and include only related constants, instrumentation, and tests.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/service/auth_test.go`:
- Around line 408-548: Complete the span attribute assertions in the four tests:
add IdentityTypeAttr validation to TestCheckSpanAttributes_AllowedRequest,
AuthConfigNamespaceAttr validation to TestCheckSpanAttributes_DeniedRequest,
AuthResponseCodeAttr validation with the NOT_FOUND value to
TestCheckSpanAttributes_ServiceNotFound, and AuthDenialReasonAttr validation to
TestCheckSpanAttributes_InvalidRequest. Use the expected values emitted by each
path and preserve the existing assertions.
- Around line 390-393: Update the t.Cleanup callback in the tracer-provider test
setup to handle the error returned by tp.Shutdown, preserving restoration of
prev and ensuring shutdown failures are reported rather than ignored.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: db624617-f7df-44f9-8e18-0767f8697f95

📥 Commits

Reviewing files that changed from the base of the PR and between a2acd57 and a792584.

📒 Files selected for processing (3)
  • pkg/service/auth.go
  • pkg/service/auth_test.go
  • pkg/trace/trace.go

Comment thread pkg/service/auth_test.go
Comment thread pkg/service/auth_test.go
asanzgom and others added 2 commits August 11, 2026 15:35
Add domain-specific span attributes to the existing Check span so traces
carry actionable auth metadata instead of only authorino.request_id.

New attributes: authorino.auth.result (ALLOW/DENY),
authorino.auth.response_code, authorino.auth.denial_reason,
authorino.auth_config.name, authorino.auth_config.namespace,
authorino.identity.source, and authorino.identity.type.

Closes Kuadrant#669

Signed-off-by: Adrian Sanz Gomiz <asanzgom@redhat.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Adrián Sanz Gómiz <asanzgom@redhat.com>
Add missing assertions to the four span attribute tests: IdentityTypeAttr
in AllowedRequest, AuthConfigNamespaceAttr in DeniedRequest,
AuthResponseCodeAttr in ServiceNotFound, and AuthDenialReasonAttr in
InvalidRequest. Handle the error returned by TracerProvider.Shutdown in
the test cleanup callback.

Signed-off-by: Adrian Sanz Gomiz <asanzgom@redhat.com>
Signed-off-by: Adrián Sanz Gómiz <asanzgom@redhat.com>
@asanzgom
asanzgom force-pushed the feat/check-span-enrichment branch from 774ec95 to ea4a1f8 Compare August 11, 2026 13:35
Comment thread pkg/service/auth.go
Comment on lines +296 to +299
span.SetAttributes(
otel_attr.String(trace.AuthConfigNameAttr, authConfig.Labels["authconfig"]),
otel_attr.String(trace.AuthConfigNamespaceAttr, authConfig.Labels["namespace"]),
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should iterate over the AuthConfig labels and set them dynamically into the span, similarly to what we do with the metrics.

I understand the keys wouldn't be the same as proposed, but perhaps this is also an opportunity to standardise them across the different types of observability sources?

E.g.:

Suggested change
span.SetAttributes(
otel_attr.String(trace.AuthConfigNameAttr, authConfig.Labels["authconfig"]),
otel_attr.String(trace.AuthConfigNamespaceAttr, authConfig.Labels["namespace"]),
)
for k, v := range authConfig.Labels {
span.SetAttributes(otel_attr.String(fmt.Sprintf("authorino.authconfig.%s", k), v))
}

Comment thread pkg/service/auth.go
Comment on lines +524 to +534
func setAuthResultSpanAttrs(span otel_trace.Span, result auth.AuthResult) {
if result.Success() {
span.SetAttributes(otel_attr.String(trace.AuthResultAttr, "ALLOW"))
} else {
span.SetAttributes(otel_attr.String(trace.AuthResultAttr, "DENY"))
if result.Message != "" {
span.SetAttributes(otel_attr.String(trace.AuthDenialReasonAttr, result.Message))
}
}
span.SetAttributes(otel_attr.String(trace.AuthResponseCodeAttr, result.Code.String()))
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs documentation at https://github.com/Kuadrant/authorino/blob/main/docs/user-guides/observability.md#data-plane-tracing.

Other than the new attributes, a couple of things that seem important to get covered IMO:

  • DENY is also used along with other GRPC response codes such as UNAVAILABLE and NOT_FOUND.
    • Note: either ALLOW or DENY, the PEP can still behave otherwise. E.g.: a 50x that falls back to access granted, flipping the default failure_mode_allow
  • result.Code is the ext_authz GRPC response code, not the HTTP status code one may expect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Enrich auth pipeline trace spans with decision attributes and per-evaluator child spans

2 participants