GCP中的IAM问答
[SA-NAME]@[PROJECT-ID].iam.gserviceaccount.comP4SA 全称为 Per-Product, Per-Project Service-Account,通常在 GCP 中被称为 Service Agent(服务代理)。
当你第一次使用某些特定的 GCP 服务(如BigQuery)时,Google 会在后台自动为你创建这些 Service Agents。
它们是由 Google 管理的特殊 Service Account,目的是让这些 GCP 内部服务能够跨项目或在你的项目中安全地访问其他资源(例如:让 Cloud Build 有权限读取你的 Storage Bucket 里的代码)。
不同的 GCP 服务生成的 Service Agent 格式略有不同,但最常见的格式如下:
service-[PROJECT-NUMBER]@[SERVICE-NAME]-system.iam.gserviceaccount.com
[PROJECT-NUMBER]:你的 GCP 项目编号(注意是纯数字的 Project Number,而不是 Project ID)。
[SERVICE-NAME]:特定服务的代号,例如 compute-engine、gcp-sa-pubsub 或 cloudservices。
P4SA(Service Agent)在被 GCP 自动创建时,通常会被默认授予一个由 Google 管理的专属“服务代理角色”(Service Agent Role)。这些默认角色已经由 Google 精心硬编码,仅包含该服务正常运转所需的最小权限集。 例如,API Gateway 的服务代理会被授予 roles/apigateway.serviceAgent。 它包括如下permission。详情参见GCP 文档。请注意这个role的resource是当前项目。
iam.serviceAccounts.getAccessToken
iam.serviceAccounts.getOpenIdToken
servicemanagement.services.check
servicemanagement.services.quota
servicemanagement.services.report
service-[PROJECT-NUMBER]@[SERVICE-NAME]-system.iam.gserviceaccount.com,该P4SA project的project id为[SERVICE-NAME]。gcloud iam [service-accounts|projects|resource-manager folders|organizations] add-iam-policy-binding \
[RESOURCE] \
--member="[PRINCIPAL]" \
--role="[ROLE]"Principal是指发出请求的实体/主体。简单来说,就是“谁”或者“哪个程序”在尝试访问你的 GCP 资源。GCP IAM 允许不同类型的主体来代表人类、程序或服务。比如:
人类用户,比如可以是企业用的 Google Workspace 账号(如 alice@yourcompany.com),也可以是个人注册的 Gmail 账号(如 bob@gmail.com)。
服务账号(Service account),比如用户手动创建的 User-managed SA、系统自动生成的 P4SA (Service Agent),以及 Compute Engine 默认的服务账号。
谷歌群组,比如 dev-team@yourcompany.com
域名,它代表整个组织域名下的所有用户。比如:domain:yourcompany.com。一旦把角色赋给它,公司里的每一个人都会自动继承该权限。
所有人。
allAuthenticatedUsers:任何通过 Google 账号登录的人(全世界所有拥有 Gmail/Workspace 账号的人,不局限于你的公司)。
allUsers:互联网上的任何人(无需登录,通常用于配置完全公开的静态网站 Storage Bucket 或者是公开的 Cloud Run API)。
Workload Identity Pool(外部身份/联合身份)定义:用于让非 GCP 的外部服务(比如 AWS 的 EC2、GitHub Actions、或者你自己的本地机房)安全地访问 GCP,无需下载长期的 JSON 密钥。
场景 1:允许 A 冒充 B(Impersonation / actAs)
Resource(资源):Service Account B
Principal(主体):Service Account A
Role(角色):Service Account Token Creator
gcloud iam service-accounts add-iam-policy-binding \ sa-b@YOUR_PROJECT_ID.iam.gserviceaccount.com \ --member="serviceAccount:sa-a@YOUR_PROJECT_ID.iam.gserviceaccount.com" \ --role="roles/iam.serviceAccountTokenCreator"场景 2:让某个工程师有权管理某个特定的 Service Account
Resource(资源):my-app-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
Principal(主体):dev-lead@company.com(用户)
Role(角色):roles/iam.serviceAccountAdmin(服务账号管理员)
gcloud iam service-accounts add-iam-policy-binding \ my-app-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com \ --member="user:dev-lead@company.com" \ --role="roles/iam.serviceAccountAdmin"场景 3:允许用户在创建 VM 时,“挂载/使用”该 Service Account
Resource(资源):vm-runner-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
Principal(主体):engineer@company.com(用户)
Role(角色):roles/iam.serviceAccountUser(服务账号使用者)
gcloud iam service-accounts add-iam-policy-binding \ vm-runner-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com \ --member="user:engineer@company.com" \ --role="roles/iam.serviceAccountUser"
没有,该人类用户不会自动获得任何该Service Account的role。该人类用户对他的所有控制权,全部来自于该项目所继承下来的权限。这是因为Service Account是项目的子资源(Resource),该Service Account不属于任何人。该人类用于可以创建Service Account只是因为该人类用户拥有了某个高阶角色比如 Project Editor、Project Owner 或 Create Service Accounts)。
那么,假如该人类用户只是Project Editor,而他想把该Service Account授权给某个员工。该人类用户尝试运行gcloud iam service-accounts add-iam-policy-binding会发现权限不足。这是因为该人类用户只是Editor,不是Owner。解决这个问题需要用Project Owner或IAM Administrator执行操作,显式的把该Service Account的特定角色授予你,比如Service Account Admin。具体需要的是iam.serviceAccounts.setIamPolicy权限。参见GCP文档。
gcloud iam service-accounts add-iam-policy-binding \
my-new-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com \
--member="user:your-email@company.com" \
--role="roles/iam.serviceAccountAdmin"Service Account A 想要冒充(impersonate/actAs)Service Account B,核心逻辑是:B 是资源,A 是主体。 也就是说,B 需要给 A 授权。
具体来说,你需要在 Service Account B 的 IAM 策略中,将 Service Account Token Creator 角色授予 Service Account A。
gcloud iam service-accounts add-iam-policy-binding \
B@YOUR_PROJECT_ID.iam.gserviceaccount.com \
--member="serviceAccount:A@YOUR_PROJECT_ID.iam.gserviceaccount.com" \
--role="roles/iam.serviceAccountTokenCreator"举一个例子就是Service Account A想要进Service Account B的房子,那需要B的进入自己房子的token。那么这个时候需要A被授予生成B token的role,然后A才能拿着B的token进入B的房子。