配置对来源的访问权限:Cloud Storage

Storage Transfer Service 使用 Google 管理的服务账号(称为服务代理)从 Cloud Storage 源存储桶移动数据。首次调用 googleServiceAccounts.get 时系统会创建此服务代理。

源存储桶不需要与服务代理属于同一项目。无论存储桶位于哪个项目中,步骤都是相同的。

用户权限

要向服务代理授予所需的权限,您必须拥有来源存储桶的相关权限:

  • storage.buckets.getIamPolicy
  • storage.buckets.setIamPolicy

Storage Legacy Bucket Owner 角色 (roles/storage.legacyBucketOwner) 或 Storage Admin 角色 (roles/storage.admin) 可提供所需的权限。

在 Google Cloud 控制台中自动授予权限

如果您使用 Google Cloud 控制台创建转移作业,并且拥有用户权限中列出的权限,则系统会自动向服务代理授予来源存储桶的所需权限。

您可以跳过此页面上的步骤,直接前往创建转移作业部分。

所需权限

该服务代理必须具有针对源存储桶的以下权限:

权限 说明
storage.buckets.get 允许服务代理获取存储桶的位置。
storage.objects.list 允许服务代理列出存储桶中的对象。
storage.objects.get 允许服务代理读取存储桶中的对象。
storage.objects.create

允许服务代理在存储桶中创建对象。如果要转移到文件系统,则必须拥有此权限。

Storage Transfer Service 会在源存储桶中创建并填充两个文件夹:cloud-ingest/(包含文件系统信息)和 storage-transfer/(包含转移日志)。

storage.objects.delete 允许服务代理删除存储桶中的对象。如果您将 deleteObjectsFromSourceAfterTransfer 设置为 true,则必须拥有此权限。

以下预定义角色可共同授予所需的权限:

  • 以下角色之一:
    • Storage Object Viewer (roles/storage.objectViewer)(如果要转移到其他 Cloud Storage 存储桶)。
    • Storage Object Creator (roles/storage.objectCreator)(如果要转移到文件系统)。
  • 另外还需要以下角色之一:
    • Storage Legacy Bucket Writer (roles/storage.legacyBucketWriter)(如果需要对象删除权限)。
    • Storage Legacy Bucket Reader (roles/storage.legacyBucketReader)(如果不需要对象删除权限)。

标记为 legacy 角色的任何 Cloud Storage 角色只能在存储桶级层授予。

如需查看 Cloud Storage 角色及其权限的完整列表,请参阅 IAM 角色

对于设置了 ACL_PRESERVE 的对象 ACL,源对象还需要 ACL_PRESERVE 角色 (roles/storage.legacyObjectOwner)。对于 ACL_PRESERVE,手动添加具有 Storage Legacy Object Owner 角色的服务账号,以向源对象授予 storage.objects.getIamPolicy 权限。

授予所需权限

如需向服务代理授予所需的权限,请按照以下步骤操作。

找到服务代理的电子邮件地址

  1. 前往 googleServiceAccounts.get 参考页面

    系统会打开标题为试用此方法的交互式面板。

  2. 在该面板的请求参数下,输入您的项目 ID。您在此处指定的项目必须是您用于管理 Storage Transfer Service 的项目,该项目可能与来源存储桶的项目不同。

  3. 点击执行

    服务代理的电子邮件地址会作为 accountEmail 的值返回。复制此值。

    服务代理的电子邮件地址采用 project-PROJECT_NUMBER@storage-transfer-service.iam.gserviceaccount.com 格式。

将服务代理添加到存储桶级层政策

控制台

  1. 在 Google Cloud 控制台中,进入 Cloud Storage 存储桶页面。

    进入“存储桶”

  2. 点击您要授予角色的主账号所属存储桶关联的存储桶溢出菜单 ()。

  3. 选择修改访问权限

  4. 点击 + 添加主账号按钮。

  5. 新建主账号字段中,输入您的服务代理的账号电子邮件地址。

  6. 选择角色下拉菜单中选择 Storage Object ViewerStorage Object Creator

  7. 点击添加其他角色

  8. 选择 Storage Legacy Bucket WriterStorage Legacy Bucket Reader

  9. 点击保存

gcloud

使用 gcloud storage buckets add-iam-policy-binding 命令:

gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
--member=serviceAccount:YOUR_AGENT_EMAIL --role=roles/storage.objectViewer
gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME \
--member=serviceAccount:YOUR_AGENT_EMAIL --role=roles/storage.legacyBucketReader

其中:

  • BUCKET_NAME 是您要为主账号授予对其访问权限的存储桶的名称。例如 my-bucket
  • YOUR_AGENT_EMAIL 是您在查找服务代理的电子邮件地址中复制的代理账号电子邮件地址。

代码示例

C++

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 如需了解详情,请参阅 Cloud Storage C++ API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

namespace gcs = ::google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& role, std::string const& member) {
  auto policy = client.GetNativeBucketIamPolicy(
      bucket_name, gcs::RequestedPolicyVersion(3));

  if (!policy) throw std::move(policy).status();

  policy->set_version(3);
  for (auto& binding : policy->bindings()) {
    if (binding.role() != role || binding.has_condition()) {
      continue;
    }
    auto& members = binding.members();
    if (std::find(members.begin(), members.end(), member) == members.end()) {
      members.emplace_back(member);
    }
  }

  auto updated = client.SetNativeBucketIamPolicy(bucket_name, *policy);
  if (!updated) throw std::move(updated).status();

  std::cout << "Updated IAM policy bucket " << bucket_name
            << ". The new policy is " << *updated << "\n";
}

C#

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 有关详情,请参阅 Cloud Storage C# API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


using Google.Apis.Storage.v1.Data;
using Google.Cloud.Storage.V1;
using System;
using System.Collections.Generic;

public class AddBucketIamMemberSample
{
    public Policy AddBucketIamMember(
        string bucketName = "your-unique-bucket-name",
        string role = "roles/storage.objectViewer",
        string member = "serviceAccount:dev@iam.gserviceaccount.com")
    {
        var storage = StorageClient.Create();
        var policy = storage.GetBucketIamPolicy(bucketName, new GetBucketIamPolicyOptions
        {
            RequestedPolicyVersion = 3
        });
        // Set the policy schema version. For more information, please refer to https://cloud.google.com/iam/docs/policies#versions.
        policy.Version = 3;

        Policy.BindingsData bindingToAdd = new Policy.BindingsData
        {
            Role = role,
            Members = new List<string> { member }
        };

        policy.Bindings.Add(bindingToAdd);
        var bucketIamPolicy = storage.SetBucketIamPolicy(bucketName, policy);
        Console.WriteLine($"Added {member} with role {role} " + $"to {bucketName}");
        return bucketIamPolicy;
    }
}

Go

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 有关详情,请参阅 Cloud Storage Go API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

import (
	"context"
	"fmt"
	"io"
	"time"

	"cloud.google.com/go/iam"
	"cloud.google.com/go/storage"
)

// addBucketIAMMember adds the bucket IAM member to permission role.
func addBucketIAMMember(w io.Writer, bucketName string) error {
	// bucketName := "bucket-name"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %w", err)
	}
	defer client.Close()

	ctx, cancel := context.WithTimeout(ctx, time.Second*10)
	defer cancel()

	bucket := client.Bucket(bucketName)
	policy, err := bucket.IAM().Policy(ctx)
	if err != nil {
		return fmt.Errorf("Bucket(%q).IAM().Policy: %w", bucketName, err)
	}
	// Other valid prefixes are "serviceAccount:", "user:"
	// See the documentation for more values.
	// https://cloud.google.com/storage/docs/access-control/iam
	identity := "group:cloud-logs@google.com"
	var role iam.RoleName = "roles/storage.objectViewer"

	policy.Add(identity, role)
	if err := bucket.IAM().SetPolicy(ctx, policy); err != nil {
		return fmt.Errorf("Bucket(%q).IAM().SetPolicy: %w", bucketName, err)
	}
	// NOTE: It may be necessary to retry this operation if IAM policies are
	// being modified concurrently. SetPolicy will return an error if the policy
	// was modified since it was retrieved.
	fmt.Fprintf(w, "Added %v with role %v to %v\n", identity, role, bucketName)
	return nil
}

Java

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 有关详情,请参阅 Cloud Storage Java API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证


import com.google.cloud.Binding;
import com.google.cloud.Policy;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class AddBucketIamMember {
  /** Example of adding a member to the Bucket-level IAM */
  public static void addBucketIamMember(String projectId, String bucketName) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of your GCS bucket
    // String bucketName = "your-unique-bucket-name";

    // For more information please read:
    // https://cloud.google.com/storage/docs/access-control/iam
    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();

    Policy originalPolicy =
        storage.getIamPolicy(bucketName, Storage.BucketSourceOption.requestedPolicyVersion(3));

    String role = "roles/storage.objectViewer";
    String member = "group:example@google.com";

    // getBindingsList() returns an ImmutableList and copying over to an ArrayList so it's mutable.
    List<Binding> bindings = new ArrayList(originalPolicy.getBindingsList());

    // Create a new binding using role and member
    Binding.Builder newMemberBindingBuilder = Binding.newBuilder();
    newMemberBindingBuilder.setRole(role).setMembers(Arrays.asList(member));
    bindings.add(newMemberBindingBuilder.build());

    // Update policy to add member
    Policy.Builder updatedPolicyBuilder = originalPolicy.toBuilder();
    updatedPolicyBuilder.setBindings(bindings).setVersion(3);
    Policy updatedPolicy = storage.setIamPolicy(bucketName, updatedPolicyBuilder.build());

    System.out.printf("Added %s with role %s to %s\n", member, role, bucketName);
  }
}

Node.js

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 有关详情,请参阅 Cloud Storage Node.js API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// The ID of your GCS bucket
// const bucketName = 'your-unique-bucket-name';

// The role to grant
// const roleName = 'roles/storage.objectViewer';

// The members to grant the new role to
// const members = [
//   'user:jdoe@example.com',
//   'group:admins@example.com',
// ];

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

async function addBucketIamMember() {
  // Get a reference to a Google Cloud Storage bucket
  const bucket = storage.bucket(bucketName);

  // For more information please read:
  // https://cloud.google.com/storage/docs/access-control/iam
  const [policy] = await bucket.iam.getPolicy({requestedPolicyVersion: 3});

  // Adds the new roles to the bucket's IAM policy
  policy.bindings.push({
    role: roleName,
    members: members,
  });

  // Updates the bucket's IAM policy
  await bucket.iam.setPolicy(policy);

  console.log(
    `Added the following member(s) with role ${roleName} to ${bucketName}:`
  );

  members.forEach(member => {
    console.log(`  ${member}`);
  });
}

addBucketIamMember().catch(console.error);

PHP

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 有关详情,请参阅 Cloud Storage PHP API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

use Google\Cloud\Storage\StorageClient;

/**
 * Adds a new member / role IAM pair to a given Cloud Storage bucket.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 * @param string $role The role to which the given member should be added.
 *        (e.g. 'roles/storage.objectViewer')
 * @param string[] $members The member(s) to be added to the role.
 *        (e.g. ['group:example@google.com'])
 */
function add_bucket_iam_member(string $bucketName, string $role, array $members): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);

    $policy = $bucket->iam()->policy(['requestedPolicyVersion' => 3]);
    $policy['version'] = 3;

    $policy['bindings'][] = [
        'role' => $role,
        'members' => $members
    ];

    $bucket->iam()->setPolicy($policy);

    printf('Added the following member(s) to role %s for bucket %s' . PHP_EOL, $role, $bucketName);
    foreach ($members as $member) {
        printf('    %s' . PHP_EOL, $member);
    }
}

Python

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 有关详情,请参阅 Cloud Storage Python API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

from google.cloud import storage


def add_bucket_iam_member(bucket_name, role, member):
    """Add a new member to an IAM Policy"""
    # bucket_name = "your-bucket-name"
    # role = "IAM role, e.g., roles/storage.objectViewer"
    # member = "IAM identity, e.g., user: name@example.com"

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)

    policy = bucket.get_iam_policy(requested_policy_version=3)

    policy.bindings.append({"role": role, "members": {member}})

    bucket.set_iam_policy(policy)

    print(f"Added {member} with role {role} to {bucket_name}.")

Ruby

如需了解如何安装和使用 Cloud Storage 客户端库,请参阅 Cloud Storage 客户端库。 有关详情,请参阅 Cloud Storage Ruby API 参考文档

如需向 Cloud Storage 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证

def add_bucket_iam_member bucket_name:
  # The ID of your GCS bucket
  # bucket_name = "your-unique-bucket-name"

  require "google/cloud/storage"

  storage = Google::Cloud::Storage.new
  bucket = storage.bucket bucket_name

  role   = "roles/storage.objectViewer"
  member = "group:example@google.com"

  bucket.policy requested_policy_version: 3 do |policy|
    policy.bindings.insert role: role, members: [member]
  end

  puts "Added #{member} with role #{role} to #{bucket_name}"
end

JSON

  1. 安装并初始化 gcloud CLI,以便为 Authorization 标头生成访问令牌。

    或者,您可以创建访问令牌(使用 OAuth 2.0 Playground),并将其包含在 Authorization 标头中。

  2. 创建一个包含以下信息的 JSON 文件:

    {
    "bindings":[
      {
        "role": "roles/storage.objectViewer",
        "members":[
          "YOUR_AGENT_EMAIL"
        ]
      },
      {
        "role": "roles/storage.legacyBucketReader",
        "members":[
          "YOUR_AGENT_EMAIL"
        ]
      }
    ]
    }

    其中:

  3. 使用 cURL,通过 PUT setIamPolicy 请求调用 JSON API

    curl -X PUT --data-binary @JSON_FILE_NAME \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    -H "Content-Type: application/json" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam"

    其中:

    • JSON_FILE_NAME 是您在第 2 步中创建的文件的路径。
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是您要为主账号授予对其访问权限的存储桶的名称。例如 my-bucket