在 Docker 容器内部的容器操作系统上访问 Google Cloud 服务帐户凭据

30

如何在 Google Cloud Compute 使用 容器优化操作系统(COS)时,最佳方式从 Docker 容器内部访问 VM 项目的默认服务账户凭据?

$ gcloud compute instances create test-instance \
  --image=cos-stable --image-project=cos-cloud

$ ssh (ip of the above)
# gcloud ...
Command not found

# docker run -ti google/cloud-sdk:alpine /bin/sh
# gcloud auth activate-service-account
... --key-file: Must be specified.

如果凭据在VM上,则Docker可以挂载它们。通常,凭据会在.config/gcloud/中,并使用docker run -v ~/.config/gcloud:~/.config/gcloud image来实现。在Container OS中是否有这样的凭据可用尚不明确,特别是因为它缺少gcloud。
如果无法在VM上找到并挂载凭据,则选项似乎包括:
1. 将凭据放入容器元数据/环境变量中; 2. 为服务帐号创建一个.json凭据文件,然后 a.将其上传到VM,然后挂载它;或 b.将.json添加到容器中; 3. 运行一个Docker容器(例如cloud-sdk-docker),该容器获取凭据并通过共享挂载分区与主机共享它们。理想情况下,应使用gcloud auth activate-service-account进行操作。
是否存在一种规范或最佳实践方法来为Docker容器提供VM项目的服务帐号凭据?
Google Cloud已经具有安全策略模型,即:项目中的VM应具有服务帐号提供的访问权限。为避免复杂性和配置错误或意外的可能性,正确的解决方案将采用此现有安全模型,即不涉及创建、下载、分发和维护凭据文件。
这似乎是一个常规问题,需要使用COS、Docker和Kubernetes来解决,所以我认为我错过了一些简单的东西——但是从文档中我没有找到明显的解决方案。
编辑-注意set-service-account API-这个问题可以简化为“如何在容器操作系统中使用set-service-account API?”如果不可能(因为容器操作系统缺少gcloud和gsutil),我认为应该注意这一点,以便虚拟机用户做好计划。
编辑-对于下一个遇到此问题的人:
[local] $ ssh test-instance-ip
[test-instance] $ docker run -it gcr.io/google-appengine/python /bin/bash
[test-instance] $ pip install --upgrade google-cloud-datastore
[test-instance] $ python

>>> from google.cloud import datastore
>>> datastore_client = datastore.Client()
>>> q = datastore.query.Query(datastore_client, kind='MODEL-KIND')
>>> list(q.fetch())
[... results]

问题确实是VM实例API中设置的范围,特别是对于默认帐户禁用了 API(在VM的Cloud API access scopes标题下)。您可以按以下方式查找范围和必要的行:
> gcloud compute instances describe test-instance
...
serviceAccounts:
- email: *****-compute@developer.gserviceaccount.com
  scopes:
  - https://www.googleapis.com/auth/datastore
  ...
...

请注意,服务账户本身具有访问数据存储的权限(因此,通常可以使用服务密钥的JSON凭据键访问数据存储)。虚拟机的作用域限制了服务账户的权限。
3个回答

24

通常认证的方式是在Google Cloud SDK Docker自述文件中提到的那种。

在COS实例内部运行此命令一次:

docker run -ti --name gcloud-config google/cloud-sdk gcloud auth login

这将把您的凭据存储在gcloud-config容器卷中。

此卷应该只挂载到您希望访问您的凭据的容器中,这可能不会包括任何不是cloud-sdk的东西。

docker run --rm -ti --volumes-from gcloud-config google/cloud-sdk:alpine gcloud compute instances create test-docker --project [PROJECT]  


Created [https://www.googleapis.com/compute/v1/projects/project/zones/us-east1-b/instances/test-docker].
NAME         ZONE        MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP      STATUS
test-docker  us-east1-b  n1-standard-1               10.142.0.8   X.X.X.X  RUNNING

服务账户通常需要使用它们自己的一组凭证,这些凭证可以来自于文件、环境变量或令牌:

gcloud auth activate-service-account

如果您想让gcloud(以及Cloud SDK中的其他工具)使用服务账户凭证发送请求,请使用此命令从包含私有授权密钥的文件中导入这些凭证,并激活它们供gcloud使用。这个命令的功能与gcloud auth login相同,但是使用的是服务账户而不是您的Google用户凭据。

另外,最佳实践是为不同的实例创建不同的服务账户,而不是获取默认服务账户的密钥并使用它:

总的来说,Google建议每个需要调用Google API的实例都应该作为一个服务账户运行,该服务账户仅具备其工作所需的最小权限。在实践中,这意味着您应该按照以下过程为您的实例配置服务账户:

1 - 创建一个新的服务账户,而不是使用Compute Engine的默认服务账户。
2 - 为该服务账户授予适用于它所需资源的IAM角色。
3 - 配置实例以作为该服务账户运行。
4 - 授予该实例https://www.googleapis.com/auth/cloud-platform范围。
5 - 避免授予比必要权限更多的访问权限,并定期检查您的服务账户权限,确保它们是最新的。

更新

我不确定set-service-account是否符合您的需求。您可以使用它来更改实例使用的服务账户(但该实例必须停止,因此您无法在更改的实例中使用它来更改服务账户)。但是您可以像对其他实例一样正常使用它,请参阅:

jordim@cos ~ $ docker run --rm -ti --volumes-from gcloud-config google/cloud-sdk:alpine gcloud compute instances set-service-account instance-1 --service-account xx-compute@developer.gserviceaccount.com
Did you mean zone [us-east1-b] for instance: [instance-1] (Y/n)?  

Updated [https://www.googleapis.com/compute/v1/projects/XX/zones/us-east1-b/instances/instance-1].

4
谢谢Jordi。这里有几个要点:1. gcloud auth login将授予个人凭据,必须避免使用。2. 谷歌提供了set-service-account API,很明显是用来确定凭据的 - 但如果这些凭据不可用,那么在容器OS上使用这个API有什么意义呢?我会更新问题以记录这一点。感谢您的帮助。 - Brian M. Hunt
4
嗨Jordi,谢谢你的更新。我的期望是Docker容器可以继承它们所在实例的权限/服务账户。 - Brian M. Hunt
这与实例范围有关,而不是服务帐号权限。将实例范围设置为“允许对所有云 API 进行完全访问”,然后重试。以下是操作步骤:https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#changeserviceaccountandscopes - Tux
@TarunLalwani 我已经根据这里的有用努力给出了奖励(计时器还剩一个小时),但我还没有机会测试这个答案 - 我今天会去测试。如果它有效,我会将其标记为正确答案,否则我会评论/更新问题。很快就会回来测试。 - Brian M. Hunt
@TarunLalwani Jordi的建议确实解决了问题,即服务帐户访问范围阻止了数据存储访问。我在问题中添加了更多细节。 - Brian M. Hunt
显示剩余2条评论

3

我认为这个问题在今天并不完全适用,因此我想分享我的2分钱。

对于容器优化操作系统,如果虚拟机正在使用默认服务帐户运行,则该服务帐户会自动配置在 cloud-sdk 容器中。

user@instance-1 ~ $ docker run -it gcr.io/google.com/cloudsdktool/cloud-sdk:alpine /bin/bash
bash-5.1# gcloud config list
[component_manager]
disable_update_check = true
[core]
account = *************-compute@developer.gserviceaccount.com
disable_usage_reporting = true
project = my-project-id
[metrics]
environment = github_docker_image

Your active configuration is: [default]
bash-5.1# gcloud compute instances list
NAME        ZONE           MACHINE_TYPE  PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP  STATUS
instance-1  us-central1-a  e2-medium                  10.128.0.3   34.**.**.***  RUNNING

因此,用户不需要执行“gcloud auth login”,只要默认服务帐户具有权限并且VM已经明确启用了特定的API,就可以直接执行所有的“gcloud”命令。但是,如果在VM创建期间选择了“无服务帐户”选项,则此用例有效。

0

我认为这与计算引擎配置有关。DevopsTux已经说过了。

This is related to the instance scopes, 
not the service account permissions. 
Set the instance scope to "allow full access to all cloud APIs" 
and try again. Here is how: cloud.google.com/compute/docs/access/… – 

DevopsTux May 17, 2018 at 12:48
  1. 停止实例。
  2. 更改访问范围如下。

在此输入图像描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接