GCP - Service Account
Service Account Key
A GCP Service Account Key is a long-term, static credential (usually in the form of a downloadable .json
file) that acts as a permanent "username and password" for a service account.
It allows an application or script running outside of Google Cloud to authenticate as that service account and access GCP resources on its behalf.
- It's Long-Lived: Once you create this metal key, it works forever until you go to the security office and explicitly deactivate it (or the master locks are changed). It doesn't expire on its own.
- It's Static: The key itself doesn't change.
- It Works from Anywhere: Anyone who possesses this key—whether it's the real janitor, someone who found it on the street, or someone who stole it—can use it to enter the building. The door's lock only cares if the key fits; it doesn't know who is holding the key.
- It's a "Bearer" Token: Possession of the key grants access.
What's Inside the .json
Key File?
The JSON file contains several fields, but the most important one is the private_key
.
{
"type": "service_account",
"project_id": "my-gcp-project",
"private_key_id": "a1b2c3d4e5f6...",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvA... (a very long string of characters) ...\n-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "123456789...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
...
}
When an application uses this file, it uses the private_key
to sign a request to Google's authentication servers. Google then verifies this signature and, if it's valid, issues a short-lived OAuth 2.0 access token that the application can use to make API calls.
When Should You Use a Service Account Key? (The Legitimate, But Shrinking, Use Cases)
Historically, keys were the only way to authenticate from outside GCP. Today, with modern alternatives, their legitimate use is much more limited. You should only consider using a key when other methods are not feasible.
- On-Premise Servers: You have a physical server running in your own data center that needs to upload backups to Google Cloud Storage every night. This server is not part of any cloud environment.
- Other Cloud Providers: You have an application running in AWS or Azure that needs to access a BigQuery dataset in GCP.
- Third-Party SaaS Tools: A third-party monitoring or security tool that you use needs programmatic access to your GCP environment.
Even in these cases, a better, more secure modern alternative exists: Workload Identity Federation. This allows you to grant trust to an external identity (like an AWS IAM role or an on-premise Active Directory identity) without ever creating or managing a GCP key.
Why Are Service Account Keys So Dangerous? (The Security Risks)
Managing static keys is considered a security anti-pattern in modern cloud environments.
-
Huge Risk of Exposure: They are a file that must be stored somewhere. This makes them incredibly vulnerable to being:
- Accidentally committed to a public Git repository. This is one of the most common ways credentials are leaked. Automated bots are constantly scanning GitHub for exactly this mistake.
- Leaked from a developer's laptop.
- Left behind on a server that is later decommissioned.
- Shared insecurely over Slack or email.
-
They are Long-Lived: A stolen key works forever, or until someone notices the breach and remembers to go and manually revoke it. An attacker could have access for months without being detected. In contrast, access tokens generated via impersonation or federation typically expire in one hour.
-
Difficult to Manage and Rotate: Securely rotating keys across hundreds of applications is a massive operational burden. You have to generate a new key, securely distribute it to all your applications, and then revoke the old one, all without causing an outage. Most organizations fail to do this regularly.
The Modern, Secure Alternative: Impersonation & Federation
Instead of handing out physical copies of the master key, modern security practices prefer to grant temporary, audited access.
- For workloads inside GCP (e.g., a VM): Use the attached service account and Service Account Impersonation. The VM has its own low-privilege identity and can temporarily assume a higher-privilege role when needed. No keys are involved.
- For workloads outside GCP (e.g., on-prem or another cloud): Use Workload Identity Federation. This allows you to establish trust between your external identity provider and GCP, letting your on-prem application get short-lived GCP tokens without ever needing a GCP key.
Both Service Account Impersonation and Workload Identity Federation are processes to get a short-lived service account (OAuth 2.0) access token.
Service Account Key Alternative 1: Service Account Impersonation
Impersonation is the act of allowing one identity (like a user or another service account) to temporarily "wear the mask" of another service account and assume its permissions.
Impersonating a service account is a fundamental and powerful security practice in Google Cloud (GCP) and other cloud platforms. It's the recommended way to grant temporary, short-lived permissions to applications or users without having to manage long-term static keys.
Why is Impersonation So Important? The Security Benefits
- Eliminates Static Service Account Keys (
.json
files): This is the #1 reason as mentioned above. Impersonation relies on short-lived OAuth 2.0 access tokens instead. - Principle of Least Privilege at Scale: It allows you to grant broad permissions to a central, powerful service account (e.g., one that can deploy to production) but only allow specific, trusted identities (like your CI/CD pipeline's service account) to temporarily assume those permissions when needed.
- Clear Audit Trail: When impersonation is used, Google Cloud Audit Logs record two critical pieces of information:
- Which identity (the principal) initiated the action.
- Which identity's permissions (the target service account) were used to perform the action. This makes it crystal clear who did what, and with whose authority.
- Centralized Permission Management: You manage permissions in one place. Instead of giving 10 different developer service accounts the same 20 permissions, you create one "developer-role" service account and simply grant those 10 service accounts the permission to impersonate it.
How to Impersonate a Service Account: The Two-Step Process
To impersonate a service account, you need to set up the permissions correctly. Let's call the two identities:
- Principal: The user or service account that will do the impersonating.
- Target SA: The service account that will be impersonated.
Step 1: Grant the Impersonation Permission
The Principal needs permission to generate credentials for the Target SA. This is done by granting the Principal the "Service Account Token Creator" (roles/iam.serviceAccountTokenCreator
) role on the Target SA.
Using gcloud
(The most common way):
Let's say:
[email protected]
is your CI/CD pipeline's service account.[email protected]
is the powerful service account with permissions to deploy to Cloud Run.
You would run this command:
gcloud iam service-accounts add-iam-policy-binding \
[email protected] \
--member="serviceAccount:[email protected]" \
--role="roles/iam.serviceAccountTokenCreator"
This command says: "Allow principal-sa
to act as a token creator for deployer-sa
."
Step 2: Perform the Impersonation
Now that the permission is granted, the Principal can generate short-lived credentials for the Target SA.
Example A: A Developer on their Laptop
A developer can configure their local gcloud
CLI to act as a service account.
# 1. Authenticate gcloud with your own user account
gcloud auth login
# 2. Tell gcloud to use impersonation for all subsequent commands
gcloud config set auth/impersonate_service_account "[email protected]"
# 3. Now, any gcloud command you run...
gcloud run deploy my-app ...
# ...is executed with the permissions of 'deployer-sa', but audited as you.
To stop impersonating:
gcloud config unset auth/impersonate_service_account
Example B: A Service Account in a CI/CD Pipeline or on a VM (Workload Identity Federation)
This is the most common and secure pattern for applications. The application (running on a VM or in a CI/CD job) authenticates using its attached service account (principal-sa
). It then uses the Google Cloud client libraries to programmatically generate an access token for the target service account.
The libraries handle this mostly automatically. In Go, for instance, you would specify the target service account when you create the credentials object.
// Simplified Go example
import "google.golang.org/api/option"
import "google.golang.org/api/impersonate"
// The target service account we want to impersonate
targetSA := "[email protected]"
// Create a credentials object that will handle the impersonation flow
ts, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
TargetPrincipal: targetSA,
Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"},
})
if err != nil {
return err
}
// Now, use these credentials to create a client for any GCP service
// The client will automatically have the permissions of the 'deployer-sa'
storageClient, err := storage.NewClient(ctx, option.WithTokenSource(ts))
This code, when run as principal-sa
, will be able to perform actions on Cloud Storage using the permissions of deployer-sa
.
Service Account Key Alternative 2: Workload Identity Federation
Workload Identity Federation allows you to give an identity from outside of Google Cloud (like an application in AWS, a GitHub Actions workflow, or a server in your on-premise data center) temporary, short-lived access to your GCP resources without ever creating or managing a GCP service account key.
It's a way to establish a trust relationship between Google Cloud and another trusted Identity Provider (IdP).
How Workload Identity Federation Works
It involves three main components:
- Workload Identity Pool: This is the GCP resource where you define which external identity providers you trust. You are creating a "pool" of trusted external identities.
- Workload Identity Provider: Within the pool, you configure the details of a specific IdP. For example:
- For AWS: You provide the AWS Account ID.
- For Azure: You provide the Azure Tenant ID and Application ID.
- For GitHub Actions: You provide the repository owner and name.
- For any OIDC provider (like on-prem ADFS): You provide the issuer URL.
- IAM Policy: You then write an IAM policy that says, "Allow identities from this pool that have a specific attribute (e.g., a specific AWS IAM Role ARN or a specific GitHub repository name) the permission to impersonate a specific GCP Service Account." This is the crucial mapping step.
The Authentication Flow:
- Step 1: The external workload (e.g., a script in a GitHub Actions runner) authenticates with its native IdP and gets a signed identity token.
- Step 2: The workload calls the Google Cloud Security Token Service (STS), presenting the external token and requesting a GCP token.
- Step 3: STS validates the external token against the configured Workload Identity Provider.
- Step 4: STS checks the IAM policy to see if this external identity is allowed to impersonate a GCP service account.
- Step 5: If everything checks out, STS returns a short-lived GCP service account access token.
- Step 6: The workload uses this GCP token to make authenticated calls to GCP APIs.
Why is this a Game-Changer?
- Eliminates Static Keys: This is its #1 benefit. It completely removes the need to manage and rotate dangerous
.json
key files for external applications. - Centralized Trust Management: You manage trust at the provider level, not the key level. If you no longer trust a specific AWS account, you can disable the provider in your pool, instantly revoking access for all identities from that account.
- Leverages Existing Identities: You don't need to create and manage a parallel set of identities in GCP. Your CI/CD system or other cloud applications can use the identity they already have.
- Improved Security Posture: It adheres to the principle of least privilege and reduces your attack surface dramatically by getting rid of long-lived, shareable credentials.