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

fix(auth): allow self-signed JWT for non-GDU universe domain #10831

Merged
42 changes: 24 additions & 18 deletions auth/credentials/detect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,11 +459,10 @@ func TestDefaultCredentials_ServiceAccountKeySelfSigned_UniverseDomain(t *testin
now = func() time.Time { return time.Date(2000, 2, 1, 12, 30, 0, 0, time.UTC) }
defer func() { now = oldNow }()
wantTok := "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFiY2RlZjEyMzQ1Njc4OTAifQ.eyJpc3MiOiJnb3BoZXJAZmFrZV9wcm9qZWN0LmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2NvcGUiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9hdXRoL2Nsb3VkLXBsYXRmb3JtIiwiZXhwIjo5NDk0MTE4MDAsImlhdCI6OTQ5NDA4MjAwLCJhdWQiOiIiLCJzdWIiOiJnb3BoZXJAZmFrZV9wcm9qZWN0LmlhbS5nc2VydmljZWFjY291bnQuY29tIn0.n9Hggd-1Vw4WTQiWkh7q9r5eDsz-khU5vwkZl2VmgdUF3ZxDq1ARzchCNtTifeorzbp9C0i0vCr855G7FZkVCJXPVMcnxbwfMSafUYmVsmutbQiV9eTWfWM0_Ljiwa9GEbv1bN06Lz4LrelPKEaxsDbY6tU8LJUiome_gSMLfLk"

creds, err := DetectDefault(&DetectOptions{
CredentialsJSON: b,
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
UseSelfSignedJWT: true,
// default scopes are set in resolveDetectOptions before calling DetectDefault.
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
CredentialsJSON: b,
})
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -805,26 +804,29 @@ func TestDefaultCredentials_UniverseDomain(t *testing.T) {
{
name: "service account json with file universe domain",
opts: &DetectOptions{
CredentialsFile: "../internal/testdata/sa_universe_domain.json",
UseSelfSignedJWT: true,
CredentialsFile: "../internal/testdata/sa_universe_domain.json",
// default scopes are set in resolveDetectOptions before calling DetectDefault.
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
codyoss marked this conversation as resolved.
Show resolved Hide resolved
},
want: "example.com",
},
{
name: "service account json with options universe domain",
opts: &DetectOptions{
CredentialsFile: "../internal/testdata/sa.json",
UseSelfSignedJWT: true,
UniverseDomain: "foo.com",
CredentialsFile: "../internal/testdata/sa.json",
// default scopes are set in resolveDetectOptions before calling DetectDefault.
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
UniverseDomain: "foo.com",
},
want: "foo.com",
},
{
name: "service account json with file and options universe domain",
opts: &DetectOptions{
CredentialsFile: "../internal/testdata/sa_universe_domain.json",
UseSelfSignedJWT: true,
UniverseDomain: "foo.com",
CredentialsFile: "../internal/testdata/sa_universe_domain.json",
// default scopes are set in resolveDetectOptions before calling DetectDefault.
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
UniverseDomain: "foo.com",
},
want: "foo.com",
},
Expand Down Expand Up @@ -923,8 +925,9 @@ func TestDefaultCredentials_UniverseDomain(t *testing.T) {
{
name: "impersonated service account json",
opts: &DetectOptions{
CredentialsFile: "../internal/testdata/imp.json",
UseSelfSignedJWT: true,
CredentialsFile: "../internal/testdata/imp.json",
// default scopes are set in resolveDetectOptions before calling DetectDefault.
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
},
want: "googleapis.com",
},
Expand All @@ -938,17 +941,20 @@ func TestDefaultCredentials_UniverseDomain(t *testing.T) {
{
name: "impersonated service account json with options universe domain",
opts: &DetectOptions{
CredentialsFile: "../internal/testdata/imp.json",
UseSelfSignedJWT: true,
UniverseDomain: "foo.com",
CredentialsFile: "../internal/testdata/imp.json",
// default scopes are set in resolveDetectOptions before calling DetectDefault.
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
UniverseDomain: "foo.com",
},
want: "foo.com",
},
{
name: "impersonated service account json with file and options universe domain",
opts: &DetectOptions{
CredentialsFile: "../internal/testdata/imp_universe_domain.json",
UniverseDomain: "foo.com",
// default scopes are set in resolveDetectOptions before calling DetectDefault.
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
UniverseDomain: "foo.com",
},
want: "foo.com",
},
Expand Down
6 changes: 6 additions & 0 deletions auth/credentials/filetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,14 @@ func resolveUniverseDomain(optsUniverseDomain, fileUniverseDomain string) string
}

func handleServiceAccount(f *credsfile.ServiceAccountFile, opts *DetectOptions) (auth.TokenProvider, error) {
ud := resolveUniverseDomain(opts.UniverseDomain, f.UniverseDomain)
if opts.UseSelfSignedJWT {
return configureSelfSignedJWT(f, opts)
} else if ud != "" && ud != internalauth.DefaultUniverseDomain {
// For non-GDU universe domains, token exchange is impossible and services

Choose a reason for hiding this comment

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

this can now become
opts.UseSelfSignedJWT |= ud != "" && ud != internalauth.DefaultUniverseDomain

// must support self-signed JWTs.
opts.UseSelfSignedJWT = true
return configureSelfSignedJWT(f, opts)
}
opts2LO := &auth.Options2LO{
Email: f.ClientEmail,
Expand Down
19 changes: 19 additions & 0 deletions auth/credentials/selfsignedjwt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,25 @@ func TestDefaultCredentials_SelfSignedWithScope(t *testing.T) {
}
}

func TestDefaultCredentials_SelfSignedWithAudienceAndScope(t *testing.T) {
_, jsonKey, err := setupFakeKey()
if err != nil {
t.Fatal(err)
}
_, err = DetectDefault(&DetectOptions{
CredentialsJSON: jsonKey,
Audience: "audience",
Scopes: []string{"scope1", "scope2"},
UseSelfSignedJWT: true,
})
if err == nil {
t.Fatal("Token(): want non-nil err")
}
if want := "credentials: both scopes and audience were provided"; err.Error() != want {
t.Errorf("TokenType = %q, want %q", err, want)
}
}

// setupFakeKey generates a key we can use in the test data.
func setupFakeKey() (*rsa.PrivateKey, []byte, error) {
// Generate a key we can use in the test data.
Expand Down
2 changes: 1 addition & 1 deletion auth/internal/testdata/imp_universe_domain.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"type": "service_account",
"project_id": "fake_project",
"private_key_id": "89asd789789uo473454c47543",
"private_key": "fake",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALX0PQoe1igW12ikv1bN/r9lN749y2ijmbc/mFHPyS3hNTyOCjDvBbXYbDhQJzWVUikh4mvGBA07qTj79Xc3yBDfKP2IeyYQIFe0t0zkd7R9Zdn98Y2rIQC47aAbDfubtkU1U72t4zL11kHvoa0/RuFZjncvlr42X7be7lYh4p3NAgMBAAECgYASk5wDw4Az2ZkmeuN6Fk/y9H+Lcb2pskJIXjrL533vrDWGOC48LrsThMQPv8cxBky8HFSEklPpkfTF95tpD43iVwJRB/GrCtGTw65IfJ4/tI09h6zGc4yqvIo1cHX/LQ+SxKLGyir/dQM925rGt/VojxY5ryJR7GLbCzxPnJm/oQJBANwOCO6D2hy1LQYJhXh7O+RLtA/tSnT1xyMQsGT+uUCMiKS2bSKx2wxo9k7h3OegNJIu1q6nZ6AbxDK8H3+d0dUCQQDTrPSXagBxzp8PecbaCHjzNRSQE2in81qYnrAFNB4o3DpHyMMY6s5ALLeHKscEWnqP8Ur6X4PvzZecCWU9BKAZAkAutLPknAuxSCsUOvUfS1i87ex77Ot+w6POp34pEX+UWb+u5iFn2cQacDTHLV1LtE80L8jVLSbrbrlH43H0DjU5AkEAgidhycxS86dxpEljnOMCw8CKoUBd5I880IUahEiUltk7OLJYS/Ts1wbn3kPOVX3wyJs8WBDtBkFrDHW2ezth2QJADj3e1YhMVdjJW5jqwlD/VNddGjgzyunmiZg0uOXsHXbytYmsA545S8KRQFaJKFXYYFo2kOjqOiC1T2cAzMDjCQ==\n-----END PRIVATE KEY-----\n",
quartzmo marked this conversation as resolved.
Show resolved Hide resolved
"client_email": "sa@fake_project.iam.gserviceaccount.com",
"client_id": "gopher",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
Expand Down
Loading