1. 简介
过去,在其他方法不可用或被认为不方便时,Google API 密钥用于访问 Google API。热门用例包括访问 Google 地图 API 和 Firebase 公开的 Google API。随着 AI 模型、Gemini 等 AI 智能体、AI Studio 和智能体开发套件等代理开发框架的推出,API 密钥已成为访问 Google 大语言模型的主要方法。
API 密钥提供的保护级别较低。虽然 Google Cloud 提供了多种方法来防止密钥被滥用,但拥有有效的 API 密钥即可访问 Google API,而无需进行任何额外的身份验证或授权验证。有关限制 API 密钥使用的方法,请参阅文档。Cloud 博客中有关保护 Gemini 和 Google API 密钥的帖子提供了有关 API 密钥维护的其他建议。在此 Codelab 中,您将实践这些建议。
您将执行的操作
- 查看在 Google Cloud 上创建新 API 密钥时强制执行的限制
- 编目您的所有 API 密钥,并找出未受安全保护的密钥
- 根据现有 API 密钥的使用情况强制执行限制
- 定义在出现异常使用情况时删除密钥的自动化流程
所需条件
- 新版网络浏览器(例如 Chrome)。
- Google 账号
2. 设置
本 Codelab 中的说明假定您在 Google Cloud 控制台的 Cloud Shell 中运行命令。如果您在本地环境中安装了 gcloud CLI,则可以在本地环境中运行这些命令。
虽然可以使用 Cloud 控制台界面完成这些步骤中的操作,但方法有所不同。此 Codelab 使用命令行界面来简化互动,并更轻松地与现代 AI 智能体(例如 Antigravity CLI)集成。
启动 Cloud Shell 终端
- 在新浏览器窗口中使用 https://console.cloud.google.com/ 打开 Google Cloud 控制台。建议使用 Chrome 以获得最佳用户体验。
- 在 Google Cloud 中登录您的 Google 账号。
- 点击 Google Cloud 控制台顶部的激活 Cloud Shell
。
如果显示,请在弹出的窗口中执行以下操作:- 继续完成 Cloud Shell 信息窗口中的设置。
- 授权 Cloud Shell 使用您的凭据进行 Google Cloud API 调用。
选择 Google Cloud 项目
打开 Cloud 控制台后,系统会验证您的身份,并且通常会显示一个项目选择器供您选择项目。项目 ID 是一个包含 6 到 30 个字符的序列,由小写字母、数字和短划线符号组成,例如 qwiklabs-gcp-04-3075fc9fd77f。Cloud Shell 终端会使用所选项目配置 gcloud CLI。您将看到类似于以下内容的输出:
Your Cloud Platform project in this session is set to qwiklabs-gcp-04-3075fc9fd77f
这意味着,您后续向 gcloud 发出的命令将使用项目 ID qwiklabs-gcp-04-3075fc9fd77f。
将项目 ID 设置为环境变量 PROJECT_ID。您可以使用以下命令查看所有项目的列表:
gcloud projects list
- 如果您想使用与
gcloud中配置的项目 ID 不同的项目 ID,请替换your-project-id并运行该命令。 例如:export PROJECT_ID="your-project-id"export PROJECT_ID="qwiklabs-gcp-04-3075fc9fd77f" - 如果您想使用所选项目 ID,请运行以下命令:
export PROJECT_ID=$(gcloud config get project)
3. 限制新的 API 密钥
过去,用户可以创建完全不受限制的 API 密钥。不受限制的密钥可用于调用创建该密钥的项目中启用的任何 Google API。虽然 Google Cloud 控制台会阻止用户创建不受限的密钥,但用户仍可以使用 gcloud CLI 或直接 API 调用来创建不受限的密钥。
以下步骤展示了如何创建受限 API 密钥,以限制其只能用于特定 API 和指定网站。
- 如需创建仅限用于 Google Map 地理定位 API 的新 API 密钥,请在 shell 终端中运行以下命令:
此命令会创建一个新的 API 密钥,该密钥只能用于调用 Google 地理定位服务。gcloud services api-keys create --key-id=restricted-api-key \ --display-name="restricted api key" \ --api-target=service=geolocation.googleapis.com \ --project=${PROJECT_ID} - 添加应用限制可提高密钥安全性。将密钥的使用范围限制为仅限网站
example.com中的所有路径。运行以下命令,将应用限制添加到密钥: 您可以不将密钥的使用范围限制为特定网站,而是使用gcloud services api-keys update restricted-api-key \ --location=global \ --allowed-referrers="example.com/*" \ --project=${PROJECT_ID}--allowed-application定义允许的 Android 应用或allowed-ips定义允许的 IP 地址。如需查看所有选项,请参阅完整的文档。
清理
除非您打算使用自己创建的 API 密钥,否则请将其删除:
gcloud services api-keys delete --key-id=restricted-api-key \
--project=${PROJECT_ID}
4. 编目 API 密钥
在此步骤中,您将使用 gcloud CLI 获取 API 密钥清单。生成的列表会显示您有权访问的所有有效(未删除)API 密钥。
- 运行以下命令可查看所有密钥名称、ID 和创建日期:
输出将显示密钥的人类可读名称、密钥 ID 和密钥创建日期。它类似于以下内容:gcloud services api-keys list --project=${PROJECT_ID} \ --format='value(displayName,name.basename(),createTime.date())'api key 1 api-key-1 2024-05-10T07:53:24 api key 2 api-key-2 2025-06-12T14:47:57
- 选择一个密钥 ID,然后粘贴以下命令以检查该密钥是否受到任何限制。将
your-key-id替换为所选密钥 ID 的值:gcloud services api-keys describe "your-key-id" --project=${PROJECT_ID}
输出(采用 YAML 格式)将在 restrictions 下包含一个限制列表。
createTime: '2024-05-10T07:53:24.986528Z'
displayName: api key 1
etag: W/"u1WuY41K2tPKUZd7cfLoKg=="
name: projects/123456789012/locations/global/keys/api-key-1
restrictions:
apiTargets:
- service: geolocation.googleapis.com
browserKeyRestrictions:
allowedReferrers:
- https://example.com/*
uid: 1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6
updateTime: '2024-05-10T07:53:24.071228Z'
请注意,如果密钥从未更新,则 createTime 和 updateTime 字段将具有相同的时间戳。
- 下载并运行该脚本,该脚本会遍历您的所有项目,并输出未设置限制的所有 API 密钥:
运行脚本后,您将看到如下格式的输出:curl -fsSL -o unrestricted_api_keys.sh \ "https://github.com/GoogleCloudPlatform/devrel-demos/blob/main/security/api-key-audit/unrestricted_api_keys.sh" chmod +x unrestricted_api_keys.sh ./unrestricted_api_keys.sh 您可以在 GitHub 上 devrel-demos 代码库的 Security 文件夹中找到此 Codelab 中使用的所有脚本。DISPLAY NAME KEY ID PROJECT ID CREATION DATE Key 1 1a2b3c4d-1234-abcd-1234-a1b2c3d4e5f6 my-project-1 2024-05-10T07:53:24.071228Z
5. 了解 API 密钥的使用情况
在此步骤中,您将查询 Google Cloud 指标,以帮助您了解哪些 API 是使用您的 API 密钥调用的。借助此信息,您可以查看密钥的当前使用情况,并根据实际信息为密钥应用 API 限制,而不是猜测。
- 使用您在上一步中使用的相同密钥 ID,或选择其他密钥 ID。在以下命令中,将
your-key-id替换为所选的密钥 ID:export KEY_UID=$( gcloud services api-keys describe "your-key-id" \ --format='value(uid)' \ --project=${PROJECT_ID}) - 将搜索范围设置为回溯一年的使用情况历史记录。如果您想查找更长或更短时间段内的信息,请将
365(天数)替换为其他正数。export DAYS=365 - 刷新应用默认凭据 (ADC),以直接调用 Cloud Monitoring API。运行以下命令,并按照终端中的说明操作:
gcloud auth application-default login - 运行以下命令,向 Cloud Monitoring API 发送服务使用情况指标数据请求:
curl -s -G -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
--data-urlencode "filter=metric.type=\"serviceruntime.googleapis.com/api/request_count\" AND resource.labels.credential_id=\"apikey:${KEY_UID}\"" \
--data-urlencode "interval.startTime=$(date -u -d "${DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)" \
--data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
"https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries" \
| jq -r '.timeSeries[]?.resource.labels.service' | sort -u
该命令会查询 serviceruntime/api/request_count 内置指标,以获取标签 credential_id 与所选 API 密钥唯一 ID 匹配的数据点。然后,它会检索 service 标签的值,并在消除重复项的同时打印这些值。
API 密钥安全加固
在此步骤中,您将使用之前步骤中收集的信息,根据使用情况信息更新 API 密钥的限制配置。
您将使用上一步中使用的同一 API 密钥。如有必要,请重新运行上一步中的说明,以确保已设置环境变量 PROJECT_ID、KEY_UID 和 DAYS。
- 运行以下命令,以检索使用 API 密钥调用的 Google API 的列表:
SERVICES=$(curl -s -G -H "Authorization: Bearer $(gcloud auth application-default print-access-token)"
–data-urlencode "filter=metric.type="serviceruntime.googleapis.com/api/request_count" AND resource.labels.credential_id="apikey:${KEY_UID}""
–data-urlencode "interval.startTime=$(date -u -d "${DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)"
–data-urlencode "interval.endTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
"https://monitoring.googleapis.com/v3/projects/${PROJECT_ID}/timeSeries"
| jq -r ‘.timeSeries[]?.resource.labels.service' | sort -u)
1. Build the list of arguments to restrict the API usage for the API key based
on the retrieved list.
```shell
API_TARGET_ARGS=()
for SERVICE in $SERVICES; do
API_TARGET_ARGS+=("--api-target=service=${SERVICE}")
done
- 替换非空列表的受限 API 列表:
if [ ${#API_TARGET_ARGS[@]} -gt 0 ]; then gcloud services api-keys update "projects/${PROJECT_ID}/locations/global/keys/${KEY_UID}" \ ${API_TARGET_ARGS} fi
6. 定义异常使用情况检测
之前的步骤介绍了如何探索和强化 API 密钥。此步骤介绍了如何借助监控提醒自动响应密钥使用量的意外高峰。
以下说明将创建一个提醒,当使用 API 密钥的 API 调用速率比过去 5 分钟增加 10% 以上时,系统会触发该提醒。系统已配置提醒,以触发 Cloud Build 脚本来删除 API 密钥,防止进一步使用。您可以在接下来的 30 天内恢复密钥。如需了解如何恢复密钥,请参阅文档。
这些说明会重复使用您在前面步骤中使用的变量 PROJECT_ID 和 KEY_UID。如果您想选择其他密钥和/或项目,请按照“设置和发现 API 密钥的使用情况”步骤中的说明,为这些变量设置新值。
- 运行以下脚本以创建提醒政策文件:
提醒政策使用以下 PromQL 过滤条件来触发提醒:cat <<EOF > alert_policy.json { "displayName": "Credential API Request Count Increase Alert (Project: ${PROJECT_ID})", "combiner": "OR", "conditions": [ { "displayName": "API Request Count Increase > 10% in 5m with Min Volume", "conditionPrometheusQueryLanguage": { "query": "(sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) / (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m] offset 5m)) or on() vector(1)) > 1.10) and (sum(increase(serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\\"apikey:${KEY_UID}\\"}[5m])) > 50)", "duration": "0s", "evaluationInterval": "60s" } } ], "enabled": true } EOF 它会计算增长率,并将其与之前的窗口进行比较。只有在实际支出比目标支出高出 10% 以上时,才会触发提醒。为避免在调用总数可忽略不计时触发提醒,该提醒设置了触发条件,即窗口中的 API 调用次数超过 50 次。为了避免在前 5 分钟的速率为 0 时出现(sum( increase( serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m]) ) / (sum( increase( serviceruntime_googleapis_com:api_request_count{metric_label_credential_id="API_KEY_UID"}[5m] offset 5m) ) or on() vector(1)) > 1.10) and (sum( increase( serviceruntime_googleapis_com:api_request_count{metric_label_credential_id=\"YOUR_CREDENTIAL_ID_HERE\"}[5m])) > 50)NaN(除以零)计算,如果前一个时间段的速率为零,则用 1 替换分母。您可以更改提醒参数,例如时间段长度 (5m)、最小阈值 (50) 或 10% 增幅阈值 (1.10)。其他政策参数定义了达到条件后应触发提醒 (duration),以及应每 60 秒探测一次条件 (evaluationInterval)。 - 运行以下命令,创建一个将用于发布提醒通知的 PubSub 主题:
gcloud pubsub topics create api-key-alert-notifications --project=$PROJECT_ID - 运行以下命令,为使用 PubSub 的提醒创建通知渠道。
您将在“清理”步骤中使用CHANNEL_NAME=$(gcloud beta monitoring channels create \ --display-name="Pub/Sub Alert Channel" \ --type="pubsub" \ --channel-labels="topic=projects/$PROJECT_ID/topics/api-key-alert-notifications" \ --format='value(name)' \ --project=$PROJECT_ID)CHANNEL_NAME环境变量。 - 运行以下命令以创建新的监控提醒:
gcloud monitoring policies create --policy-from-file=alert_policy.json \ --project=$PROJECT_ID - 运行以下命令,以授予 Cloud Build 服务删除项目中的 API 密钥的权限。
可以限制PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)") gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \ --role="roles/apikeys.admin"apikeys.admin角色仅能操作 API 密钥的特定实例。如需了解详情,请参阅 IAM 条件。 - 运行以下脚本以创建用于删除 API 密钥的 Cloud Build 构建触发器。
cat <<EOF > trigger_config.yaml name: "delete-compromised-api-key" description: "Triggered by Pub/Sub alert to automatically delete the leaking API Key" pubsubConfig: topic: "projects/${PROJECT_ID}/topics/api-key-alert-notifications" build: steps: - name: "gcr.io/google.com/cloudsdktool/cloud-sdk:slim" args: - "gcloud" - "services" - "api-keys" - "delete" - "${KEY_UID}" - "--quiet" EOF - 运行以下命令以创建新的监控提醒触发器:
gcloud builds triggers create pubsub \ --trigger-config=trigger_config.yaml \ --project=$PROJECT_ID
您现在可以删除提醒政策和 Cloud Build 构建触发器配置文件:
rm alert_policy.json trigger_config.yaml
或者,您也可以使用 Terraform 方案设置此自动化。从 Google Cloud DevRel 代码库中的 abnormal-usage-detection 文件夹下载 Terraform 文件。该方案接受项目 ID 和 API 密钥 UID 作为输入参数,并设置您在此步骤中看到的资源和配置。
7. 清理
为避免您的 Google Cloud 账号产生意外费用,请务必删除本练习期间创建的 Pub/Sub 主题、Cloud Build 构建触发器和提醒政策。
运行以下命令以删除您创建的所有资源:
gcloud builds triggers delete delete-compromised-api-key \
--project=$PROJECT_ID
gcloud beta monitoring channels delete $CHANNEL_NAME \
--project=$PROJECT_ID \
--quiet
gcloud pubsub topics delete api-key-alert-notifications \
--project=$PROJECT_ID
gcloud projects remove-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/apikeys.admin"
8. 总结
在此 Codelab 中,您为 Google Cloud API 密钥实现了一个强大的端到端安全和自动化框架:
- 强化默认配置:您创建并限制了 API 密钥,以将访问权限仅限于必要的 API 和受信任的平台(例如特定的 HTTP 引荐来源网址)。
- 审核了密钥清单:您扫描了项目环境,以检测并隔离存在直接安全风险的不受限密钥。
- 分析后的使用情况数据:您以编程方式查询 Cloud Monitoring 指标数据,以分析历史密钥使用情况,从而能够根据经过验证的使用情况足迹来限制密钥。
- 自动威胁缓解:您通过将 Cloud Monitoring 提醒政策与 Pub/Sub 主题和 Cloud Build 触发器相关联,建立了一个被动“断路器”,从而可以在异常流量高峰期间自动删除遭入侵的密钥。
后续步骤
- 对所有 API 密钥施加限制:使用您在本实验中学到的知识来检测所有部分受限或不受限的 API 密钥,并应用 API 和客户端限制,
- 为 API 密钥设置“断路器”:通过设置在用量突然增加时自动删除密钥,进一步保护您的 API 密钥免遭意外使用。使用实验中所示的
gcloud命令或 Terraform。考虑利用 IAM 条件来收紧权限 - 探索监控提醒:详细了解如何使用 Google Cloud Monitoring 服务设置提醒。
- 详细了解 Google Cloud 提供的访问权限控制功能:查看访问权限边界政策和访问权限变更传播。