cloudtasks.CreateTask 失败:`缺乏 IAM 权限 "cloudtasks.tasks.create"` 即使我的账户拥有该权限
cloudtasks.CreateTask fails: `lacks IAM permission "cloudtasks.tasks.create"` even though my account has that permission
我正在关注 Creating HTTP Target tasks guide。
当我 运行 下面发布的代码时,我收到此错误:
cloudtasks.CreateTask: rpc error: code = PermissionDenied
desc = The principal (user or service account)
lacks IAM permission "cloudtasks.tasks.create" for the resource
"projects/my_project/locations/europe-west1/queues/my_queue"
(or the resource may not exist).
我已经用 gcloud auth login my@email.com
登录了。
my@email.com 具有由我的自定义云任务角色设置的以下权限:
- cloudtasks.locations.get
- cloudtasks.locations.list
- cloudtasks.queues.get
- cloudtasks.queues.list
- cloudtasks.tasks.create
- cloudtasks.tasks.delete
- cloudtasks.tasks.fullView
- cloudtasks.tasks.get
- cloudtasks.tasks.list
- cloudtasks.tasks.run
我不明白。我还应该检查什么?
main.go
// Run `PROJECT_ID=my_project QUEUE_ID=my_queue go run main.go`
package main
import (
"context"
"fmt"
"os"
cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
taskspb "google.golang.org/genproto/googleapis/cloud/tasks/v2"
)
var (
locationID = "europe-west1"
url = "example.com/callback"
message = "testing"
)
func main() {
projectID := os.Getenv("PROJECT_ID")
queueID := os.Getenv("QUEUE_ID")
task, err := createHTTPTask(projectID, locationID, queueID, url, message)
if err != nil {
fmt.Println(err)
}
fmt.Println(task)
}
// createHTTPTask creates a new task with a HTTP target then adds it to a Queue.
func createHTTPTask(projectID, locationID, queueID, url, message string) (*taskspb.Task, error) {
// Create a new Cloud Tasks client instance.
// See https://godoc.org/cloud.google.com/go/cloudtasks/apiv2
ctx := context.Background()
client, err := cloudtasks.NewClient(ctx)
if err != nil {
return nil, fmt.Errorf("NewClient: %v", err)
}
// Build the Task queue path.
queuePath := fmt.Sprintf("projects/%s/locations/%s/queues/%s", projectID, locationID, queueID)
// Build the Task payload.
// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#CreateTaskRequest
req := &taskspb.CreateTaskRequest{
Parent: queuePath,
Task: &taskspb.Task{
// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#HttpRequest
MessageType: &taskspb.Task_HttpRequest{
HttpRequest: &taskspb.HttpRequest{
HttpMethod: taskspb.HttpMethod_POST,
Url: url,
},
},
},
}
// Add a payload message if one is present.
req.Task.GetHttpRequest().Body = []byte(message)
createdTask, err := client.CreateTask(ctx, req)
if err != nil {
return nil, fmt.Errorf("cloudtasks.CreateTask: %v", err)
}
return createdTask, nil
}
云任务 API 已启用。
过去几天我一直遇到同样的问题,现在已经解决了。我用来创建 API 客户端和创建任务的库使用的凭据与我预期的不同。
对于使用 "application default credentials" 或至少让客户端自动查找凭据的用户,请查看此页面:https://cloud.google.com/docs/authentication/production#finding_credentials_automatically
我创建了一个具有所有正确角色的服务帐户,并假设 API 客户端正在使用该服务帐户。原来我没有传递密钥文件,因此它使用的是 "application default credentials"。对于我的用例,"application default credentials" 指的是 App Engine 默认服务帐户。当我为 API 客户端提供我的自定义服务帐户的密钥文件时,它起作用了。
应用程序默认凭据 (ADC) 提供了一种获取调用 Google API 时使用的凭据的方法。 gcloud auth application-default 命令组允许您管理计算机上用于本地应用程序开发的活动凭据。
使用以下命令获取用于 ADC 的新用户凭据:
gcloud auth application-default login
我正在关注 Creating HTTP Target tasks guide。 当我 运行 下面发布的代码时,我收到此错误:
cloudtasks.CreateTask: rpc error: code = PermissionDenied
desc = The principal (user or service account)
lacks IAM permission "cloudtasks.tasks.create" for the resource
"projects/my_project/locations/europe-west1/queues/my_queue"
(or the resource may not exist).
我已经用 gcloud auth login my@email.com
登录了。
my@email.com 具有由我的自定义云任务角色设置的以下权限:
- cloudtasks.locations.get
- cloudtasks.locations.list
- cloudtasks.queues.get
- cloudtasks.queues.list
- cloudtasks.tasks.create
- cloudtasks.tasks.delete
- cloudtasks.tasks.fullView
- cloudtasks.tasks.get
- cloudtasks.tasks.list
- cloudtasks.tasks.run
我不明白。我还应该检查什么?
main.go
// Run `PROJECT_ID=my_project QUEUE_ID=my_queue go run main.go`
package main
import (
"context"
"fmt"
"os"
cloudtasks "cloud.google.com/go/cloudtasks/apiv2"
taskspb "google.golang.org/genproto/googleapis/cloud/tasks/v2"
)
var (
locationID = "europe-west1"
url = "example.com/callback"
message = "testing"
)
func main() {
projectID := os.Getenv("PROJECT_ID")
queueID := os.Getenv("QUEUE_ID")
task, err := createHTTPTask(projectID, locationID, queueID, url, message)
if err != nil {
fmt.Println(err)
}
fmt.Println(task)
}
// createHTTPTask creates a new task with a HTTP target then adds it to a Queue.
func createHTTPTask(projectID, locationID, queueID, url, message string) (*taskspb.Task, error) {
// Create a new Cloud Tasks client instance.
// See https://godoc.org/cloud.google.com/go/cloudtasks/apiv2
ctx := context.Background()
client, err := cloudtasks.NewClient(ctx)
if err != nil {
return nil, fmt.Errorf("NewClient: %v", err)
}
// Build the Task queue path.
queuePath := fmt.Sprintf("projects/%s/locations/%s/queues/%s", projectID, locationID, queueID)
// Build the Task payload.
// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#CreateTaskRequest
req := &taskspb.CreateTaskRequest{
Parent: queuePath,
Task: &taskspb.Task{
// https://godoc.org/google.golang.org/genproto/googleapis/cloud/tasks/v2#HttpRequest
MessageType: &taskspb.Task_HttpRequest{
HttpRequest: &taskspb.HttpRequest{
HttpMethod: taskspb.HttpMethod_POST,
Url: url,
},
},
},
}
// Add a payload message if one is present.
req.Task.GetHttpRequest().Body = []byte(message)
createdTask, err := client.CreateTask(ctx, req)
if err != nil {
return nil, fmt.Errorf("cloudtasks.CreateTask: %v", err)
}
return createdTask, nil
}
云任务 API 已启用。
过去几天我一直遇到同样的问题,现在已经解决了。我用来创建 API 客户端和创建任务的库使用的凭据与我预期的不同。
对于使用 "application default credentials" 或至少让客户端自动查找凭据的用户,请查看此页面:https://cloud.google.com/docs/authentication/production#finding_credentials_automatically
我创建了一个具有所有正确角色的服务帐户,并假设 API 客户端正在使用该服务帐户。原来我没有传递密钥文件,因此它使用的是 "application default credentials"。对于我的用例,"application default credentials" 指的是 App Engine 默认服务帐户。当我为 API 客户端提供我的自定义服务帐户的密钥文件时,它起作用了。
应用程序默认凭据 (ADC) 提供了一种获取调用 Google API 时使用的凭据的方法。 gcloud auth application-default 命令组允许您管理计算机上用于本地应用程序开发的活动凭据。
使用以下命令获取用于 ADC 的新用户凭据:
gcloud auth application-default login