将 IAM 与 Cloud KMS 搭配使用

本主题介绍如何管理对 Cloud KMS 资源的访问权限。

概览

要管理对 Cloud KMS 资源(例如密钥和密钥环)的访问权限,您需要授予 Identity and Access Management (IAM) 角色。您可以授予或限制执行特定加密操作的权限,例如轮替密钥或加密数据。您可以针对以下资源授予 IAM 角色:

  • 密钥
  • 密钥环,由密钥环中的所有密钥继承
  • Google Cloud 项目,由项目中的所有密钥继承
  • Google Cloud 文件夹,由文件夹中所有项目中的所有密钥继承
  • Google Cloud 组织,由组织中文件夹中的所有密钥继承

如需查看 Cloud KMS 操作以及 IAM 角色和权限的完整列表,请参阅权限和角色。如需查看 Cloud KMS 资源的完整列表以及这些资源之间的关系,请参阅 Cloud KMS 资源

准备工作

要完成这些任务,您需要具备管理 Google Cloud 项目中的 Cloud KMS 资源的权限。Cloud KMS Admin 角色 (roles/cloudkms.admin) 包含所需的权限。

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册一个新帐号

  2. 在 Cloud Console 的项目选择器页面上,选择或创建 Cloud 项目。

    转到项目选择器页面

  3. 确保您的 Google Cloud 项目已启用结算功能。 了解如何确认您的项目已启用结算功能

  4. 启用所需的 API。

    启用 API

  5. 安装并初始化 Cloud SDK
  6. 创建密钥环和密钥
  7. 获取密钥环、密钥和密钥版本的资源 ID

只有具有 Owner (roles/owner) 或 Cloud KMS Admin (roles/cloudkms.admin) 角色的 IAM 成员才能授予或撤消对 Cloud KMS 资源的访问权限。

针对资源授予角色

以下示例授予一个角色,该角色提供对 Cloud KMS 密钥的访问权限:

命令行

要在命令行上使用 Cloud KMS,请先安装或升级到最新版本的 Cloud SDK

gcloud kms keys add-iam-policy-binding key \
    --keyring key-ring \
    --location location \
    --member member-type:member-email \
    --role roles/role

key 替换为密钥的名称。将 key-ring 替换为密钥所在的密钥环的名称。将 location 替换为密钥环的 Cloud KMS 位置。将 member-typemember-email 替换为成员的类型和成员的电子邮件地址。将 role 替换为要添加的角色的名称。

C#

要运行此代码,请先设置 C# 开发环境安装 Cloud KMS C# SDK


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

要运行此代码,请先设置 Go 开发环境安装 Cloud KMS Go SDK

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

要运行此代码,请先设置 Java 开发环境安装 Cloud KMS Java SDK

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

要运行此代码,请先设置 Node.js 开发环境安装 Cloud KMS Node.js SDK

//
// 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

要运行此代码,请先了解如何在 Google Cloud 上使用 PHP安装 Cloud KMS PHP SDK

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

要运行此代码,请先设置 Python 开发环境安装 Cloud KMS Python SDK

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

要运行此代码,请先设置 Ruby 开发环境安装 Cloud KMS Ruby SDK

# 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}"

撤消对资源的访问权限

要移除成员对 Cloud KMS 密钥的访问权限,请执行以下操作:

命令行

要在命令行上使用 Cloud KMS,请先安装或升级到最新版本的 Cloud SDK

gcloud kms keys remove-iam-policy-binding key \
    --keyring key-ring \
    --location location \
    --member member-type:member-email \
    --role roles/role-name

key 替换为密钥的名称。将 key-ring 替换为密钥所在的密钥环的名称。将 location 替换为密钥环的 Cloud KMS 位置。将 member-typemember-email 替换为成员的类型和成员的电子邮件地址。将 role-name 替换为要移除的角色的名称。

如需了解所有标志和可能值,请使用 --help 标志运行命令。

C#

要运行此代码,请先设置 C# 开发环境安装 Cloud KMS C# SDK


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

public class IamRemoveMemberSample
{
    public Policy IamRemoveMember(
      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.RemoveRoleMember("roles/cloudkms.cryptoKeyEncrypterDecrypter", member);

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

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

Go

要运行此代码,请先设置 Go 开发环境安装 Cloud KMS Go SDK

import (
	"context"
	"fmt"
	"io"

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

// iamRemoveMember removes the IAM member from the Cloud KMS key, if they exist.
func iamRemoveMember(w io.Writer, name, member string) error {
	// NOTE: The resource name can be either a key or a 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.Remove(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

要运行此代码,请先设置 Java 开发环境安装 Cloud KMS Java SDK

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 IamRemoveMember {

  public void iamRemoveMember() 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";
    iamRemoveMember(projectId, locationId, keyRingId, keyId, member);
  }

  // Remove the given IAM membership on the resource, if it exists.
  public void iamRemoveMember(
      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);

      // Search through the bindings and remove matches.
      String roleToFind = "roles/cloudkms.cryptoKeyEncrypterDecrypter";
      for (Binding binding : policy.getBindingsList()) {
        if (binding.getRole().equals(roleToFind) && binding.getMembersList().contains(member)) {
          binding.getMembersList().remove(member);
        }
      }

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

Node.js

要运行此代码,请先设置 Node.js 开发环境安装 Cloud KMS Node.js SDK

//
// 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 iamRemoveMember() {
  // Get the current IAM policy.
  const [policy] = await client.getIamPolicy({
    resource: resourceName,
  });

  // Build a new list of policy bindings with the user excluded.
  for (const i in policy.bindings) {
    const binding = policy.bindings[i];
    if (binding.role !== 'roles/cloudkms.cryptoKeyEncrypterDecrypter') {
      continue;
    }

    const idx = binding.members.indexOf(member);
    if (idx !== -1) {
      binding.members.splice(idx, 1);
    }
  }

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

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

return iamRemoveMember();

PHP

要运行此代码,请先了解如何在 Google Cloud 上使用 PHP安装 Cloud KMS PHP SDK

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

function iam_remove_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);

    // Remove the member from the policy by creating a new policy with everyone
    // but the member to remove.
    $newPolicy = new Policy();
    foreach ($policy->getBindings() as $binding) {
        if ($binding->getRole() !== 'roles/cloudkms.cryptoKeyEncrypterDecrypter') {
            $newPolicy->getBindings()[] = $binding;
        } else {
            $newBinding = (new Binding())
              ->setRole($binding->getRole());

            $newMembers = [];
            foreach ($binding->getMembers() as $existingMember) {
                if ($member !== $existingMember) {
                    $newMembers[] = $existingMember;
                }
            }

            $newPolicy->getBindings()[] = (new Binding())
              ->setRole($binding->getRole())
              ->setMembers($newMembers);
        }
    }

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

Python

要运行此代码,请先设置 Python 开发环境安装 Cloud KMS Python SDK

def iam_remove_member(project_id, location_id, key_ring_id, key_id, member):
    """
    Remove an IAM member from 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 remove (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})

    # Remove the member from the policy.
    for binding in policy.bindings:
        if binding.role == 'roles/cloudkms.cryptoKeyEncrypterDecrypter':
            if member in binding.members:
                binding.members.remove(member)

    # Save the updated IAM policy.
    request = {
        'resource': resource_name,
        'policy': policy
    }
    updated_policy = client.set_iam_policy(request=request)
    print('Removed {} from {}'.format(member, resource_name))
    return updated_policy

Ruby

要运行此代码,请先设置 Ruby 开发环境安装 Cloud KMS Ruby SDK

# 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

# Remove the member from the current bindings
policy.bindings.each do |bind|
  if bind.role == "roles/cloudkms.cryptoKeyEncrypterDecrypter"
    bind.members.delete member
  end
end

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

查看资源权限

如要查看 Cloud KMS 密钥的 IAM 政策,请执行以下操作:

命令行

要在命令行上使用 Cloud KMS,请先安装或升级到最新版本的 Cloud SDK

gcloud kms keys get-iam-policy key \
    --keyring key-ring \
    --location location

key 替换为密钥的名称。将 key-ring 替换为密钥所在的密钥环的名称。将 location 替换为密钥环的 Cloud KMS 位置。

如需了解所有标志和可能值,请使用 --help 标志运行命令。

C#

要运行此代码,请先设置 C# 开发环境安装 Cloud KMS C# SDK


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

public class IamGetPolicySample
{
    public Policy IamGetPolicy(
      string projectId = "my-project", string locationId = "us-east1", string keyRingId = "my-key-ring", string keyId = "my-key")
    {
        // 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);

        // Print the policy.
        foreach (Binding b in policy.Bindings)
        {
            String role = b.Role;

            foreach (String member in b.Members)
            {
                // ...
            }
        }

        // Return the policy.
        return policy;
    }
}

Go

要运行此代码,请先设置 Go 开发环境安装 Cloud KMS Go SDK

import (
	"context"
	"fmt"
	"io"

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

// iamGetPolicy retrieves and prints the Cloud IAM policy associated with the
// Cloud KMS key.
func iamGetPolicy(w io.Writer, name string) error {
	// NOTE: The resource name can be either a key or a key ring.
	//
	// name := "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key"
	// name := "projects/my-project/locations/us-east1/keyRings/my-key-ring"

	// 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 policy.
	policy, err := client.ResourceIAM(name).Policy(ctx)
	if err != nil {
		return fmt.Errorf("failed to get IAM policy: %v", err)
	}

	// Print the policy members.
	for _, role := range policy.Roles() {
		fmt.Fprintf(w, "%s\n", role)
		for _, member := range policy.Members(role) {
			fmt.Fprintf(w, "- %s\n", member)
		}
		fmt.Fprintf(w, "\n")
	}
	return nil
}

Java

要运行此代码,请先设置 Java 开发环境安装 Cloud KMS Java SDK

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 IamGetPolicy {

  public void iamGetPolicy() 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";
    iamGetPolicy(projectId, locationId, keyRingId, keyId);
  }

  // Get the IAM policy for the given key.
  public void iamGetPolicy(String projectId, String locationId, String keyRingId, String keyId)
      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);

      // Print the policy.
      System.out.printf("IAM policy:%n");
      for (Binding binding : policy.getBindingsList()) {
        System.out.printf("%s%n", binding.getRole());
        for (String member : binding.getMembersList()) {
          System.out.printf("- %s%n", member);
        }
      }
    }
  }
}

Node.js

要运行此代码,请先设置 Node.js 开发环境安装 Cloud KMS Node.js SDK

//
// 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 iamGetPolicy() {
  const [policy] = await client.getIamPolicy({
    resource: resourceName,
  });

  for (const binding of policy.bindings) {
    console.log(`Role: ${binding.role}`);
    for (const member of binding.members) {
      console.log(`  - ${member}`);
    }
  }

  return policy;
}

return iamGetPolicy();

PHP

要运行此代码,请先了解如何在 Google Cloud 上使用 PHP安装 Cloud KMS PHP SDK

use Google\Cloud\Kms\V1\KeyManagementServiceClient;

function iam_get_policy_sample(
    string $projectId = 'my-project',
    string $locationId = 'us-east1',
    string $keyRingId = 'my-key-ring',
    string $keyId = 'my-key'
) {
    // 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);

    // Print the policy.
    printf('IAM policy for %s' . PHP_EOL, $resourceName);
    foreach ($policy->getBindings() as $binding) {
        printf('%s' . PHP_EOL, $binding->getRole());

        foreach ($binding->getMembers() as $member) {
            printf('- %s' . PHP_EOL, $member);
        }
    }

    return $policy;
}

Python

要运行此代码,请先设置 Python 开发环境安装 Cloud KMS Python SDK

def iam_get_policy(project_id, location_id, key_ring_id, key_id):
    """
    Get the IAM policy for 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').

    Returns:
        Policy: 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})

    # Print the policy
    print('IAM policy for {}'.format(resource_name))
    for binding in policy.bindings:
        print(binding.role)
        for member in binding.members:
            print('- {}'.format(member))

    return policy

Ruby

要运行此代码,请先设置 Ruby 开发环境安装 Cloud KMS Ruby SDK

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

  # 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

  # Print the policy.
  puts "Policy for #{resource_name}"
  policy.bindings.each do |bind|
    puts bind.role.to_s
    bind.members.each do |member|
      puts "- #{member}"
    end
  end

  policy
end

def iam_remove_member project_id:, location_id:, key_ring_id:, key_id:, member:
  # 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

  # Remove the member from the current bindings
  policy.bindings.each do |bind|
    if bind.role == "roles/cloudkms.cryptoKeyEncrypterDecrypter"
      bind.members.delete member
    end
  end

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

  updated_policy
end

def quickstart project_id:, location_id:
  # TODO(developer): uncomment these values before running the sample.
  # project_id  = "my-project"
  # location_id = "us-east1"

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

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

  # Build the parent location name.
  location_name = client.location_path project: project_id, location: location_id

  # Call the API.
  key_rings = client.list_key_rings parent: location_name

  # Example of iterating over key rings.
  puts "Key rings in #{location_name}"
  key_rings.each do |key_ring|
    puts key_ring.name.to_s
  end

  key_rings
end

def restore_key_version project_id:, location_id:, key_ring_id:, key_id:, version_id:
  # 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"
  # version_id  = "123"

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

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

  # Build the key version name.
  key_version_name = client.crypto_key_version_path project:            project_id,
                                                    location:           location_id,
                                                    key_ring:           key_ring_id,
                                                    crypto_key:         key_id,
                                                    crypto_key_version: version_id

  # Call the API.
  restored_version = client.restore_crypto_key_version name: key_version_name
  puts "Restored key version: #{restored_version.name}"

  restored_version
end

def sign_asymmetric project_id:, location_id:, key_ring_id:, key_id:, version_id:, message:
  # 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"
  # version_id  = "123"
  # message     = "my message"

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

  # Require digest.
  require "digest"

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

  # Build the key version name.
  key_version_name = client.crypto_key_version_path project:            project_id,
                                                    location:           location_id,
                                                    key_ring:           key_ring_id,
                                                    crypto_key:         key_id,
                                                    crypto_key_version: version_id

  # Calculate the hash.
  #
  # Note: Key algorithms will require a varying hash function. For
  # example, EC_SIGN_P384_SHA384 requires SHA-384.
  digest = { sha256: Digest::SHA256.digest(message) }

  # Call the API.
  sign_response = client.asymmetric_sign name: key_version_name, digest: digest
  puts "Signature: #{Base64.strict_encode64 sign_response.signature}"

  sign_response
end

def update_key_add_rotation project_id:, location_id:, key_ring_id:, key_id:
  # 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"

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

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

  # Build the parent key name.
  key_name = client.crypto_key_path project:    project_id,
                                    location:   location_id,
                                    key_ring:   key_ring_id,
                                    crypto_key: key_id

  # Build the key.
  key = {
    name:               key_name,

    # Rotate the key every 30 days.
    rotation_period:    {
      seconds: 60 * 60 * 24 * 30
    },

    # Start the first rotation in 24 hours.
    next_rotation_time: {
      seconds: (Time.now + 60 * 60 * 24).to_i
    }
  }

  # Build the field mask.
  update_mask = { paths: ["rotation_period", "next_rotation_time"] }

  # Call the API.
  updated_key = client.update_crypto_key crypto_key: key, update_mask: update_mask
  puts "Updated key: #{updated_key.name}"

  updated_key
end

def update_key_remove_labels project_id:, location_id:, key_ring_id:, key_id:
  # 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"

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

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

  # Build the parent key name.
  key_name = client.crypto_key_path project:    project_id,
                                    location:   location_id,
                                    key_ring:   key_ring_id,
                                    crypto_key: key_id

  # Build the key.
  key = {
    name:   key_name,
    labels: {}
  }

  # Build the field mask.
  update_mask = { paths: ["labels"] }

  # Call the API.
  updated_key = client.update_crypto_key crypto_key: key, update_mask: update_mask
  puts "Updated key: #{updated_key.name}"

  updated_key
end

def update_key_remove_rotation project_id:, location_id:, key_ring_id:, key_id:
  # 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"

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

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

  # Build the parent key name.
  key_name = client.crypto_key_path project:    project_id,
                                    location:   location_id,
                                    key_ring:   key_ring_id,
                                    crypto_key: key_id

  # Build the key.
  key = {
    name:               key_name,
    rotation_period:    nil,
    next_rotation_time: nil
  }

  # Build the field mask.
  update_mask = { paths: ["rotation_period", "next_rotation_time"] }

  # Call the API.
  updated_key = client.update_crypto_key crypto_key: key, update_mask: update_mask
  puts "Updated key: #{updated_key.name}"

  updated_key
end

def update_key_set_primary project_id:, location_id:, key_ring_id:, key_id:, version_id:
  # 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"
  # version_id  = "123"

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

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

  # Build the parent key name.
  key_name = client.crypto_key_path project:    project_id,
                                    location:   location_id,
                                    key_ring:   key_ring_id,
                                    crypto_key: key_id

  # Call the API.
  updated_key = client.update_crypto_key_primary_version name: key_name, crypto_key_version_id: version_id
  puts "Updated primary #{updated_key.name} to #{version_id}"

  updated_key
end

def update_key_update_labels project_id:, location_id:, key_ring_id:, key_id:
  # 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"

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

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

  # Build the parent key name.
  key_name = client.crypto_key_path project:    project_id,
                                    location:   location_id,
                                    key_ring:   key_ring_id,
                                    crypto_key: key_id

  # Build the key.
  key = {
    name:   key_name,
    labels: {
      "new_label" => "new_value"
    }
  }

  # Build the field mask.
  update_mask = { paths: ["labels"] }

  # Call the API.
  updated_key = client.update_crypto_key crypto_key: key, update_mask: update_mask
  puts "Updated key: #{updated_key.name}"

  updated_key
end

def verify_asymmetric_signature_ec project_id:, location_id:, key_ring_id:, key_id:, version_id:, message:, signature:
  # 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"
  # version_id  = "123"
  # message     = "my message"
  # signature   = "..."

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

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

  # Build the key version name.
  key_version_name = client.crypto_key_version_path project:            project_id,
                                                    location:           location_id,
                                                    key_ring:           key_ring_id,
                                                    crypto_key:         key_id,
                                                    crypto_key_version: version_id

  # Get the public key.
  public_key = client.get_public_key name: key_version_name

  # Parse the public key.
  ec_key = OpenSSL::PKey::EC.new public_key.pem

  # Verify the signature.
  verified = ec_key.verify "sha256", signature, message
  puts "Verified: #{verified}"

  verified
end

if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.5.0")
  def verify_asymmetric_signature_rsa project_id:, location_id:, key_ring_id:, key_id:, version_id:, message:,
                                      signature:
    # 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"
    # version_id  = "123"
    # message     = "my message"
    # signature   = "..."

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

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

    # Build the key version name.
    key_version_name = client.crypto_key_version_path project:            project_id,
                                                      location:           location_id,
                                                      key_ring:           key_ring_id,
                                                      crypto_key:         key_id,
                                                      crypto_key_version: version_id

    # Get the public key.
    public_key = client.get_public_key name: key_version_name

    # Parse the public key.
    rsa_key = OpenSSL::PKey::RSA.new public_key.pem

    # Verify the signature.
    #
    # Note: The verify_pss() method only exists in Ruby 2.5+.
    verified = rsa_key.verify_pss "sha256", signature, message, salt_length: :digest, mgf1_hash: "sha256"
    puts "Verified: #{verified}"

    verified
  end
end

if $PROGRAM_NAME == __FILE__
  methods = (public_methods(false) - [:inspect, :to_s]).sort
  args = ARGV.dup
  help = ARGV.any? { |a| ["help", "--help", "h"].include? a }

  command = args.shift
  project = ENV["GOOGLE_CLOUD_PROJECT"]

  if help || command.nil? || command.empty?
    out = "Usage: bundle exec ruby #{__FILE__} [command] [arguments]\n"
    out << "\n"

    out << "Commands:\n"
    methods.each do |method_name|
      out << "  " << method_name.to_s
      public_method(method_name).parameters.each do |_, param|
        next if param == :project_id
        out << " " << param.to_s.upcase
      end
      out << "\n"
    end

    out << "\n"
    out << "Environment variables:\n"
    out << "  GOOGLE_CLOUD_PROJECT"

    puts out
  elsif !methods.include?(command.to_sym)
    puts <<~MSG.strip
      Invalid command `#{command}`.
      Run with --help for help and usage instructions.
    MSG
    exit 1
  else
    kwargs = {}

    public_method(command.to_sym).parameters.each do |_, param|
      if param == :project_id
        kwargs[:project_id] = project
      else
        val = args.shift
        if val.nil? || val.empty? # rubocop:disable Metrics/BlockNesting
          puts "Missing required parameter '#{param}' for command '#{command}'."
          exit 1
        end
        kwargs[param] = val
      end
    end

    public_send(command.to_sym, **kwargs)
  end
end

最小权限原则

要遵循最小权限原则,请向资源层次结构中的最低对象授予最有限的权限集。

  • 要授予成员加密(但不解密)数据的权限,请在密钥上授予 roles/cloudkms.cryptoKeyEncrypter 角色。

  • 要授予成员加密和解密数据的权限,请在密钥上授予 roles/cloudkms.cryptoKeyEncrypterDecrypter 角色。

  • 要授予成员验证(但不签署)数据的权限,请在密钥上授予 roles/cloudkms.publicKeyViewer 角色。

  • 要授予成员签署和验证数据的权限,请在密钥上授予 roles/cloudkms.signerVerifier 角色。

  • 要向成员授予管理密钥的权限,请在密钥上授予 roles/cloudkms.admin 角色。

但并不仅限于此。如需了解权限和角色的完整列表,请参阅 Cloud KMS 权限和角色

层次结构和继承

您可以在项目、密钥环、密钥、导入作业和其他 Cloud KMS 资源上指定政策绑定。

由于密钥属于密钥环,密钥环属于项目,因此在相应层次结构中具有特定角色或权限的成员将继承对子资源的相同权限。也就是说,项目中具有 owner 角色的用户同时也是该项目中所有密钥环和密钥的 owner。同样,如果用户被授予针对密钥环的 cloudkms.admin 角色,则他们对该密钥环中的密钥具有相关权限。

反过来却不成立。也就是说,对密钥具有权限但未被授予针对父密钥环权限的用户对该密钥环没有权限。

后续步骤