docker更安全的登录方式

安装依赖

1
2
3
4
5
yum install -y gpg

# 生成随机数,解决卡在We need to generate a lot of random bytes
# https://blog.csdn.net/qq_38493182/article/details/106506697
yum install -y rng-tools && rngd -r /dev/urandom

安装pass

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 进入源码包下载自定义规划目录
cd /usr/local/src
# 下载指定版本的源码包
wget https://git.zx2c4.com/password-store/snapshot/password-store-1.7.4.tar.xz
# 将源码包解压缩到自定义程序安装目录
tar Jxf password-store-1.7.4.tar.xz -C /usr/local/
# 进入源码解压后的目录
cd /usr/local/password-store-1.7.4
# 编译安装
make install
# 验证安装结果
pass version

使用 GPG 生成 KEY

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 4096
gpg --gen-key

# 查看生成的key
gpg --list-keys

# 通过上一步骤得到的 pub 4096R/ 后面的 id 来初始化 pass
pass init "xxxxx"

# 为 key 设置密码并保存在 pass 密码本中
pass insert admin
pass show admin

安装Docker Credential

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 进入自定义资源下载目录
cd /usr/local/src
# 下载 Docker Credetial 
wget https://github.com/docker/docker-credential-helpers/releases/download/v0.6.4/docker-credential-pass-v0.6.4-amd64.tar.gz
# 解压 Docker Credential 
tar zxvf docker-credential-pass-v0.6.4-amd64.tar.gz
# 为 Docker Credential 赋予可执行权限
chmod +x docker-credential-pass
# 将 Docker Credential 移动到环境变量中
mv docker-credential-pass /usr/local/bin/
# 查看 Docker Credentail 的版本
docker-credential-pass version
#0.6.4

验证以上登录镜像仓库的用户名密码是否保存在 pass 中

由于需要使用 tree 命令,这里需要安装

1
yum install tree -y

查看密码本中的密码原文

[root@node103 /]# docker-credential-pass list
{"192.169.5.207:8004":"admin"}
[root@node103 /]# pass
Password Store
├── admin
└── docker-credential-helpers
    ├── docker-pass-initialized-check
    └── MTkyLjE2OS41LjIwNzo4MDA0
        └── admin
[root@node103 /]# pass show docker-credential-helpers/MTkyLjE2OS41LjIwNzo4MDA0/admin
这里将显示设置的密码明文

保存密码文件路径

1
2
3
4
5
[root@node103 MTkyLjE2OS41LjIwNzo4MDA0]# cd /root/.password-store/docker-credential-helpers/MTkyLjE2OS41LjIwNzo4MDA0
[root@node103 MTkyLjE2OS41LjIwNzo4MDA0]# ll
total 4
-rw------- 1 root root 591 Aug 29 14:36 admin.gpg
[root@node103 MTkyLjE2OS41LjIwNzo4MDA0]# 

四、凭据存储使用总结

  • Docker 默认采用 config.json 文件保存 docker login 的用户名密码

  • 并且这些用户名密码都是通过 base64 加密存储的很容易被泄露

  • 我们应该切换用户名密码保存源,如 pass

  • 在需要保存 Docker 用户名密码的操作客户端都安装 pass 并根据以上配置即可

  • 配置完成通过 docker login 进行一次登录验证

  • 重启 Docker 在进行一次登录验证(此次是不需要输入登录密码的)

  • dokcer login 的操作脚本都不需要进行相应的变化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/bin/sh

if [ $(id -u) != 0 ]; then
   echo "This script must be run as root"
   exit 1
fi

yum install -y gpg

# 生成随机数,解决卡在We need to generate a lot of random bytes
# https://blog.csdn.net/qq_38493182/article/details/106506697
yum install -y rng-tools && rngd -r /dev/urandom


pass_version="1.7.4"
# 进入源码包下载自定义规划目录
cd /usr/local/src
# 下载指定版本的源码包
wget https://git.zx2c4.com/password-store/snapshot/password-store-${pass_version:-1.7.4}.tar.xz
# 将源码包解压缩到自定义程序安装目录
tar Jxf password-store-${pass_version:-1.7.4}.tar.xz -C /usr/local/
# 进入源码解压后的目录
cd /usr/local/password-store-${pass_version:-1.7.4}
# 编译安装
make install
# 验证安装结果
pass version


docker_credential_version="v0.6.4"
cd /usr/local/src
# 下载 Docker Credetial 
wget https://github.com/docker/docker-credential-helpers/releases/download/${docker_credential_version:-v0.6.4}/docker-credential-pass-${docker_credential_version:-v0.6.4}-amd64.tar.gz
# 解压 Docker Credential 
tar zxvf docker-credential-pass-${docker_credential_version:-v0.6.4}-amd64.tar.gz
# 为 Docker Credential 赋予可执行权限
chmod +x docker-credential-pass
# 将 Docker Credential 移动到环境变量中
mv docker-credential-pass /usr/local/bin/
# 查看 Docker Credentail 的版本
docker-credential-pass version





# https://www.gnupg.org/documentation/manuals/gnupg-devel/Unattended-GPG-key-generation.html
gpg2 --batch --gen-key <<EOT
    %echo Generating a default OpenPGP key
    Key-Type: default
    Key-Length: 4096
    Subkey-Type: default
    Name-Real: passwdauto1
    Name-Comment: No comment
    Name-Email: [email protected]
    Expire-Date: 0
    Passphrase: passwdauto1
    # Do a commit here, so that we can later print "done" :-)
    %commit
    %echo done
EOT

#    %pubring pubring.kbx
#    %secring trustdb.gpg

key=$(gpg2 --list-secret-keys | grep uid -B 1 | head -n 1 | sed 's/^ *//g')

echo $(gpg2 --list-secret-keys | grep uid -B 1 | head -n 1 | sed 's/^ *//g')
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
#!/bin/sh

# https://github.com/docker/docker-credential-helpers/issues/102#issuecomment-690613373
# Sets up a docker credential helper so docker login credentials are not stored encoded in base64 plain text.
# Uses the pass secret service as the credentials store.
# If previously logged in w/o cred helper, docker logout <registry> under each user or remove ~/.docker/config.json.

# Tested on Ubuntu 18.04.5 LTS.

if ! [ $(id -u) = 0 ]; then
   echo "This script must be run as root"
   exit 1
fi

echo "Installing dependencies"
apt update && apt-get -y install gnupg2 pass rng-tools jq

# Check for later releases at https://github.com/docker/docker-credential-helpers/releases
version="v0.6.3"
archive="docker-credential-pass-$version-amd64.tar.gz"
url="https://github.com/docker/docker-credential-helpers/releases/download/$version/$archive"

# Download cred helper, unpack, make executable, and move it where Docker will find it.
wget $url \
    && tar -xf $archive \
    && chmod +x docker-credential-pass \
    && mv -f docker-credential-pass /usr/local/bin/

# Done with the archive
rm -f $archive

config_path=~/.docker
config_filename=$config_path/config.json

# Could assume config.json isn't there or overwrite regardless and not use jq (or sed etc.)
# echo '{ "credsStore": "pass" }' > $config_filename

if [ ! -f $config_filename ]
then
    if [ ! -d $config_path ]
    then
        mkdir -p $config_path
    fi

    # Create default docker config file if it doesn't exist (never logged in etc.). Empty is fine currently.
    cat > $config_filename <<EOL
{
}
EOL
    echo "$config_filename created with defaults"
else
    echo "$config_filename already exists"
fi

# Whether config is new or existing, read into variable for easier file redirection (cat > truncate timing)
config_json=`cat $config_filename`

if [ -z "$config_json" ]; then
    # Empty file will prevent jq from working
    $config_json="{}"
fi

# Update Docker config to set the credential store. Used sed before but messy / edge cases.
echo "$config_json" | jq --arg credsStore pass '. + {credsStore: $credsStore}' > $config_filename

# Output / verify contents
echo "$config_filename:"
cat $config_filename | jq

# Help with entropy to prevent gpg2 full key generation hang
# Feeds data from a random number generator to the kernel's random number entropy pool
rngd -r /dev/urandom

# To cleanup extras from multiple runs: gpg --delete-secret-key <key-id>; gpg --delete-key <key-id>
echo "Generating GPG key, accept defaults but consider key size to 2048, supply user info"
gpg2 --full-generate-key

echo "Adjusting permissions"
sudo chown -R $USER:$USER ~/.gnupg
sudo find ~/.gnupg -type d -exec chmod 700 {} \;
sudo find ~/.gnupg -type f -exec chmod 600 {} \;

# List keys
gpg2 -k

key=$(gpg2 --list-secret-keys | grep uid -B 1 | head -n 1 | sed 's/^ *//g')

echo "Initializing pass with key $key"
pass init $key

echo "Leave this password blank (important):"
pass insert docker-credential-helpers/docker-pass-initialized-check

# Just a verification. Don't need to show actual password, mask it.
echo "Password verification:"
pass show docker-credential-helpers/docker-pass-initialized-check | sed -e 's/\(.\)/\*/g'

echo "Docker credential password list (empty initially):"
docker-credential-pass list

echo "Done. Ready to test. Run: sudo docker login <registry>"
echo "Afterwards run: sudo docker-credential-pass list; sudo cat ~/.docker/config.json"
updatedupdated2024-10-282024-10-28