常见问题解答和问题排查

Cloud Asset Inventory 是否为全球服务?

可以。Cloud Asset API 不依赖于位置。它具有一个全球端点,该端点用于传送 Cloud Asset Inventory 中所有受支持的区域和全球资产的元数据。Cloud Asset API 可以在任何可用区中访问。

Cloud Asset Inventory 提供何种数据一致性?

Cloud Asset Inventory 提供当前数据的最终一致性,以及历史数据的尽力一致性。尽管在实践中概率很低,但 Cloud Asset Inventory 过去仍然可能会遗漏某些资产更新。

为什么我无权使用 Cloud Asset API?

如果您无权导出资产或获取组织、项目或文件夹的历史记录,则系统会返回错误。

例如,若您不具备权限,则运行以下命令:

curl -X POST \
     -H "X-Goog-User-Project: BILLING_PROJECT_ID" \
     -H "Authorization: Bearer $(gcloud auth print-access-token)" \
     -H "Content-Type: application/json" \
     -d '{
          "outputConfig": {
            "gcsDestination": {
              "uri": "gs://BUCKET_NAME/FILENAME"
            }
          }
         }' \
         https://cloudasset.googleapis.com/v1/projects/PROJECT_ID:exportAssets

返回以下错误:

{
  "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.DebugInfo",
        "detail": "[ORIGINAL ERROR] generic::permission_denied: Request
        denied by Cloud IAM."
      }
    ]
  }
}

要解决该问题,请向项目、文件夹或组织管理员请求访问权限。根据您尝试导出或获取历史记录的资产,您需要以下角色之一或其他包含所需 Cloud Asset API 权限的角色:

  • cloudasset.viewer

  • cloudasset.owner

如需详细了解角色和权限,请参阅了解角色

如需详细了解 Cloud Asset API 的访问权限控制选项,请参阅访问权限控制

为什么我的导出内容返回权限遭拒错误?

除非您另行指定,否则 Cloud Asset Inventory 将使用活跃项目中的默认 Cloud Asset Inventory 服务帐号来管理 Pub/Sub 主题、Cloud Storage 存储分区和 BigQuery 表等资源。当您首次从项目调用 Cloud Asset Inventory API 时,系统会创建此服务帐号。默认情况下,它有权管理这些资源,前提是这些资源位于同一项目中。

在以下情况下,您可能会收到权限遭拒错误:

  • 使用 REST API 时,该 API 不会设置活跃项目,因此 Cloud Asset Inventory 不知道要使用哪个服务帐号。

  • 通过 Pub/Sub 主题、Cloud Storage 存储桶或 BigQuery 表所在的项目之外的其他项目使用 gcloud CLI 时。这意味着系统将使用活跃项目的默认 Cloud Asset Inventory 服务帐号执行任务(如果存在),并且可能无权写入其他项目的资源。

为确保在发出导出到 Pub/Sub 主题、Cloud Storage 存储分区或 BigQuery 表的请求时使用正确的服务帐号,您可以指定包含正确默认 Cloud Asset Inventory 服务帐号的项目 ID。如果要从一个项目导出到另一个项目,您还需要向服务帐号授予特定角色

gcloud

对于 gcloud CLI,将 --billing-project 标志添加到命令中,以指定包含正确服务帐号的项目 ID:

--billing-project=BILLING_PROJECT_ID

或者,您也可以在使用 gcloud CLI 运行命令之前设置结算项目。首先,检查结算项目是否与核心项目不同:

gcloud config list

然后,根据需要设置结算项目:

gcloud config set billing/quota_project BILLING_PROJECT_ID

请提供以下值:

  • BILLING_PROJECT_ID:已启用 Cloud Asset Inventory API 的项目 ID,以及有权管理您的目标 Pub/Sub 主题、Cloud Storage 存储桶或 BigQuery 表的服务帐号。

REST

对于 REST API,请添加 X-Goog-User-Project 标头以指定包含正确服务帐号的项目 ID。使用 curl 时,您可以通过 -H 标志设置标头:

-H "X-Goog-User-Project: BILLING_PROJECT_ID"

请提供以下值:

  • BILLING_PROJECT_ID:已启用 Cloud Asset Inventory API 的项目 ID,以及有权管理您的目标 Pub/Sub 主题、Cloud Storage 存储桶或 BigQuery 表的服务帐号。

将资产元数据从一个项目导出到另一个项目

如需将资产元数据从一个项目 PROJECT_A 导出到另一个项目 PROJECT_B,您必须向 PROJECT_A 中的默认 Cloud Asset Inventory 服务帐号授予对 PROJECT_B 中资源的访问权限。这可实现两件事:

  • 您可以将 PROJECT_A 中的资产元数据导出到位于 PROJECT_B 的 Pub/Sub 主题、Cloud Storage 存储桶或 BigQuery 表中。

  • 您可以使用 PROJECT_A 将资产元数据从 PROJECT_B 导出到位于 PROJECT_B 的 Pub/Sub 主题、Cloud Storage 存储桶或 BigQuery 表。

如需将资产元数据从一个项目导出到另一个项目,请按照以下说明操作:

  1. 确保在要运行请求的项目 (PROJECT_A) 中启用 Cloud Asset Inventory API

  2. PROJECT_A 中至少调用一次 Cloud Asset Inventory API,以创建默认的 Cloud Asset Inventory 服务帐号。或者,您也可以手动创建:

    gcloud beta services identity create \
        --service=cloudasset.googleapis.com \
        --project=PROJECT_A_ID
    gcloud projects add-iam-policy-binding PROJECT_A_ID \
        --member=serviceAccount:service-PROJECT_A_NUMBER@gcp-sa-cloudasset.iam.gserviceaccount.com \
        --role=roles/cloudasset.serviceAgent
    

    如何查找 Google Cloud 项目编号

    控制台

    如需查找 Google Cloud 项目编号,请完成以下步骤:

    1. 转到 Google Cloud 控制台中的信息中心页面。

      前往信息中心

    2. 点击菜单栏中的切换器框。
    3. 请选择:框中选择您的组织,然后搜索项目名称。
    4. 点击项目名称以切换到该项目。项目信息卡片中会显示项目编号。

    gcloud CLI

    您可以使用以下命令检索 Google Cloud 项目编号:

    gcloud projects describe PROJECT_ID --format="value(projectNumber)"

  3. 向服务帐号授予正确的权限。

    • 如需通过 Pub/Sub 发布到 Feed,请针对该主题向服务帐号授予 roles/pubsub.publisher 角色:

      gcloud pubsub topics add-iam-policy-binding projects/PROJECT_B_ID/topics/TOPIC_ID \
          --member=serviceAccount:service-PROJECT_A_NUMBER@gcp-sa-cloudasset.iam.gserviceaccount.com \
          --role=roles/pubsub.publisher
      
    • 如需写入 Cloud Storage 存储桶,请向该存储桶上的服务帐号授予 roles/storage.admin 角色:

      gsutil iam ch \
        serviceAccount:service-PROJECT_A_NUMBER@gcp-sa-cloudasset.iam.gserviceaccount.com:objectCreator \
        gs://BUCKET_NAME
      
    • 如需写入 BigQuery 表,请向项目的服务帐号授予 roles/bigquery.dataEditorroles/bigquery.user 角色:

      gcloud projects add-iam-policy-binding PROJECT_B_ID \
          --member=serviceAccount:service-PROJECT_A_NUMBER@gcp-sa-cloudasset.iam.gserviceaccount.com \
          --role=roles/bigquery.user
      gcloud projects add-iam-policy-binding PROJECT_B_ID \
          --member=serviceAccount:service-PROJECT_A_NUMBER@gcp-sa-cloudasset.iam.gserviceaccount.com \
          --role=roles/bigquery.dataEditor
      

发出 Cloud Asset Inventory 请求时,请务必指定 PROJECT_A 作为您要使用的项目。如需为 gcloud CLI 执行此操作,请将 --billing-project 标志设置为 PROJECT_A_ID。对于 REST,请将 X-Goog-User-Project 标头设置为 PROJECT_A_ID

为什么 Cloud Asset API 结果已过时?

系统会尽力确保 Cloud Asset API 中数据的新鲜度。虽然几乎所有资产更新在几分钟内即可供客户端使用,但在极少数情况下,Cloud Asset API 方法的结果可能不包含最新的资产更新。

为什么运行 ExportAssets 后输出临时文件?

ExportAssets 操作可能会在输出文件夹中创建临时文件。操作正在进行时,请勿移除这些临时文件。操作完成后,临时文件会自动移除。

如果临时文件仍然存在,则您可以在 ExportAssets 操作完成后,安全地移除这些临时文件。

为什么我的 Google Cloud CLI 或 Cloud Shell 凭据被拒绝?

如果从 Google Cloud CLI 或 Cloud Shell 将请求中的用户项目发送到 cloudasset.googleapis.com,您会收到如下错误消息:

Your application has authenticated using end user credentials from the
Google Cloud CLI or Cloud Shell which are not supported by the
cloudasset.googleapis.com. We recommend that most server applications
use service accounts instead. For more information about service accounts
and how to use them in your application, see
https://cloud.google.com/docs/authentication/.

如需解决此问题,请将用户项目设置为启用了 Cloud Asset API 的用户的项目 ID。这可以通过在 HTTP 请求中指定 HTTP 标头 X-Goog-User-Project 来实现。

如果您使用的是 curl,可以通过添加以下参数来完成此操作:

-H "X-Goog-User-Project: PROJECT_ID"

如果您使用的是 gcloud CLI,请指定 --billing-project PROJECT_ID 标志以及 gcloud asset 命令,或使用以下命令:

gcloud config set billing/quota_project PROJECT_ID

为什么同一资产具有不同的祖先实体?

在调用 Cloud Asset API 获取不同的元数据类型时(例如同一资产的 RESOURCE 元数据和 IAM POLICY 元数据),ancestors 字段可能会在内容类型之间不一致。这是因为每种内容类型都有不同的数据注入时间表,并且在提取过程完成之前,两者的数据注入时间表可能会不一致。请检查 update_time 字段,确保该素材资源包含最新信息。

如果不一致的情况持续超过 24 小时,请与我们联系

应以怎样的频率调用 ExportAssets API?

我们建议您按顺序针对同一项目、文件夹或组织调用 ExportAssets API;例如,在前一个调用完成后发出第二次调用。如需实时捕获资产更新,请考虑使用实时通知

接收到重复的资产更新

设置实时通知后,您可能会在 Pub/Sub 主题中收到重复的资源更新。这是由于 Pub/Sub 不保证至少传送一次,因此自动尝试重试传送所致。

为什么我没有收到项目删除通知?

关停项目后,您可以在 30 天内撤消操作。只有在项目被永久删除后,才会设置通知中的 deleted 字段。如需监控待删除的项目,您可以设置一个 Feed,其中包含项目的 lifecycleState 条件,例如 temporal_asset.asset.resource.data.lifecycleState == "DELETE_REQUESTED"

如何使用 SearchAllResources API 检索资源的 JSON 表示法?

默认情况下,如果未指定 read_maskSearchAllResources 会返回以下标准字段:

  • name

  • assetType

  • project

  • folders

  • organization

  • displayName

  • description

  • location

  • labels

  • networkTags

  • kmsKeys

  • createTime

  • updateTime

  • state

  • additionalAttributes

  • parentFullResourceName

  • parentAssetType

如果除了上面列出的字段以外,您还想检索资源元数据中的所有字段,则可以在搜索请求中指定 read_mask 标志(gcloud 中的 --read-mask)。

read_mask 是您要在结果中返回的字段列表(以英文逗号分隔)。某些字段过大(如 versionedResourcesattachedResources),因此默认情况下不包含在结果中。如需包含这些字段,可以在 read_mask 中指定它们;或使用 "*" 以包含所有可用字段read_mask 值的示例包括:"name,location""name,versionedResources""*"

下面是一个 gcloud 示例:

gcloud asset search-all-resources \
    --scope=organizations/123456 \
    --query="state=RUNNING" \
    --asset-types=compute.googleapis.com/Instance \
    --read-mask="name,versionedResources"