第2章 服务账号创建与权限配置
2.1 原理概述
服务账号(Service Account)是 Google Cloud 中的一种特殊账号,用于代表应用或服务而非最终用户调用 Google API。在 Google Play API 接入中,服务账号充当自动化发布、财务数据获取、应用管理操作的“机器人身份”。其核心认证流程基于 OAuth 2.0 的 JWT 断言(Assertion) 机制:
- 使用服务账号的私钥创建一个签名的 JWT(JSON Web )断言,包含目标 API 的 scope 和有效期。
- 将 JWT 断言发送至 Google OAuth 2.0 令牌端点(
https://oauth2.googleapis.com/),获取访问令牌(Access )。 - 携带访问令牌调用 Google Play Developer API,执行发布、查看财务数据等操作。
此机制无需交互式登录,适合 CI/CD 流水线、后端服务等无人值守场景。权限通过 Google Cloud IAM 和 Play Console 角色 两级管控,确保最小权限原则。
关键安全约束: 服务账号的私钥文件(.json)等同于密码,必须妥善保管,禁止提交到代码仓库或公开网络。
2.2 核心概念与角色
理解以下概念是正确配置的基础:
| 概念/角色 | 说明 | 配置位置 |
|---|---|---|
| Google Cloud 项目 | 承载服务账号的容器,需启用 Google Play Developer API | Google Cloud Console |
| 服务账号 | 代表自动化代理的账号实体,格式为 name@project.iam.gserviceaccount.com |
Cloud Console > IAM 和管理 |
| 私钥文件(JSON) | 包含服务账号的私钥、客户端 ID 等凭证信息,用于签名 JWT | Cloud Console > 密钥管理 |
| Play Console 角色:财务 | 查看收入、订单、订阅等财务数据 | Play Console > 用户和权限 |
| Play Console 角色:发布 | 上传 APK/AAB、管理发布轨道、提交审核 | Play Console > 用户和权限 |
| Play Console 角色:查看 | 查看应用信息、评分、崩溃报告等只读数据 | Play Console > 用户和权限 |
| Play Console 角色:管理 | 全部操作权限,包括修改元数据、管理用户 | Play Console > 用户和权限 |
权限边界提醒: Play Console 角色与 Google Cloud IAM 角色是独立的。服务账号在 Play Console 中获得的权限由 Play Console 角色控制,与 GCP IAM 角色无关。
2.3 实现流程图
下图展示了从创建服务账号到完成 Play Console 绑定的完整步骤与数据流向:
2.4 详细操作步骤
以下步骤基于 gcloud CLI 和 Web 控制台 两种方式,请根据实际环境选择。
2.4.1 创建服务账号(gcloud CLI)
gcloud iam service-accounts create play-api-sa \
--display-name="Google Play API Service Account" \
--description="用于Google Play API自动化操作"
查看创建结果:
gcloud iam service-accounts list
2.4.2 生成并下载密钥文件
gcloud iam service-accounts keys create ./play-.json \
--iam-account=play-api-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com
密钥文件内容结构示例:
{
"type": "service_account",
"project_id": "YOUR_PROJECT_ID",
"private_key_id": "a1b2c3d4e5f6...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "play-api-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com",
"client_id": "123456789012345678901",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"_uri": "https://oauth2.googleapis.com/",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/play-api-sa%40YOUR_PROJECT_ID.iam.gserviceaccount.com"
}
安全提示: 密钥文件生成后立即下载,Google Cloud 不会再次提供原始私钥内容。建议将密钥文件保存到安全的密钥管理服务(如 Google Secret Manager、HashiCorp Vault)。
2.4.3 启用 Google Play Developer API
在 Google Cloud Console 中启用 API:
gcloud services enable androidpublisher.googleapis.com \
--project=YOUR_PROJECT_ID
验证 API 已启用:
gcloud services list --enabled --filter="name=androidpublisher.googleapis.com"
2.4.4 在 Play Console 中绑定服务账号
- 登录 Google Play Console(
https://play.google.com/console)。 - 进入 设置 > API 访问。
- 点击 选择要关联的服务账号,输入服务账号的 客户端邮箱(
play-api-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com)。 - 点击 关联 完成绑定。
2.4.5 授予角色权限
在 Play Console 中关联服务账号后,需要为其分配具体角色:
- 在 API 访问 页面找到已绑定的服务账号。
- 点击 权限 区域旁的 添加应用 或直接选择应用。
- 勾选所需的角色(如 发布、财务、查看、管理),建议按最小权限原则分配。
- 点击 应用 保存配置。
生产建议: 如果服务账号只需要上传 AAB 并发布到测试轨道,仅授予 发布 角色即可,不要授予 管理 或 财务 角色。
2.5 配置验证与调试
完成配置后,通过以下方法验证服务账号是否正常工作:
2.5.1 使用 gcloud 测试认证
gcloud auth activate-service-account \
--key-file=./play-.json \
--project=YOUR_PROJECT_ID
# 验证身份
gcloud auth list
2.5.2 调用 Play Developer API 测试端点
# 获取 Access (使用OAuth 2.0)
curl -s -X POST https://oauth2.googleapis.com/ \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=YOUR_SIGNED_JWT" \
| jq .access_
# 简化方式:使用 Google API Client Library(Python 示例)
# pip install google-api-python-client google-auth
from google.oauth2 import service_account
import googleapiclient.discovery
credentials = service_account.Credentials.from_service_account_file(
'./play-.json',
scopes=['https://www.googleapis.com/auth/androidpublisher']
)
service = googleapiclient.discovery.build('androidpublisher', 'v3', credentials=credentials)
# 测试列出应用
apps = service.applications().list().execute()
print(apps)
2.5.3 检查常见错误日志
# 启用调试日志(Python)
import logging
logging.basicConfig(level=logging.DEBUG)
# 常见错误响应示例
{
"error": {
"code": 403,
"message": "The caller does not have permission",
"status": "PERMISSION_DENIED"
}
}
2.6 常见错误与解决方案
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
PERMISSION_DENIED |
服务账号未在 Play Console 中绑定,或未授予角色 | 检查 Play Console > API 访问,确认服务账号已关联并分配了角色 |
Service account not found |
客户端邮箱填写错误,或服务账号不在同一 GCP 项目 | 使用 gcloud iam service-accounts list 确认邮箱地址 |
JWT validation failed |
私钥文件损坏、过期或被吊销 | 重新生成密钥文件,并检查系统时间是否与 NTP 同步 |
Access expired |
超过 1 小时有效期,未使用 Refresh | 服务账号无法刷新 ,需重新生成 JWT 断言获取新 |
API not enabled |
Google Play Developer API 未启用 | 运行 gcloud services enable androidpublisher.googleapis.com |
| Play Console 中看不到服务账号 | 服务账号未添加到项目,或 IAM 权限不足 | 确认服务账号在 GCP 中存在,并使用拥有 服务账号管理员 角色的账号操作 |
2.7 安全最佳实践与性能优化
在生产环境中运行服务账号时,请遵循以下建议以保障安全性和稳定性:
- 密钥轮换策略: 每 90 天轮换一次私钥。使用
gcloud iam service-accounts keys create生成新密钥后,更新所有使用方,再删除旧密钥。 - 最小权限原则: 只授予服务账号完成其任务所需的最少角色。例如,仅用于发布的应用只给 发布 角色,不授予 管理 或 财务 角色。
- 密钥存储安全: 禁止将密钥文件硬编码在代码中或提交到 Git。使用 Google Secret Manager、HashiCorp Vault 或环境变量注入。
- 监控与告警: 在 GCP 中启用 服务账号密钥使用情况 审计日志,并设置告警检测异常高频调用或密钥泄露。
- 访问令牌缓存: 服务账号获取的 Access 有效期 1 小时,建议在代码中添加 缓存逻辑,避免每次请求都重新签名 JWT,减少延迟和 API 调用开销。
- 使用专用项目: 为 Play API 服务账号创建独立的 GCP 项目,与生产基础设施隔离,降低误操作风险。
缓存示例(Python):
import time
from google.oauth2 import service_account
class TokenManager:
def __init__(self, key_path, scopes):
self.key_path = key_path
self.scopes = scopes
self._ = None
self._expires_at = 0
def get_(self):
if time.time() > self._expires_at - 60:
creds = service_account.Credentials.from_service_account_file(
self.key_path, scopes=self.scopes
)
self._ = creds.
self._expires_at = creds.expiry.timestamp()
return self._
2.8 部署检查清单
在将服务账号配置迁移到生产环境前,逐项确认以下要点:
| 检查项 | 状态 | 备注 |
|---|---|---|
| 服务账号存在且状态正常 | ✅ / ❌ | gcloud iam service-accounts list |
| 私钥文件已下载并安全存储 | ✅ / ❌ | 禁止上传到公开仓库或公开可读的存储桶 |
| Google Play Developer API 已启用 | ✅ / ❌ | gcloud services enable |
| Play Console 中已绑定服务账号 | ✅ / ❌ | 设置 > API 访问 > 关联服务账号 |
| 已授予最小需要的角色 | ✅ / ❌ | 仅分配业务所需的角色(发布/财务/查看) |
| 缓存逻辑已实现 | ✅ / ❌ | 减少 JWT 签名次数,降低延迟 |
| 密钥轮换计划已制定 | ✅ / ❌ | 建议 90 天轮换一次 |
| 监控告警已配置 | ✅ / ❌ | 审计日志 + 异常检测 |
生产上线前必做: 使用测试应用和测试轨道完整走一遍 API 调用流程,确认服务账号能正常完成发布、查看财务数据等操作后再推广到正式应用。