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
16 changes: 13 additions & 3 deletions auth/credentials/filetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ func fileCredentials(b []byte, opts *DetectOptions) (*auth.Credentials, error) {
if err != nil {
return nil, err
}
tp, err = handleServiceAccount(f, opts)
universeDomain = resolveUniverseDomain(opts.UniverseDomain, f.UniverseDomain)
codyoss marked this conversation as resolved.
Show resolved Hide resolved
tp, err = handleServiceAccount(f, opts, universeDomain)
if err != nil {
return nil, err
}
projectID = f.ProjectID
universeDomain = resolveUniverseDomain(opts.UniverseDomain, f.UniverseDomain)
case credsfile.UserCredentialsKey:
f, err := credsfile.ParseUserCredentials(b)
if err != nil {
Expand Down Expand Up @@ -123,9 +123,19 @@ func resolveUniverseDomain(optsUniverseDomain, fileUniverseDomain string) string
return fileUniverseDomain
}

func handleServiceAccount(f *credsfile.ServiceAccountFile, opts *DetectOptions) (auth.TokenProvider, error) {
func handleServiceAccount(f *credsfile.ServiceAccountFile, opts *DetectOptions, universeDomain string) (auth.TokenProvider, error) {
if opts.UseSelfSignedJWT {
return configureSelfSignedJWT(f, opts)
} else if universeDomain != "" && universeDomain != 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.
if opts.Audience == "" && len(opts.scopes()) == 0 {
// Audience or scopes must be provided, although the scopes may be
// the default scopes available in resolveDetectOptions.
return nil, fmt.Errorf("credentials: audience or scopes must be provided for self-signed JWT")
}
quartzmo marked this conversation as resolved.
Show resolved Hide resolved
opts.UseSelfSignedJWT = true
return configureSelfSignedJWT(f, opts)
}
opts2LO := &auth.Options2LO{
Email: f.ClientEmail,
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