我试图使用python pubsub API使用ImpersontatedCredentials
(模拟服务帐户)创建SubscriberClient
,然后使用该客户端创建一些订阅。我试图尝试在本地运行此代码(尽管最终它将被部署为云功能)
这样做,我得到这个错误:
我创建模拟凭证的代码如下所示:过滤器:"属性。Provider_id = "integration_test_create_delete_provider_id_123";, metadata=[('x-goog-request-params', 'name=projects/my-project/subscriptions/integration_test_create_delete_provider_id_123'), ('x-goog-api-client', 'gl-python/3.8.6 grpc/1.39.0 gax/1.31.1 gccl/2.7.0')]),最后一个例外:503从插件获取元数据失败,错误:('无法获取冒充凭证:没有访问令牌或无效过期响应。', '{n "error"; {n "code": 400,n "message": "请求包含无效参数",n "status": "INVALID_ARGUMENT"n}n}n')
from google.auth import impersonated_credentials
from google.cloud import pubsub_v1
target_scopes = [
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/pubsub",
]
target_principal = ("target-svc-account@my-project.iam.gserviceaccount.com",)
def _get_impersonated_pubsub_client():
return pubsub_v1.SubscriberClient(credentials=_get_impersonated_creds())
def _get_impersonated_creds():
default_creds, _ = google.auth.default()
impersonated_creds = impersonated_credentials.Credentials(
source_credentials=default_creds,
target_principal=target_principal,
target_scopes=target_scopes,
)
return impersonated_creds
从那里,我在调用_get_impersonated_pubsub_client()
获得的客户机上调用create_subscription(request=my_request)
,大约一分钟后,我看到上述错误。
我的请求对象是这样的:
{
"name": "projects/my-project/subscriptions/integration_test_create_delete_provider_id_123",
"topic": "projects/my-project/topics/my-topic-dev-us-west1",
}
如果我在没有模拟或在SubscriberClient
构造函数中指定凭据的情况下进行相同的调用,则一切正常。
我的第一个想法是这是一个权限错误,但我仔细检查了我的源帐户具有ServiceAccountTokenCreator
角色。
另外,我试着用GCloud CLI(包括模拟)运行一个等效的命令,像这样:
gcloud pubsub subscriptions create my_subscription_name --topic=projects/my-project/topics/my-topic-dev-us-west1 --impersonate-service-account target-svc-account@my-project.iam.gserviceaccount.com
这完全如预期的那样工作——这使我相信GCP中的权限设置是正确的。
是否SubscriberClient
不能与ImpersonatedCredentials
一起工作,或者我可以做一些强制操作来使验证工作?
我还确保运行gcloud config unset auth/impersonate_service_account
和gcloud auth application-default login
,以确保我的本地凭据处于良好状态。
相关的依赖关系:
google-api-core[grpc]==1.31.1; platform_python_implementation != 'PyPy'
google-api-python-client==2.15.0; python_version >= '3.6'
google-auth-httplib2==0.1.0
google-auth==1.34.0
google-cloud-core==2.0.0b1; python_version >= '3.6'
google-cloud-firestore==2.2.0; platform_python_implementation != 'PyPy'
google-cloud-pubsub==2.7.0
google-cloud-storage==1.41.1; python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'
google-crc32c==1.1.2; python_version >= '3.6'
google-resumable-media==2.0.0b1; python_version >= '3.6'
googleapis-common-protos[grpc]==1.53.0; python_version >= '3.6'
grpc-google-iam-v1==0.12.3
grpcio==1.39.0
httplib2==0.19.1
你的Python代码看起来是正确的。
完成以下步骤:
- 列出已启用的服务:
gcloud services list——enabled
- 验证iamcredentials.googleapis.com启用。启用:
gcloud services enable iamcredentials.googleapis.com
- 验证cloudresourcemanager.googleapis.com启用。启用:
gcloud services enable cloudresourcemanager.googleapis.com
- 检查Compute Engine默认服务帐户是否具有角色roles/iam.serviceAccountTokenCreator或更好。
需要的权限有:
-
iam.serviceAccounts.getAccessToken
-
iam.serviceAccounts.getOpenIdToken(获取身份令牌需要此权限)。
gcloud projects add-iam-policy-binding [PROECT_ID]
——member "服务帐户:[GCE_DEFAULT_SA_FULL_EMAIL]">
——role "roles/iam.serviceAccountTokenCreator">
-
检查Compute Engine默认服务帐户是否存在角色roles/serviceusage.serviceUsageConsumer或更好。
gcloud projects add-iam-policy-binding [PROECT_ID]
——member "服务帐户:[GCE_DEFAULT_SA_FULL_EMAIL]">
——role "roles/serviceusage.serviceUsageConsumer">
如果没有启用/授予上述任何一个,令牌发布将失败。
注意:如果您只希望Compute Engine服务帐户能够模拟一个服务帐户,请更改步骤4以在服务帐户而不是项目上授予角色:
gcloud iam service-accounts add-iam-policy-binding [SA_FULL_EMAIL]
--member serviceAccount:[GCE_DEFAULT_SA_FULL_EMAIL]
--role roles/iam.serviceAccountTokenCreator