设置访问权限控制

访问权限控制决定了有权访问 Google Cloud 项目中的服务和资源的人员。App Engine 中提供了有关设置访问权限控制的几个不同用例:

本页面简要介绍了如何在各种用例中设置访问权限控制。

如需了解有关 Google Cloud Platform 如何处理访问权限控制的背景情况,请参阅 Identity and Access Management (IAM) 概览

向团队成员授予访问权限

如需授予开发者访问您的 Google Cloud 项目的权限,请创建以下一项或两项内容:

  • 用户账号:该账号与 Google 账号相关联,旨在代表您项目中的特定个人。

    使用用户账号时,可以通过以下工具进行身份验证:

    • Google Cloud 控制台
    • Google Cloud CLI
    • IDE 和构建工具,这些工具使用 gcloud CLI 测试和部署 App Engine 应用
  • 服务账号:旨在代表应用或进程(而非用户)。服务账号适用于自动化构建、测试和部署过程,尤其是这些过程可由多个开发者运行的情况。

    使用服务账号时,可以通过以下工具进行身份验证:

    • gcloud CLI
    • IDE 和构建工具,这些工具使用 gcloud CLI 工具测试和部署 App Engine 应用

创建用户账号

  1. 在 Google Cloud 控制台中打开 IAM 页面。

    打开 IAM 页面

  2. 点击选择项目,然后选择一个项目并点击打开

  3. 点击添加

  4. 输入电子邮件地址。

  5. 选择可授予对 App Engine 功能的访问权限的角色。

    如果用户还需要访问其他 Cloud 服务,请选择可授予对其他 Cloud 服务的访问权限的角色

  6. 点击保存

用户现在可以登录 Google Cloud 控制台以及向 gcloud CLI 授权

您还可以使用 gcloud、REST API 或客户端库创建用户账号。

创建服务账号

  1. 在 Google Cloud 控制台中打开服务账号页面。

    打开“服务账号”页面

  2. 选择您的项目,然后点击打开

  3. 点击创建服务账号

  4. 输入服务账号名称。此名称应易于显示。

  5. 点击创建

  6. 选择可授予对 App Engine 功能的访问权限的角色。

    如果该服务账号还需要访问其他 Cloud 服务,请选择可授予对其他 Cloud 服务的访问权限的角色

  7. 点击继续

  8. (可选)指定可管理该服务账号的用户账号。 您还可以指定可使用该服务账号间接访问该服务账号有权访问的所有资源的用户账号。

  9. 点击保存

    此时会显示现有服务账号的列表。

  10. (可选)如果您需要在 Google Cloud 之外使用您的服务账号,请按照说明创建服务账号密钥

后续步骤

  • 如果您要在自动化构建和部署过程中使用该服务账号,请使用服务账号向 gcloud CLI 授权
  • 如果您要在 IDE 中使用该服务账号,请按照 IDE 提供的说明进行操作。
  • 如果您需要在访问其他 Google Cloud 服务或执行任务时对 App Engine 应用的版本使用唯一的身份,则可以在 App Engine 中指定用户管理的服务账号

向您的应用授予对 Cloud 服务的访问权限

对 Cloud 服务的每次调用都需要通过身份验证并获得授权,包括 App Engine 应用对其他 Cloud 服务(如 Cloud Storage)的调用。

默认情况下,系统会授权 App Engine 应用调用同一项目中的服务。以下是默认流程的工作方式:

  1. 为启动对某项 Cloud 服务的调用,您的应用会创建一个客户端对象,其中包含您的应用与该服务交互所需的凭据和其他数据。如果您未在客户端的构造函数中指定凭据,则客户端会在应用环境中查找凭据。

    以下示例演示了如何为 Cloud Storage 创建客户端:

    Go

    
    // implicit uses Application Default Credentials to authenticate.
    func implicit() {
    	ctx := context.Background()
    
    	// For API packages whose import path is starting with "cloud.google.com/go",
    	// such as cloud.google.com/go/storage in this case, if there are no credentials
    	// provided, the client library will look for credentials in the environment.
    	storageClient, err := storage.NewClient(ctx)
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer storageClient.Close()
    
    	it := storageClient.Buckets(ctx, "project-id")
    	for {
    		bucketAttrs, err := it.Next()
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			log.Fatal(err)
    		}
    		fmt.Println(bucketAttrs.Name)
    	}
    
    	// For packages whose import path is starting with "google.golang.org/api",
    	// such as google.golang.org/api/cloudkms/v1, use NewService to create the client.
    	kmsService, err := cloudkms.NewService(ctx)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	_ = kmsService
    }
    

    Java

    static void authImplicit() {
      // If you don't specify credentials when constructing the client, the client library will
      // look for credentials via the environment variable GOOGLE_APPLICATION_CREDENTIALS.
      Storage storage = StorageOptions.getDefaultInstance().getService();
    
      System.out.println("Buckets:");
      Page<Bucket> buckets = storage.list();
      for (Bucket bucket : buckets.iterateAll()) {
        System.out.println(bucket.toString());
      }
    }

    Node.js

    // Imports the Google Cloud client library.
    const {Storage} = require('@google-cloud/storage');
    
    // Instantiates a client. If you don't specify credentials when constructing
    // the client, the client library will look for credentials in the
    // environment.
    const storage = new Storage();
    // Makes an authenticated API request.
    async function listBuckets() {
      try {
        const results = await storage.getBuckets();
    
        const [buckets] = results;
    
        console.log('Buckets:');
        buckets.forEach(bucket => {
          console.log(bucket.name);
        });
      } catch (err) {
        console.error('ERROR:', err);
      }
    }
    listBuckets();

    PHP

    // Imports the Cloud Storage client library.
    use Google\Cloud\Storage\StorageClient;
    
    /**
     * Authenticate to a cloud client library using a service account implicitly.
     *
     * @param string $projectId The Google project ID.
     */
    function auth_cloud_implicit($projectId)
    {
        $config = [
            'projectId' => $projectId,
        ];
    
        # If you don't specify credentials when constructing the client, the
        # client library will look for credentials in the environment.
        $storage = new StorageClient($config);
    
        # Make an authenticated API request (listing storage buckets)
        foreach ($storage->buckets() as $bucket) {
            printf('Bucket: %s' . PHP_EOL, $bucket->name());
        }
    }

    Python

    def implicit():
        from google.cloud import storage
    
        # If you don't specify credentials when constructing the client, the
        # client library will look for credentials in the environment.
        storage_client = storage.Client()
    
        # Make an authenticated API request
        buckets = list(storage_client.list_buckets())
        print(buckets)
    
    

    Ruby

    # project_id = "Your Google Cloud project ID"
    
    require "google/cloud/storage"
    
    # If you don't specify credentials when constructing the client, the client
    # library will look for credentials in the environment.
    storage = Google::Cloud::Storage.new project: project_id
    
    # Make an authenticated API request
    storage.buckets.each do |bucket|
      puts bucket.name
    end
  2. 默认情况下,应用环境包含来自默认 App Engine 服务账号的凭据。

    此服务账号由 Google 在您创建 App Engine 应用时创建,拥有管理和使用 Google Cloud 项目中所有 Cloud 服务的完整权限。

您可以通过执行以下任一操作来替换此默认流程:

  • 设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量。如果设置此变量,Cloud 服务将使用由该变量(而不是默认服务账号)指定的凭据。

  • 在为 Cloud 服务实例化 Client 对象时指定凭据。 例如,如果您的应用要在其他项目中调用 Cloud 服务,您可能需要手动传递凭据

如果您在代码中设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量或传递凭据,我们建议您以下列方式之一存储凭据:

  • 将凭据存储在 Datastore 模式的 Firestore (Datastore) 等安全位置,并在运行时检索这些凭据。
  • 将凭据保留在代码中,并使用密钥库(例如 Cloud KMS)对其进行加密。

如需了解每种方法的优点,请参阅选择密钥管理解决方案

向用户授予对 Cloud 资源的访问权限

如果您希望应用读取其他 Google 服务的用户数据,则需要设置适用于 Web 服务器应用的 OAuth 2.0。例如,如果您希望从 Google 云端硬盘中提取用户数据并将其用于自己的应用,请使用适用于 Web 服务器应用的 OAuth 2.0 来共享特定数据,同时仍保持其他数据(如用户名和密码)的私密性。

Google Workspace 全网域授权

如果您有 Google Workspace(以前称为 G Suite)网域,则网域管理员可授权应用代表 Google Workspace 网域中的用户访问用户数据。例如,如果一个应用使用 Google Calendar API 向 Google Workspace 网域中所有用户的日历添加活动,则该应用会使用服务账号代表用户访问 Google Calendar API。

有时候,授权服务账号代表网域中的用户访问数据被称为向服务账号进行“全网域授权”。 它仍然使用 OAuth 2.0,并且需要 Google Workspace 网域管理员对该服务账号进行全网域授权

指定服务账号

App Engine 支持使用两种类型的服务账号:

  • 版本特定服务账号:配置为已部署服务特定版本的身份的服务账号。部署现有版本或新版本时,您都可以指定一个服务账号来作为该版本的身份。例如,如果某个版本需要的权限与应用级默认服务账号不同,您便可以分配该版本特定的服务账号。如需了解详情,请参阅配置 App Engine 服务账号
  • 应用级默认服务账号:如果您未配置版本特定服务账号,则 Google Cloud 会为您的所有已部署服务使用应用级默认服务账号。您在创建应用时会分配应用级默认服务账号。如需了解详情,请参阅分配应用级默认服务账号

    如果您未分配应用级默认服务账号,则 Google Cloud 会使用自动创建的 App Engine 默认服务账号 (PROJECT_ID@appspot.gserviceaccount.com)。

    根据您的组织政策配置,默认服务账号可能会自动获得项目的 Editor 角色。我们强烈建议您通过强制执行 iam.automaticIamGrantsForDefaultServiceAccounts 组织政策限制条件来停用自动角色授予功能。如果您的组织是在 2024 年 5 月 3 日之后创建的,则默认情况下会强制执行此限制条件。

    如果您停用自动角色授予功能,则必须决定向默认服务账号授予哪些角色,然后自行授予这些角色

    如果默认服务账号已具有 Editor 角色,我们建议您将 Editor 角色替换为权限较少的角色。如需安全地修改服务账号的角色,请使用 Policy Simulator 查看更改的影响,然后授予和撤消相应的角色