Enabling Workload Identity with apigeectl Stay organized with collections Save and categorize content based on your preferences.
This topic explains how to enable Workload Identity for Apigee hybrid usingapigeectl.
If you are using Helm charts to install and manage Apigee hybrid, seeEnabling Workload Identity with Helm charts.
Note: Apigee hybrid v.1.11 only supports Workload Identity federation on GKE.Overview
Workload Identity is a way for applications running within GKE (Google Kubernetes Engine) to access Google Cloud services. For overviews of Workload Identity, see:
- Introducing Workload Identity: Better authentication for your GKE applications
- Using Workload Identity
A Google Cloud IAM service account is an identity that an application can use to make requests to Google APIs. These service accounts are referred to as GSA (Google Service Accounts) in the document. For more information about GSAs, seeService accounts.
Separately, Kubernetes also has the concept of service accounts. A service account provides an identity for processes that run in a Pod. Kubernetes service accounts are Kubernetes resources, while Google service accounts are specific to Google Cloud. For information on Kubernetes service accounts, see Configure Service Accounts for Pods in the Kubernetes documentation.
With Apigee hybrid 1.4 and later, Apigee creates and uses a Kubernetes service account for each type of component. Enabling Workload Identity allows the hybrid components to interact with the Kubernetes service accounts.
Google service accounts in Apigee hybrid without Workload Identity
Without using Workload Identity, you must link the Google service accounts to each component in your overrides.yaml file with either a reference to a cert file or a Kubernetes secret. For example:
- Cert files:
watcher: serviceAccountPath: ./apigee-org/my-hybrid-project-apigee-watcher.json
See:
- Kubernetes secret:
watcher: serviceAccountRef: my-watcher-k8s-secret
See:
Environment variables used in these procedures
These procedures make use of the following environment variables. Either set these in your command shell or replace them in the code samples with the actual values:
APIGEECTL_HOME: The directory where you have installedapigeectl.CLUSTER_LOCATION: The region or zone of your cluster, for example:us-west1.ENV_NAME: Then name of the Apigee environment.HYBRID_FILES: Your hybrid files directory, for examplehybrid-base-directory/hybrid-files.ORG_NAME: The name of your Apigee organization.PROJECT_ID: The ID of your Google Cloud project.NAMESPACE: Your Apigee namespace (usually "apigee").
Verify the environment variables:
echo $PROJECT_IDecho $ORG_NAMEecho $ENV_NAMEecho $NAMESPACEecho $CLUSTER_LOCATIONecho $APIGEECTL_HOMEecho $HYBRID_FILES
Initialize any of the variables you need:
export PROJECT_ID=my-project-idexport ORG_NAME=$PROJECT_IDexport ENV_NAME=my-environment-nameexport NAMESPACE=apigeeexport CLUSTER_LOCATION=my-cluster-locationexport APIGEECTL_HOME=hybrid-base-directory/apigeectlexport HYBRID_FILES=hybrid-base-directory/hybrid-files
Workload Identity and service account key files
When running Apigee hybrid on GKE, the standard practice is to create and download private keys (.json files) for each of the service accounts. When using Workload Identity, you do not need to download service account private keys and add them to GKE clusters.
If you have downloaded service account key files as part of your Apigee hybrid installation, you can delete them after enabling Workload Identity. In most installations, they reside in thehybrid-base-directory/hybrid-files/service-accounts/ directory.
Enable Workload Identity for Apigee hybrid
To begin, follow the instructions inPrepare to enable Workload Identity to update node pools and initialize variables prior to enabling Workload Identity.
Then, follow the instructions inSetworkloadIdentityEnabled: true and create service accounts to enable Workload Identity on your Apigee hybrid installation.
Prepare to enable Workload Identity
Before starting the install process, follow the steps in this section.
- Set the project to the project you're modifying:
gcloud config set project $PROJECT_ID
- Get the
gcloudcredentials of the cluster on which you are enabling Workload Identity with the following command: Note: If you created a zonal cluster instead of a regional cluster, get the credentials with the following command:gcloud container clusters get-credentials ${CLUSTER_NAME} \ --region${CLUSTER_LOCATION} \ --project${PROJECT_ID}gcloud container clusters get-credentials${CLUSTER_NAME} \ --zone${CLUSTER_LOCATION} \ --project${PROJECT_ID} - Verify that Workload Identity is enabled for the GKE cluster running Apigee with the following command:
Note: For zonal clusters use:gcloud container clusters describe $CLUSTER_NAME --region $CLUSTER_LOCATION --project $PROJECT_ID
gcloud container clusters describe $CLUSTER_NAME --zone $CLUSTER_LOCATION --project $PROJECT_ID
The output should include something like the following:
……status:RUNNINGsubnetwork:defaultworkloadIdentityConfig:workloadPool:my-project-id.svc.id.goog
If needed, enable workload identity on the cluster. This operation can take up to 30 minutes:
Note: If you created a zonal cluster instead of a regional cluster, use thegcloud container clusters update$CLUSTER_NAME \ --workload-pool=$PROJECT_ID.svc.id.goog \ --project$PROJECT_ID \ --region$CLUSTER_LOCATION
--zoneargument instead of--regionas in the following command:gcloud container clusters update$CLUSTER_NAME \ --workload-pool=$PROJECT_ID.svc.id.goog \ --zone$CLUSTER_LOCATION \ --project$PROJECT_ID
For more information, seeEnable Workload Identity.
- Ensure Workload Identity is enabled on each node pool.
- List your node pools with the following command:
gcloud container node-pools list \ --cluster $CLUSTER_NAME \ --region $CLUSTER_LOCATION \ --project $PROJECT_ID
Your output should look something like:
NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION apigee-runtime e2-standard-4 100 1.23.12-gke.100 apigee-data e2-standard-4 100 1.23.12-gke.100
- Ensure Workload Identity is enabled per node pool using the following command for each node pool:
gcloud container node-pools updateNODE_POOL_NAME \ --cluster=$CLUSTER_NAME \ --region $CLUSTER_LOCATION \ --project $PROJECT_ID \ --workload-metadata=GKE_METADATA
WhereNODE_POOL_NAME is the name of each node pool.
- List your node pools with the following command:
Verify or create Google service accounts
Google service accounts are created for many Apigee hybrid components during installation. Use this procedure to verify the Google service accounts and create any that are needed.
- Check the names of the Google service accounts for your project with the following command:
gcloud iam service-accounts list --project $PROJECT_ID
Your output should look something like:
Tip: If you have custom names for your service accounts that do not correspond easily with the names of the Apigee components, you can determine the role of each service account by checking the roles assigned to it and comparing the roles with the roles recommended inAbout service accounts.Prod
For non-production environments:
DISPLAY NAME EMAIL DISABLEDapigee-cassandra apigee-cassandra@my_project_id.iam.gserviceaccount.com Falseapigee-logger apigee-logger@my_project_id.iam.gserviceaccount.com Falseapigee-mart apigee-mart@my_project_id.iam.gserviceaccount.com Falseapigee-metrics apigee-metrics@my_project_id.iam.gserviceaccount.com Falseapigee-runtime apigee-runtime@my_project_id.iam.gserviceaccount.com Falseapigee-synchronizer apigee-synchronizer@my_project_id.iam.gserviceaccount.com Falseapigee-udca apigee-udca@my_project_id.iam.gserviceaccount.com Falseapigee-watcher apigee-watcher@my_project_id.iam.gserviceaccount.com False
Non-prod
For non-production environments:
DISPLAY NAME EMAIL DISABLEDapigee-non-prod apigee-non-prod@my_project_id.iam.gserviceaccount.com False
Use the following command to check the roles assigned to a service account:
gcloud projects get-iam-policy ${PROJECT_ID} \ --flatten="bindings[].members" \ --format='table(bindings.role)' \ --filter="SERVICE_ACCOUNT_NAME"If you need to create the Google service accounts for your project, there are two methods you can use:
- Use the
create-service-accounttool included with apigee in theapigeectl/tools/directory. This tool can create all the service accounts with a single command or let you create them individually.create-service-accountgenerates key files for each service account and downloads them. Using Workload Identity, you will not need these key files. If you are concerned about the security of these key files, you may want to delete them. Alternatively you can usegcloudto create the service accounts and assign the appropriate roles to them. - Use the
gcloud iam service-accounts createcommand to create the service accounts one at a time and thegcloud projects add-iam-policy-bindingcommand to assign the appropriate roles to each service account. This method requires you to create each service account individually, but lets you avoid downloading the key files.
Use the following command to create a Google service account per component:create-service-accountProd
For non-production environments:
$APIGEECTL_HOME/tools/create-service-account --env prod --dir $APIGEECTL_HOME/../service-accounts
This command will create the following service accounts:
apigee-cassandraapigee-loggerapigee-martapigee-metricsapigee-runtimeapigee-synchronizerapigee-udcaapigee-watcher
Non-prod
For non-production environments:
$APIGEECTL_HOME/tools/create-service-account --env non-prod --dir $APIGEECTL_HOME/../service-accounts
This command will create a single service accounts,
apigee-non-prod, with all the roles assigned needed to manage all Apigee components.gcloudCreate the following service accounts and assign roles to them.
Tip: If you want to use custom names, change the red service account name in the code sample to the name you want to use.- Service account:
apigee-cassandra,role:roles/storage.objectAdminCreate the account:
gcloud iam service-accounts createapigee-cassandra \ --display-name="apigee-cassandra" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-cassandra@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/storage.objectAdmin"
- Service account:
apigee-logger,role:roles/logging.logWriterCreate the account:
gcloud iam service-accounts createapigee-logger \ --display-name="apigee-logger" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-logger@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/logging.logWriter"
- Service account:
apigee-mart,role:roles/apigeeconnect.AgentCreate the account:
gcloud iam service-accounts createapigee-mart \ --display-name="apigee-mart" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-mart@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigeeconnect.Agent"
- Service account:
apigee-metrics,role:roles/monitoring.metricWriterCreate the account:
gcloud iam service-accounts createapigee-metrics \ --display-name="apigee-metrics" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-metrics@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/monitoring.metricWriter"
- Service account:
apigee-runtime,role:No role assigned.Create the account:
gcloud iam service-accounts createapigee-runtime \ --display-name="apigee-runtime" \ --project $PROJECT_ID
- Service account:
apigee-synchronizer,role:roles/apigee.synchronizerManagerCreate the account:
gcloud iam service-accounts createapigee-synchronizer \ --display-name="apigee-synchronizer" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-synchronizer@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigee.synchronizerManager"
- Service account:
apigee-udca,role:roles/apigee.analyticsAgentCreate the account:
gcloud iam service-accounts createapigee-udca \ --display-name="apigee-udca" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-udca@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigee.analyticsAgent"
- Service account:
apigee-watcher,role:roles/apigee.runtimeAgentCreate the account:
gcloud iam service-accounts createapigee-watcher \ --display-name="apigee-watcher" \ --project $PROJECT_ID
Assign the role:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:apigee-watcher@$PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/apigee.runtimeAgent"
- Use the
SetworkloadIdentityEnabled: true and create service accounts
apigeectl creates Kubernetes service accounts for each Apigee hybrid component when you setworkloadIdentityEnabled: true in your overrides file and apply the changes.
- Add the bolded line below to your
overrides.yamlfile under thegcpstanza. This enables Workload Identity for your installation and triggersapigeectlto create the Kubernetes service accounts when you apply the configuration:gcp: projectID: "my-project-id" name: "my-project-id" region: "analytics-region"workloadIdentityEnabled: true
- Add the bolded lines below to your
overrides.yamlfile under thecassandrastanza. This triggers the creation of theapigee-cassandra-backupKubernetes service account:cassandra: ...backup: enabled: true
- Apply the changes with
apigeectlwith the--restoreflag: Note: The$APIGEECTL_HOME/apigeectl apply -f overrides/overrides.yaml --restore
--restoreflag triggers creation of theapigee-cassandra-restoreKubernetes service account. - Verify the service accounts with the following command:
kubectl get sa -n $NAMESPACE
Your output should look something like the following. The Kubernetes service accounts inbold are the ones you will need to annotate with your Google service accounts:
NAME SECRETS AGEapigee-cassandra-backup 1 11mapigee-cassandra-restore 1 11mapigee-cassandra-schema-setup-my-project-id-123abcd-sa 1 11mapigee-cassandra-schema-val-my-project-id-123abcd 1 11mapigee-cassandra-user-setup-my-project-id-123abcd-sa 1 11mapigee-connect-agent-my-project-id-123abcd-sa 1 11mapigee-datastore-default-sa 1 11mapigee-ingressgateway 1 11mapigee-ingressgateway-my-project-id-123abcd 1 11mapigee-ingressgateway-manager 1 11mapigee-init 1 11mapigee-mart-my-project-id-123abcd-sa 1 11mapigee-metrics-sa 1 11mapigee-mint-task-scheduler-my-project-id-123abcd-sa 1 11mapigee-redis-default-sa 1 11mapigee-redis-envoy-default-sa 1 11mapigee-runtime-my-project-id-env-name-234bcde-sa 1 11mapigee-synchronizer-my-project-id-env-name-234bcde-sa 1 11mapigee-udca-my-project-id-123abcd-sa 1 11mapigee-udca-my-project-id-env-name-234bcde-sa 1 11mapigee-watcher-my-project-id-123abcd-sa 1 11mdefault 1 11m
Annotate the Kubernetes service accounts with the Google service accounts
For each Apigee component annotate the corresponding Kubernetes service accounts with the Google service account for the component.
Org-level components
You will have only one instance of each Kubernetes service account for your Apigee org.
| Component | Kubernetes Service Account | Google Service Account |
|---|---|---|
| Cassandra | apigee-cassandra-backup | apigee-cassandra |
apigee-cassandra-restore | apigee-cassandra | |
apigee-cassandra-schema-setup-my-project-id-num-id1-sa | apigee-cassandra | |
apigee-cassandra-schema-val-my-project-id-num-id1 | apigee-cassandra | |
apigee-cassandra-user-setup-my-project-id-num-id1-sa | apigee-cassandra | |
apigee-datastore-default-sa | apigee-cassandra | |
| Apigee Connect | apigee-connect-agent-my-project-id-num-id1-sa | apigee-mart |
| MART | apigee-mart-my-project-id-num-id1-sa | apigee-mart |
| Metrics | apigee-metrics-sa | apigee-metrics | UDCA (org-level) | apigee-udca-my-project-id-num-id1-sa | apigee-udca |
| Watcher | apigee-watcher-my-project-id-num-id1-sa | apigee-watcher |
Env-level components
You will have one instance of each Kubernetes service account for each Apigee environment.
| Component | Kubernetes Service Account | Google Service Account |
|---|---|---|
| Apigee Runtime | apigee-runtime-my-project-id-env-name-num-id2-sa | apigee-runtime |
| Synchronizer | apigee-synchronizer-my-project-id-env-name-num-id2-sa | apigee-synchronizer |
| UDCA (env-level) | apigee-udca-my-project-id-env-name-num-id2-sa | apigee-udca |
create-service-account, in the following commands replace the red service account name with the correct service account name for the component. For example, if your Cassandra service account is namedmy-cassandra-accnt-1, then replaceapigee-cassandra with that name in the command. In the following commands use the Kubernetes service account names returned by thekubectl get sa -n $NAMESPACE command, for example:apigee-cassandra-schema-val-hybrid-example-project-123abcd.
In this procedure, for each Kubernetes service account, you will:
- Bind the Kubernetes service account and the principal Google service account to the
roles/iam.workloadIdentityUserIAM role. - Annotate the Kubernetes service account with the Google service account.
- Bind the roles and annotate the service accounts.
Org-level components
Annotate Kubernetes service accounts for the org-level components. You will need to do this once for each component in your Apigee organization.
- Cassandra
The Cassandra component has six associated Kubernetes service accounts:
apigee-cassandra-backupapigee-cassandra-restoreapigee-cassandra-schema-setupapigee-cassandra-schema-val(val= validation)apigee-cassandra-user-setupapigee-datastore-default
Prod
apigee-cassandra-backup- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-cassandra"
KSA_NAME="apigee-cassandra-backup" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-restore- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-restore"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-setup-service-account-name- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-schema-setup-service-account-name"
Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-val-service-account-name- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-schema-val-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-user-setup-service-account-name- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-user-setup-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
apigee-datastore-default-sa- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-datastore-default-sa"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
apigee-cassandra-backup- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-non-prod"
KSA_NAME="apigee-connect-agent-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-restore- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-restore"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-setup-service-account-name- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-schema-setup-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-schema-val-service-account-name- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-schema-val-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-cassandra-user-setup-service-account-name- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-cassandra-user-setup-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
apigee-datastore-default-sa- Redefine the
KSA_NAMEenvironment variable:KSA_NAME="apigee-datastore-default-sa"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Apigee Connect
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-mart"
KSA_NAME="apigee-connect-agent-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variable:KSA_NAME="apigee-connect-agent-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
- MART
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-mart"
KSA_NAME="apigee-mart-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variable:KSA_NAME="apigee-mart-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
- Apigee metrics
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-metrics"
KSA_NAME="apigee-metrics-sa" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variable:KSA_NAME="apigee-metrics-sa"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
- UDCA (org-level)
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-udca"
KSA_NAME="apigee-udca-org-level-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variables:KSA_NAME="apigee-udca-org-level-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
- Apigee Watcher
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-watcher"
KSA_NAME="apigee-watcher-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variable:KSA_NAME="apigee-watcher-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
For each environment:
- Runtime
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-runtime"
KSA_NAME="apigee-runtime-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variable:KSA_NAME="apigee-runtime-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
- Synchronizer
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-synchronizer"
KSA_NAME="apigee-synchronizer-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variable:KSA_NAME="apigee-synchronizer-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
- UDCA (env-level)
Prod
- Define the
KSA_NAMEandGSA_NAMEenvironment variables:GSA_NAME="apigee-udca"
KSA_NAME="apigee-udca-env-level-service-account-name" - Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Non-prod
- Define the
KSA_NAMEenvironment variable:KSA_NAME="apigee-udca-env-level-service-account-name"
- Bind the IAM role:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:$PROJECT_ID.svc.id.goog[$NAMESPACE/$KSA_NAME]" \ $GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
- Annotate the service account:
kubectl annotate serviceaccount \ --namespace $NAMESPACE $KSA_NAME iam.gke.io/gcp-service-account=apigee-non-prod@$PROJECT_ID.iam.gserviceaccount.com
- Define the
- Cassandra
- Validate if the steps worked:
gcloud config set project $PROJECT_ID
kubectl run --rm -it --image google/cloud-sdk:slim \ --namespace $NAMESPACE workload-identity-test\ -- gcloud auth list
If you don't see a command prompt, try pressingEnter.
If the steps were correctly run, you should see a response like the following:
CredentialedAccountsACTIVEACCOUNT*GSA@PROJECT_ID.iam.gserviceaccount.com
- If upgrading from a previous install, clean up secrets that contained service account private keys:
kubectl delete secrets -n $NAMESPACE $(k get secrets -n $NAMESPACE | grep svc-account | awk '{print $1}') - Check logs:
kubectl logs -n $NAMESPACE -l app=apigee=synchronizer,env=$ENV_NAME,org=$ORG_NAME apigee-synchronizer
- (Optional) You can see the status of your Kubernetes service accounts in theKubernetes: Workloads Overview page in the Google Cloud console.Note: You may see an error status for the
apigee-cassandra-backupandapigee-cassandra-restoreservice accounts. This is because you are not currently running backup or restore, and these processes have not been fully configured yet. For more information on Cassandra backup and restore, seefeedbackCassandra backup overview.
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-12-17 UTC.