Overview
Cloud Functions should run with a user-managed service account instead of the project default service account. Default service accounts are shared identities and are commonly over-privileged relative to a single function's needs.
Using a dedicated runtime service account limits the impact of function compromise, makes IAM review easier, and aligns the function's permissions with least privilege.
Remediation guidance
Remediation
Redeploy the function with a dedicated runtime service account and grant only the permissions required by the function.
Google Cloud CLI
Create a dedicated service account if needed. Replace {{manual.serviceAccountId}} and {{manual.displayName}} with your approved naming convention.
gcloud iam service-accounts create {{manual.serviceAccountId}} \
--project {{asset.cloudAccountID}} \
--display-name "{{manual.displayName}}"
Redeploy the function with the dedicated service account. Replace {{manual.serviceAccountEmail}} with the target service account. Keep the rest of your existing deployment flags, trigger settings, runtime, and source configuration unchanged.
gcloud functions deploy {{asset.name}} \
--project {{asset.cloudAccountID}} \
--region {{asset.region}} \
--service-account {{manual.serviceAccountEmail}}
Validate the runtime service account:
gcloud functions describe {{asset.name}} \
--project {{asset.cloudAccountID}} \
--region {{asset.region}} \
--format 'value(serviceConfig.serviceAccountEmail)'
Rollout guidance
- Confirm whether the function is Cloud Functions 1st gen or 2nd gen and keep the correct deployment flags for its generation.
- Grant least-privilege roles to the dedicated service account before redeploying.
- Validate trigger delivery, outbound API calls, and logs after redeployment.
- Remove broad roles from default service accounts after all dependent functions are migrated.
References
- https://cloud.google.com/functions/docs/securing/function-identity
- https://cloud.google.com/sdk/gcloud/reference/functions/deploy
Query logic
These are the stored checks tied to this control.
GCP Functions using the default service account
Connectors
Covered asset types
Expected check: eq []
{
functions(
where: {
serviceAccountEmail_MATCHES: ".*(compute@developer\\.gserviceaccount\\.com|appspot\\.gserviceaccount\\.com)$"
}
) {
...AssetFragment
}
}
Google Cloud