設定及管理 bucket 的 IAM 政策

總覽

本頁說明如何在值區上設定 Identity and Access Management (IAM) 政策,控管這些值區中物件和代管資料夾的存取權。

如要瞭解其他存取權控管方法,請參閱下列資源:

必要的角色

如要取得設定及管理值區 IAM 政策所需的權限,請要求管理員授予您值區的 Storage 管理員 (roles/storage.admin) IAM 角色。

這個角色具備下列權限,可設定及管理 Bucket 的 IAM 政策:

  • storage.buckets.get

  • storage.buckets.getIamPolicy

  • storage.buckets.setIamPolicy

  • storage.buckets.update

  • storage.buckets.list

    • 如果您打算使用Google Cloud 控制台執行本頁面的工作,才需要這項權限。

您也可以透過自訂角色取得這些權限。

在值區層級政策中新增主體

如需和 Cloud Storage 有關的角色清單,請參閱 IAM 角色。如要瞭解您授予 IAM 角色的實體,請參閱主體 ID

控制台

  1. 在 Google Cloud 控制台,前往「Cloud Storage bucket」頁面。

    前往「Buckets」(值區) 頁面

  2. 在 bucket 清單中,點選要將角色授予主體的 bucket 名稱。

  3. 選取靠近頁面上方的 [Permissions] (權限) 分頁標籤。

  4. 按一下「授予存取權」按鈕。

    系統會顯示「新增主體」對話方塊。

  5. 在「New principals」(新增主體) 欄位中,輸入需要存取值區的一或多個身分。

  6. 從「Select a role」(請選取角色) 下拉式選單中選取一或多個角色。您選取的角色會顯示在面板中,系統還會針對這些角色所授予的權限提供簡短說明。

  7. 按一下 [儲存]

如要瞭解如何透過 Google Cloud 控制台取得 Cloud Storage 作業失敗的詳細錯誤資訊,請參閱「疑難排解」一文。

指令列

使用 buckets add-iam-policy-binding 指令

gcloud storage buckets add-iam-policy-binding gs://BUCKET_NAME --member=PRINCIPAL_IDENTIFIER --role=IAM_ROLE

其中:

  • BUCKET_NAME 是您要授予主體存取權的值區名稱。例如:my-bucket

  • PRINCIPAL_IDENTIFIER 可識別您要授予值區存取權的對象。例如,user:jeffersonloveshiking@gmail.com。如需主體 ID 格式清單,請參閱「主體 ID」。

  • IAM_ROLE 是您授予主體的 IAM 角色。例如:roles/storage.objectViewer

用戶端程式庫

C++

詳情請參閱 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 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 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 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 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 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 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 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

REST API

JSON

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 建立包含下列資訊的 JSON 檔案:

    {
    "bindings":[
      {
        "role": "IAM_ROLE",
        "members":[
          "PRINCIPAL_IDENTIFIER"
        ]
      }
    ]
    }

    其中:

    • IAM_ROLE 是您要授予的 IAM 角色。例如:roles/storage.objectViewer

    • PRINCIPAL_IDENTIFIER 可識別您要授予值區存取權的對象。例如,user:jeffersonloveshiking@gmail.com。如需主體 ID 格式清單,請參閱「主體 ID」。

  3. 使用 cURL 來透過 PUT setIamPolicy 要求呼叫呼叫 JSON API

    curl -X PUT --data-binary @JSON_FILE_NAME \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam"

    其中:

    • JSON_FILE_NAME 是您在步驟 2 建立的檔案路徑。

    • BUCKET_NAME 是您要授予主體存取權的值區名稱。例如:my-bucket

查看值區的 IAM 政策

控制台

  1. 在 Google Cloud 控制台,前往「Cloud Storage bucket」頁面。

    前往「Buckets」(值區) 頁面

  2. 在值區清單中,按一下要查看政策的值區名稱。

  3. 前往「Bucket details」(值區詳細資料) 頁面,點選「Permissions」(權限) 分頁標籤。

    套用至值區的身分與存取權管理政策會顯示在「權限」部分。

  4. 選用:使用「篩選器」列篩選結果。

    如果您依主體進行搜尋,結果會顯示該主體已獲授權的所有角色。

指令列

使用 buckets get-iam-policy 指令

gcloud storage buckets get-iam-policy gs://BUCKET_NAME

其中 BUCKET_NAME 是您要查看其 IAM 政策的值區名稱。例如:my-bucket

用戶端程式庫

C++

詳情請參閱 Cloud Storage C++ API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

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

  if (!policy) throw std::move(policy).status();
  std::cout << "The IAM policy for bucket " << bucket_name << " is "
            << *policy << "\n";
}

C#

詳情請參閱 Cloud Storage C# API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


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

public class ViewBucketIamMembersSample
{
    public Policy ViewBucketIamMembers(string bucketName = "your-unique-bucket-name")
    {
        var storage = StorageClient.Create();
        var policy = storage.GetBucketIamPolicy(bucketName, new GetBucketIamPolicyOptions
        {
            RequestedPolicyVersion = 3
        });

        foreach (var binding in policy.Bindings)
        {
            Console.WriteLine($"Role: {binding.Role}");
            Console.WriteLine("Members:");
            foreach (var member in binding.Members)
            {
                Console.WriteLine($"{member}");
            }
        }
        return policy;
    }
}

Go

詳情請參閱 Cloud Storage Go API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

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

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

// getBucketPolicy gets the bucket IAM policy.
func getBucketPolicy(w io.Writer, bucketName string) (*iam.Policy3, error) {
	// bucketName := "bucket-name"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("storage.NewClient: %w", err)
	}
	defer client.Close()

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

	policy, err := client.Bucket(bucketName).IAM().V3().Policy(ctx)
	if err != nil {
		return nil, fmt.Errorf("Bucket(%q).IAM().V3().Policy: %w", bucketName, err)
	}
	for _, binding := range policy.Bindings {
		fmt.Fprintf(w, "%q: %q (condition: %v)\n", binding.Role, binding.Members, binding.Condition)
	}
	return policy, nil
}

Java

詳情請參閱 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;

public class ListBucketIamMembers {
  public static void listBucketIamMembers(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 policy =
        storage.getIamPolicy(bucketName, Storage.BucketSourceOption.requestedPolicyVersion(3));

    // Print binding information
    for (Binding binding : policy.getBindingsList()) {
      System.out.printf("Role: %s Members: %s\n", binding.getRole(), binding.getMembers());

      // Print condition if one is set
      boolean bindingIsConditional = binding.getCondition() != null;
      if (bindingIsConditional) {
        System.out.printf("Condition Title: %s\n", binding.getCondition().getTitle());
        System.out.printf("Condition Description: %s\n", binding.getCondition().getDescription());
        System.out.printf("Condition Expression: %s\n", binding.getCondition().getExpression());
      }
    }
  }
}

Node.js

詳情請參閱 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';

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

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

async function viewBucketIamMembers() {
  // For more information please read:
  // https://cloud.google.com/storage/docs/access-control/iam
  const results = await storage
    .bucket(bucketName)
    .iam.getPolicy({requestedPolicyVersion: 3});

  const bindings = results[0].bindings;

  console.log(`Bindings for bucket ${bucketName}:`);
  for (const binding of bindings) {
    console.log(`  Role: ${binding.role}`);
    console.log('  Members:');

    const members = binding.members;
    for (const member of members) {
      console.log(`    ${member}`);
    }

    const condition = binding.condition;
    if (condition) {
      console.log('  Condition:');
      console.log(`    Title: ${condition.title}`);
      console.log(`    Description: ${condition.description}`);
      console.log(`    Expression: ${condition.expression}`);
    }
  }
}

viewBucketIamMembers().catch(console.error);

PHP

詳情請參閱 Cloud Storage PHP API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

use Google\Cloud\Storage\StorageClient;

/**
 * View Bucket IAM members for a given Cloud Storage bucket.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 */
function view_bucket_iam_members(string $bucketName): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);

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

    printf('Printing Bucket IAM members for Bucket: %s' . PHP_EOL, $bucketName);
    printf(PHP_EOL);

    foreach ($policy['bindings'] as $binding) {
        printf('Role: %s' . PHP_EOL, $binding['role']);
        printf('Members:' . PHP_EOL);
        foreach ($binding['members'] as $member) {
            printf('  %s' . PHP_EOL, $member);
        }

        if (isset($binding['condition'])) {
            $condition = $binding['condition'];
            printf('  with condition:' . PHP_EOL);
            printf('    Title: %s' . PHP_EOL, $condition['title']);
            printf('    Description: %s' . PHP_EOL, $condition['description']);
            printf('    Expression: %s' . PHP_EOL, $condition['expression']);
        }
        printf(PHP_EOL);
    }
}

Python

詳情請參閱 Cloud Storage Python API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

from google.cloud import storage


def view_bucket_iam_members(bucket_name):
    """View IAM Policy for a bucket"""
    # bucket_name = "your-bucket-name"

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

    policy = bucket.get_iam_policy(requested_policy_version=3)

    for binding in policy.bindings:
        print(f"Role: {binding['role']}, Members: {binding['members']}")

Ruby

詳情請參閱 Cloud Storage Ruby API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

def view_bucket_iam_members 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

  policy = bucket.policy requested_policy_version: 3
  policy.bindings.each do |binding|
    puts "Role: #{binding.role}"
    puts "Members: #{binding.members}"

    # if a conditional binding exists print the condition.
    if binding.condition
      puts "Condition Title: #{binding.condition.title}"
      puts "Condition Description: #{binding.condition.description}"
      puts "Condition Expression: #{binding.condition.expression}"
    end
  end
end

REST API

JSON

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 使用 cURL 透過 GET getIamPolicy 要求呼叫 JSON API

    curl -X GET \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam"

    其中 BUCKET_NAME 是您要查看其 IAM 政策的值區名稱。例如:my-bucket

從值區層級政策中移除主體

控制台

  1. 在 Google Cloud 控制台,前往「Cloud Storage bucket」頁面。

    前往「Buckets」(值區) 頁面

  2. 在 bucket 清單中,點選要移除主體角色的 bucket 名稱。

  3. 前往「Bucket details」(值區詳細資料) 頁面,點選「Permissions」(權限) 分頁標籤。

    套用至值區的身分與存取權管理政策會顯示在「權限」部分。

  4. 在「View by principals」(依主體檢視) 分頁中,選取要移除主體的核取方塊。

  5. 按一下「移除存取權」按鈕。

  6. 在隨即出現的重疊視窗中,按一下「確認」

如要瞭解如何透過 Google Cloud 控制台取得 Cloud Storage 作業失敗的詳細錯誤資訊,請參閱「疑難排解」一文。

指令列

使用 buckets remove-iam-policy-binding 指令

gcloud storage buckets remove-iam-policy-binding  gs://BUCKET_NAME --member=PRINCIPAL_IDENTIFIER --role=IAM_ROLE

其中:

  • BUCKET_NAME 是您要撤銷存取權的值區名稱。例如:my-bucket

  • PRINCIPAL_IDENTIFIER 會識別要撤銷存取權的對象。例如,user:jeffersonloveshiking@gmail.com。如需主體 ID 格式清單,請參閱「主體 ID」。

  • IAM_ROLE 是您要撤銷的 IAM 角色。例如:roles/storage.objectViewer

用戶端程式庫

C++

詳情請參閱 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);
  std::vector<google::cloud::storage::NativeIamBinding> updated_bindings;
  for (auto& binding : policy->bindings()) {
    auto& members = binding.members();
    if (binding.role() == role && !binding.has_condition()) {
      members.erase(std::remove(members.begin(), members.end(), member),
                    members.end());
    }
    if (!members.empty()) {
      updated_bindings.emplace_back(std::move(binding));
    }
  }
  policy->bindings() = std::move(updated_bindings);

  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 C# API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


using Google.Cloud.Storage.V1;
using System;
using System.Linq;

public class RemoveBucketIamMemberSample
{
    public void RemoveBucketIamMember(
        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;

        foreach (var binding in policy.Bindings.Where(c => c.Role == role).ToList())
        {
            // Remove the role/member combo from the IAM policy.
            binding.Members = binding.Members.Where(m => m != member).ToList();
            // Remove role if it contains no members.
            if (binding.Members.Count == 0)
            {
                policy.Bindings.Remove(binding);
            }
        }
        // Set the modified IAM policy to be the current IAM policy.
        storage.SetBucketIamPolicy(bucketName, policy);
        Console.WriteLine($"Removed {member} with role {role} from {bucketName}");
    }
}

Go

詳情請參閱 Cloud Storage Go API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

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

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

// removeBucketIAMMember removes the bucket IAM member.
func removeBucketIAMMember(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
	// member string, role iam.RoleName
	identity := "group:cloud-logs@google.com"
	var role iam.RoleName = "roles/storage.objectViewer"

	policy.Remove(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, "Removed %v with role %v from %v\n", identity, role, bucketName)
	return nil
}

Java

詳情請參閱 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.List;

public class RemoveBucketIamMember {
  public static void removeBucketIamMember(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());

    // Remove role-member binding without a condition.
    for (int index = 0; index < bindings.size(); index++) {
      Binding binding = bindings.get(index);
      boolean foundRole = binding.getRole().equals(role);
      boolean foundMember = binding.getMembers().contains(member);
      boolean bindingIsNotConditional = binding.getCondition() == null;

      if (foundRole && foundMember && bindingIsNotConditional) {
        bindings.set(index, binding.toBuilder().removeMembers(member).build());
        break;
      }
    }

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

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

Node.js

詳情請參閱 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 revoke
// const roleName = 'roles/storage.objectViewer';

// The members to revoke the roles from
// 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 removeBucketIamMember() {
  // 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});

  // Finds and updates the appropriate role-member group, without a condition.
  const index = policy.bindings.findIndex(
    binding => binding.role === roleName && !binding.condition
  );

  const role = policy.bindings[index];
  if (role) {
    role.members = role.members.filter(
      member => members.indexOf(member) === -1
    );

    // Updates the policy object with the new (or empty) role-member group
    if (role.members.length === 0) {
      policy.bindings.splice(index, 1);
    } else {
      policy.bindings.index = role;
    }

    // Updates the bucket's IAM policy
    await bucket.iam.setPolicy(policy);
  } else {
    // No matching role-member group(s) were found
    throw new Error('No matching role-member group(s) found.');
  }

  console.log(
    `Removed the following member(s) with role ${roleName} from ${bucketName}:`
  );
  members.forEach(member => {
    console.log(`  ${member}`);
  });
}

removeBucketIamMember().catch(console.error);

PHP

詳情請參閱 Cloud Storage PHP API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

use Google\Cloud\Storage\StorageClient;

/**
 * Removes a member / role IAM pair from a given Cloud Storage bucket.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 * @param string $role The role from which the specified member should be removed.
 *        (e.g. 'roles/storage.objectViewer')
 * @param string $member The member to be removed from the specified role.
 *        (e.g. 'group:example@google.com')
 */
function remove_bucket_iam_member(string $bucketName, string $role, string $member): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);
    $iam = $bucket->iam();
    $policy = $iam->policy(['requestedPolicyVersion' => 3]);
    $policy['version'] = 3;

    foreach ($policy['bindings'] as $i => $binding) {
        // This example only removes member from bindings without a condition.
        if ($binding['role'] == $role && !isset($binding['condition'])) {
            $key = array_search($member, $binding['members']);
            if ($key !== false) {
                unset($binding['members'][$key]);

                // If the last member is removed from the binding, clean up the
                // binding.
                if (count($binding['members']) == 0) {
                    unset($policy['bindings'][$i]);
                    // Ensure array keys are sequential, otherwise JSON encodes
                    // the array as an object, which fails when calling the API.
                    $policy['bindings'] = array_values($policy['bindings']);
                } else {
                    // Ensure array keys are sequential, otherwise JSON encodes
                    // the array as an object, which fails when calling the API.
                    $binding['members'] = array_values($binding['members']);
                    $policy['bindings'][$i] = $binding;
                }

                $iam->setPolicy($policy);
                printf('User %s removed from role %s for bucket %s' . PHP_EOL, $member, $role, $bucketName);
                return;
            }
        }
    }

    throw new \RuntimeException('No matching role-member group(s) found.');
}

Python

詳情請參閱 Cloud Storage Python API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

from google.cloud import storage


def remove_bucket_iam_member(bucket_name, role, member):
    """Remove member from bucket 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)

    for binding in policy.bindings:
        print(binding)
        if binding["role"] == role and binding.get("condition") is None:
            binding["members"].discard(member)

    bucket.set_iam_policy(policy)

    print(f"Removed {member} with role {role} from {bucket_name}.")

Ruby

詳情請參閱 Cloud Storage Ruby API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

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

  # For more information please read: https://cloud.google.com/storage/docs/access-control/iam

  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.each do |binding|
      if binding.role == role && binding.condition.nil?
        binding.members.delete member
      end
    end
  end

  puts "Removed #{member} with role #{role} from #{bucket_name}"
end

REST API

JSON

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 取得已套用至 bucket 的現有政策,方法是使用 cURL 透過 GET getIamPolicy 要求呼叫 JSON API

    curl -X GET \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam"

    其中 BUCKET_NAME 是您要查看其 IAM 政策的值區名稱。例如:my-bucket

  3. 建立一個 JSON 檔案,其中須包含您在上個步驟擷取的政策。

  4. 編輯 JSON 檔案,從政策中移除主體。

  5. 使用 cURL 來透過 PUT setIamPolicy 要求呼叫呼叫 JSON API

    curl -X PUT --data-binary @JSON_FILE_NAME \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam"

    其中:

    • JSON_FILE_NAME 是您在步驟 3 建立的檔案路徑。

    • BUCKET_NAME 是您要移除存取權的值區名稱。例如:my-bucket

在 bucket 上使用 IAM 條件

下列各節說明如何在值區中新增及移除 IAM 條件。如要查看值區的 IAM 條件,請參閱「查看值區的 IAM 政策」。如要進一步瞭解如何搭配使用 IAM 條件和 Cloud Storage,請參閱「條件」一文。

您必須先啟用值區的統一值區層級存取權,才能新增條件。

為 bucket 設定新條件

控制台

  1. 在 Google Cloud 控制台,前往「Cloud Storage bucket」頁面。

    前往「Buckets」(值區) 頁面

  2. 在值區清單中,找出要新增條件的值區,然後點選該值區的名稱。

  3. 前往「Bucket details」(值區詳細資料) 頁面,點選「Permissions」(權限) 分頁標籤。

    套用至值區的身分與存取權管理政策會顯示在「權限」部分。

  4. 按一下「+ 授予存取權」

  5. 在「New principals」(新增主體) 欄位中,填寫要授予值區存取權的主體。

  6. 針對要套用條件的每個角色:

    1. 選取要授予主體的角色

    2. 按一下「新增條件」,開啟「編輯條件」表單。

    3. 填寫條件的標題。「說明」欄位為選填。

    4. 使用「條件建構工具」以視覺化方式建構條件,或使用「條件編輯器」分頁輸入 CEL 運算式

    5. 按一下「儲存」,返回「新增主體」表單。如要新增多個角色,請按一下「新增其他角色」

  7. 按一下 [儲存]

如要瞭解如何透過 Google Cloud 控制台取得 Cloud Storage 作業失敗的詳細錯誤資訊,請參閱「疑難排解」一文。

指令列

  1. 建立 JSON 或 YAML 檔案,定義條件,包括條件的 title、條件的屬性邏輯 expression,以及條件的 description (選用)。

    請注意,Cloud Storage 僅支援 expression 中的「日期/時間」、「資源類型」和「資源名稱」屬性。

  2. 使用 buckets add-iam-policy-binding 指令並加上 --condition-from-file 旗標:

gcloud storage buckets add-iam-policy-binding  gs://BUCKET_NAME --member=PRINCIPAL_IDENTIFIER --role=IAM_ROLE --condition-from-file=CONDITION_FILE

其中:

  • BUCKET_NAME 是您要授予主體存取權的值區名稱。例如:my-bucket

  • PRINCIPAL_IDENTIFIER 識別條件的適用對象。例如,user:jeffersonloveshiking@gmail.com。如需主體 ID 格式清單,請參閱「主體 ID」。

  • IAM_ROLE 是您授予主體的 IAM 角色。例如:roles/storage.objectViewer

  • CONDITION_FILE 是您在上一個步驟中建立的檔案。

或者,您也可以使用 --condition 旗標,直接在指令中加入條件,而不使用 --condition-from-file 旗標。

用戶端程式庫

C++

詳情請參閱 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,
   std::string const& condition_title,
   std::string const& condition_description,
   std::string const& condition_expression) {
  auto policy = client.GetNativeBucketIamPolicy(
      bucket_name, gcs::RequestedPolicyVersion(3));
  if (!policy) throw std::move(policy).status();

  policy->set_version(3);
  policy->bindings().emplace_back(gcs::NativeIamBinding(
      role, {member},
      gcs::NativeExpression(condition_expression, condition_title,
                            condition_description)));

  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";

  std::cout << "Added member " << member << " with role " << role << " to "
            << bucket_name << ":\n";
  std::cout << "with condition:\n"
            << "\t Title: " << condition_title << "\n"
            << "\t Description: " << condition_description << "\n"
            << "\t Expression: " << condition_expression << "\n";
}

C#

詳情請參閱 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 AddBucketConditionalIamBindingSample
{
    /// <summary>
    /// Adds a conditional Iam policy to a bucket.
    /// </summary>
    /// <param name="bucketName">The name of the bucket.</param>
    /// <param name="role">The role that members may assume.</param>
    /// <param name="member">The identifier of the member who may assume the provided role.</param>
    /// <param name="title">Title for the expression.</param>
    /// <param name="description">Description of the expression.</param>
    /// <param name="expression">Describes the conditions that need to be met for the policy to be applied.
    /// It's represented as a string using Common Expression Language syntax.</param>
    public Policy AddBucketConditionalIamBinding(
        string bucketName = "your-unique-bucket-name",
        string role = "roles/storage.objectViewer",
        string member = "serviceAccount:dev@iam.gserviceaccount.com",
        string title = "title",
        string description = "description",
        string expression = "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")")
    {
        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 },
            Condition = new Expr
            {
                Title = title,
                Description = description,
                Expression = expression
            }
        };

        policy.Bindings.Add(bindingToAdd);

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

Go

詳情請參閱 Cloud Storage Go API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

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

	"cloud.google.com/go/iam/apiv1/iampb"
	"cloud.google.com/go/storage"
	"google.golang.org/genproto/googleapis/type/expr"
)

// addBucketConditionalIAMBinding adds bucket conditional IAM binding.
func addBucketConditionalIAMBinding(w io.Writer, bucketName, role, member, title, description, expression string) error {
	// bucketName := "bucket-name"
	// role := "bucket-level IAM role"
	// member := "bucket-level IAM member"
	// title := "condition title"
	// description := "condition description"
	// expression := "condition expression"
	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().V3().Policy(ctx)
	if err != nil {
		return fmt.Errorf("Bucket(%q).IAM().V3().Policy: %w", bucketName, err)
	}

	policy.Bindings = append(policy.Bindings, &iampb.Binding{
		Role:    role,
		Members: []string{member},
		Condition: &expr.Expr{
			Title:       title,
			Description: description,
			Expression:  expression,
		},
	})

	if err := bucket.IAM().V3().SetPolicy(ctx, policy); err != nil {
		return fmt.Errorf("Bucket(%q).IAM().V3().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 with condition %v %v %v\n", member, role, bucketName, title, description, expression)
	return nil
}

Java

詳情請參閱 Cloud Storage Java API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


import com.google.cloud.Binding;
import com.google.cloud.Condition;
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 AddBucketIamConditionalBinding {
  /** Example of adding a conditional binding to the Bucket-level IAM */
  public static void addBucketIamConditionalBinding(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";

    // Create a condition
    String conditionTitle = "Title";
    String conditionDescription = "Description";
    String conditionExpression =
        "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")";
    Condition.Builder conditionBuilder = Condition.newBuilder();
    conditionBuilder.setTitle(conditionTitle);
    conditionBuilder.setDescription(conditionDescription);
    conditionBuilder.setExpression(conditionExpression);

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

    // Add condition to a binding
    Binding.Builder newBindingBuilder =
        Binding.newBuilder()
            .setRole(role)
            .setMembers(Arrays.asList(member))
            .setCondition(conditionBuilder.build());
    bindings.add(newBindingBuilder.build());

    // Update policy with new conditional binding
    Policy.Builder updatedPolicyBuilder = originalPolicy.toBuilder();
    updatedPolicyBuilder.setBindings(bindings).setVersion(3);

    storage.setIamPolicy(bucketName, updatedPolicyBuilder.build());

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

Node.js

詳情請參閱 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',
// ];

// Create a condition
// const title = 'Title';
// const description = 'Description';
// const expression = 'resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")';

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

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

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

  // Gets and updates the bucket's IAM policy
  const [policy] = await bucket.iam.getPolicy({requestedPolicyVersion: 3});

  // Set the policy's version to 3 to use condition in bindings.
  policy.version = 3;

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

  // 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}`);
  });

  console.log('with condition:');
  console.log(`  Title: ${title}`);
  console.log(`  Description: ${description}`);
  console.log(`  Expression: ${expression}`);
}

addBucketConditionalBinding().catch(console.error);

PHP

詳情請參閱 Cloud Storage PHP API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

use Google\Cloud\Storage\StorageClient;

/**
 * Adds a conditional IAM binding to a bucket's IAM policy.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 * @param string $role The role that will be given to members in this binding.
 *        (e.g. 'roles/storage.objectViewer')
 * @param string[] $members The member(s) associated with this binding.
 *        (e.g. ['group:example@google.com'])
 * @param string $title The title of the condition. (e.g. 'Title')
 * @param string $description The description of the condition.
 *        (e.g. 'Condition Description')
 * @param string $expression The condition specified in CEL expression language.
 *        (e.g. 'resource.name.startsWith("projects/_/buckets/bucket-name/objects/prefix-a-")')
 *
 * To see how to express a condition in CEL, visit:
 * @see https://cloud.google.com/storage/docs/access-control/iam#conditions.
 */
function add_bucket_conditional_iam_binding(string $bucketName, string $role, array $members, string $title, string $description, string $expression): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);

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

    $policy['version'] = 3;

    $policy['bindings'][] = [
        'role' => $role,
        'members' => $members,
        'condition' => [
            'title' => $title,
            'description' => $description,
            'expression' => $expression,
        ],
    ];

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

    printf('Added the following member(s) with role %s to %s:' . PHP_EOL, $role, $bucketName);
    foreach ($members as $member) {
        printf('    %s' . PHP_EOL, $member);
    }
    printf('with condition:' . PHP_EOL);
    printf('    Title: %s' . PHP_EOL, $title);
    printf('    Description: %s' . PHP_EOL, $description);
    printf('    Expression: %s' . PHP_EOL, $expression);
}

Python

詳情請參閱 Cloud Storage Python API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

from google.cloud import storage


def add_bucket_conditional_iam_binding(
    bucket_name, role, title, description, expression, members
):
    """Add a conditional IAM binding to a bucket's IAM policy."""
    # bucket_name = "your-bucket-name"
    # role = "IAM role, e.g. roles/storage.objectViewer"
    # members = {"IAM identity, e.g. user: name@example.com}"
    # title = "Condition title."
    # description = "Condition description."
    # expression = "Condition expression."

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

    policy = bucket.get_iam_policy(requested_policy_version=3)

    # Set the policy's version to 3 to use condition in bindings.
    policy.version = 3

    policy.bindings.append(
        {
            "role": role,
            "members": members,
            "condition": {
                "title": title,
                "description": description,
                "expression": expression,
            },
        }
    )

    bucket.set_iam_policy(policy)

    print(f"Added the following member(s) with role {role} to {bucket_name}:")

    for member in members:
        print(f"    {member}")

    print("with condition:")
    print(f"    Title: {title}")
    print(f"    Description: {description}")
    print(f"    Expression: {expression}")

Ruby

詳情請參閱 Cloud Storage Ruby API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

def add_bucket_conditional_iam_binding 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"
  title       = "Title"
  description = "Description"
  expression  = "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"

  bucket.policy requested_policy_version: 3 do |policy|
    policy.version = 3
    policy.bindings.insert(
      role:      role,
      members:   member,
      condition: {
        title:       title,
        description: description,
        expression:  expression
      }
    )
  end

  puts "Added #{member} with role #{role} to #{bucket_name} with condition #{title} #{description} #{expression}"
end

REST API

JSON

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 使用 GET getIamPolicy 要求,將 bucket 的 IAM 政策儲存至暫存 JSON 檔案:

    curl \
    'https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam' \
    --header 'Authorization: Bearer $(gcloud auth print-access-token)' > tmp-policy.json

    其中 BUCKET_NAME 是相關值區的名稱。例如:my-bucket

  3. 在文字編輯器中編輯 tmp-policy.json 檔案,在 IAM 政策的繫結中新增條件:

    {
        "version": VERSION,
        "bindings": [
          {
            "role": "IAM_ROLE",
            "members": [
              "PRINCIPAL_IDENTIFIER"
            ],
            "condition": {
              "title": "TITLE",
              "description": "DESCRIPTION",
              "expression": "EXPRESSION"
            }
          }
        ],
        "etag": "ETAG"
    }

    其中:

    • VERSIONIAM 政策版本,如果 bucket 設有 IAM 條件,則必須為 3。

    • IAM_ROLE 是條件適用的角色。例如:roles/storage.objectViewer

    • PRINCIPAL_IDENTIFIER 識別條件的適用對象。例如:user:jeffersonloveshiking@gmail.com。如需主體 ID 格式清單,請參閱「主體 ID」。

    • TITLE 是條件的標題。例如:expires in 2019

    • DESCRIPTION 是條件的選填說明。例如:Permission revoked on New Year's

    • EXPRESSION以屬性為基礎的邏輯運算式。例如:request.time < timestamp(\"2019-01-01T00:00:00Z\")。如需更多運算式範例,請參閱「條件屬性參考資料」。請注意,Cloud Storage 僅支援「日期/時間」、「資源類型」和「資源名稱」屬性。

    請勿修改 ETAG

  4. 使用 PUT setIamPolicy 要求,在值區中設定修改後的 IAM 政策:

    curl -X PUT --data-binary @tmp-policy.json \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam"

    其中 BUCKET_NAME 是相關值區的名稱。例如:my-bucket

從值區移除條件

控制台

  1. 在 Google Cloud 控制台,前往「Cloud Storage bucket」頁面。

    前往「Buckets」(值區) 頁面

  2. 在值區清單中,找出要移除條件的值區,然後點選該值區的名稱。

  3. 前往「Bucket details」(值區詳細資料) 頁面,點選「Permissions」(權限) 分頁標籤。

    套用至值區的身分與存取權管理政策會顯示在「權限」部分。

  4. 按一下與條件相關聯主體的「編輯」圖示

  5. 在隨即顯示的「編輯存取權」重疊視窗中,按一下要刪除的條件名稱。

  6. 在隨即顯示的「編輯條件」重疊視窗中,按一下「刪除」,然後按一下「確認」

  7. 按一下 [儲存]

如要瞭解如何透過 Google Cloud 控制台取得 Cloud Storage 作業失敗的詳細錯誤資訊,請參閱「疑難排解」一文。

指令列

  1. 使用 buckets get-iam-policy 指令,將 bucket 的 IAM 政策儲存至暫時的 JSON 檔案。

    gcloud storage buckets get-iam-policy gs://BUCKET_NAME > tmp-policy.json
  2. 在文字編輯器中編輯 tmp-policy.json 檔案,從 IAM 政策中移除條件。

  3. 使用 buckets set-iam-policy 在 bucket 上設定修改後的 IAM 政策。

    gcloud storage buckets set-iam-policy gs://BUCKET_NAME tmp-policy.json

程式碼範例

C++

詳情請參閱 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& condition_title,
   std::string const& condition_description,
   std::string const& condition_expression) {
  auto policy = client.GetNativeBucketIamPolicy(
      bucket_name, gcs::RequestedPolicyVersion(3));
  if (!policy) throw std::move(policy).status();

  policy->set_version(3);
  auto& bindings = policy->bindings();
  auto e = std::remove_if(
      bindings.begin(), bindings.end(),
      [role, condition_title, condition_description,
       condition_expression](gcs::NativeIamBinding b) {
        return (b.role() == role && b.has_condition() &&
                b.condition().title() == condition_title &&
                b.condition().description() == condition_description &&
                b.condition().expression() == condition_expression);
      });
  if (e == bindings.end()) {
    std::cout << "No matching binding group found.\n";
    return;
  }
  bindings.erase(e);
  auto updated = client.SetNativeBucketIamPolicy(bucket_name, *policy);
  if (!updated) throw std::move(updated).status();

  std::cout << "Conditional binding was removed.\n";
}

C#

詳情請參閱 Cloud Storage C# API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


using Google.Apis.Storage.v1.Data;
using Google.Cloud.Storage.V1;
using System;
using System.Linq;

public class RemoveBucketConditionalIamBindingSample
{
    public Policy RemoveBucketConditionalIamBinding(
        string bucketName = "your-unique-bucket-name",
        string role = "roles/storage.objectViewer",
        string title = "title",
        string description = "description",
        string expression = "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")")
    {
        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;

        var bindingsToRemove = policy.Bindings.Where(binding => binding.Role == role
              && binding.Condition != null
              && binding.Condition.Title == title
              && binding.Condition.Description == description
              && binding.Condition.Expression == expression).ToList();
        if (bindingsToRemove.Count() > 0)
        {
            foreach (var binding in bindingsToRemove)
            {
                policy.Bindings.Remove(binding);
            }
            // Set the modified IAM policy to be the current IAM policy.
            policy = storage.SetBucketIamPolicy(bucketName, policy);
            Console.WriteLine("Conditional Binding was removed.");
        }
        else
        {
            Console.WriteLine("No matching conditional binding found.");
        }
        return policy;
    }
}

Go

詳情請參閱 Cloud Storage Go API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

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

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

// removeBucketConditionalIAMBinding removes bucket conditional IAM binding.
func removeBucketConditionalIAMBinding(w io.Writer, bucketName, role, title, description, expression string) error {
	// bucketName := "bucket-name"
	// role := "bucket-level IAM role"
	// title := "condition title"
	// description := "condition description"
	// expression := "condition expression"
	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().V3().Policy(ctx)
	if err != nil {
		return fmt.Errorf("Bucket(%q).IAM().V3().Policy: %w", bucketName, err)
	}

	// Find the index of the binding matching inputs.
	i := -1
	for j, binding := range policy.Bindings {
		if binding.Role == role && binding.Condition != nil {
			condition := binding.Condition
			if condition.Title == title &&
				condition.Description == description &&
				condition.Expression == expression {
				i = j
			}
		}
	}

	if i == -1 {
		return fmt.Errorf("no matching binding group found")
	}

	// Get a slice of the bindings, removing the binding at index i.
	policy.Bindings = append(policy.Bindings[:i], policy.Bindings[i+1:]...)

	if err := bucket.IAM().V3().SetPolicy(ctx, policy); err != nil {
		return fmt.Errorf("Bucket(%q).IAM().V3().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.Fprintln(w, "Conditional binding was removed")
	return nil
}

Java

詳情請參閱 Cloud Storage Java API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。


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

public class RemoveBucketIamConditionalBinding {
  /** Example of removing a conditional binding to the Bucket-level IAM */
  public static void removeBucketIamConditionalBinding(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";

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

    // Create a condition to compare against
    Condition.Builder conditionBuilder = Condition.newBuilder();
    conditionBuilder.setTitle("Title");
    conditionBuilder.setDescription("Description");
    conditionBuilder.setExpression(
        "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")");

    Iterator iterator = bindings.iterator();
    while (iterator.hasNext()) {
      Binding binding = (Binding) iterator.next();
      boolean foundRole = binding.getRole().equals(role);
      boolean conditionsEqual = conditionBuilder.build().equals(binding.getCondition());

      // Remove condition when the role and condition are equal
      if (foundRole && conditionsEqual) {
        iterator.remove();
        break;
      }
    }

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

    System.out.println("Conditional Binding was removed.");
  }
}

Node.js

詳情請參閱 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',
// ];

// Create a condition
// const title = 'Title';
// const description = 'Description';
// const expression = 'resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")';

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

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

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

  // Gets and updates the bucket's IAM policy
  const [policy] = await bucket.iam.getPolicy({requestedPolicyVersion: 3});

  // Set the policy's version to 3 to use condition in bindings.
  policy.version = 3;

  // Finds and removes the appropriate role-member group with specific condition.
  const index = policy.bindings.findIndex(
    binding =>
      binding.role === roleName &&
      binding.condition &&
      binding.condition.title === title &&
      binding.condition.description === description &&
      binding.condition.expression === expression
  );

  const binding = policy.bindings[index];
  if (binding) {
    policy.bindings.splice(index, 1);

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

    console.log('Conditional Binding was removed.');
  } else {
    // No matching role-member group with specific condition were found
    throw new Error('No matching binding group found.');
  }
}

removeBucketConditionalBinding().catch(console.error);

PHP

詳情請參閱 Cloud Storage PHP API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

use Google\Cloud\Storage\StorageClient;

/**
 * Removes a conditional IAM binding from a bucket's IAM policy.
 *
 * To see how to express a condition in CEL, visit:
 * @see https://cloud.google.com/storage/docs/access-control/iam#conditions.
 *
 * @param string $bucketName The name of your Cloud Storage bucket.
 *        (e.g. 'my-bucket')
 * @param string $role the role that will be given to members in this binding.
 *        (e.g. 'roles/storage.objectViewer')
 * @param string $title The title of the condition. (e.g. 'Title')
 * @param string $description The description of the condition.
 *        (e.g. 'Condition Description')
 * @param string $expression Te condition specified in CEL expression language.
 *        (e.g. 'resource.name.startsWith("projects/_/buckets/bucket-name/objects/prefix-a-")')
 */
function remove_bucket_conditional_iam_binding(string $bucketName, string $role, string $title, string $description, string $expression): void
{
    $storage = new StorageClient();
    $bucket = $storage->bucket($bucketName);

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

    $policy['version'] = 3;

    $key_of_conditional_binding = null;
    foreach ($policy['bindings'] as $key => $binding) {
        if ($binding['role'] == $role && isset($binding['condition'])) {
            $condition = $binding['condition'];
            if ($condition['title'] == $title
                 && $condition['description'] == $description
                 && $condition['expression'] == $expression) {
                $key_of_conditional_binding = $key;
                break;
            }
        }
    }

    if ($key_of_conditional_binding != null) {
        unset($policy['bindings'][$key_of_conditional_binding]);
        // Ensure array keys are sequential, otherwise JSON encodes
        // the array as an object, which fails when calling the API.
        $policy['bindings'] = array_values($policy['bindings']);
        $bucket->iam()->setPolicy($policy);
        print('Conditional Binding was removed.' . PHP_EOL);
    } else {
        print('No matching conditional binding found.' . PHP_EOL);
    }
}

Python

詳情請參閱 Cloud Storage Python API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

from google.cloud import storage


def remove_bucket_conditional_iam_binding(
    bucket_name, role, title, description, expression
):
    """Remove a conditional IAM binding from a bucket's IAM policy."""
    # bucket_name = "your-bucket-name"
    # role = "IAM role, e.g. roles/storage.objectViewer"
    # title = "Condition title."
    # description = "Condition description."
    # expression = "Condition expression."

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

    policy = bucket.get_iam_policy(requested_policy_version=3)

    # Set the policy's version to 3 to use condition in bindings.
    policy.version = 3

    condition = {
        "title": title,
        "description": description,
        "expression": expression,
    }
    policy.bindings = [
        binding
        for binding in policy.bindings
        if not (binding["role"] == role and binding.get("condition") == condition)
    ]

    bucket.set_iam_policy(policy)

    print("Conditional Binding was removed.")

Ruby

詳情請參閱 Cloud Storage Ruby API 參考說明文件

如要驗證 Cloud Storage,請設定應用程式預設憑證。 詳情請參閱「設定用戶端程式庫的驗證機制」。

def remove_bucket_conditional_iam_binding 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"
  title       = "Title"
  description = "Description"
  expression  = "resource.name.startsWith(\"projects/_/buckets/bucket-name/objects/prefix-a-\")"

  bucket.policy requested_policy_version: 3 do |policy|
    policy.version = 3

    binding_to_remove = nil
    policy.bindings.each do |b|
      condition = {
        title:       title,
        description: description,
        expression:  expression
      }
      if b.role == role && b.condition &&
         b.condition.title == title &&
         b.condition.description == description &&
         b.condition.expression == expression
        binding_to_remove = b
      end
    end
    if binding_to_remove
      policy.bindings.remove binding_to_remove
      puts "Conditional Binding was removed."
    else
      puts "No matching conditional binding found."
    end
  end
end

REST API

JSON

  1. 安裝並初始化 gcloud CLI,以便為 Authorization 標頭產生存取權杖。

  2. 使用 GET getIamPolicy 要求,將 bucket 的 IAM 政策儲存至暫存 JSON 檔案:

    curl \
    'https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam' \
    --header 'Authorization: Bearer $(gcloud auth print-access-token)' > tmp-policy.json

    其中 BUCKET_NAME 是您要授予存取權的值區名稱。例如:my-bucket

  3. 在文字編輯器中編輯 tmp-policy.json 檔案,從 IAM 政策中移除條件。

  4. 使用 PUT setIamPolicy 要求,在值區中設定修改後的 IAM 政策:

    curl -X PUT --data-binary @tmp-policy.json \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/iam"

    其中 BUCKET_NAME 是您要修改 IAM 政策的值區名稱。例如:my-bucket

最佳做法

您應設定最低必要角色,將所需存取權授予主體。舉例來說,如果小組成員只需要讀取儲存在值區中的物件,請授予「Storage 物件檢視者」(roles/storage.objectViewer) 角色,而非「Storage 物件管理員」(roles/storage.objectAdmin) 角色。同樣地,如果小組成員需要值區物件的完整控制權,但不需要值區本身的控制權,請授予「Storage Object Admin」(Storage 物件管理員) (roles/storage.objectAdmin) 角色,而非「Storage Admin」(Storage 管理員) (roles/storage.admin) 角色。

後續步驟