首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Google云任务不能授权云运行错误PERMISSION_DENIED(7):HTTP状态代码403

Google云任务不能授权云运行错误PERMISSION_DENIED(7):HTTP状态代码403
EN

Stack Overflow用户
提问于 2021-08-22 07:09:29
回答 2查看 1.3K关注 0票数 0

这个问题与Google任务无法对云运行进行身份验证非常相似,但我没有使用自己的域。我正在使用云运行域本身。

我遵循了以下两个教程(两者都有点类似):

https://cloud.google.com/run/docs/triggering/using-tasks

https://cloud.google.com/tasks/docs/creating-http-target-tasks

我不确定是否有更多的教程,我错过了,但下面是完整的场景。

我有一些基于Django REST的API运行在Google上,它们是公开的。此外,我可以在没有任何问题的情况下使用它们(尽管随后需要身份验证)。

我已经创建了一个Google任务队列,我使用以下代码将任务发送给它

代码语言:javascript
复制
class QueueTaskMixin:
    def send_task(self, payload=None):
        url = 'https://my-public-cloud-run-app.a.run.app/api/conversation_types/'

        client = tasks_v2.CloudTasksClient(credentials=credentials)
        # `credentials` above belongs to a service account which have all sort of accesses
        # Cloud SQL Admin
        # Cloud SQL Client
        # Cloud SQL Editor
        # Cloud Tasks Admin
        # Cloud Tasks Task Runner
        # Service Account Token Creator
        # Service Account User
        # Cloud Run Admin
        # Cloud Run Invoker
        # Cloud Run Service Agent
        # Storage Admin
  
        parent = client.queue_path(
            project=settings.GS_PROJECT_ID,
            location=settings.GS_Q_REGION,
            queue=settings.GS_Q_NAME)

        task = {
            'http_request':
                {
                    'headers': {
                        'Content-type': 'application/json',
                    },
                    'http_method': tasks_v2.HttpMethod.POST,
                    'url': url,
                    'oidc_token': {
                        'service_account_email': settings.GS_Q_IAM_EMAIL,
                         # GS_Q_IAM_EMAIL is a another Service account that has
                         # Cloud Tasks Enqueuer
                         # Service Account User
                         # Cloud Run Invoker
                    }
                }
        }

        if payload:
            if isinstance(payload, dict):
                payload = json.dumps(payload)
            converted_payload = payload.encode()
            task['http_request']['body'] = converted_payload

        response = client.create_task(
            request={'parent': parent, 'task': task}
        )

        print('Created task {}'.format(response.name))

现在我得到了PERMISSION_DENIED(7): HTTP status code 403错误。我的API日志显示了相同的内容:

代码语言:javascript
复制
"POST /api/conversation_types/ HTTP/1.1" 403 58 "-" "Google-Cloud-Tasks"
Forbidden: /api/conversation_types/

现在我不确定的是,这个403错误是否由

  1. 两个谷歌服务试图相互授权
  2. 或者我的API。因为我的API需要身份验证/授权。如前所述,用户需要使用他们的用户名和密码登录,他们将获得一个JWT令牌,然后他们可以调用这个API。

关于这些文档,我不确定我必须在哪里提供API用户名/密码/JWT令牌。文件上说:

代码语言:javascript
复制
To authenticate between Cloud Tasks and an HTTP Target handler, Cloud Tasks creates a header token. This token is based on the credentials in the Cloud Tasks Enqueuer service account, identified by its email address.

是否需要以用户身份将此服务帐户电子邮件地址添加到我的API中?我是用oidc还是oauth

任何评论或回答都非常感谢。

更新1 -在从中删除auth之后,云任务能够成功地调用。那么现在我如何使用云任务来运行我的API呢?

更新2 -尝试使用OAuthToken并获得错误

代码语言:javascript
复制
400 Invalid url for HttpRequest.oauth_token. The hostname in the url must end with ".googleapis.com"

看来只能使用OIDC令牌了。

更新3 - Google说:

代码语言:javascript
复制
OIDC tokens are signed JSON Web Tokens (JWT) and are used primarily to assert identity and not to provide any implicit authorization against a resource, unlike OAuth tokens, which do provide access.

这是否意味着OIDC令牌不能用于授权?因为我这里有授权错误。不能使用OIDC,不能使用OAuth,那么使用什么呢?

根据@johnhanley的注释,更新4,我已经更新了API以接受Bearer令牌进行身份验证。但是,即使我的API正确地获得了令牌,它也无法授权它,并且会产生invalid token错误(我使用curl命令验证了它)。在令牌格式不正确或令牌不正确的两种情况下,API只是返回403禁止的错误)。

任何人都可以告诉用户如何将密码(我可以在API中为服务帐户用户电子邮件生成密码)给服务帐户,以便使用该密码和电子邮件ID作为用户名,OIDC可以生成一个令牌并使用它进行身份验证。还是我走错方向了?

EN

回答 2

Stack Overflow用户

发布于 2021-08-23 10:33:32

检查云任务服务代理(service-[project-number]@gcp-sa-cloudtasks.iam.gserviceaccount.com)在您的IAM管理控制台页面中的存在,并授予他roles/iam.serviceAccountTokenCreator角色。

票数 0
EN

Stack Overflow用户

发布于 2021-09-02 06:13:29

不要关闭身份验证,它确实有效。下面是以bash命令和注释的形式来解释这些步骤的一些步骤

设置一些变量

代码语言:javascript
复制
PROJECT_ID='my-gcp-project-123'
TASK_ENQUER_SVC_ACCOUNT='tasks-creator-svc'
TASKS_SRV_ACCOUNT='cloud-tasks-svc'
CLOUD_RUN_SRV_ACCOUNT='cloud-run-svc'
GPC_REGION='australia-southeast1'

创建云任务队列

代码语言:javascript
复制
gcloud tasks queues create my-task-queue

创建一个用于发送任务的服务帐户--您需要cloudtasks.enqueuerserviceAccountUser

代码语言:javascript
复制
gcloud iam service-accounts create $TASK_ENQUER_SVC_ACCOUNT \
    --display-name "Service account for sending cloud tasks"
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member \
    serviceAccount:$TASK_ENQUER_SVC_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com \
    --role "roles/logging.logWriter"
# cloudtasks.enqueuer role is needed to create tasks
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member \
    serviceAccount:$TASK_ENQUER_SVC_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com \
    --role "roles/cloudtasks.enqueuer"
# service account user role is needed for permission iam.serviceAccounts.actAs
# so a task can be generated as service account $TASKS_SRV_ACCOUNT
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member \
    serviceAccount:$TASK_ENQUER_SVC_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com \
    --role "roles/iam.serviceAccountUser"

创建运行云运行服务的服务帐户

代码语言:javascript
复制
gcloud iam service-accounts create $CLOUD_RUN_SRV_ACCOUNT \
    --display-name "Service account for running cloud run service"
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member \
    serviceAccount:$CLOUD_RUN_SRV_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com \
    --role "roles/logging.logWriter"

创建云任务将使用的服务帐户-不需要特殊权限。

代码语言:javascript
复制
gcloud iam service-accounts create $TASKS_SRV_ACCOUNT \
    --display-name "Service account for the cloud-tasks"
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member \
    serviceAccount:$TASKS_SRV_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com \
    --role "roles/logging.logWriter"

使用ingress=allno-allow-unauthenticated部署云运行服务

云任务不使用无服务器的VPC连接器,所以入口需要全部。

代码语言:javascript
复制
gcloud run deploy my-cloud-run-service \
    --image=us.gcr.io/${PROJECT_ID}/my-docker-image \
    --concurrency=1 \
    --cpu=2 \
    --memory=250Mi \
    --max-instances=10 \
    --platform=managed \
    --region=$GPC_REGION \
    --no-allow-unauthenticated \
    --port=8080 \
    --service-account=$CLOUD_RUN_SRV_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com \
    --ingress=all \
    --project=${PROJECT_ID}

现在必须授予TASKS_SRV_ACCOUNT调用云运行目标服务的权限

代码语言:javascript
复制
gcloud run services add-iam-policy-binding my-cloud-run-service \
    --member=serviceAccount:$TASKS_SRV_ACCOUNT@${PROJECT_ID}.iam.gserviceaccount.com \
    --role=roles/run.invoker \
    --region=$GPC_REGION

然后,您可以按照本步骤https://cloud.google.com/tasks/docs/creating-http-target-tasks#token上的指令发送带有身份验证令牌的云任务。

service_account_email参数是上面创建的TASKS_SRV_ACCOUNT

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68879202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档