dockerfile拉取私库镜像_Docker私有镜像拉取错误no basic auth credentials

最近,我们遇到了一个Docker私有镜像拉取的错误,花费了数小时研究Docker私有仓库(Registry)凭证存储的细节才能弄清楚。尽管最终修复起来很容易,但是我们在凭据存储设计的过程中了解了一两件事,以及如何对Docker私有仓库(Registry)凭证进行安全配置。

Docker私有镜像拉取失败的情况如下:

Blimp有时需要从Docker私有仓库(Registry)中拉取私有镜像。这通常可以正常工作,但是不幸的是,有时拉取私有镜像时,会收到以下错误消息:

Get https://1234.dkr.ecr.us-east-1.amazonaws.com/v2/blimp/blimp/manifests/v0.1: no basic auth credentials

要了解我们是如何解决的,首先你需要了解Docker凭证。

Docker的外部证书存储

一般建议,存储Docker凭证要放在外部凭证存储中。通常位于~/.docker/config.json的Docker配置文件中。

企业中使用私有镜像仓库,通常都需要开启认证,认证凭据可能是用户在企业中通用的账户。但docker login以后,会在~/.docker/config.json中保存base64以后的用户名、密码,这样,在一些多人使用的服务器上,就会出现账号泄露的问题。

有没有解决方法呢?

docker提供credentials store,也就是讲密码存储到外置的credentials store中。

目前支持如下几种:

对于linux服务器来说,只能选择pass,因为D-Bus需要X11支持,而Apple和Microsoft看上去就不像是给Linux准备的。

因此,为了提高Docker凭据的安全性,你可以在Docker配置文件中使用两个字段来配置Docker获取凭据和存储凭据的方式:credsStore和credHelpers。

credsStore告诉Docker使用哪个帮助程序与凭证存储(credentials store)进行交互。所有帮助程序的名称都以docker-credential-开头,credsStore的值为帮助程序名称的后缀。

如果你使用Mac笔记本电脑,则可能会使用Mac OS钥匙串。使用Mac OS钥匙串后的帮助程序的名称是docker-credential-osxkeychain。因此,你Docker配置文件config.json将包括以下内容:

{

"credsStore": "osxkeychain"

}

如果要查看Docker当前为你提供的凭据是什么,可以使用list命令。例如:

docker-credential-osxkeychain list

输出信息是一对服务器和用户名列表。例如:

{

"http://quay.io":"kklin",

"https://index.docker.io":"kevinklin"

}

credHelpers是帮助程序( helpers ),用于生成短暂的凭据。例如,如果你使用gcr,gcloud会安装一个credHelper来使用你的Google登录名获取令牌的。采用这种方式后,Docker永远不会直接拥有你的Google凭据, docker-credential-gcloud充当Docker和Google凭据之间的中间人。

但即使我们对Docker login密码加密保存,仍然得到如下的错误消息:

Get https://1234.dkr.ecr.us-east-1.amazonaws.com/v2/blimp/blimp/manifests/v0.1: no basic auth credentials

通过上文,我们知道可以通过运行docker-credential-osxkeychain list和get命令来查看1234.dkr.ecr.us-east-1.amazonaws.com的凭据,分析判断那么为什么会收到一个错误消息-没有任何凭据(no basic auth credentials)?

Docker1.11版本前:私有仓库密码存储在配置文件中

Docker1.11版本前,Docker配置文件config.json通过auths字段来存储凭据,直到2016年1.11版本才能够使用外部凭据存储。

每当你登录私有仓库时,Docker都会将auths的值设置为你的密码。你的配置文件可能包含以下内容:

{

"auths": {

"https://index.docker.io/v1/": {

"auth": "YW11cmRhY2E6c3VwZXJzZWNyZXRwYXNzd29yZA=="

},

"localhost:5001": {

"auth": "aGVzdHVzZXI6dGVzdHBhc3N3b3Jk"

}

}

}

因此在采用credsStore后,当你使用docker login进行登录时,你的凭据还会被存储,但其中的字段auths不包含用户名或密码。结果看起来像这样:

{

"auths": {

"https://index.docker.io/v1/": {}

}

但Docker拉取镜像时从auths 和 credsStore两者同时获取凭据。因此,Docker拉取镜像时会有两份凭据,一份具有正确的用户名和密码,而一份则完全没有密码。

不幸的是,Docker偏爱使用auths中的https://的凭证,并尝试使用空凭证拉取镜像。因此,会有no basic auth credentials错误。

通过上文,我们确定了问题是一个空凭证被添加到 Docker配置文件config.json 中,我们就很容易解决该问题。我们需要做的就是添加一条if语句以跳过空凭据:

addCredentials := func(authConfigs map[string]clitypes.AuthConfig) {

for host, cred := range authConfigs {

// Don't add empty config sections.

if cred.Username != "" ||

cred.Password != "" ||

cred.Auth != "" ||

cred.Email != "" ||

cred.IdentityToken != "" ||

cred.RegistryToken != "" {

creds[host] = types.AuthConfig{

Username:      cred.Username,

Password:      cred.Password,

Auth:          cred.Auth,

Email:         cred.Email,

ServerAddress: cred.ServerAddress,

IdentityToken: cred.IdentityToken,

RegistryToken: cred.RegistryToken,

}

}

}

}

Docker凭证安全风险

很多使用Docker的组织,可能仍在使用传统的auths方法。如果是这样,你的~/.docker/config.json可能看起来像这样:

{

"auths": {

"https://index.docker.io/v1/": {

"auth": "YW11cmRhY2E6c3VwZXJzZWNyZXRwYXNzd29yZA=="

},

"localhost:5001": {

"auth": "aGVzdHVzZXI6dGVzdHBhc3N3b3Jk"

}

}

}

这看起来很安全,密码似乎是一堆乱码。你们会想,这些密码肯定是加密的吧?

其实,Docker所做的只是使用base64对密码进行编码。正如David Rieger在Hacker Noon上指出的那样,

Base64乍一看可能看起来像加密,但事实并非如此。Base64是一种编码方案,不是加密方案。你只需复制Base64字符串,然后在几秒钟内将其转换为ASCII。

那个看似安全的密码aGVzdHVzZXI6dGVzdHBhc3N3b3Jk,读取密码所需要做的只是对base64进行解码:

$ echo aGVzdHVzZXI6dGVzdHBhc3N3b3Jk| base64 -D

hestuser:testpassword

因此,如果未对Docker配置文件中的密码加密,则Docker将以纯文本格式存储你的密码。纯文本格式的好消息是,解决问题很容易,但是也容易被泄露和攻击。

为此,Docker提供了credentials store,也就是把密码存储到外置的credentials store中。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部