创建和管理服务帐号密钥

本页面介绍了如何使用 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 上,而不公开部分仅供您使用。如需详细了解公钥/私钥对,请参阅服务帐号密钥

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

默认情况下,服务帐号密钥永不过期。您可以使用资源设置指定服务帐号密钥的有效时长。如需了解详情,请参阅指定用户管理的密钥的过期时间

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

控制台

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

    转到“服务帐号”
    其余步骤将自动显示在控制台中。

  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')

列出服务帐号密钥

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

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

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

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

控制台

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

    转到“服务帐号”
    其余步骤将自动显示在控制台中。

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

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 正确

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

控制台

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

使用 gcloud CLI 或 REST API。控制台中不提供此数据。

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

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

    转到“服务帐号”
    其余步骤将自动显示在控制台中。

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

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. 在控制台中,转到服务帐号页面。

    转到“服务帐号”
    其余步骤将自动显示在控制台中。

  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 进行身份验证。您可以随时启用已停用的密钥

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

您可以在控制台中查看已停用的密钥,但不能使用控制台停用密钥。请改用 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 进行身份验证。

您不能使用控制台启用服务帐号密钥。请改用 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. 在控制台中,转到服务帐号页面。

    转到“服务帐号”
    其余步骤将自动显示在控制台中。

  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 赠金,用于运行、测试和部署工作负载。

免费开始使用