第2章 服务账号创建与权限配置

2.1 原理概述

服务账号(Service Account)是 Google Cloud 中的一种特殊账号,用于代表应用或服务而非最终用户调用 Google API。在 Google Play API 接入中,服务账号充当自动化发布、财务数据获取、应用管理操作的“机器人身份”。其核心认证流程基于 OAuth 2.0 的 JWT 断言(Assertion) 机制:

  1. 使用服务账号的私钥创建一个签名的 JWT(JSON Web )断言,包含目标 API 的 scope 和有效期。
  2. 将 JWT 断言发送至 Google OAuth 2.0 令牌端点(https://oauth2.googleapis.com/),获取访问令牌(Access )。
  3. 携带访问令牌调用 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 绑定的完整步骤与数据流向:

服务账号创建与权限配置流程 创建服务账号 生成密钥文件 下载JSON密钥 Play Console 绑定 授予角色权限 完成配置 核心数据流 服务账号私钥 → JWT 断言签名 → OAuth2.0 令牌端点获取 Access → 调用 Play API

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 中绑定服务账号

  1. 登录 Google Play Console(https://play.google.com/console)。
  2. 进入 设置 > API 访问。
  3. 点击 选择要关联的服务账号,输入服务账号的 客户端邮箱(play-api-sa@YOUR_PROJECT_ID.iam.gserviceaccount.com)。
  4. 点击 关联 完成绑定。

2.4.5 授予角色权限

在 Play Console 中关联服务账号后,需要为其分配具体角色:

  1. 在 API 访问 页面找到已绑定的服务账号。
  2. 点击 权限 区域旁的 添加应用 或直接选择应用。
  3. 勾选所需的角色(如 发布、财务、查看、管理),建议按最小权限原则分配。
  4. 点击 应用 保存配置。
生产建议: 如果服务账号只需要上传 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 调用流程,确认服务账号能正常完成发布、查看财务数据等操作后再推广到正式应用。