From 094faa3002f37bc211997c0ac769c3731813e0b3 Mon Sep 17 00:00:00 2001 From: BrennaEpp Date: Tue, 2 Jan 2024 17:58:07 -0800 Subject: [PATCH 1/2] feat(storage): support auto-detection of access ID for external_account creds --- storage/bucket.go | 30 ++++++++++++++++++------------ storage/bucket_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/storage/bucket.go b/storage/bucket.go index 1059d4e8b7dd..a9018b4c738c 100644 --- a/storage/bucket.go +++ b/storage/bucket.go @@ -275,18 +275,24 @@ func (b *BucketHandle) detectDefaultGoogleAccessID() (string, error) { err := json.Unmarshal(b.c.creds.JSON, &sa) if err != nil { returnErr = err - } else if sa.CredType == "impersonated_service_account" { - start, end := strings.LastIndex(sa.SAImpersonationURL, "/"), strings.LastIndex(sa.SAImpersonationURL, ":") - - if end <= start { - returnErr = errors.New("error parsing impersonated service account credentials") - } else { - return sa.SAImpersonationURL[start+1 : end], nil - } - } else if sa.CredType == "service_account" && sa.ClientEmail != "" { - return sa.ClientEmail, nil } else { - returnErr = errors.New("unable to parse credentials; only service_account and impersonated_service_account credentials are supported") + switch sa.CredType { + case "impersonated_service_account", "external_account": + start, end := strings.LastIndex(sa.SAImpersonationURL, "/"), strings.LastIndex(sa.SAImpersonationURL, ":") + + if end <= start { + returnErr = errors.New("error parsing impersonated service account credentials") + } else { + return sa.SAImpersonationURL[start+1 : end], nil + } + case "service_account": + if sa.ClientEmail != "" { + return sa.ClientEmail, nil + } + returnErr = errors.New("empty service account client email") + default: + returnErr = errors.New("unable to parse credentials; only service_account, external_account and impersonated_service_account credentials are supported") + } } } @@ -302,7 +308,7 @@ func (b *BucketHandle) detectDefaultGoogleAccessID() (string, error) { } } - return "", fmt.Errorf("storage: unable to detect default GoogleAccessID: %w. Please provide the GoogleAccessID or use a supported means for autodetecting it (see https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_[BucketHandle.SignedURL]_and_[BucketHandle.GenerateSignedPostPolicyV4])", returnErr) + return "", fmt.Errorf("storage: unable to detect default GoogleAccessID: %w. Please provide the GoogleAccessID or use a supported means for autodetecting it (see https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_signing)", returnErr) } func (b *BucketHandle) defaultSignBytesFunc(email string) func([]byte) ([]byte, error) { diff --git a/storage/bucket_test.go b/storage/bucket_test.go index 6ba32daf1463..4924188c4430 100644 --- a/storage/bucket_test.go +++ b/storage/bucket_test.go @@ -1200,6 +1200,41 @@ func TestDetectDefaultGoogleAccessID(t *testing.T) { }, expectSuccess: false, }, + { + name: "malformed creds", + serviceAccount: "default@my-project.iam.gserviceaccount.com", + creds: func(sa string) string { + return fmt.Sprintf(`{ + "type": "service_account" + "project_id": "my-project", + "private_key_id": "my1", + "private_key": "-----BEGIN PRIVATE KEY-----\nkey\n-----END PRIVATE KEY-----\n", + "client_email": "%s", + }`, sa) + }, + expectSuccess: false, + }, + { + name: "external creds", + serviceAccount: "default@my-project.iam.gserviceaccount.com", + creds: func(sa string) string { + return fmt.Sprintf(`{ + "type": "external_account", + "audience": "//iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$PROVIDER_ID", + "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request", + "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/%s:generateAccessToken", + "token_url": "https://sts.googleapis.com/v1/token", + "credential_source": { + "environment_id": "id", + "region_url": "region_url", + "url": "url", + "regional_cred_verification_url": "ver_url", + "imdsv2_session_token_url": "tok_url" + } + }`, sa) + }, + expectSuccess: true, + }, } for _, tc := range testCases { From e90b64afb49a0ca71b4ee29328ed28a19c17d2c6 Mon Sep 17 00:00:00 2001 From: BrennaEpp Date: Wed, 31 Jan 2024 19:37:41 -0800 Subject: [PATCH 2/2] added external acc to error message --- storage/bucket.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/bucket.go b/storage/bucket.go index a9018b4c738c..0344ef9de310 100644 --- a/storage/bucket.go +++ b/storage/bucket.go @@ -281,7 +281,7 @@ func (b *BucketHandle) detectDefaultGoogleAccessID() (string, error) { start, end := strings.LastIndex(sa.SAImpersonationURL, "/"), strings.LastIndex(sa.SAImpersonationURL, ":") if end <= start { - returnErr = errors.New("error parsing impersonated service account credentials") + returnErr = errors.New("error parsing external or impersonated service account credentials") } else { return sa.SAImpersonationURL[start+1 : end], nil }