Skip to content

feat(proxy): let authz hooks add headers to target requests - #647

Open
sfc-gh-pkowalewski wants to merge 1 commit into
mainfrom
proxy-policy-target-metadata
Open

sfc-gh-pkowalewski wants to merge 1 commit into
mainfrom
proxy-policy-target-metadata

Conversation

@sfc-gh-pkowalewski

@sfc-gh-pkowalewski sfc-gh-pkowalewski commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

A proxy policy can only allow or deny a call. Some setups need the policy to hand information about its decision to the target, for example which rule allowed the request, so the target can act on it. Request metadata is the natural place for that, but the proxy opens the stream to the target before it authorizes the first request, and gRPC sends metadata when a stream opens, so there is no moment where a policy result can be attached.

Solution

A policy or hook can now set TargetMetadata on the authorization input, and the proxy sends it with the call to the target.

To authorize before the stream opens, the new NewCredentialsDialer records the identity each target presents during the TLS handshake, which is the same identity policies see today. The proxy authorizes the first request with it and then opens the stream with the metadata attached.

Metadata cannot change once a stream is open, so a later request that produces different metadata closes the stream. The proxy binary switches to the new dialer. The existing dialer keeps its current behaviour and rejects calls whose policy sets metadata.

sequenceDiagram
    participant C as Client
    participant P as Proxy
    participant T as Target

    C->>P: Request
    P->>T: Connect (TLS handshake)
    T-->>P: Target identity
    Note over P: Authorize the first request.<br/>The policy may set TargetMetadata.
    P->>T: Open stream with TargetMetadata
    P->>T: First request
    T-->>P: Response
    P-->>C: Response
    C->>P: Later request
    Note over P: Authorize again. If TargetMetadata<br/>differs, close with PermissionDenied.
    P->>T: Later request
Loading

Testing

The existing proxy tests now run through the new dialer and pass, also with the race detector.

New tests check that the metadata reaches the target for unary, server streaming and bidirectional calls, that a client stream with no requests still works, that a mid stream change is rejected, and that the old dialer refuses calls that set metadata. Two more check that an unreachable target still reports the underlying connection error and that a cancelled call returns Canceled. Each new test fails when the behaviour it covers is removed.

I also deployed the change to a staging proxy with a hook that sets metadata on one method. The target received it on that method only, the end to end suite passed, streaming, fan out and dry run calls behaved as before, and error rates did not change.

go test ./... passes apart from TestServerWithUnixCredentials, which fails the same way on main on macOS because it depends on local group membership.

@sfc-gh-pkowalewski
sfc-gh-pkowalewski marked this pull request as ready for review October 27, 2026 16:28
@sfc-gh-pkowalewski
sfc-gh-pkowalewski force-pushed the proxy-policy-target-metadata branch 2 times, most recently from 3c919c4 to 081d80b Compare October 27, 2026 19:02
A policy or hook can set RPCAuthInput.TargetMetadata while the proxy
authorizes a call, and the proxy sends it to the target as request
metadata. NewCredentialsDialer records each target's identity at the
handshake, so the first request is authorized before the stream to the
target opens. A later message that changes the metadata closes the
stream, and the proxy binary now uses the new dialer.
@sfc-gh-pkowalewski
sfc-gh-pkowalewski force-pushed the proxy-policy-target-metadata branch from 081d80b to d0b1c4f Compare October 27, 2026 19:13
@sfc-gh-pkowalewski sfc-gh-pkowalewski changed the title feat(proxy): let policies attach metadata to proxied calls feat(proxy): let authz hooks add headers to target requests Oct 27, 2026
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.

1 participant