generate_access_token() 主题为 Google 服务帐户
generate_access_token() with subject for Google service account
在 python 中,我正在尝试通过服务帐户使用 Delegated domain-wide authority 调用 GMail API, 不使用 使用 SERVICE_ACCOUNT_FILE
.
我的 objective 是为了避免为服务帐户创建秘密 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 管理员中向服务帐户授予权限后,我收到以下错误:
{'message': 'Precondition check failed.', '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)
但这需要创建一个密钥,我想避免这种情况。
有没有办法在上面的第一个代码示例中传递主题?
据我所知这是不可能的
很高兴被证明是错误的!
我把它作为免责声明,因为你是对的,它没有明确否认这种可能性。它通常不要求文档明确表达你可以而不是用它做的一切,尽管我确实看到这里可能会造成混淆,所以可能值得向文档页面“发送反馈” .
说明书怎么说
Preparing to make an authorized API call
After you obtain the client email address and private key from the API Console ...
它在任何地方都没有说“这是一个可选步骤”。在 Directory API instructions on domain-wide delegation, or the Reports API
等其他地方也是如此
不使用Keys的建议
以下内容来自您链接的文章:
Use service account keys only if there is no viable alternative
A service account key lets an application authenticate as a service
account, similar to how a user might authenticate with a username and
password.
当您将服务帐户附加到 App Engine 实例时,实例就像用户,服务帐户就是它的用户帐户。它充当实例的一种标识。关于此的更多信息 .
因此,服务帐户充当另一个帐户的唯一方法是使用密钥[=65] =]。同样,用户使用密钥来充当服务帐户的唯一方法是使用密钥。因此,如果您尝试启用全域委派,前提是您希望服务帐户 就像 其他帐户一样, 有一个密钥是必不可少的,无论服务帐户是否附加到 App Engine 实例。
当然,没有明确提到您可以 不 在没有钥匙的情况下实现这一点。尽管它也没有提到您 可以 。从我 运行 的测试中,我 运行 的结果与你的相似,所以看起来你就是做不到。如免责声明中所述,我很乐意被证明是错误的,但是,我怀疑这是由于漏洞而非预期行为造成的。
您没有提到为什么需要全域授权,所以您可能需要评估一下是否真的需要它。通常只需要 OAuth 流程,其中应用程序 oh-behalf 用户的行为,而不是 as-if 用户的行为.
参考资料
在 python 中,我正在尝试通过服务帐户使用 Delegated domain-wide authority 调用 GMail API, 不使用 使用 SERVICE_ACCOUNT_FILE
.
我的 objective 是为了避免为服务帐户创建秘密 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 管理员中向服务帐户授予权限后,我收到以下错误:
{'message': 'Precondition check failed.', '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)
但这需要创建一个密钥,我想避免这种情况。
有没有办法在上面的第一个代码示例中传递主题?
据我所知这是不可能的
很高兴被证明是错误的!
我把它作为免责声明,因为你是对的,它没有明确否认这种可能性。它通常不要求文档明确表达你可以而不是用它做的一切,尽管我确实看到这里可能会造成混淆,所以可能值得向文档页面“发送反馈” .
说明书怎么说
Preparing to make an authorized API call
After you obtain the client email address and private key from the API Console ...
它在任何地方都没有说“这是一个可选步骤”。在 Directory API instructions on domain-wide delegation, or the Reports API
等其他地方也是如此不使用Keys的建议
以下内容来自您链接的文章:
Use service account keys only if there is no viable alternative
A service account key lets an application authenticate as a service account, similar to how a user might authenticate with a username and password.
当您将服务帐户附加到 App Engine 实例时,实例就像用户,服务帐户就是它的用户帐户。它充当实例的一种标识。关于此的更多信息
因此,服务帐户充当另一个帐户的唯一方法是使用密钥[=65] =]。同样,用户使用密钥来充当服务帐户的唯一方法是使用密钥。因此,如果您尝试启用全域委派,前提是您希望服务帐户 就像 其他帐户一样, 有一个密钥是必不可少的,无论服务帐户是否附加到 App Engine 实例。
当然,没有明确提到您可以 不 在没有钥匙的情况下实现这一点。尽管它也没有提到您 可以 。从我 运行 的测试中,我 运行 的结果与你的相似,所以看起来你就是做不到。如免责声明中所述,我很乐意被证明是错误的,但是,我怀疑这是由于漏洞而非预期行为造成的。
您没有提到为什么需要全域授权,所以您可能需要评估一下是否真的需要它。通常只需要 OAuth 流程,其中应用程序 oh-behalf 用户的行为,而不是 as-if 用户的行为.