引言:薅羊毛薅出的“麻烦”

作为一名开发者,想必大家对各大云厂商的新手大礼包都不陌生。最近,我也顺手薅到了 Google Cloud Platform (GCP) 的 300 美元赠金。看着账户里的余额,我的第一反应就是:赶紧去试试 Google 最新的 Vertex AI 大模型!

在我的设想中,接下来的流程应该是这样的:

  1. 打开控制台。
  2. 找到“生成 API Key”。
  3. 复制一段字符串,扔进代码里。
  4. 跑通,下班!

毕竟,在使用 OpenAI 或各种 SaaS 服务时,这套流程我已经闭着眼睛都能走完。然而,当我在 GCP 的控制台里一通翻找后,却发现事情并没有这么简单。

GCP 并没有直接扔给我一个简单的字符串,而是要求我去配置一个叫做 “服务账号 (Service Account)” 的东西,给它分配 Vertex AI User 的权限,最后……它给了我一个长长的 JSON 格式的私钥文件

这让我不禁思考:为什么 GCP 非要搞得这么复杂?一个简单的 API Key 难道不好吗?

这篇博客,我想和大家分享一下我在配置 Vertex AI 权限时的发现,以及这背后隐藏的现代云计算安全架构的演进趋势。


发现问题:API Key 的局限与服务账号的登场

在习惯了“一键生成 API Key”的爽快感后,面对 GCP 的 Service AccountJSON Key,我起初是有些抗拒的。但静下心来仔细研究后,我发现了 API Key 在企业级场景下的致命弱点。

API Key:方便,但脆弱

想象一下,API Key 就像是你家大门的物理钥匙:

  • 认钥不认人: 只要拿到了钥匙,任何人都能开门。API Key 也是如此,它通常只用于标识“这个请求属于哪个项目(以便计费)”,而无法精确到“谁”在发起请求。
  • 牵一发而动全身: 如果这把钥匙不小心泄露(比如误传到了 GitHub),黑客就能毫无阻碍地调用你项目下所有允许使用该 Key 的服务。在云时代,这可能意味着瞬间产生巨额账单。
  • 缺乏粒度: 你很难用一把物理钥匙实现“只能进客厅,不能进卧室”的限制。

Service Account:代表“机器”的合法身份

GCP 给出的解决方案是:不要用物理钥匙,我们要发“工作牌”。

服务账号 (Service Account) 的本质是一个特殊的“机器用户”。它代表了一个真实的身份实体,只不过这个实体不是坐在电脑前的你,而是你的应用程序、虚拟机或自动化脚本。

在配置 Vertex AI 时,我执行了类似这样的授权操作(或者在控制台点选):

gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:my-bot@my-project.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"

这行命令的意义在于:我把 Vertex AI User 这个角色,授予了 my-bot 这个“机器员工”。这就将应用的权限纳入了统一的 IAM(身份和访问控制)体系,实现了 最小权限原则 (Least Privilege) 。即使 my-bot 的凭证泄露,攻击者也只能调用 Vertex AI,而动不了我数据库里的数据。


深入分析:那个复杂的 JSON 文件到底在干嘛?

好,我接受了服务账号的概念,但那个 JSON 文件又是怎么回事?为什么不直接把密码传给 Google 验证?

打开那个 JSON 文件,你会看到类似这样的结构(核心是 private_key):

{
  "type": "service_account",
  "project_id": "my-project",
  "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
  "client_email": "my-bot@...gserviceaccount.com"
}

这正是 GCP 安全设计的核心:基于非对称加密和动态 Token 的 OAuth 2.0 机制

其实,当我用 Python SDK (google-cloud-aiplatform) 调用大模型时,这段长长的私钥从未在网络上传输过! 它的工作流程是这样的:

  1. 本地签名: 我的本地代码读取 JSON 文件,用里面的 private_key 对自己的身份信息进行加密签名,生成一个 JWT(JSON Web Token)。
  2. 获取短期“通行证”: 代码将这个 JWT 发送给 Google 的认证服务器。Google 用公钥验证签名无误后,返回一个短期有效的 Access Token(通常寿命只有 1 小时)。
  3. 调用服务: 拿着这个临时的 Access Token,代码才真正去调用 Vertex AI 的接口。

这种设计的优势显而易见:

  1. 私钥不走网络,降低被拦截风险。
  2. 短期 Token 即使被盗,很快也会自动失效。
  3. 密码学签名提供了比静态字符串高得多的安全保证。

总结升华:未来的趋势是“无密钥化”

经历了从抱怨“太麻烦”到理解“真安全”的过程,我深刻意识到,传统的、长期的“静态密钥(API Key)”正在被淘汰。

“身份驱动、动态授权” 才是未来企业级云服务(包括 AI 基础设施)的必然趋势。

  1. 凭证生命周期的极度缩短: 1 小时的有效期可能还是太长,未来的凭证甚至会做到“单次请求有效”。
  2. 零信任架构 (Zero Trust) 的普及: 系统不再信任任何网络环境,只信任经过加密验证的“身份”。你的请求是否安全,不光看密码对不对,还要结合上下文(请求时间、IP 地址、设备状态等)进行动态评估。
  3. 最终目标:无密钥化。 事实上,如果你的代码是运行在 GCP 的虚拟机(GCE)或云函数上,你根本不需要下载那个 JSON 文件。底层服务会自动为你分配短期的 Access Token(应用程序默认凭据 ADC)。在跨云平台场景下(比如在 AWS 上调用 GCP),现在也有了 Workload Identity Federation 这样的技术,实现两边云厂商的“互信”,彻底消灭跨环境传输密钥的需求。

结语

为了用上这 300 刀的羊毛,我多花了一个小时研究 GCP 的 IAM 权限模型。但我认为这是值得的。

虽然在做个人的小 Demo 时,写一串 API Key 确实方便快捷。但如果我们要构建生产级别的、可扩展的 AI 应用,理解并拥抱这种基于身份的动态授权机制,将是我们必须要跨越的技术门槛。

毕竟,在享受大模型带来的巨大能力的同时,我们也得有能力拴住这匹狂奔的野马。

创建密钥Json文件相关代码

# ==========================================
# 1. 动态获取并设置基础环境变量
# ==========================================

# 获取当前 gcloud 登录的账号邮箱
USER_EMAIL=$(gcloud config get-value core/account)
echo "当前登录账号: $USER_EMAIL"

# 获取当前选定的项目 ID
PROJECT_ID=$(gcloud config get-value core/project)
echo "当前项目 ID: $PROJECT_ID"

# 动态获取组织 ID (提取列表中的第一个组织 ID)
# 注意:个人免费版默认没有组织架构,如果有组织此命令才有效
ORG_ID=$(gcloud organizations list --format="value(ID)" --limit=1)

# 定义你要使用的服务账号前缀 (可自行修改)
SA_NAME="vertex-express"
# 自动拼接出完整的服务账号邮箱地址
SA_EMAIL="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"


# ==========================================
# 2. 赋予当前账号相应的管理员权限
# ==========================================

# 给你自己账号 -> 项目所有者(最高权限)
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="user:$USER_EMAIL" \
    --role="roles/owner"

# 给你自己账号 -> 组织策略管理员 
# (增加了一个判断,只有在你拥有组织架构时才执行,避免在个人账号下报错)
if [ -n "$ORG_ID" ]; then
    gcloud organizations add-iam-policy-binding $ORG_ID \
        --member="user:$USER_EMAIL" \
        --role="roles/orgpolicy.policyAdmin"
else
    echo "未检测到组织结构,跳过组织级别的授权。"
fi


# ==========================================
# 3. 组织策略与 API 配置
# ==========================================

# 解除禁止创建服务账号密钥 (直接在项目级别覆盖策略)
gcloud resource-manager org-policies disable-enforce iam.disableServiceAccountKeyCreation \
    --project=$PROJECT_ID

# 启用 Vertex AI API
gcloud services enable aiplatform.googleapis.com --project=$PROJECT_ID


# ==========================================
# 4. 服务账号的创建与授权
# ==========================================

# 检查服务账号是否存在,如果不存在则自动创建
if ! gcloud iam service-accounts list --project=$PROJECT_ID --format="value(email)" | grep -q "^$SA_EMAIL$"; then
    echo "未找到对应的服务账号,正在创建: $SA_NAME..."
    gcloud iam service-accounts create $SA_NAME \
        --display-name="Vertex AI Express Service Account" \
        --project=$PROJECT_ID
fi

# 查看项目里所有服务账号 (供确认)
gcloud iam service-accounts list --project=$PROJECT_ID

# 给该服务账号授权 Vertex AI User 角色
gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member="serviceAccount:$SA_EMAIL" \
    --role="roles/aiplatform.user"


# ==========================================
# 5. 生成并管理服务账号密钥
# ==========================================

# 定义密钥下载后保存的本地路径 (保存在当前用户的主目录下)
KEY_FILE="$HOME/vertex-key.json"

# 创建密钥并下载到指定路径
echo "正在生成服务账号密钥..."
gcloud iam service-accounts keys create $KEY_FILE \
    --iam-account=$SA_EMAIL \
    --project=$PROJECT_ID

# 查看该服务账号下已创建的密钥(验证是否生成成功)
gcloud iam service-accounts keys list \
    --iam-account=$SA_EMAIL \
    --project=$PROJECT_ID

echo "✅ 配置流程全部完成!凭证密钥已成功保存至: $KEY_FILE"

创建完成后,直接在右上方3个点点击,然后点击下载,在原始路径上追加路径/vertex-key.json,下载出来的文件即可上传到New API的vertex ai渠道使用

Leave a comment