【发布时间】:2021-10-07 16:36:07
【问题描述】:
在 python 中,我试图通过Delegated domain-wide authority 的服务帐户调用 GMail API,没有 使用SERVICE_ACCOUNT_FILE。
我的目标是避免为服务帐户创建秘密 Key。相反,我将Service Account Token Creator 角色分配给了流程所有者(我在本地开发中,App Engine 服务帐户在生产中)。
在下面的代码中,我成功获取并使用了服务帐户的访问令牌,没有任何SERVICE_ACCOUNT_FILE。
from google.cloud.iam_credentials_v1 import IAMCredentialsClient
from google.oauth2.credentials import Credentials
import googleapiclient.discovery
tk = IAMCredentialsClient().generate_access_token(
name=f'projects/-/serviceAccounts/{service_id}',
scope=['https://www.googleapis.com/auth/gmail.insert'],
# subject='admin@my.domain' doesn't work here :'(
)
service = googleapiclient.discovery.build('gmail', 'v1', credentials=Credentials(tk.access_token))
response = service.users().messages().insert(userId='user@my.domain', body=body).execute()
问题是,在my.domain 的 Google Admin 中授予服务帐户权限后,我收到以下错误:
{'message': '前置条件检查失败。', 'domain': 'global', 'reason': 'failedPrecondition'}
我怀疑我缺少的是subject,即my.domain 管理员的电子邮件。
我知道我可以通过以不同方式构造 credentials 来提供 subject:
from google.oauth2 import service_account
credentials = service_account.Credentials.from_service_account_file(key_file, scopes=scopes)
delegated_credentials = credentials.with_subject('admin@my.domain'). # <- I need this
service = googleapiclient.discovery.build('gmail', 'v1', credentials=delegated_credentials)
但这需要创建一个密钥,我想避免这样做。
上面第一个代码示例中有没有办法传递主题?
【问题讨论】:
-
您能解释一下为什么要避免创建密钥吗?
-
Google 似乎不鼓励它,例如。 here: "Use service account keys only if there is no viable alternative"。就我而言,似乎有另一种选择,因为我设法在没有任何用户管理密钥的情况下获得服务的访问令牌。仅缺少该服务对另一个用户的模拟(如果使用密钥进行身份验证,它可以这样做)。
-
所以你想运行一个“附加”服务帐户?你确定你是从一个受支持的平台上运行它并且有attached它吗?
-
我遇到了将服务帐户附加到资源的概念。不幸的是,在我们当前的工作流程中,我们为每个客户创建一个服务帐户(我们是多租户)。 IIUC 只能有一个服务帐户附加到我们的 App Engine 实例。
-
我认为在这种情况下这可能是您问题的答案 - stackoverflow.com/questions/55354070/… - 即服务帐户标识应用引擎实例,因此您不能将多个附加到它。跨度>
标签: python-3.x google-api gmail-api google-iam