Web应用多用户调用GCE API:选OAuth还是服务账号认证?
多用户认证调用GCE API的解决方案
核心思路
从当前的单服务账号服务器到服务器模式,切换为OAuth 2.0授权码流程实现多用户身份认证,结合Google IAM权限控制,让同事用自己的Google账号登录Web应用后,以最小必要权限操作GCE实例。
步骤拆解
一、切换认证方式:OAuth 2.0授权码流程
服务器到服务器模式依赖服务账号密钥,无法区分用户身份,不适合多用户场景。OAuth授权码流程是Web应用多用户认证的标准方案:
- 用户点击Web应用的登录按钮,跳转到Google登录页面完成身份验证
- 用户授权Web应用访问GCE权限后,Google返回授权码
- Web应用用授权码换取访问令牌(有效期1小时)和刷新令牌(长期有效)
- 用用户的访问令牌调用GCE API,令牌过期时自动用刷新令牌续期
二、配置IAM权限(最小权限原则)
- 创建自定义IAM角色,仅包含所需的GCE操作权限,比如:
compute.instances.create(创建实例)compute.instances.start(启动实例)compute.instances.list(查看实例列表,按需添加)
- 将该自定义角色分配给需要访问的同事账号,或创建Google组统一管理(把同事加入组后给组分配角色,更方便批量维护)
- 禁止直接分配
editor/owner这类宽权限角色,避免误操作风险
三、Web应用集成实现
1. 创建OAuth客户端ID
- 登录Google Cloud Console → 进入「API和服务」→「凭据」→「创建凭据」→「OAuth客户端ID」
- 应用类型选「Web应用」,填写名称并添加授权回调URL(比如
https://your-app-domain.com/auth/callback) - 保存生成的客户端ID和客户端密钥,后续在应用中使用
2. 集成登录与API调用逻辑(以Python Flask为例)
from flask import Flask, redirect, request, session from google_auth_oauthlib.flow import Flow from googleapiclient.discovery import build from google.oauth2.credentials import Credentials app = Flask(__name__) app.secret_key = 'your-app-secret-key' # 替换为实际密钥 # 初始化OAuth流 flow = Flow.from_client_secrets_file( 'client_secret.json', # 下载的OAuth客户端配置文件 scopes=['https://www.googleapis.com/auth/compute'], redirect_uri='https://your-app-domain.com/auth/callback' ) @app.route('/login') def login(): auth_url, state = flow.authorization_url( access_type='offline', # 申请刷新令牌 include_granted_scopes='true' ) session['state'] = state return redirect(auth_url) @app.route('/auth/callback') def auth_callback(): flow.fetch_token(authorization_response=request.url) credentials = flow.credentials # 加密存储用户凭据到会话/数据库,避免明文泄露 session['credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes } return redirect('/launch-vm') @app.route('/launch-vm') def launch_vm(): # 从会话中获取用户凭据 credentials = Credentials(**session['credentials']) # 构建GCE API客户端 compute = build('compute', 'v1', credentials=credentials) # 提交VM启动请求(替换为你的项目、区域和实例配置) project_id = 'your-gce-project-id' zone = 'us-central1-a' instance_config = { 'name': 'user-vm-xxx', 'machineType': f'zones/{zone}/machineTypes/n1-standard-1', 'disks': [{ 'boot': True, 'initializeParams': { 'sourceImage': 'projects/debian-cloud/global/images/debian-11-bullseye-v20230918' } }], 'networkInterfaces': [{ 'network': 'global/networks/default', 'accessConfigs': [{ 'type': 'ONE_TO_ONE_NAT', 'name': 'External NAT' }] }] } request = compute.instances().insert(project=project_id, zone=zone, body=instance_config) response = request.execute() return f"VM启动请求已提交,实例ID:{response['name']}"
3. 令牌管理注意事项
- 访问令牌有效期1小时,需用刷新令牌自动续期,避免用户重复登录
- 务必加密存储用户的凭据(尤其是刷新令牌),禁止明文存储
四、可选优化
- 服务账号代理:如果需要统一控制权限但保留用户审计轨迹,可让用户认证后代理指定服务账号操作,需给用户分配
roles/iam.serviceAccountTokenCreator角色 - 审计日志:开启Google Cloud Audit Logs,记录所有GCE操作的用户身份和操作详情,方便追踪排查
- 组权限管理:用Google Workspace组批量管理用户权限,新增/移除用户只需操作组,无需逐个修改IAM配置
内容的提问来源于stack exchange,提问作者Marctrix
相关产品推荐
相关产品推荐

