Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

credentials, transport, grpc : add a call option to override the :authority header on a per-RPC basis #8068

Open
wants to merge 9 commits into
base: master
Choose a base branch
from

Conversation

eshitachandwani
Copy link
Member

Fixes: #5361

RELEASE NOTES:

  • Added a CallAuthority callOption that can be used to overwrite the http :authority header on per-RPC basis.
  • Introduces an option AuthorityValidator interface which needs to be implemented by credentials that want to allow authority overwrite.
  • Adds implementations of AuthorityValidator interface for Insecure and TLS credentials.

@eshitachandwani eshitachandwani added Type: Feature New features or improvements in behavior Area: Auth Includes regular credentials API and implementation. Also includes advancedtls, authz, rbac etc. labels Feb 6, 2025
@eshitachandwani eshitachandwani added this to the 1.71 Release milestone Feb 6, 2025
Copy link

codecov bot commented Feb 6, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 82.36%. Comparing base (0003b4f) to head (b1583a6).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8068      +/-   ##
==========================================
+ Coverage   82.32%   82.36%   +0.04%     
==========================================
  Files         387      387              
  Lines       39064    39091      +27     
==========================================
+ Hits        32159    32197      +38     
+ Misses       5593     5584       -9     
+ Partials     1312     1310       -2     
Files with missing lines Coverage Δ
credentials/credentials.go 87.87% <ø> (ø)
credentials/insecure/insecure.go 83.33% <100.00%> (+1.51%) ⬆️
credentials/tls.go 88.46% <100.00%> (+1.88%) ⬆️
internal/transport/http2_client.go 91.77% <100.00%> (+0.06%) ⬆️
internal/transport/transport.go 91.56% <ø> (ø)
rpc_util.go 80.97% <100.00%> (+0.29%) ⬆️
stream.go 81.54% <100.00%> (-0.24%) ⬇️

... and 19 files with indirect coverage changes

Copy link
Contributor

@purnesh42H purnesh42H left a comment

Choose a reason for hiding this comment

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

Overall lgtm. Just few minor comments. I think we can combine some individual into t-tests.

@@ -120,6 +120,14 @@ type AuthInfo interface {
AuthType() string
}

// AuthorityValidator defines an interface for validating the authority used to
Copy link
Contributor

Choose a reason for hiding this comment

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

no need to mention "defines an interface". Can just say "AuthorityValidator validates the authority....."

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

// precedence to determine the :authority header. Any value in Host field of
// CallHdr is overwritten. But before overriding, we validate the authority
// string against the peer certificates and fail the RPC with `UNAVAILABLE`
// status code if eirther of the condition fails.
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: either

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

if !ok {
return nil, &NewStreamError{Err: status.Error(codes.Unavailable, fmt.Sprintf("credentials type %s does not implement the AuthorityValidator interface", t.authInfo.AuthType())), AllowTransparentRetry: false}
}
err := auth.ValidateAuthority(callHdr.Authority)
Copy link
Contributor

Choose a reason for hiding this comment

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

can combine this with if

Copy link
Member Author

Choose a reason for hiding this comment

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

Done.

//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a
// later release.
func CallAuthority(auth string) CallOption {
Copy link
Contributor

Choose a reason for hiding this comment

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

should we call it PerRPCAuthority? Similar to PerRPCCredentials?

//
// Notice: This type is EXPERIMENTAL and may be changed or removed in a
// later release.
type AuthorityOverrideCallOption struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

If we name above PerRPCAuthority, AuthorityOverrideCallOption can change to PerRPCAuthorityCallOption

defer cancel()

_, err = testgrpc.NewTestServiceClient(cc).EmptyCall(ctx, &testpb.Empty{}, grpc.CallAuthority(tt.expectedAuth))
if tt.expectRPCError {
Copy link
Contributor

Choose a reason for hiding this comment

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

s/expect/want

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

}
}

func (s) TestTLSCredsWithNoAuthorityOverride(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

the tests tls_ext_test.go should already be testing this right? Does this need to be here? or it should just be another test case in the above TestAuthorityCallOptionsWithTLSCreds

// Perform a test RPC with a specified call authority.
ctx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
defer cancel()

Copy link
Contributor

Choose a reason for hiding this comment

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

nix new line

}

// FakeCredsNoAuthValidator is a test credential that does not implement AuthorityValidator.
type FakeCredsNoAuthValidator struct {
Copy link
Contributor

Choose a reason for hiding this comment

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

the FakeCreds can be at the top

// TestCallOptionWithNoAuthorityValidator tests the CallAuthority call option
// with custom credentials that do not implement AuthorityValidator and verifies
// that it fails with `UNAVAILABLE` status code.
func (s) TestCallOptionWithNoAuthorityValidator(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same. This can be another test case in test with CustomCreds

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

@purnesh42H
Copy link
Contributor

Also, don't feel strongly but may be we can utilize the setup in tls_ext_test or move the tls tests to tls_ext_test.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Auth Includes regular credentials API and implementation. Also includes advancedtls, authz, rbac etc. Type: Feature New features or improvements in behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

grpc: add a call option to override the :authority header on a per-RPC basis
3 participants