1

我正在尝试从 AWS EC2 或 Lambda 在 GCP 存储中签名 URL,我已经为权限生成了一个 JSON 文件,提供了我的 AWS 账户 ID 和授予 EC2 或 Lambda 的角色。即使拥有存储管理员或所有者权限,当我调用签名 URL 时,我也会得到:Error: The caller does not have permission.

我使用了 GCP 文档提供的代码。

const {Storage} = require('@google-cloud/storage');
const storage = new Storage(); 
const options = {
  version: 'v4',
  action: 'read',
  expires: Date.now() + 15 * 60 * 1000, // 15 minutes
};
 // Get a v4 signed URL for reading the file
 const [url] = await storage
 .bucket(bucketName)
 .file(fileName)
 .getSignedUrl(options);

谁能告诉我我错过了什么?怎么了?似乎是专业人士

*** 更新。

我正在创建一个服务帐户,将此服务帐户存储管理员授予我的项目,然后创建拉入Workload Identity Pools,设置 AWS 和我的 AWS 帐户 ID,然后通过我的 AWS 身份匹配角色授予访问权限,下载 JSON,并放置环境变量- GOOGLE_APPLICATION_CREDENTIALS- 我的 JSON 文件的路径和GOOGLE_CLOUD_PROJECT- 我的项目 ID。如何正确加载该clientLibraryConfig.json文件以运行我需要的功能?

更新** 2

我的 clientLibraryConfig JSON 有以下内容..

{
  "type": "external_account",
  "audience": "..",
  "subject_token_type": "..",
  "service_account_impersonation_url": "..",
  "token_url": "..",
  "credential_source": {
    "environment_id": "aws1",
    "region_url": "..",
    "url": "..",
    "regional_cred_verification_url": ".."
  }
}

如何从此配置文件在节点 js SDK 中生成访问令牌以从 AWS ec2 访问 GCP 存储?

4

1 回答 1

1

您必须为 IAM 服务账户设置以下权限:

  • Storage Object Creator:用于创建签名 URL。
  • 服务帐户令牌创建者角色:此角色允许模拟服务帐户以创建 OAuth2 访问令牌、签署 Blob 或签署 JWT。

此外,您可以尝试在 GCP 中本地运行以使用服务帐户对 URL 进行签名。

  1. 您可以将现有私钥用于服务帐户。密钥可以是 JSON 或 PKCS12 格式。

  2. 使用该命令gsutil signurl并传递上一步中私钥的路径以及存储桶和对象的名称。

例如,如果您使用存储在 Desktop 文件夹中的密钥,则以下命令将生成一个签名 URL,供用户查看对象 cat.jpegfor 10 分钟。

gsutil signurl -d 10m Desktop/private-key.json gs://example-bucket/cat.jpeg

如果成功,响应应如下所示:

URL    HTTP Method    Expiration    Signed URL
gs://example-bucket/cat.jpeg GET 2018-10-26 15:19:52 https://storage.googleapis.
com/example-bucket/cat.jpeg?x-goog-signature=2d2a6f5055eb004b8690b9479883292ae74
50cdc15f17d7f99bc49b916f9e7429106ed7e5858ae6b4ab0bbbdb1a8ccc364dad3a0da2caebd308
87a70c5b2569d089ceb8afbde3eed4dff5116f0db5483998c175980991fe899fbd2cd8cb813b0016
5e8d56e0a8aa7b3d7a12ee1baa8400611040f05b50a1a8eab5ba223fe5375747748de950ec7a4dc5
0f8382a6ffd49941c42498d7daa703d9a414d4475154d0e7edaa92d4f2507d92c1f7e811a7cab64d
f68b5df4857589259d8d0bdb5dc752bdf07bd162d98ff2924f2e4a26fa6b3cede73ad5333c47d146
a21c2ab2d97115986a12c28ff37346d6c2ca83e5618ec8ad95632710b489b75c35697d781c38e&
x-goog-algorithm=GOOG4-RSA-SHA256&x-goog-credential=example%40example-project.
iam.gserviceaccount.com%2F20181026%2Fus%2Fstorage%2Fgoog4_request&x-goog-date=
20201026T211942Z&x-goog-expires=3600&x-goog-signedheaders=host

签名 URL 是以https://storage.googleapis.com开头的字符串,它可能跨越多行。任何人都可以在指定的时间范围内(在本例中为 10 分钟)使用 URL 访问相关资源(在本例中为 cat.jpeg)。因此,如果这在本地有效,那么您可以开始配置 Workload Identity Federation 来模拟您的服务帐户。在此链接中,您将找到部署它的指南。

要使用您的 Workload Identity Federation 从 AWS 访问资源,您需要查看是否已配置以下要求:

  • 工作负载身份池已创建。

  • AWS 已作为身份提供者添加到工作负载身份池中(Google 组织策略需要允许来自 AWS 的联合)。

  • 模拟服务帐户的权限已授予外部帐户。

我将添加本指南以配置 Workload Identity Federation。

完成上述要求后,您将需要生成服务帐户凭据,该文件将仅包含非敏感元数据,以指导库如何检索外部​​主题令牌并将它们交换为服务帐户令牌,正如您提到的该文件可以是 config.json 并且可以运行以下命令生成:

# Generate an AWS configuration file.
gcloud iam workload-identity-pools create-cred-config \
    projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$POOL_ID/providers/$AWS_PROVIDER_ID \
    --service-account $SERVICE_ACCOUNT_EMAIL \
    --aws \
    --output-file /path/to/generated/config.json

需要替换以下变量的地方:

  • $PROJECT_NUMBER:Google Cloud 项目编号。
  • $POOL_ID:工作负载身份池 ID。
  • $AWS_PROVIDER_ID:AWS 提供商 ID。

  • $SERVICE_ACCOUNT_EMAIL:要模拟的服务帐户的电子邮件。

为您的外部身份生成 JSON 凭证配置文件后,您可以将路径存储在 GOOGLE_APPLICATION_CREDENTIALS环境变量中。

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/config.json

因此,有了这个,库可以自动选择正确的客户端类型并从配置文件中初始化凭证。请注意,在 Node.js 中使用具有应用程序默认凭据的外部身份时,服务帐户也需要角色/浏览器,或者您可以传递项目 ID 以避免需要将角色/浏览器授予服务帐户,如波纹管代码:

async function main() {
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/cloud-platform'
  // Pass the project ID explicitly to avoid the need to grant `roles/browser` to the service account
  // or enable Cloud Resource Manager API on the project.
  projectId: 'CLOUD_RESOURCE_PROJECT_ID',
  });
  const client = await auth.getClient();
  const projectId = await auth.getProjectId();
  // List all buckets in a project.
  const url = `https://storage.googleapis.com/storage/v1/b?project=${projectId}`;
  const res = await client.request({ url });
  console.log(res.data);
}
于 2022-02-04T19:53:26.793 回答