创建和管理服务帐号密钥

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本页面介绍了如何使用 Google Cloud Console、Google Cloud CLIIdentity and Access Management API 或某个 Google Cloud 客户端库来创建和管理服务帐号密钥。

准备工作

所需的角色

如需获得管理服务帐号密钥所需的权限,请让管理员向您授予项目的 Service Account Key Admin (roles/iam.serviceAccountKeyAdmin) IAM 角色或者您要管理其密钥的服务帐号。如需详细了解如何授予角色,请参阅管理访问权限

如需了解详情,请参阅服务帐号角色

IAM 基本角色还包含管理服务帐号密钥的权限。您不应在生产环境中授予基本角色,但可以在开发或测试环境中授予这些角色。

创建服务帐号密钥

如要在 Google Cloud 之外(例如在其他平台上或在本地)使用服务帐号,您必须首先确定服务帐号的身份。为确保安全地实现此目标,您可以使用公钥/私钥对。 创建服务帐号密钥时,公共部分存储在 Google Cloud 上,而不公开部分仅供您使用。如需详细了解公钥/私钥对,请参阅服务帐号密钥

您可以使用 Google Cloud 控制台、gcloud CLI、serviceAccounts.keys.create() 方法或某种客户端库创建服务帐号密钥。一个服务帐号最多可以有 10 个密钥。

在下面的示例中,SA_NAME 是您的服务帐号的名称,而 PROJECT_ID 是您的 Google Cloud 项目的 ID。您可以从 Google Cloud 控制台中的服务帐号页面检索 SA_NAME@PROJECT_ID.iam.gserviceaccount.com 字符串。

控制台

  1. 在 Google Cloud 控制台中,转到服务帐号页面。

    转到“服务帐号”

  2. 选择一个项目。
  3. 服务帐号页面上,点击要为其创建密钥的服务帐号的电子邮件地址。
  4. 点击密钥标签页。
  5. 点击添加密钥下拉菜单,然后选择创建新密钥
  6. 选择 JSON 作为密钥类型,然后点击创建

点击创建即会下载服务帐号密钥文件。下载密钥文件后,您无法再次下载。

下载的密钥采用以下格式,其中 PRIVATE_KEY 是公钥/私钥对的私钥部分:

{
  "type": "service_account",
  "project_id": "PROJECT_ID",
  "private_key_id": "KEY_ID",
  "private_key": "-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY\n-----END PRIVATE KEY-----\n",
  "client_email": "SERVICE_ACCOUNT_EMAIL",
  "client_id": "CLIENT_ID",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/SERVICE_ACCOUNT_EMAIL"
}

务必要安全存储密钥文件,因为它能够以服务帐号的身份进行身份验证。您可以根据需要移动并重命名此文件。

您可以使用服务帐号密钥文件来将应用作为服务帐号进行身份验证

gcloud

执行 gcloud iam service-accounts keys create 命令来创建服务帐号密钥。

替换以下值:

  • KEY_FILE:私钥的新输出文件的路径,例如 ~/sa-private-key.json
  • SA_NAME:要为其创建密钥的服务帐号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
gcloud iam service-accounts keys create KEY_FILE \
    --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

输出:

created key [e44da1202f82f8f4bdd9d92bc412d1d8a837fa83] of type [json] as
[/usr/home/username/KEY_FILE] for
[SA_NAME@PROJECT_ID.iam.gserviceaccount.com]

现在,服务帐号密钥文件已下载到您的机器上。下载密钥文件后,您无法再次下载。

下载的密钥采用以下格式,其中 PRIVATE_KEY 是公钥/私钥对的私有部分:

{
  "type": "service_account",
  "project_id": "PROJECT_ID",
  "private_key_id": "KEY_ID",
  "private_key": "-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY\n-----END PRIVATE KEY-----\n",
  "client_email": "SERVICE_ACCOUNT_EMAIL",
  "client_id": "CLIENT_ID",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/SERVICE_ACCOUNT_EMAIL"
}

务必要安全存储密钥文件,因为它能够以服务帐号的身份进行身份验证。您可以根据需要移动并重命名此文件。

您可以使用服务帐号密钥文件来将应用作为服务帐号进行身份验证

REST

projects.serviceAccounts.keys.create 方法可为服务帐号创建密钥。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_NAME:您要为其创建密钥的服务帐号的名称。
  • KEY_ALGORITHM:可选。用于密钥的密钥算法。默认值(随时可能更改)为 2048 位 RSA 密钥。如需查看所有可能值的列表,请参阅 ServiceAccountKeyAlgorithm 参考文档

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys

请求 JSON 正文:

{
  "keyAlgorithm": "KEY_ALGORITHM"
}

如需发送您的请求,请展开以下选项之一:

响应中包含您的服务帐号的密钥。返回的密钥采用以下格式,其中 ENCODED_PRIVATE_KEY 是公钥/私钥对的私有部分,采用 base64 编码。

{
  "name": "projects/PROJECT_ID/serviceAccounts/SERVICE_ACCOUNT_EMAIL/keys/KEY_ID",
  "privateKeyType": "TYPE_GOOGLE_CREDENTIALS_FILE",
  "privateKeyData": "ENCODED_PRIVATE_KEY",
  "validAfterTime": "DATE",
  "validBeforeTime": "DATE",
  "keyAlgorithm": "KEY_ALG_RSA_2048"
}

如要创建可用于以服务帐号身份进行身份验证的密钥文件,请解码私钥数据并将其保存在文件中:

Linux

运行以下命令:

echo 'ENCODED_PRIVATE_KEY' | base64 --decode > PATH

PATH 替换为您要保存密钥的文件的路径。使用 .json 文件扩展名。

macOS

运行以下命令:

echo 'ENCODED_PRIVATE_KEY' | base64 --decode > PATH

PATH 替换为您要保存密钥的文件的路径。使用 .json 文件扩展名。

PowerShell

  1. 将已编码的私钥数据 (ENCODED_PRIVATE_KEY) 保存在文件中。

  2. 使用 certutil 对文件进行解码:

    certutil -decode ENCODED_FILE DECODED_FILE
    

    替换以下值:

    • ENCODED_FILE:包含已编码私钥数据的文件的路径。
    • DECODED_FILE:您要在其中保存密钥的文件的路径。使用 .json 文件扩展名。

务必要安全存储密钥数据,因为它能够以服务帐号的身份进行身份验证。

您可以使用服务帐号密钥文件来将应用作为服务帐号进行身份验证

C++

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

namespace iam = ::google::cloud::iam;
return [](std::string const& name) {
  iam::IAMClient client(iam::MakeIAMConnection());
  auto response = client.CreateServiceAccountKey(
      name,
      google::iam::admin::v1::ServiceAccountPrivateKeyType::
          TYPE_GOOGLE_CREDENTIALS_FILE,
      google::iam::admin::v1::ServiceAccountKeyAlgorithm::KEY_ALG_RSA_2048);
  if (!response) throw std::runtime_error(response.status().message());
  std::cout << "ServiceAccountKey successfully created: "
            << response->DebugString() << "\n"
            << "Please save the key in a secure location, as they cannot "
               "be downloaded later\n";
  return response->name();
}

C#

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


using System;
using System.Text;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Iam.v1;
using Google.Apis.Iam.v1.Data;

public partial class ServiceAccountKeys
{
    public static ServiceAccountKey CreateKey(string serviceAccountEmail)
    {
        var credential = GoogleCredential.GetApplicationDefault()
            .CreateScoped(IamService.Scope.CloudPlatform);
        var service = new IamService(new IamService.Initializer
        {
            HttpClientInitializer = credential
        });

        var key = service.Projects.ServiceAccounts.Keys.Create(
            new CreateServiceAccountKeyRequest(),
            "projects/-/serviceAccounts/" + serviceAccountEmail)
            .Execute();

        // The PrivateKeyData field contains the base64-encoded service account key
        // in JSON format.
        // TODO(Developer): Save the below key (jsonKeyFile) to a secure location.
        //  You cannot download it later.
        byte[] valueBytes = System.Convert.FromBase64String(key.PrivateKeyData);
        string jsonKeyContent = Encoding.UTF8.GetString(valueBytes);

        Console.WriteLine("Key created successfully");
        return key;
    }
}

Go

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

import (
	"context"
	// "encoding/base64"
	"fmt"
	"io"

	iam "google.golang.org/api/iam/v1"
)

// createKey creates a service account key.
func createKey(w io.Writer, serviceAccountEmail string) (*iam.ServiceAccountKey, error) {
	ctx := context.Background()
	service, err := iam.NewService(ctx)
	if err != nil {
		return nil, fmt.Errorf("iam.NewService: %v", err)
	}

	resource := "projects/-/serviceAccounts/" + serviceAccountEmail
	request := &iam.CreateServiceAccountKeyRequest{}
	key, err := service.Projects.ServiceAccounts.Keys.Create(resource, request).Do()
	if err != nil {
		return nil, fmt.Errorf("Projects.ServiceAccounts.Keys.Create: %v", err)
	}
	// The PrivateKeyData field contains the base64-encoded service account key
	// in JSON format.
	// TODO(Developer): Save the below key (jsonKeyFile) to a secure location.
	// You cannot download it later.
	// jsonKeyFile, _ := base64.StdEncoding.DecodeString(key.PrivateKeyData)
	fmt.Fprintf(w, "Key created successfully")
	return key, nil
}

Java

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


import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.iam.v1.Iam;
import com.google.api.services.iam.v1.IamScopes;
import com.google.api.services.iam.v1.model.CreateServiceAccountKeyRequest;
import com.google.api.services.iam.v1.model.ServiceAccountKey;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Base64;
import java.util.Collections;

public class CreateServiceAccountKey {

  // Creates a key for a service account.
  public static String createKey(String projectId, String serviceAccountName) {
    // String projectId = "my-project-id";
    // String serviceAccountName = "my-service-account-name";

    Iam service = null;
    try {
      service = initService();
    } catch (IOException | GeneralSecurityException e) {
      System.out.println("Unable to initialize service: \n" + e);
      return null;
    }

    String serviceAccountEmail = serviceAccountName + "@" + projectId + ".iam.gserviceaccount.com";
    try {
      ServiceAccountKey key =
          service
              .projects()
              .serviceAccounts()
              .keys()
              .create(
                  "projects/-/serviceAccounts/" + serviceAccountEmail,
                  new CreateServiceAccountKeyRequest())
              .execute();

      // The privateKeyData field contains the base64-encoded service account key
      // in JSON format.
      // TODO(Developer): Save the below key (jsonKeyFile) to a secure location.
      //  You cannot download it later.
      String jsonKeyFile = new String(Base64.getDecoder().decode(key.getPrivateKeyData()));

      System.out.println("Key created successfully");
      String keyName = key.getName();
      return keyName.substring(keyName.lastIndexOf("/") + 1).trim();
    } catch (IOException e) {
      System.out.println("Unable to create service account key: \n" + e);
      return null;
    }
  }

  private static Iam initService() throws GeneralSecurityException, IOException {
    // Use the Application Default Credentials strategy for authentication. For more info, see:
    // https://cloud.google.com/docs/authentication/production#finding_credentials_automatically
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(IamScopes.CLOUD_PLATFORM));
    // Initialize the IAM service, which can be used to send requests to the IAM API.
    Iam service =
        new Iam.Builder(
            GoogleNetHttpTransport.newTrustedTransport(),
            JacksonFactory.getDefaultInstance(),
            new HttpCredentialsAdapter(credential))
            .setApplicationName("service-account-keys")
            .build();
    return service;
  }
}

Python

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

import os

from google.oauth2 import service_account
import googleapiclient.discovery

def create_key(service_account_email):
    """Creates a key for a service account."""

    credentials = service_account.Credentials.from_service_account_file(
        filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
        scopes=['https://www.googleapis.com/auth/cloud-platform'])

    service = googleapiclient.discovery.build(
        'iam', 'v1', credentials=credentials)

    key = service.projects().serviceAccounts().keys().create(
        name='projects/-/serviceAccounts/' + service_account_email, body={}
        ).execute()

    # The privateKeyData field contains the base64-encoded service account key
    # in JSON format.
    # TODO(Developer): Save the below key {json_key_file} to a secure location.
    #  You cannot download it again later.
    # import base64
    # json_key_file = base64.b64decode(key['privateKeyData']).decode('utf-8')

    if not key['disabled']:
        print('Created json key')

列出服务帐号密钥

您可以使用 Google Cloud 控制台、gcloud CLI、serviceAccount.keys.list() 方法或某个客户端库列出服务帐号的密钥。

serviceAccount.keys.list() 方法通常用于审核服务帐号和密钥,或者构建用于管理服务帐号的自定义工具。

要了解您的密钥属于哪个项目,您可以以 JSON 文件的格式下载该密钥并查看该文件。

您可能会发现有些列出的密钥并不是由您创建的。这些密钥由 Google 创建,由 Service Account Credentials API 使用。如需了解详情,请参阅 Google 管理的密钥对

控制台

  1. 在 Google Cloud 控制台中,转到服务帐号页面。

    转到“服务帐号”

  2. 选择一个项目。
  3. 服务帐号页面上,点击要列出其密钥的服务帐号的电子邮件地址。
  4. 点击密钥。 Google Cloud 控制台会显示该服务帐号的密钥列表。

gcloud

执行 gcloud iam service-accounts keys list 命令来列出服务帐号密钥。

替换以下值:

  • SA_NAME:要为其列出密钥的服务帐号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
gcloud iam service-accounts keys list \
    --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

输出:

KEY_ID CREATED_AT EXPIRES_AT 已停用
8e6e3936d7024646f8ceb39792006c07f4a9760c 2021-01-01T21:01:42Z 9999-12-31T23:59:59Z  
937c98f870f5c8db970af527aa3c12fd88b1c20a 2021-01-01T20:55:40Z 9999-12-31T23:59:59Z True

REST

projects.serviceAccounts.keys.list 方法可列出服务帐号的所有服务帐号密钥。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_NAME:您要列出其密钥的服务帐号的名称。
  • KEY_TYPES:可选。您想要在响应中包含的密钥类型的英文逗号分隔列表。密钥类型会指出密钥是由用户管理 (USER_MANAGED) 还是由系统管理 (SYSTEM_MANAGED)。如果留空,则返回所有密钥。

HTTP 方法和网址:

GET https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys?keyTypes=KEY_TYPES

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "keys": [
    {
      "name": "projects/my-project/serviceAccounts/my-service-account@my-project.iam.gserviceaccount.com/keys/90c48f61c65cd56224a12ab18e6ee9ca9c3aee7c",
      "validAfterTime": "2020-03-04T17:39:47Z",
      "validBeforeTime": "9999-12-31T23:59:59Z",
      "keyAlgorithm": "KEY_ALG_RSA_2048",
      "keyOrigin": "GOOGLE_PROVIDED",
      "keyType": "USER_MANAGED"
    },
    {
      "name": "projects/my-project/serviceAccounts/my-service-account@my-project.iam.gserviceaccount.com/keys/e5e3800831ac1adc8a5849da7d827b4724b1fce8",
      "validAfterTime": "2020-03-31T23:50:09Z",
      "validBeforeTime": "9999-12-31T23:59:59Z",
      "keyAlgorithm": "KEY_ALG_RSA_2048",
      "keyOrigin": "GOOGLE_PROVIDED",
      "keyType": "USER_MANAGED"
    },
    {
      "name": "projects/my-project/serviceAccounts/my-service-account@my-project.iam.gserviceaccount.com/keys/b97699f042b8eee6a846f4f96259fbcd13e2682e",
      "validAfterTime": "2020-05-17T18:58:13Z",
      "validBeforeTime": "9999-12-31T23:59:59Z",
      "keyAlgorithm": "KEY_ALG_RSA_2048",
      "keyOrigin": "GOOGLE_PROVIDED",
      "keyType": "USER_MANAGED",
      "disabled": true
    }
  ]
}

C++

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

namespace iam = ::google::cloud::iam;
[](std::string const& service_account_name,
   std::vector<std::string> const& key_type_labels) {
  iam::IAMClient client(iam::MakeIAMConnection());
  std::vector<google::iam::admin::v1::ListServiceAccountKeysRequest::KeyType>
      key_types;
  for (auto const& type : key_type_labels) {
    if (type == "USER_MANAGED") {
      key_types.push_back(google::iam::admin::v1::
                              ListServiceAccountKeysRequest::USER_MANAGED);
    } else if (type == "SYSTEM_MANAGED") {
      key_types.push_back(google::iam::admin::v1::
                              ListServiceAccountKeysRequest::SYSTEM_MANAGED);
    }
  }
  auto response =
      client.ListServiceAccountKeys(service_account_name, key_types);
  if (!response) throw std::runtime_error(response.status().message());
  std::cout << "ServiceAccountKeys successfully retrieved: "
            << response->DebugString() << "\n";
}

C#

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


using System;
using System.Collections.Generic;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Iam.v1;
using Google.Apis.Iam.v1.Data;

public partial class ServiceAccountKeys
{
    public static IList<ServiceAccountKey> ListKeys(string serviceAccountEmail)
    {
        var credential = GoogleCredential.GetApplicationDefault()
            .CreateScoped(IamService.Scope.CloudPlatform);
        var service = new IamService(new IamService.Initializer
        {
            HttpClientInitializer = credential
        });

        var response = service.Projects.ServiceAccounts.Keys
            .List($"projects/-/serviceAccounts/{serviceAccountEmail}")
            .Execute();
        foreach (ServiceAccountKey key in response.Keys)
        {
            Console.WriteLine("Key: " + key.Name);
        }
        return response.Keys;
    }
}

Go

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

import (
	"context"
	"fmt"
	"io"

	iam "google.golang.org/api/iam/v1"
)

// listKey lists a service account's keys.
func listKeys(w io.Writer, serviceAccountEmail string) ([]*iam.ServiceAccountKey, error) {
	ctx := context.Background()
	service, err := iam.NewService(ctx)
	if err != nil {
		return nil, fmt.Errorf("iam.NewService: %v", err)
	}

	resource := "projects/-/serviceAccounts/" + serviceAccountEmail
	response, err := service.Projects.ServiceAccounts.Keys.List(resource).Do()
	if err != nil {
		return nil, fmt.Errorf("Projects.ServiceAccounts.Keys.List: %v", err)
	}
	for _, key := range response.Keys {
		fmt.Fprintf(w, "Listing key: %v", key.Name)
	}
	return response.Keys, nil
}

Java

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

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.iam.v1.Iam;
import com.google.api.services.iam.v1.IamScopes;
import com.google.api.services.iam.v1.model.ServiceAccountKey;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;

public class ListServiceAccountKeys {

  // Lists all keys for a service account.
  public static void listKeys(String projectId, String serviceAccountName) {
    // String projectId = "my-project-id";
    // String serviceAccountName = "my-service-account-name";

    Iam service = null;
    try {
      service = initService();
    } catch (IOException | GeneralSecurityException e) {
      System.out.println("Unable to initialize service: \n" + e.toString());
      return;
    }

    String serviceAccountEmail = serviceAccountName + "@" + projectId + ".iam.gserviceaccount.com";
    try {
      List<ServiceAccountKey> keys =
          service
              .projects()
              .serviceAccounts()
              .keys()
              .list("projects/-/serviceAccounts/" + serviceAccountEmail)
              .execute()
              .getKeys();

      for (ServiceAccountKey key : keys) {
        System.out.println("Key: " + key.getName());
      }
    } catch (IOException e) {
      System.out.println("Unable to list service account keys: \n" + e.toString());
    }
  }

  private static Iam initService() throws GeneralSecurityException, IOException {
    // Use the Application Default Credentials strategy for authentication. For more info, see:
    // https://cloud.google.com/docs/authentication/production#finding_credentials_automatically
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(IamScopes.CLOUD_PLATFORM));
    // Initialize the IAM service, which can be used to send requests to the IAM API.
    Iam service =
        new Iam.Builder(
                GoogleNetHttpTransport.newTrustedTransport(),
                JacksonFactory.getDefaultInstance(),
                new HttpCredentialsAdapter(credential))
            .setApplicationName("service-account-keys")
            .build();
    return service;
  }
}

Python

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

import os

from google.oauth2 import service_account
import googleapiclient.discovery

def list_keys(service_account_email):
    """Lists all keys for a service account."""

    credentials = service_account.Credentials.from_service_account_file(
        filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
        scopes=['https://www.googleapis.com/auth/cloud-platform'])

    service = googleapiclient.discovery.build(
        'iam', 'v1', credentials=credentials)

    keys = service.projects().serviceAccounts().keys().list(
        name='projects/-/serviceAccounts/' + service_account_email).execute()

    for key in keys['keys']:
        print('Key: ' + key['name'])

获取服务帐号密钥

您可以使用 gcloud CLI 或 REST API 获取一个服务帐号密钥的公钥数据。此外还可以使用 Google Cloud 控制台、gcloud CLI 或 REST API 来获取密钥的元数据,例如密钥使用的算法,以及密钥是由您管理还是由 Google 管理。

控制台

如需获取服务帐号密钥的公钥数据,请执行以下操作

使用 gcloud CLI 或 REST API。Google Cloud 控制台中不提供这些操作。

如需获取服务帐号密钥的元数据,请执行以下操作

  1. 在 Google Cloud 控制台中,转到服务帐号页面。

    转到“服务帐号”

  2. 选择一个项目。
  3. 服务帐号页面上,点击要列出其密钥的服务帐号的电子邮件地址。
  4. 点击密钥。 Google Cloud 控制台会显示服务帐号的密钥列表,其中包括各密钥的元数据。

gcloud

如需获取服务帐号密钥的公钥数据,请执行以下操作

运行 gcloud beta iam service-accounts keys get-public-key 命令:

gcloud beta iam service-accounts keys get-public-key KEY_ID \
    --iam-account=SA_NAME --output-file=FILENAME

请提供以下值:

  • KEY_ID:您要获取的公钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要获取的密钥,然后复制其 ID。
  • SA_NAME:您要获取其公钥的服务帐号的名称。
  • FILENAME:要在其中保存公钥数据的文件。

默认情况下,公钥数据使用 X.509 PEM 格式保存。如需获取原始公钥,请运行带有附加标志 --type=raw 的该命令。

例如,以下命令会获取属于服务帐号 my-service-account@my-project.iam.gserviceaccount.com 的密钥 c97cc34494c07c9b483701f28368f20145b9ef97 的公钥数据,然后将公钥数据保存到 public_key.pem 文件中:

gcloud beta iam service-accounts keys get-public-key \
    c97cc34494c07c9b483701f28368f20145b9ef97 \
    --iam-account=my-service-account@my-project.iam.gserviceaccount.com \
    --output-file=public_key.pem

如需获取服务帐号密钥的元数据,请执行以下操作

运行 gcloud iam service-accounts keys list 命令:

gcloud iam service-accounts keys list --iam-account=SA_NAME \
    --filter="name~KEY_ID" --format=json

请提供以下值:

  • SA_NAME:您要获取其密钥元数据的服务帐号的名称。
  • KEY_ID:您要查看其元数据的密钥的 ID。

例如,以下命令会获取属于服务帐号 my-service-account@my-project.iam.gserviceaccount.com 的密钥 c97cc34494c07c9b483701f28368f20145b9ef97 的元数据:

gcloud iam service-accounts keys list \
    --iam-account=my-service-account@my-project.iam.gserviceaccount.com \
    --filter="name~c97cc34494c07c9b483701f28368f20145b9ef97" --format=json

REST

projects.serviceAccounts.keys.get 方法将返回该服务帐号的一个公钥的相关信息。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_NAME:您要获取其公钥的服务帐号的名称。
  • KEY_ID:您要获取的公钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要获取的密钥,然后从 name 字段的末尾复制其 ID。密钥的 ID 是 keys/ 之后的所有内容。
  • KEY_TYPE:用于返回公钥的格式。使用 TYPE_X509_PEM_FILE 可指定 X.509 PEM 格式,或使用 TYPE_RAW_PUBLIC_KEY 以指定原始公钥。如果省略此查询参数,则该方法会返回密钥的元数据,而不会返回公钥数据。

HTTP 方法和网址:

GET https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys/KEY_ID?publicKeyType=KEY_TYPE

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "name": "projects/my-project/serviceAccounts/my-service-account@my-project.iam.gserviceaccount.com/keys/f4a83933ac07cf52bb74e0e66d99662a09f51a36",
  "validAfterTime": "2021-12-10T17:32:06Z",
  "validBeforeTime": "9999-12-31T23:59:59Z",
  "publicKeyData": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvRENDQWVTZ0F3SUJBZ0lJT2lCdm9hR09nV0F3RFFZSktvWklodmNOQVFFRkJRQXdJREVlTUJ3R0ExVUUKQXhNVk1UQXhNVGsxTlRFMk5UWXlPRGszTmpFek1qQXpNQ0FYRFRJeE1USXhNREUzTXpJd05sb1lEems1T1RreApNak14TWpNMU9UVTVXakFnTVI0d0hBWURWUVFERXhVeE1ERXhPVFUxTVRZMU5qSTRPVGMyTVRNeU1ETXdnZ0VpCk1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRQzdzeDBFcXVUMGNwSXhlczl1SW0yRy9DS3EKdnc4YTl2a2JkaWZZbDZHSDh1ZUxEWDhGNHVUeEVQMkNzU3JLTHZtOFo2My9IVUxnWjBtQXByb0JlM08vaVR1ZwpmYVZ0NVNtakhvWm9YQ1lpbjR0MS93SkpvdDhrRFdPeDZhOEdieUdqZ215ak8yYk1XdEtaQ2dqeGZ3cUV0MmN3CklnajA5VzJKYTlHTWRsdVA0VGVubTRKSkJoaFpFbTJ1bVAwYVZZdkRnUWF5d0RCYnJuNG8yY0EzSWplRDZGM1gKK0VHRDNKU0s4VW02Sk5sM21adGp6VWNZSHBrYkF0U1A2ZDI5d1RmZkdIRFY0THJRWlM3bG15d3hsb3p5WnpaawpCOFpHckMzSkF1MVNVRTdQOTN6bWtFb1B6MlRUNWhaYXZMWFQ5TGM2SExiRklRVHFnVEJVWHlNMkpIcGZBZ01CCkFBR2pPREEyTUF3R0ExVWRFd0VCL3dRQ01BQXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CWUdBMVVkSlFFQi93UU0KTUFvR0NDc0dBUVVGQndNQ01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQkhPNXlpUDY3NkE4UEN2RjdRSzdFMApYZVljbzdsSStFZkowaGJrWVlmdUtnSENPcXcvd3FBbCtOSithanljT2FPWDFPMlRZN3ZOc05pR2t3eWc2QXdqCklhL1NHVjd3NkxpS2JldFRuSVp4UlhRY25lcnVvZEwycUR5eWphMDJJSXJVTmVKY1o0MVJBNXRTL3NkcTFGNm4KM0NjSXFoZTI1OTA4TUNna3cwaFB1K0VLbFF6R1B5T3pVRHBLdXg0cnRBaHJTYTBUVW1wbEMxdTJnUk1YRkF6aApWUjU0V2dNa2tabURyalBNeWdBS3JmNkd0bHo2VHRTYTVLb1BWdGpsWExUQkxaSnlhdk4zc1F2dFlBK1NFQWpWCnA1N1ZabFBYZmR0dWN4ekJaOC9zS25SOHNyYU5hVWFjamg1NEE1Nm1URTE3b0IyUWkrTHBJUTYvNnVqVnNXaUYKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=",
  "keyAlgorithm": "KEY_ALG_RSA_2048",
  "keyOrigin": "GOOGLE_PROVIDED",
  "keyType": "USER_MANAGED"
}

上传服务帐号的公钥

您可以上传用户管理的密钥对的公钥部分,以将其与服务帐号相关联。上传公钥后,您可以将密钥对中的私钥用作服务帐号密钥。

您上传的密钥必须是封装在 X.509 v3 证书中并以 base64 编码的 RSA 公钥。您可以使用 OpenSSL 等工具生成此格式的密钥和证书。

例如,以下命令会生成 2048 位 RSA 密钥对,并将公钥封装在有效期为 365 天的自签名证书中:

openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
    -keyout /path/to/private_key.pem \
    -out /path/to/public_key.pem \
    -subj "/CN=unused"

然后,您可以上传 public_key.pem 文件作为服务帐号的公钥。

如需停用为项目上传密钥的功能,请参阅限制服务帐号密钥上传

控制台

  1. 在 Google Cloud 控制台中,转到服务帐号页面。

    转到“服务帐号”

  2. 选择一个项目。
  3. 服务帐号页面上,点击要为其上传密钥的服务帐号的电子邮件地址。
  4. 点击密钥标签页。
  5. 点击添加密钥下拉菜单,然后选择上传现有密钥
  6. 点击浏览,然后找到并选择您的公钥文件。或者,您也可以复制公钥文件的内容,并将其粘贴到粘贴现有密钥框中。
  7. 点击上传

gcloud

执行 gcloud iam service-accounts keys upload 命令来上传用于签署服务帐号密钥的公钥。

替换以下值:

  • KEY_FILE:包含要上传的密钥数据的文件的路径,例如 ./public_key.pem
  • SA_NAME:要为其上传密钥的服务帐号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
gcloud iam service-accounts keys upload KEY_FILE \
    --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

输出包含所上传密钥的唯一标识符:

Name: projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys/c7b74879da78e4cdcbe7e1bf5e129375c0bfa8d0

如需确定该命令是否成功运行,请执行 gcloud iam service-accounts keys list 命令:

gcloud iam service-accounts keys list \
    --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

输出将包含创建密钥后返回的相同唯一标识符:

KEY_ID CREATED_AT EXPIRES_AT 已停用
c7b74879da78e4cdcbe7e1bf5e129375c0bfa8d0 2019-06-26T21:01:42Z 9999-12-31T23:59:59Z  

REST

projects.serviceAccounts.keys.upload 方法可上传用户管理的密钥对中的公钥,并将此公钥添加到服务帐号。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_NAME:要与密钥关联的服务帐号的名称。
  • PUBLIC_KEY_DATA:密钥对的公钥数据。必须是封装在 X.509 v3 证书中的 RSA 公钥。使用 base64 对公钥数据进行编码,包括第一行 -----BEGIN CERTIFICATE----- 和最后一行 -----END CERTIFICATE-----

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys:upload

请求 JSON 正文:

{
  "publicKeyData": "PUBLIC_KEY_DATA"
}

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
  "name": "projects/my-project/serviceAccounts/my-service-account@my-project.iam.gserviceaccount.com/keys/c7b74879da78e4cdcbe7e1bf5e129375c0bfa8d0",
  "validAfterTime": "2020-05-17T19:31:19Z",
  "validBeforeTime": "2021-05-17T19:31:19Z",
  "keyAlgorithm": "KEY_ALG_RSA_2048",
  "keyOrigin": "USER_PROVIDED",
  "keyType": "USER_MANAGED"
}

停用服务帐号密钥

停用服务帐号密钥会导致您无法使用该密钥向 Google API 进行身份验证。您可以随时启用已停用的密钥

删除服务帐号密钥之前,我们建议您先停用密钥,等到您确定不再需要该密钥时,即可将其删除。

您可以在 Google Cloud 控制台中查看已停用的密钥,但无法使用 Google Cloud 控制台停用密钥。请改用 gcloud CLI 或 REST API。

gcloud

执行 gcloud iam service-accounts keys disable 命令可停用服务帐号密钥。

替换以下值:

  • KEY_ID:要停用的密钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要停用的密钥,然后复制其 ID。
  • SA_NAME:密钥所属服务帐号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
gcloud iam service-accounts keys disable KEY_ID \
    --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

输出:

Disabled key [KEY_ID] for service account
[SA_NAME@PROJECT_ID.iam.gserviceaccount.com]

REST

projects.serviceAccounts.keys.disable 方法可停用服务帐号密钥。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_NAME:您要停用其密钥的服务帐号的名称。
  • KEY_ID:您要停用的密钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要停用的密钥,然后从 name 字段的末尾复制其 ID。密钥的 ID 是 keys/ 之后的所有内容。

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys/KEY_ID:disable

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
}

启用服务帐号密钥

停用服务帐号密钥后,您可以随时启用该密钥,然后使用该密钥向 Google API 进行身份验证。

您不能使用 Google Cloud 控制台来启用服务帐号密钥。请改用 gcloud CLI 或 REST API。

gcloud

执行 gcloud iam service-accounts keys enable 命令可启用服务帐号密钥。

替换以下值:

  • KEY_ID:要启用的密钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要启用的密钥,然后复制其 ID。
  • SA_NAME:密钥所属服务帐号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
gcloud iam service-accounts keys enable KEY_ID \
    --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

输出:

Enabled key [KEY_ID] for service account
[SA_NAME@PROJECT_ID.iam.gserviceaccount.com]

REST

projects.serviceAccounts.keys.enable 方法可启用服务帐号密钥。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_NAME:您要启用其密钥的服务帐号的名称。
  • KEY_ID:您要启用的密钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要启用的密钥,然后从 name 字段的末尾复制其 ID。密钥的 ID 是 keys/ 之后的所有内容。

HTTP 方法和网址:

POST https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys/KEY_ID:enable

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
}

删除服务帐号密钥

删除服务帐号密钥会永久阻止您使用该密钥向 Google API 进行身份验证。

您不能恢复删除的密钥。在删除密钥之前,我们建议您先停用密钥,然后等到您确定不再需要该密钥时,即可将其删除。

最佳做法是定期轮替您的服务帐号密钥。您可以通过执行以下操作来轮替密钥:

  1. 创建新密钥。
  2. 将您的应用更新为使用新密钥。
  3. 停用旧密钥。
  4. 等待足够长的时间,以确认系统不再使用旧密钥。
  5. 删除旧密钥。

控制台

  1. 在 Google Cloud 控制台中,转到服务帐号页面。

    转到“服务帐号”

  2. 选择一个项目。
  3. 服务帐号页面上,点击要删除其密钥的服务帐号的电子邮件地址。
  4. 点击密钥标签页。
  5. 从密钥列表中,针对您想删除的每个密钥点击删除

gcloud

执行 gcloud iam service-accounts keys delete 命令来删除服务帐号密钥。

替换以下值:

  • KEY_ID:要删除的密钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要删除的密钥,然后复制其 ID。
  • SA_NAME:密钥所属服务帐号的名称。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
gcloud iam service-accounts keys delete KEY_ID \
    --iam-account=SA_NAME@PROJECT_ID.iam.gserviceaccount.com

输出:

Deleted key [KEY_ID] for service account
[SA_NAME@PROJECT_ID.iam.gserviceaccount.com]

REST

projects.serviceAccounts.keys.delete 方法可删除服务帐号密钥。

在使用任何请求数据之前,请先进行以下替换:

  • PROJECT_ID:您的 Google Cloud 项目 ID。项目 ID 是字母数字字符串,例如 my-project
  • SA_NAME:您要删除其密钥的服务帐号的名称。
  • KEY_ID:您要删除的密钥的 ID。 如需查找密钥的 ID,请列出服务帐号的所有密钥,找到要删除的密钥,然后从 name 字段的末尾复制其 ID。密钥的 ID 是 keys/ 之后的所有内容。

HTTP 方法和网址:

DELETE https://iam.googleapis.com/v1/projects/PROJECT_ID/serviceAccounts/SA_NAME@PROJECT_ID.iam.gserviceaccount.com/keys/KEY_ID

如需发送您的请求,请展开以下选项之一:

您应该收到类似以下内容的 JSON 响应:

{
}

C++

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

namespace iam = ::google::cloud::iam;
[](std::string const& name) {
  iam::IAMClient client(iam::MakeIAMConnection());
  auto response = client.DeleteServiceAccountKey(name);
  if (!response.ok()) throw std::runtime_error(response.message());
  std::cout << "ServiceAccountKey successfully deleted.\n";
}

C#

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


using System;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Iam.v1;
using Google.Apis.Iam.v1.Data;

public partial class ServiceAccountKeys
{
    public static void DeleteKey(string fullKeyName)
    {
        var credential = GoogleCredential.GetApplicationDefault()
            .CreateScoped(IamService.Scope.CloudPlatform);
        var service = new IamService(new IamService.Initializer
        {
            HttpClientInitializer = credential
        });

        service.Projects.ServiceAccounts.Keys.Delete(fullKeyName).Execute();
        Console.WriteLine("Deleted key: " + fullKeyName);
    }
}

Go

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

import (
	"context"
	"fmt"
	"io"

	iam "google.golang.org/api/iam/v1"
)

// deleteKey deletes a service account key.
func deleteKey(w io.Writer, fullKeyName string) error {
	ctx := context.Background()
	service, err := iam.NewService(ctx)
	if err != nil {
		return fmt.Errorf("iam.NewService: %v", err)
	}

	_, err = service.Projects.ServiceAccounts.Keys.Delete(fullKeyName).Do()
	if err != nil {
		return fmt.Errorf("Projects.ServiceAccounts.Keys.Delete: %v", err)
	}
	fmt.Fprintf(w, "Deleted key: %v", fullKeyName)
	return nil
}

Java

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

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.iam.v1.Iam;
import com.google.api.services.iam.v1.IamScopes;
import com.google.api.services.iam.v1.model.ServiceAccountKey;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.List;

public class DeleteServiceAccountKey {

  // Deletes a service account key.
  public static void deleteKey(String projectId, String serviceAccountName) {
    // String projectId = "my-project-id";
    // String serviceAccountName = "my-service-account-name";

    Iam service = null;
    try {
      service = initService();
    } catch (IOException | GeneralSecurityException e) {
      System.out.println("Unable to initialize service: \n" + e.toString());
      return;
    }

    String serviceAccountEmail = serviceAccountName + "@" + projectId + ".iam.gserviceaccount.com";
    try {
      // First, get the name of the key using List() or Get()
      List<ServiceAccountKey> keys =
          service
              .projects()
              .serviceAccounts()
              .keys()
              .list("projects/-/serviceAccounts/" + serviceAccountEmail)
              .execute()
              .getKeys();
      String keyToDelete = keys.get(0).getName();

      // Then you can delete the key
      service.projects().serviceAccounts().keys().delete(keyToDelete).execute();

      System.out.println("Deleted key: " + keyToDelete);
    } catch (IOException e) {
      System.out.println("Unable to delete service account key: \n" + e.toString());
    }
  }

  private static Iam initService() throws GeneralSecurityException, IOException {
    // Use the Application Default Credentials strategy for authentication. For more info, see:
    // https://cloud.google.com/docs/authentication/production#finding_credentials_automatically
    GoogleCredentials credential =
        GoogleCredentials.getApplicationDefault()
            .createScoped(Collections.singleton(IamScopes.CLOUD_PLATFORM));
    // Initialize the IAM service, which can be used to send requests to the IAM API.
    Iam service =
        new Iam.Builder(
                GoogleNetHttpTransport.newTrustedTransport(),
                JacksonFactory.getDefaultInstance(),
                new HttpCredentialsAdapter(credential))
            .setApplicationName("service-account-keys")
            .build();
    return service;
  }
}

Python

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

import os

from google.oauth2 import service_account
import googleapiclient.discovery

def delete_key(full_key_name):
    """Deletes a service account key."""

    credentials = service_account.Credentials.from_service_account_file(
        filename=os.environ['GOOGLE_APPLICATION_CREDENTIALS'],
        scopes=['https://www.googleapis.com/auth/cloud-platform'])

    service = googleapiclient.discovery.build(
        'iam', 'v1', credentials=credentials)

    service.projects().serviceAccounts().keys().delete(
        name=full_key_name).execute()

    print('Deleted key: ' + full_key_name)

后续步骤

自行试用

如果您是 Google Cloud 新手,请创建一个帐号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。

免费开始使用