使用 CMEK(客户管理的加密密钥)

转到概念

本页面介绍如何将 Cloud Key Management Service 加密密钥与 Cloud Storage 搭配使用,包括在存储分区上设置默认密钥以及将密钥添加到个别对象。Cloud KMS 加密密钥是“客户管理的加密密钥”,该密钥由 Cloud KMS 创建并由您负责管理。

如需了解有关 Cloud KMS 的更多常规信息,请参阅 Cloud KMS

前提条件

在 Cloud Storage 中使用此功能之前,您应该:

  1. 为将用于存储您的加密密钥的项目启用 Cloud KMS API。

    启用该 API

  2. 对存储加密密钥的项目拥有足够的权限:

    • 如果您拥有将存储您的密钥的项目,则您很可能已具备必要的权限。

    • 如果您计划创建新的加密密钥环和密钥,则应具备 cloudkms.keyRings.createcloudkms.cryptoKey.create 权限。

    • 无论您是计划使用新的密钥环和密钥还是现有的密钥环和密钥,您都应对将用于加密的密钥具有 cloudkms.cryptoKey.setIamPolicy 权限。

      此权限可让您为 Cloud Storage 服务帐号提供 Cloud KMS 密钥的访问权限。

    • 以上权限包含在 Cloud KMS Admin 角色中。

      如需了解如何获取此角色或其他 Cloud KMS 角色,请参阅将 IAM 与 Cloud KMS 搭配使用

  3. 具备足够的权限来处理 Cloud Storage 存储分区中的对象:

    • 如果您拥有存储分区所属的项目,那么您很可能已具备所需的权限。

    • 如果使用 IAM,您应具有 storage.objects.create 权限(以便将对象写入存储分区)以及 storage.objects.get 权限(以便从存储分区读取对象)。如需了解如何获取具有这些权限的角色(例如 Storage Object Admin),请参阅使用 IAM 权限

    • 如果使用 ACL,您应具有存储分区范围的 WRITER 权限(以便将对象写入存储分区)以及对象范围的 READER 权限(以便从存储分区读取对象)。如需了解如何执行此操作,请参阅设置 ACL

  4. 拥有 Cloud KMS 密钥环,并且该密钥环中至少包含一个密钥

  5. 获取与您的 Cloud Storage 存储分区所属项目关联的服务帐号的电子邮件地址

将 Cloud KMS 密钥分配给服务帐号

要使用客户管理的加密密钥,您必须授权 Cloud Storage 服务帐号使用 Cloud KMS 密钥。

控制台

  1. 在 Google Cloud Console 中打开 Cloud Key Management Service 密钥浏览器。
    打开 Cloud KMS 密钥浏览器
  2. 点击包含所需密钥的密钥环的名称。

  3. 选中所需密钥对应的复选框。

    右侧窗格中的权限标签变为可用。

  4. 添加成员对话框中,指定要授予访问权限的 Cloud Storage 服务帐号的电子邮件地址。

  5. 选择角色下拉列表中,选择 Cloud KMS CryptoKey Encrypter/Decrypter

  6. 点击添加

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil kms authorize 命令,向与您的存储分区关联的服务帐号授予使用 Cloud KMS 密钥加密和解密对象的权限:

gsutil kms authorize -p PROJECT_STORING_OBJECTS -k KEY_RESOURCE

其中:

  • PROJECT_STORING_OBJECTS 是包含待加密或解密对象的项目的 ID,例如 my-pet-project
  • KEY_RESOURCE 是您的 Cloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key

如果您想移除授予的权限,则需要使用 gcloud 命令行工具或 Google Cloud Console。

代码示例

C#

如需了解详情,请参阅 Cloud Storage C# API 参考文档


using Google.Cloud.Iam.V1;
using Google.Cloud.Kms.V1;

public class IamAddMemberSample
{
    public Policy IamAddMember(
      string projectId = "my-project", string locationId = "us-east1", string keyRingId = "my-key-ring", string keyId = "my-key",
      string member = "user:foo@example.com")
    {
        // Create the client.
        KeyManagementServiceClient client = KeyManagementServiceClient.Create();

        // Build the resource name.
        CryptoKeyName resourceName = new CryptoKeyName(projectId, locationId, keyRingId, keyId);

        // The resource name could also be a key ring.
        // var resourceName = new KeyRingName(projectId, locationId, keyRingId);

        // Get the current IAM policy.
        Policy policy = client.GetIamPolicy(resourceName);

        // Add the member to the policy.
        policy.AddRoleMember("roles/cloudkms.cryptoKeyEncrypterDecrypter", member);

        // Save the updated IAM policy.
        Policy result = client.SetIamPolicy(resourceName, policy);

        // Return the resulting policy.
        return result;
    }
}

Go

如需了解详情,请参阅 Cloud Storage Go API 参考文档

import (
	"context"
	"fmt"
	"io"

	kms "cloud.google.com/go/kms/apiv1"
)

// iamAddMember adds a new IAM member to the Cloud KMS key
func iamAddMember(w io.Writer, name, member string) error {
	// NOTE: The resource name can be either a key or a key ring. If IAM
	// permissions are granted on the key ring, the permissions apply to all keys
	// in the key ring.
	//
	// name := "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key"
	// member := "user:foo@example.com"

	// Create the client.
	ctx := context.Background()
	client, err := kms.NewKeyManagementClient(ctx)
	if err != nil {
		return fmt.Errorf("failed to create kms client: %v", err)
	}

	// Get the current IAM policy.
	handle := client.ResourceIAM(name)
	policy, err := handle.Policy(ctx)
	if err != nil {
		return fmt.Errorf("failed to get IAM policy: %v", err)
	}

	// Grant the member permissions. This example grants permission to use the key
	// to encrypt data.
	policy.Add(member, "roles/cloudkms.cryptoKeyEncrypterDecrypter")
	if err := handle.SetPolicy(ctx, policy); err != nil {
		return fmt.Errorf("failed to save policy: %v", err)
	}

	fmt.Fprintf(w, "Updated IAM policy for %s\n", name)
	return nil
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

import com.google.cloud.kms.v1.CryptoKeyName;
import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.iam.v1.Binding;
import com.google.iam.v1.Policy;
import java.io.IOException;

public class IamAddMember {

  public void iamAddMember() throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String locationId = "us-east1";
    String keyRingId = "my-key-ring";
    String keyId = "my-key";
    String member = "user:foo@example.com";
    iamAddMember(projectId, locationId, keyRingId, keyId, member);
  }

  // Add the given IAM member to the key.
  public void iamAddMember(
      String projectId, String locationId, String keyRingId, String keyId, String member)
      throws IOException {
    // Initialize client that will be used to send requests. This client only
    // needs to be created once, and can be reused for multiple requests. After
    // completing all of your requests, call the "close" method on the client to
    // safely clean up any remaining background resources.
    try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
      // Build the key version name from the project, location, key ring, key,
      // and key version.
      CryptoKeyName resourceName = CryptoKeyName.of(projectId, locationId, keyRingId, keyId);

      // The resource name could also be a key ring.
      // KeyRingName resourceName = KeyRingName.of(projectId, locationId, keyRingId);

      // Get the current policy.
      Policy policy = client.getIamPolicy(resourceName);

      // Create a new IAM binding for the member and role.
      Binding binding =
          Binding.newBuilder()
              .setRole("roles/cloudkms.cryptoKeyEncrypterDecrypter")
              .addMembers(member)
              .build();

      // Add the binding to the policy.
      Policy newPolicy = policy.toBuilder().addBindings(binding).build();

      client.setIamPolicy(resourceName, newPolicy);
      System.out.printf("Updated IAM policy for %s%n", resourceName.toString());
    }
  }
}

Node.js

如需了解详情,请参阅 Cloud Storage Node.js API 参考文档

//
// TODO(developer): Uncomment these variables before running the sample.
//
// const projectId = 'my-project';
// const locationId = 'us-east1';
// const keyRingId = 'my-key-ring';
// const keyId = 'my-key';
// const member = 'user:foo@example.com';

// Imports the Cloud KMS library
const {KeyManagementServiceClient} = require('@google-cloud/kms');

// Instantiates a client
const client = new KeyManagementServiceClient();

// Build the resource name
const resourceName = client.cryptoKeyPath(
  projectId,
  locationId,
  keyRingId,
  keyId
);

// The resource name could also be a key ring.
// const resourceName = client.keyRingPath(projectId, locationId, keyRingId);

async function iamAddMember() {
  // Get the current IAM policy.
  const [policy] = await client.getIamPolicy({
    resource: resourceName,
  });

  // Add the member to the policy.
  policy.bindings.push({
    role: 'roles/cloudkms.cryptoKeyEncrypterDecrypter',
    members: [member],
  });

  // Save the updated policy.
  const [updatedPolicy] = await client.setIamPolicy({
    resource: resourceName,
    policy: policy,
  });

  console.log('Updated policy');
  return updatedPolicy;
}

return iamAddMember();

PHP

如需了解详情,请参阅 Cloud Storage PHP API 参考文档

use Google\Cloud\Iam\V1\Binding;
use Google\Cloud\Kms\V1\KeyManagementServiceClient;

function iam_add_member_sample(
    string $projectId = 'my-project',
    string $locationId = 'us-east1',
    string $keyRingId = 'my-key-ring',
    string $keyId = 'my-key',
    string $member = 'user:foo@example.com'
) {
    // Create the Cloud KMS client.
    $client = new KeyManagementServiceClient();

    // Build the resource name.
    $resourceName = $client->cryptoKeyName($projectId, $locationId, $keyRingId, $keyId);

    // The resource name could also be a key ring.
    // $resourceName = $client->keyRingName($projectId, $locationId, $keyRingId);

    // Get the current IAM policy.
    $policy = $client->getIamPolicy($resourceName);

    // Add the member to the policy.
    $bindings = $policy->getBindings();
    $bindings[] = (new Binding())
        ->setRole('roles/cloudkms.cryptoKeyEncrypterDecrypter')
        ->setMembers([$member]);
    $policy->setBindings($bindings);

    // Save the updated IAM policy.
    $updatedPolicy = $client->setIamPolicy($resourceName, $policy);
    printf('Added %s' . PHP_EOL, $member);
    return $updatedPolicy;
}

Python

如需了解详情,请参阅 Cloud Storage Python API 参考文档

def iam_add_member(project_id, location_id, key_ring_id, key_id, member):
    """
    Add an IAM member to a resource.

    Args:
        project_id (string): Google Cloud project ID (e.g. 'my-project').
        location_id (string): Cloud KMS location (e.g. 'us-east1').
        key_ring_id (string): ID of the Cloud KMS key ring (e.g. 'my-key-ring').
        key_id (string): ID of the key to use (e.g. 'my-key').
        member (string): Member to add (e.g. 'user:foo@example.com')

    Returns:
        Policy: Updated Cloud IAM policy.

    """

    # Import the client library.
    from google.cloud import kms

    # Create the client.
    client = kms.KeyManagementServiceClient()

    # Build the resource name.
    resource_name = client.crypto_key_path(project_id, location_id, key_ring_id, key_id)

    # The resource name could also be a key ring.
    # resource_name = client.key_ring_path(project_id, location_id, key_ring_id);

    # Get the current policy.
    policy = client.get_iam_policy(request={'resource': resource_name})

    # Add the member to the policy.
    policy.bindings.add(
        role='roles/cloudkms.cryptoKeyEncrypterDecrypter',
        members=[member])

    # Save the updated IAM policy.
    request = {
        'resource': resource_name,
        'policy': policy
    }

    updated_policy = client.set_iam_policy(request=request)
    print('Added {} to {}'.format(member, resource_name))
    return updated_policy

Ruby

如需了解详情,请参阅 Cloud Storage Ruby API 参考文档

# TODO(developer): uncomment these values before running the sample.
# project_id  = "my-project"
# location_id = "us-east1"
# key_ring_id = "my-key-ring"
# key_id      = "my-key"
# member      = "user:foo@example.com"

# Require the library.
require "google/cloud/kms"

# Create the client.
client = Google::Cloud::Kms.key_management_service

# Build the resource name.
resource_name = client.crypto_key_path project:    project_id,
                                       location:   location_id,
                                       key_ring:   key_ring_id,
                                       crypto_key: key_id

# The resource name could also be a key ring.
# resource_name = client.key_ring_path project: project_id, location: location_id, key_ring: key_ring_id

# Create the IAM client.
iam_client = Google::Cloud::Kms::V1::IAMPolicy::Client.new

# Get the current IAM policy.
policy = iam_client.get_iam_policy resource: resource_name

# Add the member to the policy.
policy.bindings << Google::Iam::V1::Binding.new(
  members: [member],
  role:    "roles/cloudkms.cryptoKeyEncrypterDecrypter"
)

# Save the updated policy.
updated_policy = iam_client.set_iam_policy resource: resource_name, policy: policy
puts "Added #{member}"

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个包含以下信息的 .json 文件:

    {
      "policy": {
        "bindings": {
          "role": "roles/cloudkms.cryptoKeyEncrypterDecrypter",
          "members": "SERVICE_ACCOUNT_EMAIL_ADDRESS"
        },
      }
    }

    其中,SERVICE_ACCOUNT_EMAIL_ADDRESS 是与您的服务帐号相关联的电子邮件地址,例如 service-7550275089395@gs-project-accounts.iam.gserviceaccount.com

  3. 使用 cURL,通过 POST setIamPolicy 请求调用 Cloud KMS API:

    curl -X POST --data-binary @JSON_FILE_NAME.json \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    -H "Content-Type: application/json" \
    "https://cloudkms.googleapis.com/v1/KEY_RESOURCE:setIamPolicy"

    其中:

    • JSON_FILE_NAME 是您在第 2 步中创建的文件的名称。
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • KEY_RESOURCE 是您的 Cloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key

XML API

您不能使用 XML API 将 Cloud KMS 分配给服务帐号。请改用其他 Cloud Storage 工具,例如 gsutil。

使用默认加密密钥

添加或更改存储分区的默认密钥

要添加或更改在将对象写入存储分区时默认使用的 Cloud KMS 密钥:

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 在存储分区列表中,点击所需的存储分区。

  3. 在存储分区详情页面中,点击配置标签页。

  4. 点击与“加密类型”条目关联的铅笔图标

  5. 如果存储分区当前未使用 Cloud KMS 密钥,请选择客户管理的密钥单选按钮。

  6. 在与客户管理的密钥关联的下拉菜单中,选择一个可用密钥。

  7. 点击保存

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil kms encryption 命令:

gsutil kms encryption -k KEY_RESOURCE gs://BUCKET_NAME

其中:

  • KEY_RESOURCE 是您的 Cloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key
  • BUCKET_NAME 是相关存储分区的名称, 例如 my-bucket

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

Setting default KMS key for bucket gs://my-bucket...

代码示例

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& key_name) {
  StatusOr<gcs::BucketMetadata> updated = client.PatchBucket(
      bucket_name, gcs::BucketMetadataPatchBuilder().SetEncryption(
                       gcs::BucketEncryption{key_name}));
  if (!updated) throw std::runtime_error(updated.status().message());

  if (!updated->has_encryption()) {
    std::cerr << "The change to set the encryption attribute on bucket "
              << updated->name()
              << " was sucessful, but the encryption is not set."
              << "This is unexpected, maybe a concurrent change?\n";
    return;
  }

  std::cout << "Successfully set default KMS key on bucket "
            << updated->name() << " to "
            << updated->encryption().default_kms_key_name << "."
            << "\nFull metadata: " << *updated << "\n";
}

C#

如需了解详情,请参阅 Cloud Storage C# API 参考文档

private void AddBucketDefaultKmsKey(string bucketName,
    string keyLocation, string kmsKeyRing, string kmsKeyName)
{
    string KeyPrefix = $"projects/{s_projectId}/locations/{keyLocation}";
    string FullKeyringName = $"{KeyPrefix}/keyRings/{kmsKeyRing}";
    string FullKeyName = $"{FullKeyringName}/cryptoKeys/{kmsKeyName}";
    var storage = StorageClient.Create();
    var bucket = storage.GetBucket(bucketName, new GetBucketOptions()
    {
        Projection = Projection.Full
    });
    bucket.Encryption = new Bucket.EncryptionData
    {
        DefaultKmsKeyName = FullKeyName
    };
    var updatedBucket = storage.UpdateBucket(bucket, new UpdateBucketOptions()
    {
        // Avoid race conditions.
        IfMetagenerationMatch = bucket.Metageneration,
    });
}

Go

如需了解详情,请参阅 Cloud Storage Go API 参考文档

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

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

// setBucketDefaultKMSKey sets the Cloud KMS encryption key for the bucket.
func setBucketDefaultKMSKey(w io.Writer, bucketName, keyName string) error {
	// bucketName := "bucket-name"
	// keyName := "key"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %v", err)
	}
	defer client.Close()

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

	bucket := client.Bucket(bucketName)
	bucketAttrsToUpdate := storage.BucketAttrsToUpdate{
		Encryption: &storage.BucketEncryption{DefaultKMSKeyName: keyName},
	}
	if _, err := bucket.Update(ctx, bucketAttrsToUpdate); err != nil {
		return fmt.Errorf("Bucket(%q).Update: %v", bucketName, err)
	}
	fmt.Fprintf(w, "Default KMS Key Name: %v", bucketAttrsToUpdate.Encryption.DefaultKMSKeyName)
	return nil
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

// Instantiate a Google Cloud Storage client
Storage storage = StorageOptions.getDefaultInstance().getService();

// The name of the existing bucket to set a default KMS key for, e.g. "my-bucket"
// String bucketName = "my-bucket"

// The name of the KMS-key to use as a default
// Key names are provided in the following format:
// 'projects/<PROJECT>/locations/<LOCATION>/keyRings/<RING_NAME>/cryptoKeys/<KEY_NAME>'
// String kmsKeyName = ""

BucketInfo bucketInfo =
    BucketInfo.newBuilder(bucketName).setDefaultKmsKeyName(kmsKeyName).build();

Bucket bucket = storage.update(bucketInfo);

System.out.println("Default KMS Key Name: " + bucket.getDefaultKmsKeyName());

Node.js

如需了解详情,请参阅 Cloud Storage Node.js API 参考文档

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const defaultKmsKeyName = 'KMS key resource id, e.g. my-key';

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

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

async function enableDefaultKMSKey() {
  await storage.bucket(bucketName).setMetadata({
    encryption: {
      defaultKmsKeyName,
    },
  });

  console.log(
    `Default KMS key for ${bucketName} was set to ${defaultKmsKeyName}.`
  );
}

enableDefaultKMSKey().catch(console.error);

PHP

如需了解详情,请参阅 Cloud Storage PHP API 参考文档

use Google\Cloud\Storage\StorageClient;

/**
 * Enable a bucket's requesterpays metadata.
 *
 * @param string $projectId Your Google Cloud project ID.
 * @param string $bucketName Name of your Google Cloud Storage bucket.
 * @param string $kmsKeyName KMS key ID to use as the default KMS key.
 *
 * @return void
 */
function enable_default_kms_key($projectId, $bucketName, $kmsKeyName)
{
    $storage = new StorageClient([
        'projectId' => $projectId
    ]);
    $bucket = $storage->bucket($bucketName);
    $bucket->update([
        'encryption' => [
            'defaultKmsKeyName' => $kmsKeyName
        ]
    ]);
    printf('Default KMS key for %s was set to %s' . PHP_EOL,
        $bucketName,
        $bucket->info()['encryption']['defaultKmsKeyName']);
}

Python

如需了解详情,请参阅 Cloud Storage Python API 参考文档

from google.cloud import storage

def enable_default_kms_key(bucket_name, kms_key_name):
    """Sets a bucket's default KMS key."""
    # bucket_name = "your-bucket-name"
    # kms_key_name = "projects/PROJ/locations/LOC/keyRings/RING/cryptoKey/KEY"

    storage_client = storage.Client()
    bucket = storage_client.get_bucket(bucket_name)
    bucket.default_kms_key_name = kms_key_name
    bucket.patch()

    print(
        "Set default KMS key for bucket {} to {}.".format(
            bucket.name, bucket.default_kms_key_name
        )
    )

Ruby

如需了解详情,请参阅 Cloud Storage Ruby API 参考文档

# bucket_name     = "Name of your Google Cloud Storage bucket"
# default_kms_key = "KMS key resource id"

require "google/cloud/storage"

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

bucket.default_kms_key = default_kms_key

puts "Default KMS key for #{bucket.name} was set to #{bucket.default_kms_key}"

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个包含以下信息的 .json 文件:

    {
      "encryption": {
        "defaultKmsKeyName": "KEY_RESOURCE"
      }
    }

    其中,KEY_RESOURCE 是您的 Cloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key

  3. 使用 cURL,通过 PATCH Bucket 请求调用 JSON API:

    curl -X PATCH --data-binary @JSON_FILE_NAME.json \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    -H "Content-Type: application/json" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME?fields=encryption"

    其中:

    • JSON_FILE_NAME 是您在第 2 步中创建的文件。
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是相关存储分区的名称,例如 my-bucket

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个包含以下信息的 .xml 文件:

    <EncryptionConfiguration>
      <DefaultKmsKeyName>KEY_RESOURCE</DefaultKmsKeyName>
    </EncryptionConfiguration>

    其中,KEY_RESOURCE 是您的 Cloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key

  3. 使用 cURL,通过 PUT Bucket 请求和 encryption 查询字符串参数调用 XML API:

    curl -X PUT --data-binary @XML_FILE_NAME.xml \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    "https://storage.googleapis.com/BUCKET_NAME?encryptionConfig"

    其中:

    • XML_FILE_NAME 是您在第 2 步中创建的文件。
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是相关存储分区的名称,例如 my-bucket

查看存储分区的默认密钥

要查看当前设为存储分区的默认密钥的 Cloud KMS 密钥,请执行以下操作:

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 在存储分区列表中,点击所需的存储分区。

  3. 在存储分区详情页面中,点击配置标签页。

  4. 存储分区的当前默认密钥显示在加密密钥字段中。

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil kms encryption 命令:

gsutil kms encryption gs://BUCKET_NAME

其中,BUCKET_NAME 是您要查看其密钥的存储分区的名称,例如 my-bucket

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

Default encryption key for gs://my-bucket:
KEY_RESOURCE

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 使用 cURL,通过包含所需 fieldsGET Bucket 请求调用 JSON API:

    curl -X GET -H "Authorization: Bearer OAUTH2_TOKEN" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME?fields=encryption"

    其中:

    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是您要查看其密钥的存储分区的名称,例如 my-bucket

    响应类似如下示例:

    {
      "encryption" : {
         "defaultKmsKeyName": "KEY_RESOURCE"
       },
    }

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 使用 cURL,通过包含 encryption 查询参数的 GET Bucket 请求调用 XML API:

    curl -X GET -H "Authorization: Bearer OAUTH2_TOKEN" \
    "https://storage.googleapis.com/BUCKET_NAME?encryptionConfig"

    其中:

    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是您要查看其密钥的存储分区的名称,例如 my-bucket

    响应类似如下示例:

    <EncryptionConfiguration>
      <DefaultKmsKeyName>KEY_RESOURCE</DefaultKmsKeyName>
    </EncryptionConfiguration>

从存储分区中移除默认密钥

要移除存储分区中设置的任何默认 Cloud KMS 密钥,请执行以下操作:

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 在存储分区列表中,点击所需的存储分区。

  3. 在存储分区详情页面中,点击配置标签页。

  4. 点击与“加密类型”条目关联的铅笔图标

  5. 选择 Google 管理的密钥单选按钮。

  6. 点击保存

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil kms encryption 命令:

gsutil kms encryption -d gs://BUCKET_NAME

其中 BUCKET_NAME 是相关存储分区的名称,例如 my-bucket

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

Clearing default encryption key for gs://my-bucket...

代码示例

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name) {
  StatusOr<gcs::BucketMetadata> updated = client.PatchBucket(
      bucket_name, gcs::BucketMetadataPatchBuilder().ResetEncryption());
  if (!updated) throw std::runtime_error(updated.status().message());

  std::cout << "Successfully removed default KMS key on bucket "
            << updated->name() << "\n";
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

public class RemoveBucketDefaultKMSKey {
  public static void removeBucketDefaultKmsKey(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";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    Bucket bucket = storage.get(bucketName);
    bucket.toBuilder().setDefaultKmsKeyName(null).build().update();

    System.out.println("Default KMS key was removed from " + bucketName);
  }
}

Python

如需了解详情,请参阅 Cloud Storage Python API 参考文档

from google.cloud import storage

def bucket_delete_default_kms_key(bucket_name):
    """Delete a default KMS key of bucket"""
    # bucket_name = "your-bucket-name"

    storage_client = storage.Client()

    bucket = storage_client.get_bucket(bucket_name)
    bucket.default_kms_key_name = None
    bucket.patch()

    print("Default KMS key was removed from {}".format(bucket.name))
    return bucket

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个包含以下信息的 .json 文件:

    {
      "encryption": {
        "defaultKmsKeyName": null
      }
    }
  3. 使用 cURL,通过 PATCH Bucket 请求调用 JSON API:

    curl -X PATCH --data-binary @JSON_FILE_NAME.json \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    -H "Content-Type: application/json" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME?fields=encryption"

    其中:

    • JSON_FILE_NAME 是您在第 2 步中创建的文件。
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是相关存储分区的名称,例如 my-bucket

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个包含以下信息的 .xml 文件:

    <EncryptionConfiguration></EncryptionConfiguration>
  3. 使用 cURL,通过 PUT Bucket 请求和 encryption 查询字符串参数调用 XML API:

    curl -X PUT --data-binary @XML_FILE_NAME.xml \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    "https://storage.googleapis.com/BUCKET_NAME?encryptionConfig"

    其中:

    • XML_FILE_NAME 是您在第 2 步中创建的文件。
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是相关存储分区的名称,例如 my-bucket

使用 Cloud KMS 密钥加密对象

您可以使用 Cloud KMS 密钥加密单个对象。如果您要使用与存储分区上设置的默认密钥不同的密钥,或者您没有在存储分区上设置默认密钥,则此功能非常有用。

控制台

您不能使用 Cloud Console 来加密个别对象。请改用 gsutil 或客户端库。

gsutil

  1. 将以下选项添加到 .boto 配置文件[GSUtil] 部分:

    encryption_key = KEY_RESOURCE

    其中,KEY_RESOURCE 是您的 Cloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key

  2. 按照正常方式将对象写入存储分区,例如使用 gsutil cpgsutil rewrite

代码示例

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& object_name, std::string const& old_csek_key_base64,
   std::string const& new_cmek_key_name) {
  StatusOr<gcs::ObjectMetadata> metadata = client.RewriteObjectBlocking(
      bucket_name, object_name, bucket_name, object_name,
      gcs::SourceEncryptionKey::FromBase64Key(old_csek_key_base64),
      gcs::DestinationKmsKeyName(new_cmek_key_name));
  if (!metadata) throw std::runtime_error(metadata.status().message());

  std::cout << "Changed object " << metadata->name() << " in bucket "
            << metadata->bucket()
            << " from using CSEK to CMEK key.\nFull Metadata: " << *metadata
            << "\n";
}

C#

如需了解详情,请参阅 Cloud Storage C# API 参考文档

        private void UploadEncryptedFileWithKmsKey(string bucketName,
            string keyLocation, string kmsKeyRing, string kmsKeyName,
            string localPath, string objectName = null)
        {
            string KeyPrefix = $"projects/{s_projectId}/locations/{keyLocation}";
            string FullKeyringName = $"{KeyPrefix}/keyRings/{kmsKeyRing}";
            string FullKeyName = $"{FullKeyringName}/cryptoKeys/{kmsKeyName}";

            var storage = StorageClient.Create();
            using (var f = File.OpenRead(localPath))
            {
                objectName = objectName ?? Path.GetFileName(localPath);
                storage.UploadObject(bucketName, objectName, null, f,
                    new UploadObjectOptions()
                    {
                        KmsKeyName = FullKeyName
                    });
                Console.WriteLine($"Uploaded {objectName}.");
            }
        }

Go

如需了解详情,请参阅 Cloud Storage Go API 参考文档

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

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

// uploadWithKMSKey writes an object using Cloud KMS encryption.
func uploadWithKMSKey(w io.Writer, bucket, object, keyName string) error {
	// bucket := "bucket-name"
	// object := "object-name"
	// keyName := "projects/projectId/locations/global/keyRings/keyRingID/cryptoKeys/cryptoKeyID"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %v", err)
	}
	defer client.Close()

	obj := client.Bucket(bucket).Object(object)

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

	// Encrypt the object's contents.
	wc := obj.NewWriter(ctx)
	wc.KMSKeyName = keyName
	if _, err := wc.Write([]byte("top secret")); err != nil {
		return fmt.Errorf("Writer.Write: %v", err)
	}
	if err := wc.Close(); err != nil {
		return fmt.Errorf("Writer.Close: %v", err)
	}
	fmt.Fprintf(w, "Uploaded blob %v with KMS key.\n", object)
	return nil
}

Node.js

如需了解详情,请参阅 Cloud Storage Node.js API 参考文档

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const filename = 'Local file to upload, e.g. ./local/path/to/file.txt';
// const kmsKeyName = 'KMS key resource id, e.g. my-key';

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

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

async function uploadFileWithKmsKey() {
  // Uploads a local file to the bucket with the kms key
  await storage.bucket(bucketName).upload(filename, {
    kmsKeyName,
  });

  console.log(`${filename} uploaded to ${bucketName} using ${kmsKeyName}.`);
}

uploadFileWithKmsKey().catch(console.error);

PHP

如需了解详情,请参阅 Cloud Storage PHP API 参考文档

use Google\Cloud\Storage\StorageClient;

/**
 * Upload a file using KMS encryption.
 *
 * @param string $projectId Your Google Cloud project ID.
 * @param string $bucketName the name of your Google Cloud bucket.
 * @param string $objectName the name of the object.
 * @param string $source the path to the file to upload.
 * @param string $kmsKeyName KMS key ID used to encrypt objects server side.
 *
 * @return Psr\Http\Message\StreamInterface
 */
function upload_with_kms_key($projectId, $bucketName, $objectName, $source, $kmsKeyName)
{
    $storage = new StorageClient([
        'projectId' => $projectId,
    ]);
    $file = fopen($source, 'r');
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->upload($file, [
        'name' => $objectName,
        'destinationKmsKeyName' => $kmsKeyName,
    ]);
    printf('Uploaded %s to gs://%s/%s using encryption key %s' . PHP_EOL,
        basename($source),
        $bucketName,
        $objectName,
        $kmsKeyName);
}

Python

如需了解详情,请参阅 Cloud Storage Python API 参考文档

from google.cloud import storage

def object_csek_to_cmek(bucket_name, blob_name, encryption_key, kms_key_name):
    """Change a blob's customer-supplied encryption key to KMS key"""
    # bucket_name = "your-bucket-name"
    # blob_name = "your-object-name"
    # encryption_key = "TIbv/fjexq+VmtXzAlc63J4z5kFmWJ6NdAPQulQBT7g="
    # kms_key_name = "projects/PROJ/locations/LOC/keyRings/RING/cryptoKey/KEY"

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

    current_encryption_key = base64.b64decode(encryption_key)
    source_blob = bucket.blob(blob_name, encryption_key=current_encryption_key)

    destination_blob = bucket.blob(blob_name, kms_key_name=kms_key_name)
    token, rewritten, total = destination_blob.rewrite(source_blob)

    while token is not None:
        token, rewritten, total = destination_blob.rewrite(source_blob, token=token)

    print(
        "Blob {} in bucket {} is now managed by the KMS key {} instead of a customer-supplied encryption key".format(
            blob_name, bucket_name, kms_key_name
        )
    )
    return destination_blob

Ruby

如需了解详情,请参阅 Cloud Storage Ruby API 参考文档

# bucket_name       = "Your Google Cloud Storage bucket name"
# local_file_path   = "Path to local file to upload"
# storage_file_path = "Path to store the file in Google Cloud Storage"
# kms_key           = "KMS key resource id"

require "google/cloud/storage"

storage = Google::Cloud::Storage.new

bucket = storage.bucket bucket_name

file = bucket.create_file local_file_path, storage_file_path,
                          kms_key: kms_key

puts "Uploaded #{file.name} and encrypted service side using #{file.kms_key}"

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

以下示例使用客户管理的加密密钥对对象进行加密:

byte[] data = "Hello, World!".getBytes(UTF_8);

// The name of the existing bucket to set a default KMS key for, e.g. "my-bucket"
// String bucketName = "my-bucket"

// The name of the KMS-key to use as a default
// Key names are provided in the following format:
// 'projects/<PROJECT>/locations/<LOCATION>/keyRings/<RING_NAME>/cryptoKeys/<KEY_NAME>'
// String kmsKeyName = ""

BlobId blobId = BlobId.of(bucketName, blobName);
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).setContentType("text/plain").build();
Blob blob = storage.create(blobInfo, data, BlobTargetOption.kmsKeyName(kmsKeyName));

以下示例将用于对对象进行加密的密钥从客户提供的加密密钥更改为客户管理的加密密钥:

import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

public class ChangeObjectCSEKtoKMS {
  public static void changeObjectFromCSEKtoKMS(
      String projectId,
      String bucketName,
      String objectName,
      String decryptionKey,
      String kmsKeyName) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

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

    // The ID of your GCS object
    // String objectName = "your-object-name";

    // The Base64 encoded decryption key, which should be the same key originally used to encrypt
    // the object
    // String decryptionKey = "TIbv/fjexq+VmtXzAlc63J4z5kFmWJ6NdAPQulQBT7g=";

    // The name of the KMS key to manage this object with
    // String kmsKeyName =
    // "projects/your-project-id/locations/global/keyRings/your-key-ring/cryptoKeys/your-key";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    BlobId blobId = BlobId.of(bucketName, objectName);
    Storage.CopyRequest request =
        Storage.CopyRequest.newBuilder()
            .setSource(blobId)
            .setSourceOptions(Storage.BlobSourceOption.decryptionKey(decryptionKey))
            .setTarget(blobId, Storage.BlobTargetOption.kmsKeyName(kmsKeyName))
            .build();
    storage.copy(request);

    System.out.println(
        "Object "
            + objectName
            + " in bucket "
            + bucketName
            + " is now managed by the KMS key "
            + kmsKeyName
            + " instead of a customer-supplied encryption key");
  }
}

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 将对象的数据添加到请求正文。

  3. 使用 cURL,通过 POST Object 请求调用 JSON API:

    curl -X POST --data-binary @OBJECT \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    -H "Content-Type: OBJECT_CONTENT_TYPE" \
    "https://storage.googleapis.com/upload/storage/v1/b/BUCKET_NAME/o?uploadType=media&name=OBJECT_NAME&kmsKeyName=KEY_RESOURCE"

    其中:

    • OBJECT 是要上传的对象的路径,例如 Desktop/dog.png
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • OBJECT_CONTENT_TYPE 是该对象的内容类型,例如 image/png
    • BUCKET_NAME 是对象要上传到的存储分区的名称。例如 my-bucket
    • OBJECT_NAME 是要上传的对象的名称,例如 pets/dog.png
    • KEY_RESOURCECloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 将对象的数据添加到请求正文。

  3. 使用 cURL,通过 PUT Object 请求调用 XML API:

    curl -X PUT --data-binary @OBJECT \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    -H "Content-Type: OBJECT_CONTENT_TYPE" \
    -H "x-goog-encryption-kms-key-name: KEY_RESOURCE" \
    "https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME"

    其中:

    • OBJECT 是要上传的对象的路径,例如 Desktop/dog.png
    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • OBJECT_CONTENT_TYPE 是该对象的内容类型,例如 image/png
    • BUCKET_NAME 是对象要上传到的存储分区的名称。例如 my-bucket
    • OBJECT_NAME 是要上传的对象的名称,例如 pets/dog.png
    • KEY_RESOURCE 是您的 Cloud KMS 密钥资源,例如 projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key

确定用于加密对象的密钥

要查找用于加密对象的 Cloud KMS 密钥的名称,请执行以下操作:

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 在存储分区列表中,点击存放所需对象的存储分区的名称。

    此时会打开存储分区详情页面,其中对象标签已选中。

  3. 导航到可能位于文件夹中的对象。

  4. 加密列中,将鼠标悬停在所需对象的条目上。

    密钥名称采用以下格式显示:

    LOCATION/KEY_RING_NAME/KEY_NAME/KEY_VERSION

gsutil

使用 gsutil stat 命令:

gsutil stat gs://BUCKET_NAME/OBJECT_NAME

其中:

  • BUCKET_NAME 是包含加密对象的存储分区的名称,例如 my-bucket
  • OBJECT_NAME 是加密对象的名称, 例如 pets/dog.png

如果成功,则响应会包含密钥名称:

gs://my-bucket/pets/dog.png:
...
KMS key: projects/my-pet-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key
...

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 使用 cURL,通过 GET Object 请求调用 JSON API:

    curl -X GET \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    "https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME?fields=kmsKeyName"

    其中:

    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是包含加密对象的存储分区的名称,例如 my-bucket
    • OBJECT_NAME 是加密对象的名称,例如 pets/dog.png

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 使用 cURL,通过 GET Object 请求调用 XML API:

    curl -X GET \
    -H "Authorization: Bearer OAUTH2_TOKEN" \
    "https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME?encryption"

    其中:

    • OAUTH2_TOKEN 是您在第 1 步中生成的访问令牌。
    • BUCKET_NAME 是包含加密对象的存储分区的名称,例如 my-bucket
    • OBJECT_NAME 是加密对象的名称,例如 pets/dog.png

解密对象

系统会自动解密使用客户管理的加密密钥加密的对象,前提是相关服务帐号有权访问该密钥。如需了解详情,请参阅具有客户管理的加密密钥的服务帐号

后续步骤