GoogleCloudPlatform / pbmm-on-gcp-onboarding

GCP Canadian Public Sector Landing Zone overlay on top of the TEF via CFT modules - a secure cloud foundation
https://cloud.google.com/architecture/security-foundations
Apache License 2.0
45 stars 56 forks source link

service account impersonation for developer accounts #449

Closed obriensystems closed 3 months ago

obriensystems commented 6 months ago

see - https://github.com/GoogleCloudPlatform/pubsec-declarative-toolkit/wiki/DevOps#google-api-calls-using-service-account-impersonation

Steps

on the client

Enabling service [cloudresourcemanager.googleapis.com] on project [boot-proj-old]... Operation "operations/acat.p2-480508879674-b955b8a6-4f61-4fc1-9504-d8895c8bc107" finished successfully.

Credentials saved to file: [C:\Users\micha\AppData\Roaming\gcloud\application_default_credentials.json] C:\soft\gcloud>gcloud config get project boot-proj-old


## on the owner org
- switch to a project used to get GCP ids on the owning org

michael@cloudshell:~/tef-olapp-p1gen6$ gcloud config set project boot-proj-olapp Updated property [core/project]. michael@cloudshell:~/tef-olapp-p1gen6 (boot-proj-olapp)$

- get billing and org id

michael@cloudshell:~/tef-olapp-p1gen6 (boot-proj-olapp)$ BOOT_PROJECT_ID=boot-proj-olapp michael@cloudshell:~/tef-olapp-p1gen6 (boot-proj-olapp)$ BILLING_FORMAT="--format=value(billingAccountName)" michael@cloudshell:~/tef-olapp-p1gen6 (boot-proj-olapp)$ BILLING_ID=$(gcloud billing projects describe $BOOT_PROJECT_ID $BILLING_FORMAT | sed 's/.*\///') michael@cloudshell:~/tef-olapp-p1gen6 (boot-proj-olapp)$ ORG_ID=$(gcloud projects get-ancestors $BOOT_PROJECT_ID --format='get(id)' | tail -1) michael@cloudshell:~/tef-olapp-p1gen6 (boot-proj-olapp)$ echo $ORG_ID 630...

- create a project to hold the service account on the owning org

gcloud projects create "service-account-olapp" --name="service-account-olapp" --set-as-default --folder="865611452734" gcloud beta billing projects link "service-account-olapp" --billing-account "${BILLING_ID}"

- create a service account on the owning org (optionally add a project level iam role (owner)

gcloud iam service-accounts create sa-external --description="sa-external" --display-name="sa-external"

export SA_EMAIL=sa-external@service-account-olapp.iam.gserviceaccount.com gcloud projects add-iam-policy-binding service-account-olapp --member="serviceAccount:sa-external@service-account-olapp.iam.gserviceaccount.com" --role="roles/owner"

- create a group for local or external user accounts impersonating the service accounts

gcloud services enable cloudresourcemanager.googleapis.com gcloud services enable cloudidentity.googleapis.com gcloud identity groups create sa-external@obrienlabs.app --organization="obrienlabs.app"

- add external users to the group

gcloud services enable cloudidentity.googleapis.com gcloud identity groups memberships add --group-email="sa-external@obrienlabs.app" --member-email="michael@obrienlabs.dev" ERROR: (gcloud.identity.groups.memberships.add) FAILED_PRECONDITION: Error(4023): Cannot create membership in group 'groups/00pkwqa14lbq4ir' for member 'michael@obrienlabs.dev' because the group does not allow members outside the organization

- turn off organization policy on external access
- - https://apps.google.com/supportwidget/articlehome?hl=en&article_url=https%3A%2F%2Fsupport.google.com%2Fa%2Fanswer%2F167097%3Fhl%3Den&assistant_id=generic-unu&product_context=167097&product_name=UnuFlow&trigger_context=a
- turn on "Group owners can allow external members"
![image](https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/assets/24765473/91dd5222-10f0-4d1b-bb11-f415e9dc0d50)

- retry associate external user to the group
- use console (admin not gcp (error))
- 
![image](https://github.com/GoogleCloudPlatform/pbmm-on-gcp-onboarding/assets/24765473/b29616fd-d74a-463b-8ebb-7087971ac7b8)
- add service account token creator role to the sa group at the org level

export GROUP_EMAIL=sa-external@obrienlabs.app gcloud organizations add-iam-policy-binding "${ORG_ID}" --member=group:${GROUP_EMAIL} --role=roles/iam.serviceAccountTokenCreator --condition=None

- add LZ roles to service account at the org level

gcloud organizations add-iam-policy-binding "${ORG_ID}" --member="serviceAccount:${SA_EMAIL}" --role=roles/resourcemanager.organizationAdmin --condition=None

https://cloud.google.com/docs/authentication/use-service-account-impersonation

## On the client
- in a local gcp sdk shell - authenticate to your user account
- in the shell - impersonate the service account

gcloud init gcloud services enable iamcredentials.googleapis.com

C:\soft\gcloud>gcloud config set auth/impersonate_service_account sa-external@service-account-olapp.iam.gserviceaccount.com Updated property [auth/impersonate_service_account].

C:\soft\gcloud>gcloud auth application-default set-quota-project service-account-olapp WARNING: This command is using service account impersonation. All API calls will be executed as [sa-external@service-account-olapp.iam.gserviceaccount.com]. ERROR: (gcloud.auth.application-default.set-quota-project) Failed to impersonate [sa-external@service-account-olapp.iam.gserviceaccount.com]. Make sure the account that's trying to impersonate it has access to the service account itself and the "roles/iam.serviceAccountTokenCreator" role.


check

michael@cloudshell:~/tef-olapp-p1gen6 (service-account-olapp)$ gcloud organizations get-iam-policy "${ORG_ID}"

C:\soft\gcloud>gcloud init
Welcome! This command will take you through the configuration of gcloud.

Settings from your current configuration [default] are:
accessibility:
  screen_reader: 'False'
auth:
  impersonate_service_account: sa-external@service-account-olapp.iam.gserviceaccount.com
core:
  account: michael@obrienlabs.dev
  disable_usage_reporting: 'False'
  project: boot-proj-old

Pick configuration to use:
 [1] Re-initialize this configuration [default] with new settings
 [2] Create a new configuration
Please enter your numeric choice:  1

Your current configuration has been set to: [default]

You can skip diagnostics next time by using the following flag:
  gcloud init --skip-diagnostics

Network diagnostic detects and fixes local network connection issues.
Checking network connection...done.
Reachability Check passed.
Network diagnostic passed (1/1 checks passed).

Choose the account you would like to use to perform operations for this configuration:
 [1] michael@obrienlabs.dev
 [2] Log in with a new account
Please enter your numeric choice:  1

You are logged in as: [michael@obrienlabs.dev].

WARNING: This command is using service account impersonation. All API calls will be executed as [sa-external@service-account-olapp.iam.gserviceaccount.com].
WARNING: This command is using service account impersonation. All API calls will be executed as [sa-external@service-account-olapp.iam.gserviceaccount.com].
Pick cloud project to use:
 [1] boot-proj-olapp
 [2] fortigate-terraform-olapp
 [3] gcloud-ola
 [4] kcc-olapp
 [5] prj-b-cicd-wm4z
 [6] prj-b-seed-31ca
 [7] service-account-olapp
 [8] tef-olapp
 [9] tef-olapp-p1gen6
 [10] Enter a project ID
 [11] Create a new project
Please enter numeric choice or text value (must exactly match list item):  7

Your current project has been set to: [service-account-olapp].

Not setting default zone/region (this feature makes it easier to use
[gcloud compute] by setting an appropriate default value for the
--zone and --region flag).
See https://cloud.google.com/compute/docs/gcloud-compute section on how to set
default compute region and zone manually. If you would like [gcloud init] to be
able to do this for you the next time you run it, make sure the
Compute Engine API is enabled for your project on the
https://console.developers.google.com/apis page.

Your Google Cloud SDK is configured and ready to use!

* Commands that require authentication will use michael@obrienlabs.dev by default
* Commands will reference project `service-account-olapp` by default
Run `gcloud help config` to learn how to change individual settings

This gcloud configuration is called [default]. You can create additional configurations if you work with multiple accounts and/or projects.
Run `gcloud topic configurations` to learn more.

Some things to try next:

* Run `gcloud --help` to see the Cloud Platform services you can interact with. And run `gcloud help COMMAND` to get help on any gcloud command.
* Run `gcloud topic --help` to learn about advanced features of the SDK like arg files and output formatting
* Run `gcloud cheat-sheet` to see a roster of go-to `gcloud` commands.

recheck

C:\soft\gcloud>gcloud config set project service-account-olapp
WARNING: Your active project does not match the quota project in your local Application Default Credentials file. This might result in unexpected quota issues.

To update your Application Default Credentials quota project, use the `gcloud auth application-default set-quota-project` command.
WARNING: This command is using service account impersonation. All API calls will be executed as [sa-external@service-account-olapp.iam.gserviceaccount.com].
WARNING: This command is using service account impersonation. All API calls will be executed as [sa-external@service-account-olapp.iam.gserviceaccount.com].
Updated property [core/project].

C:\soft\gcloud>

TODO

obriensystems commented 6 months ago
michael@cloudshell:~$ gcloud config set project sa-old
Updated property [core/project].
michael@cloudshell:~ (sa-old)$ gcloud services enable iamcredentials.googleapis.com
Operation "operations/acat.p2-971541578014-640b7729-23f8-44f0-bcdb-1577afafc93c" finished successfully.
michael@cloudshell:~ (sa-old)$ 

1431  gcloud auth
 1432  gcloud init
 1433  gcloud config set project service-accounts-old
 1434  gcloud auth login
 1435  gcloud auth application-default login --impersonate-service-account sa-g...z-tef@sa-test-gcp.iam.gserviceaccount.com
 1436  gcloud auth application-default login --impersonate-service-account sa-...s-lz-tef@sa-test-gcp.iam.gserviceaccount.com
 1437  gcloud config set project sa-test-gcp
 1438  gcloud config get project
mromascanu123 commented 5 months ago

The issue seems to be related to the execution of gcloud commands. As long as it's just about Terraform execution there is no need for the user to directly impersonate an SA - terraform will do it if specifying an export GOOGLE_IMPERSONATE_SERVICE_ACCOUNT =SA-to-use-with-required permissions

There aren't many gcloud commands in the localized procedure and in fact their outcomes are independent of the progress of TF deployment. Specifically in 1-org gcloud scc notifications describe "scc-notify" --organization=${ORGANIZATION_ID} export ACCESS_CONTEXT_MANAGER_ID=$(gcloud access-context-manager policies list --organization ${ORGANIZATION_ID} --format="value(name)") in 3-networks-hub-and-spoke export ACCESS_CONTEXT_MANAGER_ID=$(gcloud access-context-manager policies list --organization ${ORGANIZATION_ID} --format="value(name)")

These could be executed even before starting 0-bootstrap and thereafter rely only on TF impersonation

Will test

github-actions[bot] commented 3 months ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days