设置访问权限控制机制

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

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

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

向团队成员授予访问权限

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

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

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

    • Google Cloud Console
    • 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 Console 以及向 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

    C#

    public object AuthImplicit(string projectId)
    {
        // If you don't specify credentials when constructing the client, the
        // client library will look for credentials in the environment.
        var credential = GoogleCredential.GetApplicationDefault();
        var storage = StorageClient.Create(credential);
        // Make an authenticated API request.
        var buckets = storage.ListBuckets(projectId);
        foreach (var bucket in buckets)
        {
            Console.WriteLine(bucket.Name);
        }
        return null;
    }
    
  2. 默认情况下,应用环境包含来自默认 App Engine 服务帐号的凭据。

    此服务帐号由 Google 在您创建 App Engine 应用时创建,拥有管理和使用 GCP 项目中所有 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 支持使用两种类型的服务帐号:

  • 默认情况下,系统会自动使用 Editor 角色创建 App Engine 默认服务帐号;如果未指定用户管理的服务帐号,该默认服务帐号将是 App Engine 应用所有版本的默认身份。我们建议您将默认服务帐号的默认权限修改为最能代表 App Engine 应用的访问权限需求的角色。
  • 用户管理的服务帐号是您在 Identity and Access Management (IAM) 中创建的服务帐号。您可以为一个版本指定用户管理的服务帐号,该帐号用于在访问其他 App Engine 服务以及为该版本执行任务时。