Skip to content

Commit 55b0516

Browse files
authored
fix(transport): relax universe checks (#2376)
This PR serves to relax universe mismatch checks, as a user specifying credentials via the option.WithTokenSource has provided a form of credential where the universe information is not directly accessible. In these cases, we no longer perform the universe mismatch checks. This PR also augments the existing mismatch checks to exercise a more diverse set of client options.
1 parent a8d9414 commit 55b0516

File tree

3 files changed

+95
-15
lines changed

3 files changed

+95
-15
lines changed

transport/grpc/dial.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,12 @@ func dial(ctx context.Context, insecure bool, o *internal.DialSettings) (*grpc.C
181181
if err != nil {
182182
return nil, err
183183
}
184-
if o.GetUniverseDomain() != credsUniverseDomain {
185-
return nil, internal.ErrUniverseNotMatch(o.GetUniverseDomain(), credsUniverseDomain)
184+
if o.TokenSource == nil {
185+
// We only validate non-tokensource creds, as TokenSource-based credentials
186+
// don't propagate universe.
187+
if o.GetUniverseDomain() != credsUniverseDomain {
188+
return nil, internal.ErrUniverseNotMatch(o.GetUniverseDomain(), credsUniverseDomain)
189+
}
186190
}
187191
grpcOpts = append(grpcOpts, grpc.WithPerRPCCredentials(grpcTokenSource{
188192
TokenSource: oauth.TokenSource{TokenSource: creds.TokenSource},

transport/http/dial.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,12 @@ func newTransport(ctx context.Context, base http.RoundTripper, settings *interna
9292
if err != nil {
9393
return nil, err
9494
}
95-
if settings.GetUniverseDomain() != credsUniverseDomain {
96-
return nil, internal.ErrUniverseNotMatch(settings.GetUniverseDomain(), credsUniverseDomain)
95+
if settings.TokenSource == nil {
96+
// We only validate non-tokensource creds, as TokenSource-based credentials
97+
// don't propagate universe.
98+
if settings.GetUniverseDomain() != credsUniverseDomain {
99+
return nil, internal.ErrUniverseNotMatch(settings.GetUniverseDomain(), credsUniverseDomain)
100+
}
97101
}
98102
paramTransport.quotaProject = internal.GetQuotaProject(creds, settings.QuotaProject)
99103
ts := creds.TokenSource

transport/http/dial_test.go

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ package http
77
import (
88
"context"
99
"fmt"
10+
"strings"
1011
"testing"
1112

1213
"go.opencensus.io/plugin/ochttp"
1314
"golang.org/x/oauth2"
1415
"golang.org/x/oauth2/google"
15-
"google.golang.org/api/internal"
1616
"google.golang.org/api/option"
1717
)
1818

@@ -41,16 +41,88 @@ func TestNewClient(t *testing.T) {
4141
}
4242
}
4343

44-
func TestNewClient_MismatchedUniverseDomainCreds(t *testing.T) {
44+
func TestNewClient_MismatchedUniverseChecks(t *testing.T) {
45+
4546
rootTokenScope := "https://www.googleapis.com/auth/cloud-platform"
46-
universeDomain := "example.com"
47-
universeDomainDefault := "googleapis.com"
48-
creds := &google.Credentials{} // universeDomainDefault
49-
wantErr := internal.ErrUniverseNotMatch(universeDomain, universeDomainDefault)
50-
_, _, err := NewClient(context.Background(), option.WithUniverseDomain(universeDomain),
51-
option.WithCredentials(creds), option.WithScopes(rootTokenScope))
52-
53-
if err.Error() != wantErr.Error() {
54-
t.Fatalf("got: %v, want: %v", err, wantErr)
47+
otherUniverse := "example.com"
48+
defaultUniverse := "googleapis.com"
49+
fakeCreds := `
50+
{"type": "service_account",
51+
"project_id": "some-project",
52+
"universe_domain": "UNIVERSE"}`
53+
54+
// utility function to make a fake credential quickly
55+
makeFakeCredF := func(universe string) option.ClientOption {
56+
data := []byte(strings.ReplaceAll(fakeCreds, "UNIVERSE", universe))
57+
creds, _ := google.CredentialsFromJSON(context.Background(), data, rootTokenScope)
58+
return option.WithCredentials(creds)
59+
}
60+
61+
testCases := []struct {
62+
description string
63+
opts []option.ClientOption
64+
wantErr bool
65+
}{
66+
{
67+
description: "default creds and no universe",
68+
opts: []option.ClientOption{
69+
option.WithCredentials(&google.Credentials{}),
70+
},
71+
wantErr: false,
72+
},
73+
{
74+
description: "default creds and default universe",
75+
opts: []option.ClientOption{
76+
option.WithCredentials(&google.Credentials{}),
77+
option.WithUniverseDomain(defaultUniverse),
78+
},
79+
wantErr: false,
80+
},
81+
{
82+
description: "default creds and mismatched universe",
83+
opts: []option.ClientOption{
84+
option.WithCredentials(&google.Credentials{}),
85+
option.WithUniverseDomain(otherUniverse),
86+
},
87+
wantErr: true,
88+
},
89+
{
90+
description: "foreign universe creds and default universe",
91+
opts: []option.ClientOption{
92+
makeFakeCredF(otherUniverse),
93+
option.WithUniverseDomain(defaultUniverse),
94+
},
95+
wantErr: true,
96+
},
97+
{
98+
description: "foreign universe creds and foreign universe",
99+
opts: []option.ClientOption{
100+
makeFakeCredF(otherUniverse),
101+
option.WithUniverseDomain(otherUniverse),
102+
},
103+
wantErr: false,
104+
},
105+
{
106+
description: "tokensource + mismatched universe",
107+
opts: []option.ClientOption{
108+
option.WithTokenSource(oauth2.StaticTokenSource(&oauth2.Token{})),
109+
option.WithUniverseDomain(otherUniverse),
110+
},
111+
wantErr: false,
112+
},
113+
}
114+
115+
for _, tc := range testCases {
116+
opts := []option.ClientOption{
117+
option.WithScopes(rootTokenScope),
118+
}
119+
opts = append(opts, tc.opts...)
120+
_, _, gotErr := NewClient(context.Background(), opts...)
121+
if tc.wantErr && gotErr == nil {
122+
t.Errorf("%q: wanted error, got none", tc.description)
123+
}
124+
if !tc.wantErr && gotErr != nil {
125+
t.Errorf("%q: wanted success, got err: %v", tc.description, gotErr)
126+
}
55127
}
56128
}

0 commit comments

Comments
 (0)