go - 无法使用默认服务帐户和谷歌云库从谷歌 Kubernetes 引擎访问谷歌云存储

标签 go google-api google-cloud-storage google-kubernetes-engine service-accounts

我编写了一个应用程序,它具有使用 go lang 通过 Google Kubernetes Engine 上传图像的功能。其他一切正常,但当我尝试将图像写入 Google Cloud Storage 时,我一直遇到问题。

这是我在 golang 中实际使用 google storage api 的代码:

func putImage(imageURL string, image multipart.File) bool {
    fmt.Println("Putting into image location : " + imageURL)

    contextBackground := context.Background()
    storageClient, err := storage.NewClient(contextBackground)
    if err != nil {
        fmt.Println("No client.")
        return false
    }

    bucket := storageClient.Bucket("mytestbucketname")
    bucketWriter := bucket.Object(imageURL).NewWriter(contextBackground)
    bucketWriter.ContentType = "image/jpg"
    bucketWriter.CacheControl = "public, max-age=0"

    size, err := io.Copy(bucketWriter, image)
    if err != nil {
        fmt.Println("failed to put image")
        return false
    }

    fmt.Println(size)
    fmt.Println("Successfully put image")
    bucketWriter.Close()
    return true
}

上面的函数总是返回 true 并且 size 总是大于 0。但是,当我检查桶时,它实际上并没有任何东西。所以我研究了一下,发现默认的服务账户只有对云存储的读取权限。这很奇怪,因为它应该返回 false 或 size 应该为 0 甚至输出权限被拒绝的错误。

官方的 cloud.google.com/go/storage API 说 Bucket() 函数返回一个实际上不执行任何网络操作的 BucketHandle,这对于为什么我没有收到权限被拒绝错误(?)是有道理的。因此,我决定检查我是否真的从客户端或存储桶中获取任何内容,只是为了查看读取权限是否有效。我添加了以下代码:

attr, err := bucket.Attrs(contextBackground)
if err != nil {
    fmt.Println(err.Error())
}
fmt.Println("bucket name : " + attr.Name)

此时我开始遇到关闭我的应用程序的 fatal error 。我在尝试检索存储桶的属性时遇到的错误是:

Get https://www.googleapis.com/storage/v1/b/mytestbucketname?alt=json&prettyPrint=false&projection=full: oauth2: cannot fetch token: Post https://oauth2.googleapis.com/token: x509: certificate signed by unknown authority

所以我想我需要为我的图像添加 ca 证书。但这对我来说听起来不合逻辑,因为如果我在 Google Kubernetes Engine 中运行我的图像并且它正在访问我的 Google Cloud Storage,鉴于它已经具有具有读取权限的默认服务帐户,为什么我需要证书?我创建了一个版本为 1.12.8-gke.10 的新集群,并确保禁用问题客户端证书,并确保我具有对存储的读取权限,但仍然遇到相同的错误。我将这一行添加到我的 docker 文件中,但仍然出现相同的错误:

RUN apk --no-cache add ca-certificates && update-ca-certificates

我已经研究了两天,现在我的想法已经用完了。我的问题是我在使用默认权限时尝试从 Kubernetes Engine 访问存储桶属性时一直给我“x.509 证书由未知授权机构签名”错误我做错了什么?从技术上讲,获取存储桶属性只是一个读取功能,我应该能够在默认权限下执行此操作,对吧?如果有人有任何想法或曾经遇到过同样的问题,请给我一些帮助!谢谢!

最佳答案

如果您使用的是默认集群服务帐户,则需要确保集群有 sufficient scopes to write to storage .通过 default ,GKE 集群只有读取范围,阻止对 GCS 存储桶的写入尝试。

gke-default:
https://www.googleapis.com/auth/devstorage.read_only
https://www.googleapis.com/auth/logging.write
https://www.googleapis.com/auth/monitoring
https://www.googleapis.com/auth/service.management.readonly
https://www.googleapis.com/auth/servicecontrol
https://www.googleapis.com/auth/trace.append

如果不启用写入范围,无论凭据如何,您都无法写入存储桶。

Note: You can use the access token only for scopes that you specified when you created the instance. For example, if the instance has been granted only the https://www.googleapis.com/auth/storage-full scope for Google Cloud Storage, then it can't use the access token to make a request to BigQuery.

如果您想绕过作用域,请为应用程序创建一个自定义服务帐户,下载 JWT token 并将这些凭据直接装载到您的代码中。这是 recommended method to authenticate your application针对 Google API

关于go - 无法使用默认服务帐户和谷歌云库从谷歌 Kubernetes 引擎访问谷歌云存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57056164/

相关文章:

json - 在 UnmarshalJSON 函数中调用 json.Unmarshal 不会导致堆栈溢出

go - 检查进程是否有窗口

c# - 如何使用 API v3 .NET 删除 Google 日历中的事件?

c# - 在 C# 中将对象上传到谷歌云存储桶

go - 是否导出嵌入错误?

json - 如何在 Go 中生成带有排序键的 JSON?

android - 如何在多项 Activity 中正确使用 Google Plus 登录?

android - "411 Length required"- 来自使用 Android API 10 及更低版本的 Google Docs Api 的响应

python - 谷歌云存储 python list_blobs 性能

linux - 合并 Google Cloud Storage 中的文件