Skip to content

feat(auth): add public Authorizer interface for Event Ledger#256

Open
raza-khan0108 wants to merge 3 commits into
NVIDIA:mainfrom
raza-khan0108:feat/180-eventledger-authorizer
Open

feat(auth): add public Authorizer interface for Event Ledger#256
raza-khan0108 wants to merge 3 commits into
NVIDIA:mainfrom
raza-khan0108:feat/180-eventledger-authorizer

Conversation

@raza-khan0108

@raza-khan0108 raza-khan0108 commented Jul 19, 2026

Copy link
Copy Markdown

TL;DR

Add a public Go Authorizer interface, structured data models (AuthRequest, AuthResult, Action), and open-source implementations (NoopAuthorizer, WebhookAuthorizer) inside src/libraries/go/lib/pkg/auth. This decouples open-source builds such as Event Ledger from proprietary internal authorization services.

Additional Details

  • Problem: Upstream Event Ledger currently imports and calls a proprietary internal authorization service client library. This creates a hard dependency on closed-source code, preventing clean compilation in open-source self-managed builds and restricting operators from plugging in external identity providers or policy engines.
  • Solution:
    • Defined the Authorizer interface with an Authorize(ctx context.Context, req *AuthRequest) (*AuthResult, error) contract, aligned with established pluggable patterns in nats-auth-callout and llm-api-gateway.
    • Added NoopAuthorizer for local development, standalone testing, and single-tenant deployments (Allowed: true for all requests).
    • Added WebhookAuthorizer to delegate access evaluation via HTTP POST callouts (application/json) to external endpoints, enabling integration with enterprise identity gateways or Open Policy Agent (OPA) sidecars.
  • Next Steps: Upstream Event Ledger middleware can now be refactored to consume the Authorizer interface (pkg/auth.Authorizer) instead of directly importing proprietary client libraries.

For the Reviewer

Please review the interface definition and error handling in:

  • src/libraries/go/lib/pkg/auth/authorizer.go
  • src/libraries/go/lib/pkg/auth/authorizer_test.go
  • src/libraries/go/lib/pkg/auth/BUILD.bazel

Verify that the AuthRequest and AuthResult structs provide sufficient context for downstream control plane and compute plane services adopting open-source authorization.

For QA

  • Verified NoopAuthorizer allows valid requests and rejects nil requests with ErrUnauthorized.
  • Verified WebhookAuthorizer using httptest.Server against 200 OK allowed, 200 OK denied, 401 Unauthorized, 403 Forbidden, and 500 Internal Server Error scenarios.
  • Verified Bazel target integration by updating srcs in src/libraries/go/lib/pkg/auth/BUILD.bazel.

Is QA Needed? No manual QA needed until integrated into downstream service charts.

Issues

Fixes #180

Checklist

  • I am familiar with the Contributing Guidelines.
  • I have signed off my commits for Developer Certificate of Origin (DCO) compliance.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

Summary by CodeRabbit

  • New Features
    • Added a shared authorization abstraction with request/response models and standardized errors for unauthorized, forbidden, and internal failures.
    • Introduced a permissive no-op authorizer for non-policy scenarios.
    • Added webhook-based authorization with configurable endpoint, pluggable HTTP client, request timeouts, safe handling of redirects, and capped response processing.
  • Tests
    • Added unit tests for constructor/options validation, successful webhook authorization, HTTP status-to-result mapping, oversized/invalid webhook responses, and transport error handling.

Add public Authorizer interface, data models, and open-source implementations (NoopAuthorizer and WebhookAuthorizer) inside src/libraries/go/lib/pkg/auth. This decouples open-source builds like Event Ledger from proprietary authorization services.

Ref: NVIDIA#180
@raza-khan0108
raza-khan0108 requested a review from a team as a code owner July 19, 2026 16:16
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 06fe13e8-0f9e-485b-a6bc-a11a323c7fe3

📥 Commits

Reviewing files that changed from the base of the PR and between 2039d58 and b650faa.

📒 Files selected for processing (2)
  • src/libraries/go/lib/pkg/auth/authorizer.go
  • src/libraries/go/lib/pkg/auth/authorizer_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/libraries/go/lib/pkg/auth/authorizer_test.go
  • src/libraries/go/lib/pkg/auth/authorizer.go

📝 Walkthrough

Walkthrough

Adds a public Go authorization interface with no-op and webhook implementations, exported request/result types, HTTP status mapping, bounded response handling, unit tests, and Bazel source registration.

Changes

Authorization providers

Layer / File(s) Summary
Authorization contract and no-op provider
src/libraries/go/lib/pkg/auth/authorizer.go, src/libraries/go/lib/pkg/auth/authorizer_test.go
Defines authorization errors, request/result models, the Authorizer interface, and permissive no-op authorization behavior with tests.
Webhook authorization provider
src/libraries/go/lib/pkg/auth/authorizer.go, src/libraries/go/lib/pkg/auth/authorizer_test.go
Adds configurable webhook construction, redirect prevention, context-bound HTTP POST authorization, bounded response reads, status mapping, error wrapping, and coverage for transport and malformed-response failures.
Authorization build registration
src/libraries/go/lib/pkg/auth/BUILD.bazel
Registers the authorizer implementation and tests in the Go Bazel targets.

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

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant WebhookAuthorizer
  participant HTTPClient
  participant AuthorizationService
  Caller->>WebhookAuthorizer: Authorize(ctx, AuthRequest)
  WebhookAuthorizer->>HTTPClient: POST JSON request
  HTTPClient->>AuthorizationService: HTTP authorization request
  AuthorizationService-->>HTTPClient: status and AuthResult
  HTTPClient-->>WebhookAuthorizer: HTTP response
  WebhookAuthorizer-->>Caller: AuthResult or authorization error
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a public Authorizer interface and implementations for Event Ledger.
Linked Issues check ✅ Passed The PR satisfies #180 by introducing a public Go authorization interface usable by open-source builds without the proprietary service dependency.
Out of Scope Changes check ✅ Passed The changes stay focused on the auth interface, its implementations, and supporting tests/build updates; no unrelated scope is evident.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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: 3

🧹 Nitpick comments (1)
src/libraries/go/lib/pkg/auth/authorizer.go (1)

147-155: 🩺 Stability & Availability | 🔵 Trivial

Instrument the webhook authorization call. Wrap the client transport with otelhttp.NewTransport and add redacted structured logs on failures. Do not log Credential or the request body; if you add metrics, keep labels bounded and cover any new label values with tests.

🤖 Prompt for 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.

In `@src/libraries/go/lib/pkg/auth/authorizer.go` around lines 147 - 155,
Instrument the webhook request in the authorizer flow around httpReq and
w.client.Do by using an otelhttp.NewTransport-wrapped client transport and
adding structured, redacted failure logs. Exclude Credential and request body
from all logs; if introducing metrics, use only bounded labels and add tests for
every new label value.

Sources: Coding guidelines, Path instructions

🤖 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 `@src/libraries/go/lib/pkg/auth/authorizer.go`:
- Around line 130-133: Update the authorizer constructor around the opts loop to
skip nil WebhookOption values before invoking them, then validate the resolved
HTTP client and return an error when it is nil instead of returning a usable
authorizer. Add coverage for both nil options and WithHTTPClient(nil).
- Around line 142-171: Update the error-wrapping paths in the authorizer request
flow—covering json.Marshal, http.NewRequestWithContext, w.client.Do, and the
response decoder—to preserve each underlying cause for errors.Is/errors.As. Use
wrapping that retains both ErrAuthorizerInternal and the original error, while
keeping the existing contextual messages and sentinel behavior.
- Around line 124-128: Configure the http.Client created in WebhookAuthorizer to
reject redirects, and apply the same no-redirect policy to any injected client
before webhook requests are sent. Update the WebhookAuthorizer-related tests
with a regression case verifying 307/308 responses do not replay the POST or
expose AuthRequest.Credential to the redirect target.

---

Nitpick comments:
In `@src/libraries/go/lib/pkg/auth/authorizer.go`:
- Around line 147-155: Instrument the webhook request in the authorizer flow
around httpReq and w.client.Do by using an otelhttp.NewTransport-wrapped client
transport and adding structured, redacted failure logs. Exclude Credential and
request body from all logs; if introducing metrics, use only bounded labels and
add tests for every new label value.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e38b79d2-3341-4565-8433-d25c6da3916c

📥 Commits

Reviewing files that changed from the base of the PR and between c79102d and b185abc.

📒 Files selected for processing (3)
  • src/libraries/go/lib/pkg/auth/BUILD.bazel
  • src/libraries/go/lib/pkg/auth/authorizer.go
  • src/libraries/go/lib/pkg/auth/authorizer_test.go

Comment thread src/libraries/go/lib/pkg/auth/authorizer.go Outdated
Comment thread src/libraries/go/lib/pkg/auth/authorizer.go
Comment thread src/libraries/go/lib/pkg/auth/authorizer.go Outdated
Comment thread src/libraries/go/lib/pkg/auth/authorizer.go
Remove event-ledger-specific Action constants (ActionReadEvents,
ActionWriteEvents, ActionAdmin) from the shared pkg/auth library.
Keeping only the Action type here; consuming services define their
own action values in their own packages.

Disable HTTP redirects on WebhookAuthorizer so that 307/308
responses cannot replay a POST carrying AuthRequest.Credential to
an unintended redirect target. The default client is constructed
with noRedirectPolicy. Any caller-injected client that has no
CheckRedirect set receives the same policy from the constructor.

Guard against nil WebhookOption values and nil HTTP clients in
NewWebhookAuthorizer, returning an error rather than producing an
authorizer that panics at call time.

Read the full webhook response body upfront with io.ReadAll so it
is available on all non-200 paths. The 403 Reason is now populated
from the body when present; non-200 errors include the body text
for production debuggability. Switch from json.NewDecoder to
json.Unmarshal since bytes are already in memory.

Wrap all underlying errors with %w instead of %v throughout
Authorize so callers can inspect the error chain with errors.Is
and errors.As.

Extend the test suite with coverage for: nil option rejection, nil
client rejection, 403 body propagation, non-200 body in error
messages, 307 and 308 redirect blocking regression cases, and
injected-client redirect-policy enforcement.

Ref: NVIDIA#180
Signed-off-by: coffeecoder08 <razawarsi828@gmail.com>
@raza-khan0108

raza-khan0108 commented Jul 21, 2026

Copy link
Copy Markdown
Author

Pushed as commit 2039d585 on feat/180-eventledger-authorizer.
All four issues from the review have been resolved.


1. Action constants moved out of pkg/auth

Reviewer: shelleyshen-0 (authorizer.go:59)

The three event-ledger-specific constants have been removed from the shared library:

-const (
-    ActionReadEvents  Action = "eventledger.events.read"
-    ActionWriteEvents Action = "eventledger.events.write"
-    ActionAdmin       Action = "eventledger.admin"
-)

pkg/auth now exports only type Action string. Each consuming service declares its own values:

// in event-ledger's own constants package
const (
    ActionReadEvents  auth.Action = "eventledger.events.read"
    ActionWriteEvents auth.Action = "eventledger.events.write"
    ActionAdmin       auth.Action = "eventledger.admin"
)

The authorizer_test.go file was updated to use package-local test constants (testActionRead, testActionWrite) so the shared package has no dependency on service-specific strings.


2. Upfront response-body reading for debuggability

Reviewer: shelleyshen-0 (authorizer.go:161)

The response body is now read once upfront with io.ReadAll and reused across all status-code branches:

  • 403 Forbidden: Reason is populated from the body when non-empty; falls back to "forbidden by policy" for empty bodies.
  • Non-200 errors: the body text is included in the error message for production log context.
  • Decode path: switched from json.NewDecoder streaming to json.Unmarshal since the bytes are already in memory.
respBody, err := io.ReadAll(resp.Body)
if err != nil {
    return nil, fmt.Errorf("%w: failed to read webhook response body: %w", ErrAuthorizerInternal, err)
}

if resp.StatusCode == http.StatusForbidden {
    reason := "forbidden by policy"
    if len(respBody) > 0 {
        reason = string(respBody)
    }
    return &AuthResult{Allowed: false, Reason: reason}, nil
}
if resp.StatusCode != http.StatusOK {
    return nil, fmt.Errorf("%w: unexpected status %d from webhook: %s", ErrAuthorizerInternal, resp.StatusCode, respBody)
}

3. HTTP redirect blocking (credential leak prevention)

Reviewer: coderabbitai (authorizer.go:128)

A noRedirectPolicy function is added that returns http.ErrUseLastResponse, causing http.Client to surface the redirect response directly rather than following it. This prevents 307/308 from replaying a POST that carries AuthRequest.Credential to an unintended target.

  • The default client in NewWebhookAuthorizer is constructed with CheckRedirect: noRedirectPolicy.
  • Injected clients that have CheckRedirect == nil also receive the policy from the constructor.

Regression tests added for both 307 TemporaryRedirect and 308 PermanentRedirect, verifying the redirect target never receives the request.


4. Nil option and nil client guards

Reviewer: coderabbitai (authorizer.go:133)

NewWebhookAuthorizer now validates inputs before returning:

for _, opt := range opts {
    if opt == nil {
        return nil, errors.New("webhook option must not be nil")
    }
    opt(w)
}
if w.client == nil {
    return nil, errors.New("webhook HTTP client must not be nil")
}

This covers two previously panicking cases:

  • A nil value passed directly in the opts slice.
  • WithHTTPClient(nil) setting the client field to nil, producing a panic on the first Do call.

5. Full error-chain preservation with %w

Reviewer: coderabbitai (authorizer.go:171)

All fmt.Errorf calls in Authorize now use %w for the underlying error instead of %v, so callers can inspect the full chain:

// Before
return nil, fmt.Errorf("%w: failed to marshal auth request: %v", ErrAuthorizerInternal, err)

// After
return nil, fmt.Errorf("%w: failed to marshal auth request: %w", ErrAuthorizerInternal, err)

This applies to marshal, request-creation, transport, body-read, and decode error sites, enabling errors.Is and errors.As to unwrap to the root cause.


Test coverage added

Test case What it covers
nil option returns error Constructor rejects nil WebhookOption
nil HTTP client returns error WithHTTPClient(nil) rejected at construction
webhook returns forbidden status with body 403 body propagated to Reason
webhook returns unexpected status code with body Non-200 body present in error string
307 redirect does not replay POST to redirect target Redirect-blocking regression
308 redirect does not replay POST to redirect target Redirect-blocking regression
injected client without redirect policy gets no-redirect applied Constructor enforces policy on injected clients

@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: 3

♻️ Duplicate comments (1)
src/libraries/go/lib/pkg/auth/authorizer.go (1)

145-148: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Enforce redirect blocking for every injected client.

A non-nil custom CheckRedirect is preserved here, so it can follow a 307/308 and replay AuthRequest.Credential. Always install noRedirectPolicy on the authorizer's private client instance; do not mutate a caller-owned shared client. Update the custom-client test to verify its transport/timeout are retained while redirects remain blocked.

🤖 Prompt for 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.

In `@src/libraries/go/lib/pkg/auth/authorizer.go` around lines 145 - 148, Update
the authorizer initialization around w.client and noRedirectPolicy to always
install noRedirectPolicy, regardless of any injected CheckRedirect value, on a
private client instance rather than mutating the caller-owned client. Preserve
the injected client’s transport and timeout settings, and update the
custom-client test to verify those settings remain intact while redirects are
blocked.
🤖 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 `@src/libraries/go/lib/pkg/auth/authorizer_test.go`:
- Around line 171-185: Extend the webhook authorizer tests around the existing
unexpected-status case with injected-client scenarios for transport failure,
response-body read failure, and malformed JSON on a 200 response. For each case,
assert that authorization returns no response and that errors.Is recognizes both
ErrAuthorizerInternal and the corresponding underlying sentinel error.

In `@src/libraries/go/lib/pkg/auth/authorizer.go`:
- Around line 175-177: Update the response-body handling in the authorizer
request flow to read through a size-limited reader instead of calling io.ReadAll
directly, and return ErrAuthorizerInternal when the configured maximum is
exceeded. Preserve existing read-error wrapping and status handling for
responses within the limit, and add a test covering an oversized webhook
response.
- Around line 169-171: Instrument the outbound request in the authorizer flow
around w.client.Do with an OTEL client span and W3C Trace Context propagation,
following the existing outbound HTTP patterns in the same authorizer
implementation. Mark transport errors and non-OK HTTP responses on the span
while preserving the current error returns and response handling.

---

Duplicate comments:
In `@src/libraries/go/lib/pkg/auth/authorizer.go`:
- Around line 145-148: Update the authorizer initialization around w.client and
noRedirectPolicy to always install noRedirectPolicy, regardless of any injected
CheckRedirect value, on a private client instance rather than mutating the
caller-owned client. Preserve the injected client’s transport and timeout
settings, and update the custom-client test to verify those settings remain
intact while redirects are blocked.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9eb97021-00c4-4913-a33a-870835a28b89

📥 Commits

Reviewing files that changed from the base of the PR and between b185abc and 2039d58.

📒 Files selected for processing (2)
  • src/libraries/go/lib/pkg/auth/authorizer.go
  • src/libraries/go/lib/pkg/auth/authorizer_test.go

Comment on lines +171 to +185
t.Run("webhook returns unexpected status code with body", func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("upstream unavailable"))
}))
defer server.Close()

authorizer, err := NewWebhookAuthorizer(server.URL)
require.NoError(t, err)

res, err := authorizer.Authorize(ctx, &AuthRequest{Action: testActionRead})
require.ErrorIs(t, err, ErrAuthorizerInternal)
assert.Contains(t, err.Error(), "upstream unavailable")
assert.Nil(t, res)
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Cover the new error-wrapping paths.

Add injected-client tests for transport failure, response-body read failure, and malformed 200 JSON. Assert both ErrAuthorizerInternal and the underlying sentinel via errors.Is.

As per coding guidelines, “Code changes must include tests”; as per path instructions, “Tests are included for behavior changes—especially request/auth-path logic and error handling.”

🤖 Prompt for 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.

In `@src/libraries/go/lib/pkg/auth/authorizer_test.go` around lines 171 - 185,
Extend the webhook authorizer tests around the existing unexpected-status case
with injected-client scenarios for transport failure, response-body read
failure, and malformed JSON on a 200 response. For each case, assert that
authorization returns no response and that errors.Is recognizes both
ErrAuthorizerInternal and the corresponding underlying sentinel error.

Sources: Coding guidelines, Path instructions

Comment on lines +169 to +171
resp, err := w.client.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("%w: webhook request failed: %w", ErrAuthorizerInternal, err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and inspect relevant regions.
git ls-files src/libraries/go/lib/pkg/auth/authorizer.go
wc -l src/libraries/go/lib/pkg/auth/authorizer.go
cat -n src/libraries/go/lib/pkg/auth/authorizer.go | sed -n '1,260p'

# Search for tracing / otel usage in the auth package and nearby code.
rg -n "otel|trace\.|propagat|Inject|Span|Start\(" src/libraries/go/lib/pkg/auth src/libraries/go/lib/pkg -g'*.go'

Repository: NVIDIA/nvcf

Length of output: 50367


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the existing instrumented HTTP client pattern in the auth package.
cat -n src/libraries/go/lib/pkg/auth/auth_token_fetcher.go | sed -n '1,180p'

# Also inspect the generic HTTP client helper used elsewhere for tracing conventions.
cat -n src/libraries/go/lib/pkg/nvkit/clients/http_client.go | sed -n '220,260p'

Repository: NVIDIA/nvcf

Length of output: 8345


Instrument the webhook authorization request. Add an OTEL client span around w.client.Do, propagate W3C Trace Context, and mark transport/non-OK failures as errors to match the other outbound HTTP paths in src/libraries/go/lib/pkg/auth/authorizer.go:169-191.

🤖 Prompt for 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.

In `@src/libraries/go/lib/pkg/auth/authorizer.go` around lines 169 - 171,
Instrument the outbound request in the authorizer flow around w.client.Do with
an OTEL client span and W3C Trace Context propagation, following the existing
outbound HTTP patterns in the same authorizer implementation. Mark transport
errors and non-OK HTTP responses on the span while preserving the current error
returns and response handling.

Sources: Coding guidelines, Path instructions

Comment on lines +175 to +177
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("%w: failed to read webhook response body: %w", ErrAuthorizerInternal, err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Bound webhook response-body reads.

io.ReadAll lets a faulty or hostile webhook consume unbounded memory before status handling. Read through a size-limited reader and return ErrAuthorizerInternal when the limit is exceeded; add an oversized-response test.

🤖 Prompt for 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.

In `@src/libraries/go/lib/pkg/auth/authorizer.go` around lines 175 - 177, Update
the response-body handling in the authorizer request flow to read through a
size-limited reader instead of calling io.ReadAll directly, and return
ErrAuthorizerInternal when the configured maximum is exceeded. Preserve existing
read-error wrapping and status handling for responses within the limit, and add
a test covering an oversized webhook response.

…izer

Add OTEL transport instrumentation to the default WebhookAuthorizer
HTTP client, matching the pattern used by TokenFetcher. W3C Trace
Context is propagated on every outbound webhook call via the
otelhttp.NewTransport wrapper.

Bound webhook response-body reads with io.LimitReader at 4096 bytes
to prevent a faulty or hostile endpoint from consuming unbounded
memory. The limit is expressed as the exported-to-test constant
maxWebhookResponseBytes so tests can assert against it directly.

Extend the test suite to cover the new error-wrapping paths:
- transport failure (TCP dial to a closed port) asserts ErrAuthorizerInternal
- oversized response body asserts ErrAuthorizerInternal and that the
  error length respects the size cap
- malformed JSON on a 200 response asserts ErrAuthorizerInternal

Ref: NVIDIA#180
Signed-off-by: coffeecoder08 <razawarsi828@gmail.com>

@shelleyshen-0 shelleyshen-0 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Approved. Thanks for your contribution.

Comment thread src/libraries/go/lib/pkg/auth/authorizer.go Outdated
@sbaum1994

Copy link
Copy Markdown
Contributor

@raza-khan0108 can you please rebase and resolve or address code rabbit suggestions, then should be good to merge

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.

Replace the proprietary Event Ledger authorization integration

3 participants