From 8a9cbf9f4e4ff6d242e7eac470fcaac563de137c Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Sat, 9 Apr 2022 14:27:00 -0700 Subject: [PATCH 1/7] attempt to handle GCPs OIDC credentials --- iterative/gcp/provider.go | 19 +++++++++++++++++-- iterative/utils/helpers.go | 9 +++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/iterative/gcp/provider.go b/iterative/gcp/provider.go index 1527438f..52d58541 100644 --- a/iterative/gcp/provider.go +++ b/iterative/gcp/provider.go @@ -324,9 +324,24 @@ func getProjectService() (string, *gcp_compute.Service, error) { } if credentials.ProjectID == "" { - return "", nil, errors.New("Couldn't extract the project identifier from the given credentials!") + // Coerce Credentials to handle GCP OIDC auth + // Common ProjectID ENVs: + // https://github.com/google-github-actions/auth/blob/b05f71482f54380997bcc43a29ef5007de7789b1/src/main.ts#L187-L191 + // https://github.com/hashicorp/terraform-provider-google/blob/d6734812e2c6a679334dcb46932f4b92729fa98c/google/provider.go#L64-L73 + env_project := utils.MultiEnvLoadFirst([]string{ + "CLOUDSDK_CORE_PROJECT", + "CLOUDSDK_PROJECT", + "GCLOUD_PROJECT", + "GCP_PROJECT", + "GOOGLE_CLOUD_PROJECT", + "GOOGLE_PROJECT", + }) + if env_project == "" { + return "", nil, errors.New("Couldn't extract the project identifier from the given credentials!") + } + credentials.ProjectID = env_project } - + // re-visit below after test / credentials.JSON as a seperate field is not/? updated with project id found from env os.Setenv("GOOGLE_APPLICATION_CREDENTIALS_DATA", string(credentials.JSON)) return credentials.ProjectID, service, nil } diff --git a/iterative/utils/helpers.go b/iterative/utils/helpers.go index 28ba71fb..a0baf756 100644 --- a/iterative/utils/helpers.go +++ b/iterative/utils/helpers.go @@ -89,6 +89,15 @@ func SetId(d *schema.ResourceData) { } } +func MultiEnvLoadFirst(envs []string) string { + for _, val := range envs { + if env_value := os.Getenv(val); env_value != "" { + return env_value + } + } + return "" +} + func LoadGCPCredentials() string { credentialsData := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS_DATA") if len(credentialsData) == 0 { From 0078ba07c9311f0cc9649f82459cd274357ae5da Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Wed, 13 Apr 2022 12:20:11 -0700 Subject: [PATCH 2/7] yank from project from oidc json creds --- iterative/gcp/provider.go | 11 ++++++++--- iterative/utils/helpers.go | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/iterative/gcp/provider.go b/iterative/gcp/provider.go index 52d58541..7387ad76 100644 --- a/iterative/gcp/provider.go +++ b/iterative/gcp/provider.go @@ -307,8 +307,8 @@ func getServiceAccountData(saString string) (string, []string) { func getProjectService() (string, *gcp_compute.Service, error) { var credentials *google.Credentials var err error - - if credentialsData := []byte(utils.LoadGCPCredentials()); len(credentialsData) > 0 { + credentialsData := []byte(utils.LoadGCPCredentials()) + if len(credentialsData) > 0 { credentials, err = google.CredentialsFromJSON(oauth2.NoContext, credentialsData, gcp_compute.ComputeScope) } else { credentials, err = google.FindDefaultCredentials(oauth2.NoContext, gcp_compute.ComputeScope) @@ -337,7 +337,12 @@ func getProjectService() (string, *gcp_compute.Service, error) { "GOOGLE_PROJECT", }) if env_project == "" { - return "", nil, errors.New("Couldn't extract the project identifier from the given credentials!") + // last effort to load + fromCredentialsID, err := utils.GCPCoerceOIDCCredentials(credentialsData) + if err != nil { + return "", nil, fmt.Errorf("Couldn't extract the project identifier from the given credentials!: [%w]", err) + } + env_project = fromCredentialsID } credentials.ProjectID = env_project } diff --git a/iterative/utils/helpers.go b/iterative/utils/helpers.go index a0baf756..8797f25c 100644 --- a/iterative/utils/helpers.go +++ b/iterative/utils/helpers.go @@ -2,6 +2,8 @@ package utils import ( "context" + "encoding/json" + "errors" "fmt" "os" "strings" @@ -98,6 +100,29 @@ func MultiEnvLoadFirst(envs []string) string { return "" } +func GCPCoerceOIDCCredentials(rawCreds []byte) (string, error) { + hack := make(map[string]interface{}) + err := json.Unmarshal(rawCreds, &hack) + if err != nil { + return "", err + } + saString := fmt.Sprint(hack["service_account_impersonation_url"]) + // saString example: "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/cml@cml-pulse.iam.gserviceaccount.com:generateAccessToken" + if saString == "" { + return "", errors.New("[GCP OIDC] Unable to load service_account_impersonation_url") + } + // from saString, yank this + // -----------------------v.........v---------------------- + // (...serviceAccounts/cml@cml-pulse.iam.gserviceaccount.com:...) + atIndex := strings.Index(saString, "@") + 1 + iamIndex := strings.Index(saString, ".iam.") + if atIndex == -1 || iamIndex == -1 { + return "", errors.New("[GCP OIDC] Failed to get Project ID from service_account_impersonation_url") + } + projectID := saString[atIndex:iamIndex] + return projectID, nil +} + func LoadGCPCredentials() string { credentialsData := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS_DATA") if len(credentialsData) == 0 { From 1cecc2a111222a3540598a8e8c96712d548a8cab Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Wed, 13 Apr 2022 14:29:56 -0700 Subject: [PATCH 3/7] hacky test --- iterative/gcp/provider.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/iterative/gcp/provider.go b/iterative/gcp/provider.go index 7387ad76..105f0e7b 100644 --- a/iterative/gcp/provider.go +++ b/iterative/gcp/provider.go @@ -328,14 +328,15 @@ func getProjectService() (string, *gcp_compute.Service, error) { // Common ProjectID ENVs: // https://github.com/google-github-actions/auth/blob/b05f71482f54380997bcc43a29ef5007de7789b1/src/main.ts#L187-L191 // https://github.com/hashicorp/terraform-provider-google/blob/d6734812e2c6a679334dcb46932f4b92729fa98c/google/provider.go#L64-L73 - env_project := utils.MultiEnvLoadFirst([]string{ - "CLOUDSDK_CORE_PROJECT", - "CLOUDSDK_PROJECT", - "GCLOUD_PROJECT", - "GCP_PROJECT", - "GOOGLE_CLOUD_PROJECT", - "GOOGLE_PROJECT", - }) + // env_project := utils.MultiEnvLoadFirst([]string{ + // "CLOUDSDK_CORE_PROJECT", + // "CLOUDSDK_PROJECT", + // "GCLOUD_PROJECT", + // "GCP_PROJECT", + // "GOOGLE_CLOUD_PROJECT", + // "GOOGLE_PROJECT", + // }) + env_project := "" if env_project == "" { // last effort to load fromCredentialsID, err := utils.GCPCoerceOIDCCredentials(credentialsData) From bfd9aff886b33f5292b942eaf6c5e066f5262eae Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Wed, 13 Apr 2022 14:39:59 -0700 Subject: [PATCH 4/7] Revert "hacky test" This reverts commit 3c919d5be6252ad5e81f2e1a04ef5df89f182616. --- iterative/gcp/provider.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/iterative/gcp/provider.go b/iterative/gcp/provider.go index 105f0e7b..7387ad76 100644 --- a/iterative/gcp/provider.go +++ b/iterative/gcp/provider.go @@ -328,15 +328,14 @@ func getProjectService() (string, *gcp_compute.Service, error) { // Common ProjectID ENVs: // https://github.com/google-github-actions/auth/blob/b05f71482f54380997bcc43a29ef5007de7789b1/src/main.ts#L187-L191 // https://github.com/hashicorp/terraform-provider-google/blob/d6734812e2c6a679334dcb46932f4b92729fa98c/google/provider.go#L64-L73 - // env_project := utils.MultiEnvLoadFirst([]string{ - // "CLOUDSDK_CORE_PROJECT", - // "CLOUDSDK_PROJECT", - // "GCLOUD_PROJECT", - // "GCP_PROJECT", - // "GOOGLE_CLOUD_PROJECT", - // "GOOGLE_PROJECT", - // }) - env_project := "" + env_project := utils.MultiEnvLoadFirst([]string{ + "CLOUDSDK_CORE_PROJECT", + "CLOUDSDK_PROJECT", + "GCLOUD_PROJECT", + "GCP_PROJECT", + "GOOGLE_CLOUD_PROJECT", + "GOOGLE_PROJECT", + }) if env_project == "" { // last effort to load fromCredentialsID, err := utils.GCPCoerceOIDCCredentials(credentialsData) From 4082ba2086d6ae0db93f7b81066cf9eb01e8a0be Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Wed, 13 Apr 2022 14:42:59 -0700 Subject: [PATCH 5/7] remove old comment --- iterative/gcp/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iterative/gcp/provider.go b/iterative/gcp/provider.go index 7387ad76..13e199ac 100644 --- a/iterative/gcp/provider.go +++ b/iterative/gcp/provider.go @@ -346,7 +346,7 @@ func getProjectService() (string, *gcp_compute.Service, error) { } credentials.ProjectID = env_project } - // re-visit below after test / credentials.JSON as a seperate field is not/? updated with project id found from env + os.Setenv("GOOGLE_APPLICATION_CREDENTIALS_DATA", string(credentials.JSON)) return credentials.ProjectID, service, nil } From 33c7cf3f7a7cafb3d72d31bb7ddbed14fb8b3b16 Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Wed, 13 Apr 2022 14:46:03 -0700 Subject: [PATCH 6/7] better var name --- iterative/gcp/provider.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/iterative/gcp/provider.go b/iterative/gcp/provider.go index 13e199ac..3825dfda 100644 --- a/iterative/gcp/provider.go +++ b/iterative/gcp/provider.go @@ -328,7 +328,7 @@ func getProjectService() (string, *gcp_compute.Service, error) { // Common ProjectID ENVs: // https://github.com/google-github-actions/auth/blob/b05f71482f54380997bcc43a29ef5007de7789b1/src/main.ts#L187-L191 // https://github.com/hashicorp/terraform-provider-google/blob/d6734812e2c6a679334dcb46932f4b92729fa98c/google/provider.go#L64-L73 - env_project := utils.MultiEnvLoadFirst([]string{ + coercedProjectID := utils.MultiEnvLoadFirst([]string{ "CLOUDSDK_CORE_PROJECT", "CLOUDSDK_PROJECT", "GCLOUD_PROJECT", @@ -336,15 +336,15 @@ func getProjectService() (string, *gcp_compute.Service, error) { "GOOGLE_CLOUD_PROJECT", "GOOGLE_PROJECT", }) - if env_project == "" { + if coercedProjectID == "" { // last effort to load fromCredentialsID, err := utils.GCPCoerceOIDCCredentials(credentialsData) if err != nil { return "", nil, fmt.Errorf("Couldn't extract the project identifier from the given credentials!: [%w]", err) } - env_project = fromCredentialsID + coercedProjectID = fromCredentialsID } - credentials.ProjectID = env_project + credentials.ProjectID = coercedProjectID } os.Setenv("GOOGLE_APPLICATION_CREDENTIALS_DATA", string(credentials.JSON)) From 55c3e6a24732a3a706c0f3ba7c60d83ad2e0564b Mon Sep 17 00:00:00 2001 From: Daniel Barnes Date: Wed, 13 Apr 2022 16:45:02 -0700 Subject: [PATCH 7/7] simply --- iterative/gcp/provider.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iterative/gcp/provider.go b/iterative/gcp/provider.go index 3825dfda..394cbd16 100644 --- a/iterative/gcp/provider.go +++ b/iterative/gcp/provider.go @@ -307,8 +307,8 @@ func getServiceAccountData(saString string) (string, []string) { func getProjectService() (string, *gcp_compute.Service, error) { var credentials *google.Credentials var err error - credentialsData := []byte(utils.LoadGCPCredentials()) - if len(credentialsData) > 0 { + + if credentialsData := []byte(utils.LoadGCPCredentials()); len(credentialsData) > 0 { credentials, err = google.CredentialsFromJSON(oauth2.NoContext, credentialsData, gcp_compute.ComputeScope) } else { credentials, err = google.FindDefaultCredentials(oauth2.NoContext, gcp_compute.ComputeScope) @@ -338,7 +338,7 @@ func getProjectService() (string, *gcp_compute.Service, error) { }) if coercedProjectID == "" { // last effort to load - fromCredentialsID, err := utils.GCPCoerceOIDCCredentials(credentialsData) + fromCredentialsID, err := utils.GCPCoerceOIDCCredentials(credentials.JSON) if err != nil { return "", nil, fmt.Errorf("Couldn't extract the project identifier from the given credentials!: [%w]", err) }