Skip to content

Commit

Permalink
feat: generate a default audience for clients (#475)
Browse files Browse the repository at this point in the history
This option will be used to generate self-signed JWTs when the
client is authenticated with a service account and the user does
not provide additional scopes.

Also, now marking the generated scopes as default so we can
distinguish between generated and user provided scopes.

Related: googleapis/google-api-go-client#738
  • Loading branch information
codyoss committed Dec 3, 2020
1 parent 8667b90 commit ed195cc
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 4 deletions.
24 changes: 23 additions & 1 deletion internal/gengapic/client_init.go
Expand Up @@ -67,8 +67,9 @@ func (g *generator) clientOptions(serv *descriptor.ServiceDescriptorProto, servN
p(" return []option.ClientOption{")
p(" internaloption.WithDefaultEndpoint(%q),", host)
p(" internaloption.WithDefaultMTLSEndpoint(%q),", generateDefaultMTLSEndpoint(host))
p(" internaloption.WithDefaultAudience(%q),", generateDefaultAudience(host))
p(" internaloption.WithDefaultScopes(DefaultAuthScopes()...),")
p(" option.WithGRPCDialOption(grpc.WithDisableServiceConfig()),")
p(" option.WithScopes(DefaultAuthScopes()...),")
p(" option.WithGRPCDialOption(grpc.WithDefaultCallOptions(")
p(" grpc.MaxCallRecvMsgSize(math.MaxInt32))),")
p(" }")
Expand Down Expand Up @@ -310,3 +311,24 @@ func generateDefaultMTLSEndpoint(defaultEndpoint string) string {
}
return defaultEndpoint
}

// generateDefaultAudience transforms a host into a an audience that can be used
// as the `aud` claim in a JWT.
func generateDefaultAudience(host string) string {
aud := host
// Add a scheme if not present.
if !strings.Contains(aud, "://") {
aud = "https://" + aud
}
// Remove port, and everything after, if present.
if strings.Count(aud, ":") > 1 {
firstIndex := strings.Index(aud, ":")
secondIndex := strings.Index(aud[firstIndex+1:], ":") + firstIndex + 1
aud = aud[:secondIndex]
}
// Add trailing slash if not present.
if !strings.HasSuffix(aud, "/") {
aud = aud + "/"
}
return aud
}
24 changes: 24 additions & 0 deletions internal/gengapic/client_init_test.go
Expand Up @@ -208,3 +208,27 @@ func TestClientInit(t *testing.T) {
txtdiff.Diff(t, tst.tstName, g.pt.String(), filepath.Join("testdata", tst.tstName+".want"))
}
}

func TestGenerateDefaultAudience(t *testing.T) {
tests := []struct {
name string
host string
want string
}{
{name: "plain host", host: "foo.googleapis.com", want: "https://foo.googleapis.com/"},
{name: "host with port", host: "foo.googleapis.com:443", want: "https://foo.googleapis.com/"},
{name: "host with scheme", host: "https://foo.googleapis.com", want: "https://foo.googleapis.com/"},
{name: "host with scheme and port", host: "https://foo.googleapis.com:1234", want: "https://foo.googleapis.com/"},
{name: "host is a proper audience", host: "https://foo.googleapis.com/", want: "https://foo.googleapis.com/"},
{name: "host with non-http scheme", host: "ftp://foo.googleapis.com", want: "ftp://foo.googleapis.com/"},
{name: "host with path", host: "foo.googleapis.com:443/extra/path", want: "https://foo.googleapis.com/"},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
if got := generateDefaultAudience(tc.host); got != tc.want {
t.Errorf("generateDefaultAudience(%q) = %q, want %q", tc.host, got, tc.want)
}
})
}
}
3 changes: 2 additions & 1 deletion internal/gengapic/testdata/empty_opt.want
Expand Up @@ -9,8 +9,9 @@ func defaultClientOptions() []option.ClientOption {
return []option.ClientOption{
internaloption.WithDefaultEndpoint("foo.googleapis.com:443"),
internaloption.WithDefaultMTLSEndpoint("foo.mtls.googleapis.com:443"),
internaloption.WithDefaultAudience("https://foo.googleapis.com/"),
internaloption.WithDefaultScopes(DefaultAuthScopes()...),
option.WithGRPCDialOption(grpc.WithDisableServiceConfig()),
option.WithScopes(DefaultAuthScopes()...),
option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(math.MaxInt32))),
}
Expand Down
3 changes: 2 additions & 1 deletion internal/gengapic/testdata/foo_opt.want
Expand Up @@ -9,8 +9,9 @@ func defaultFooClientOptions() []option.ClientOption {
return []option.ClientOption{
internaloption.WithDefaultEndpoint("foo.googleapis.com:443"),
internaloption.WithDefaultMTLSEndpoint("foo.mtls.googleapis.com:443"),
internaloption.WithDefaultAudience("https://foo.googleapis.com/"),
internaloption.WithDefaultScopes(DefaultAuthScopes()...),
option.WithGRPCDialOption(grpc.WithDisableServiceConfig()),
option.WithScopes(DefaultAuthScopes()...),
option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(math.MaxInt32))),
}
Expand Down
3 changes: 2 additions & 1 deletion internal/gengapic/testdata/host_port_opt.want
Expand Up @@ -7,8 +7,9 @@ func defaultBarClientOptions() []option.ClientOption {
return []option.ClientOption{
internaloption.WithDefaultEndpoint("foo.googleapis.com:1234"),
internaloption.WithDefaultMTLSEndpoint("foo.mtls.googleapis.com:1234"),
internaloption.WithDefaultAudience("https://foo.googleapis.com/"),
internaloption.WithDefaultScopes(DefaultAuthScopes()...),
option.WithGRPCDialOption(grpc.WithDisableServiceConfig()),
option.WithScopes(DefaultAuthScopes()...),
option.WithGRPCDialOption(grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(math.MaxInt32))),
}
Expand Down

0 comments on commit ed195cc

Please sign in to comment.