英文:
Google container registry golang moby authentication
问题
我正在使用Google容器注册表来托管我的Docker镜像。我还在使用用于Golang的moby客户端与其进行交互。我正在使用JSON服务密钥方法,它似乎可以与RegistryLogin一起正常工作。响应文本为“登录成功”。然而,我不知道如何使用返回的身份验证密钥进行ImagePull操作。在底层,设置RegistryAuth似乎会将传递的任何字符串设置为X-Registry-Auth标头,Google似乎没有在任何地方提到这一点。
我尝试将返回的密钥作为RegistryAuth传递,我尝试运行RegistryLogin然后不使用RegistryAuth进行拉取。我尝试对我的auth配置进行base64编码,并将其作为RegistryAuth发送。无论我尝试什么,都会得到“Error response from daemon: repository xxx not found: does not exist or no pull access”。在命令行中使用相同的详细信息运行docker login然后docker pull可以正常工作。我的代码如下:
authConfig := types.AuthConfig{
Username: "_json_key",
Password: string(decodedKey),
ServerAddress: "https://gcr.io",
}
_, err = engine.Client.RegistryLogin(ctx, authConfig)
if err != nil {
return err
}
responseBody, err := engine.Client.ImagePull(ctx, image, types.ImagePullOptions{
})
defer responseBody.Close()
if err != nil {
return err
}
decodedKey是JSON密钥文件的内容。有什么办法可以使其工作吗?
英文:
I'm using google container registry to host my docker images. I'm also using the moby client for golang to interact with it. I'm using the JSON service key approach which seems to work fine with RegistryLogin. The response text is Login Successful. However, I have no idea how to use the returned authentication key with ImagePull. Under the hood setting RegistryAuth appears to set whatever string passed as the X-Registry-Auth header, Google doesn't seem to mention this anywhere.
I've tried passing the returned key as RegistryAuth, I've tried running RegistryLogin and then just pulling without RegistryAuth. I've tried base64 encoding my auth config and sending that in RegistryAuth. No matter what I try I get "Error response from daemon: repository xxx not found: does not exist or no pull access". Running docker login and then docker pull with the same details works fine on cli. My code is:
authConfig := types.AuthConfig{
Username: "_json_key",
Password: string(decodedKey),
ServerAddress: "https://gcr.io",
}
_, err = engine.Client.RegistryLogin(ctx, authConfig)
if err != nil {
return err
}
responseBody, err := engine.Client.ImagePull(ctx, image, types.ImagePullOptions{
})
defer responseBody.Close()
if err != nil {
return err
}
decodedKey is the JSON key file content. Any ideas how to get this to work?
答案1
得分: 2
(我假设你已经找到了解决方法或者找到了替代方法,但我会在这里记录下来以供其他人参考)
你需要将其编组为JSON,然后进行base64编码。除了docker cli的代码之外,我没有在任何地方看到这个文档。
不幸的是,当我尝试包含github.com/docker/cli/cli/command
时,由于cli存储库的vendor目录被包含在go的包源路径中的方式,我遇到了这个错误:
./gcp.go:73:47: cannot use authc (type "github.com/docker/docker/api/types".AuthConfig)
as type "github.com/docker/cli/vendor/github.com/docker/docker/api/types".AuthConfig
in argument to command.EncodeAuthToBase64
Go编译器无法识别它们是相同类型,这很烦人。但是复制这个功能很简单:
buf, _ = json.Marshal(authConfig)
regauth := base64.URLEncoding.EncodeToString(buf)
pullopts := types.ImagePullOptions{RegistryAuth:regauth}
responseBody, err := engine.Client.ImagePull(ctx, image, pullopts)
...
*在我看来,一个更好的实现方式是在pullopts中有一个types.RequestPrivilegeFunc,它可以动态地从http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
获取access_token
字段。这样就不需要担心应用凭据的安全性了。我自己还没有尝试过这种方法。
希望这能帮到你,尽管有点晚了18个月。
顺便说一句,Google支持部门无法提供任何关于此问题的信息,gcr.io和docker文档也没有提供太多线索。解决方案是设置cli身份验证,然后修改docker cli工具的自定义版本,以便我可以看到实际发生的情况。
*编辑: 所以我尝试了这个方法,但据我所知,PullOptions中声明的PrivilegeFunc
函数从未被调用过。我不知道为什么。很遗憾,这似乎是一个更清晰的解决方案。不过,上面的过程代码对我来说有效。
英文:
(I assume you've already figured it out or have figured out an alternative method, but I'll document it here for the next person)
You need to marshal it to JSON, then base64 encode it. I haven't seen this documented anywhere except the code for the docker cli.
Unfortunately, when I tried to include github.com/docker/cli/cli/command
I got this error, due to the way the cli repo's vendor directory gets included in go's package source path:
./gcp.go:73:47: cannot use authc (type "github.com/docker/docker/api/types".AuthConfig)
as type "github.com/docker/cli/vendor/github.com/docker/docker/api/types".AuthConfig
in argument to command.EncodeAuthToBase64
The Go compiler doesn't recognize that they are the same type, which is annoying. But it's simple enough to replicate the functionality:
buf, _ = json.Marshal(authConfig)
regauth := base64.URLEncoding.EncodeToString(buf)
pullopts := types.ImagePullOptions{RegistryAuth:regauth}
responseBody, err := engine.Client.ImagePull(ctx, image, pullopts)
...
*IMHO, a better implementation would be to have a types.RequestPrivilegeFunc in the pullopts that gets the access_token
field from http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
on the fly. That way there's no app credentials to worry about securing. I haven't tried that yet, myself.
Hopefully that helps, despite it being 18 months late.
FWIW, Google support wasn't able to provide any information about this, and the gcr.io and docker documentation didn't provide much to go on, either. The solution was in getting the cli auth set up and then hacking a custom version of the docker cli tool so that I could see what was really going on.
*EDIT: So I tried this but AFAICT the PrivilegeFunc
function declared in PullOptions is never called. I have no idea why. Too bad, it seemed like a much cleaner solution. The procedural code above works for me, though.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论