第7节 Docker私有仓库的安全加密HTTPS实现
书接上文,再开一个135的IP机器作为
nginx反代
1、当前拓扑
132和133两个harbor的双向复制上一篇已经搞定,基本简单的实现了就。
下面134就是client访问135这个nginx。
2、docker跑一个nginx
services:
nginx:
image: nginx:1.27.0
container_name: nginx_server
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/html:/usr/share/nginx/html
- ./nginx/logs:/var/log/nginx
restart: always
# 说明:
# - 使用最新的 nginx 镜像。
# - 映射容器的 80 和 443 端口到主机。
# - 映射本地的 nginx 配置文件目录到容器的配置文件目录。
# - 映射本地的 html 文件目录到容器的 html 文件目录。
# - 映射本地的日志文件目录到容器的日志文件目录。
# - 设置容器重启策略为 always。
up一下
编写配置文件
同样做成服务
vim /lib/systemd/system/nginxd.service
[unit]
Description=nginxd
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/local/bin/docker-compose -f /apps/nginx/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /apps/nginx/docker-compose.yml down
[Install]
WantedBy=multi-user.target
此时就实现了反代了
但是此时登入有问题的,因为轮询调度,ID密码输入,再点就调度到另一台Harbor上去了。
验证就用同样的密码 分别登入两台Harbor就行了,不用测了没问题的,不放心可以测的。
就是nginx调度轮询,没有session导致的。估计连三次握手都握不起来,更遑论验证密码呢!
所以改成session调度
1、会话绑定,也就是nginx的session调度:①基于cookie的(harbor的cookie是多少也不知道)②基于源IP的(PAT环境就不适合了)
2、session复制,tomcat里有这个功能可以做,harbor没有做不了。
3、redis,理论上可以,但是harbor不知道怎么配置redis,让harbor去redis读session。
下面基于session
1、cookie好像是sid👇
但是好像不能确定
所以还是用👇
2、源IP来做会话保持吧
ip_hash说是源IP,其实是源IP的/24,不是/32的
所以得用hash👇
应该是做成服务了,所以出现问题了,
①docker-compose管理的就用docker-compose来管理,不要用docker;
②做成服务的,就要用服务来start,restart,stop,不要用docker来弄。
systemctl restart nginxd
就好了
上传镜像要需要注意https
因为现在是nginx代理的,所以insecure-registries里要写nginx的地址或域名
再次登入OK
由于没做dns,直接改tag为IP👇,但是报错了
这是因为当初登入的是IP地址,不是域名👆,👇
这样,报错就和IP PUSH的时候一致了
报错写明:Entity Too Large
再次push ok
HTTPS实现
HTTPS的SSL证书可以做在nginx上
也可以做在单机版的Harbor上
新版Harbor本身的SSL证书比老版的要复杂些
https://goharbor.io/docs/2.11.0/install-config/configure-https/
以下是对上面链接内容的简要说明👇
1、CA的私钥
2、CA用私钥自签名
3、CA给他用户也就是server颁发证书
3.1 server的私钥
3.2 server的申请文件
3.3 CA给server颁发证书
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=yourdomain.com
DNS.2=yourdomain
DNS.3=hostname
EOF
比老版多了一个文件👆,然哥们我一看,这不就是让下面PC浏览器显示安全的关键操作嘛,就是subectAltname就是我之前折腾的那东西啊👇
其实不是什么 比老板 多了了,而是时代变了(屎大便了),浏览器要人为安全就得这么干,不仅仅是Harbor的新老版本之分,而是所有的都变了。
然后还有一个nginx的ssl生成的便捷脚本也是一样
两处地方都是用到了一个知识点👇
然后这里Harbor的ssl解决方案里自然跑不掉这个新的政策subject Alternative name的意义。
啊~~~~ 继续学习
继续说明https://goharbor.io/docs/2.11.0/install-config/configure-https/这里的内容
👇这个其实好像是无用功,理论上是转换个,其实就是内容都一样,就是改了个后缀名称
其实官方这么些,也是对的,①改后缀②用这种方式改后缀也是大而全的cli
①因为docker deamon会认为.crt是CA的,所以要改成.cert作为client证书,client就是CA的用户,而CA的用户也就是 PC--SERVER ,的server服务器证书了。上图client就指的是server
链接里同样有不完善的地方
这里点进去也不是很明朗,就是yml文件的ssl配置。
以下是实验
# 创建证书相关数据的目录
mkdir -p /data/harbor/certs
cd /data/harbor/certs
# 生成CA的私钥
openssl genrsa -out ca.key 4096
# 生成CA的自签名证书
openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=CN/ST=Shanghai/L=Shanghai/O=example/OU=Personal/CN=ca.ming.org" \
-key ca.key \
-out ca.crt
# 生成harbor主机的私钥
openssl genrsa -out harbor.ming.org.key 4096
# 生成harbor主机的证书申请
openssl req -sha512 -new \
-subj "/C=CN/ST=Shanghai/L=Shanghai/O=example/OU=Personal/CN=harbor.ming.org" \
-key harbor.ming.org.key \
-out harbor.ming.org.csr
# 创建x509 v3扩展文件(时代变了新增内容)
cat > v3.ext <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=ming.org
DNS.2=yourdomain
DNS.3=hostname
EOF
# 给harbor主机颁发证书
openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in harbor.ming.org.csr \
-out harbor.ming.org.crt
# 最终文件列表如下
ca.crt ca.key ca.srl
harbor.ming.org.crt
harbor.ming.org.csr
harbor.ming.org.key
v3.ext
#新版的最终文件列表如下
ca.crt
ca.key
harbor.ming.org.crt
harbor.ming.org.csr
harbor.ming.org.key
v3.ext
# 查看证书内容cli
openssl x509 -in cacert.pem -noout -text
然后
mkdir -p /data/harbor/certs/
cp harbor.ming.org.crt harbor.ming.org.key /data/harbor/certs/
vim /apps/harbor/harbor.yml
......
hostname: harbor.ming.org # 注意:此行必须是网站的域名,而且harbor主机的/etc/hosts可以不解析此域名,不能是IP地址,否则登入时会报如下错苏
Error response from daemon: Get "https://harbor.ming.org/v2/": Get "https://192.168.126.132/service/token?account=admin&client_id=docker&offline_token=true&service=harbor-registry": x509: cannot validate certificate for 192.168.126.132 because it doesn't contain any IP SANs
# 而且 之前Harbor HA那会也对hostname有写法要求,好像写IP就得用IP去做HA。在👇这一篇里有提到 ,不过当时没有测试域名写个解析得效果可惜了:https://oneyearice.github.io/1-%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF%E5%92%8C%E5%A0%A1%E5%9E%92%E6%9C%BAJumpServer%E5%AE%9E%E6%88%98/4-Docker%E7%BD%91%E7%BB%9C%E7%AE%A1%E7%90%86%E5%92%8Cdocker-compose%E7%BC%96%E6%8E%92%E5%92%8C%E4%BB%93%E5%BA%93%E7%AE%A1%E7%90%86/6-Docker%E7%A7%81%E6%9C%89%E4%BB%93%E5%BA%93Harbor%E9%AB%98%E5%8F%AF%E7%94%A8%E5%92%8C%E5%8F%8C%E5%90%91%E5%A4%8D%E5%88%B6.html
# https related config
https:
# https port for harbor, default is 443
port: 443
# The path of cert and key files for nginx
certificate: /data/harbor/certs/harbor.ming.org.crt
private_key: /data/harbor/certs/harbor.ming.org.key
......
# 使上面的配置生效
cd /apps/harbor/
./prepare
docker-compose down -v
docker-compose up -d
以下使过程截图
生成证书文件
1、生成ca的key,用这个key生成ca的自签名 # key就是私钥
看看时间到是否10年
2、生成用户的key,用这个key 生成csr证书申请文件
3、生成openssl v3 扩展文件
4、利用ca.crt和ca.key和用户的csr文件生成用户的证书文件,并生成serial字符串
这里上图少了一个换行符,导致CLI卡住不动
查看生成的用户证书,确认时限10年
将上面的证书文件配到Harbor上
就使用,用户key和crt文件。
然后重新启动harbor的dockers,也就是
docker-compose down -v docker-compose up -d
不过之前使写了service的
所以直接restart就行
慢慢就重新创建了👆 一定要做好数据卷的持久保存。
1分钟大概
访问就看到鸟
然后导入证书,试试域名访问,已经IP访问的效果
然后要测试是否可以上传下载镜像,因为开了ssl
然后还要测试HA,因为之前是用的IP还互指HA的,当时用域名还不行咧。
好一个个来
1、导入证书
双击导入
IP访问不行,换域名试试
发现
少了通配符,去试试,重新颁发crt,不麻烦,因为Harbor调用路径没发生变化,文件名称不会改变,# 但是要./prepare的因为crt文件名称没变,但是内容变了,容器不是链接而是内容的复制进去到容器里的。
重启harbor也就是docker-compose down 然后docker-compose up -d
发现PC浏览器还是老的证书
于是怀疑要./prepare一下,
果然
然后导出来,再导进去
不行
可惜了,先试试FQDN
继续改
删除老的证书
导出导入
FQDN写错了
改
重启harbor试试
导出导入,谁让你这么玩的,你可真牛逼,受信任的根证书颁发机构,这个是要导入CA的证书,FUCK
终于可以了
回到过去,通配符的设置
FUCK
然后修正DNS
所以结论来了
只要 证书主题背景的备用名称 里的通配符包含哪个就行了呢?
👇这个无所谓,你和域名不一样无所谓,
所以结论
就是证书主体背景的备用名称 包含你访问的域名就行了,其他无所谓
然后就是要PC导入ca.crt CA的证书到受信任的根证书颁发机构
√ 最后修正为规范的统一的配置
# 创建证书相关数据的目录
mkdir -p /data/harbor/certs
cd /data/harbor/certs
# 生成CA的私钥
openssl genrsa -out ca.key 4096
# 生成CA的自签名证书
openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=CN/ST=Shanghai/L=Shanghai/O=example/OU=Personal/CN=ca.ming.org" \
-key ca.key \
-out ca.crt
# 生成harbor主机的私钥
openssl genrsa -out harbor.ming.org.key 4096
# 生成harbor主机的证书申请
openssl req -sha512 -new \
-subj "/C=CN/ST=Shanghai/L=Shanghai/O=example/OU=Personal/CN=harbor.ming.org" \
-key harbor.ming.org.key \
-out harbor.ming.org.csr
# 创建x509 v3扩展文件(时代变了新增内容)
cat > v3.ext <<EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=*.ming.org
DNS.2=ming.org
EOF
# 给harbor主机颁发证书
openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in harbor.ming.org.csr \
-out harbor.ming.org.crt
# 最终文件列表如下
ca.crt ca.key ca.srl
harbor.ming.org.crt
harbor.ming.org.csr
harbor.ming.org.key
v3.ext
#新版的最终文件列表如下
ca.crt
ca.key
harbor.ming.org.crt
harbor.ming.org.csr
harbor.ming.org.key
v3.ext
# 查看证书内容cli
openssl x509 -in cacert.pem -noout -text
# 这两行无所谓,就是调用文件路径一致就行,我的没变化直接用
#mkdir -p /data/harbor/certs/
#cp harbor.ming.org.crt harbor.ming.org.key /data/harbor/certs/
vim /apps/harbor/harbor.yml
......
hostname: harbor.ming.org # 注意:此行必须是网站的域名,而且harbor主机的/etc/hosts可以不解析此域名,不能是IP地址,否则登入时会报如下错 ★然而俺实测并不会,而且HA要求必须是IP。不过我是先用的域名然后再改回去的。就是说ssl证书生成的时候都是域名来着。有什么关系,harbor的东西和ssl证书生成过程并没有关系。所以这里必须写IP,就是为了HA能够OK。然后IP这边做SSL也没有问题。可能是我的harbor版本搞吧。
Error response from daemon: Get "https://harbor.wang.org/v2/": Get "https://10.0.0.102/service/token?account=admin&client_id=docker&offline_token=true&service=harbor-registry": x509: cannot validate certificate for 10.0.0.102 because it doesn't contain any IP SANs
#之前Harbor HA那会也对hostname有写法要求,好像写IP就得用IP去做HA。在👇这一篇里有提到 ,不过当时没有测试域名写个解析得效果可惜了:https://oneyearice.github.io/1-%E5%AE%B9%E5%99%A8%E6%8A%80%E6%9C%AF%E5%92%8C%E5%A0%A1%E5%9E%92%E6%9C%BAJumpServer%E5%AE%9E%E6%88%98/4-Docker%E7%BD%91%E7%BB%9C%E7%AE%A1%E7%90%86%E5%92%8Cdocker-compose%E7%BC%96%E6%8E%92%E5%92%8C%E4%BB%93%E5%BA%93%E7%AE%A1%E7%90%86/6-Docker%E7%A7%81%E6%9C%89%E4%BB%93%E5%BA%93Harbor%E9%AB%98%E5%8F%AF%E7%94%A8%E5%92%8C%E5%8F%8C%E5%90%91%E5%A4%8D%E5%88%B6.html
# https related config
https:
# https port for harbor, default is 443
port: 443
# The path of cert and key files for nginx
certificate: /data/harbor/certs/harbor.ming.org.crt
private_key: /data/harbor/certs/harbor.ming.org.key
......
# 使上面的配置生效
cd /apps/harbor/
./prepare
docker-compose down -v
docker-compose up -d
然后要测试是否可以上传下载镜像,因为开了ssl
然后还要测试HA,因为之前是用的IP还互指HA的,当时用域名还不行咧。
2、检查HA
由于132这台改成域名+ssl,果然
同样要 安装ca.crt吧
yum install -y ca-certificates # 一般就有
# 1√ 根证书到/etc/pki/ca-trust/source/anchors目录中远程就scp啦
cp ca.crt /etc/pki/ca-trust/source/anchors/
# 2√ 执行以下命令来更新 CA 证书存储,以便系统识别新的 CA 证书。
update-ca-trust
# 如果根证书是以*.pem结尾,需要转换成crt,然后再执行上述步骤。命令如下:
openssl x509 -in ca.pem -inform PEM -out ca.crt
============
# 你可以使用 openssl 命令来验证 CA 证书是否已经成功安装。运行以下命令并检查输出是否包含你刚才添加的 CA 证书。
# 这个也可以不做,直接用curl -L 域名 测试效果就行了,排查故障倒是分布检查需要的
openssl verify -CAfile /etc/pki/tls/certs/ca-bundle.crt your_cert.pem
#确保系统信任新的 CA 证书:在安装和更新 CA 证书后,系统应该信任由这个 CA 证书签署的所有证书。可以使用以下命令测试:
# 其实没必要,直接curl -L 域名就行了,就能测试了,这个👇是没有做上面步骤的时候测试的吧,不管了。
curl --cacert /etc/pki/tls/certs/ca-bundle.crt https://your-secured-site.com
测试
算了改回去,将132的harbor.yml里hostname改成IP地址,重新./prepare 再restart harbor
不对啊,
1、如果要做HA,那么就是nginx顶前面,就nginx自己做HTTPS就行了,HA之间就用IP。没毛病。
2、如果不做HA,那么就是单台,那么也就无需这里测试什么连接性了,对吧。
3、其实可以做到132 133 134 两台harbor自带ssl,一个nginx也带ssl的,就是hostname用IP就行了,具体如下👇测试OK:
试试看吧,改回IP
然后去看132,harhor.yml里的hostname改为IP后的HTTPS是否OK吧。。
没问题啊
谁说一定要域名的
然后要测试是否可以上传下载镜像,因为开了ssl
3、测试上传下载image
目前上传ok,但也要知道没有走https上传
删除insecure-registries里的相关站点👆,让其走ssl。
这个被拒绝了,要登入一下看看
1、登入是要登入的,就是/root/.docker/config.json里有这个域名的信息
2、重启了docker,harbor服务估计也有问题,80没了
3、导入ca解决证书不信任问题,但是只是停留在curl层面就像PC打开浏览器的效果
4、即使curl层面判断安全了,但是docker push login 还是不认。
5、所以OS系统层面有系统层面的信任途径,docker有docker层面的信任途径
OS就是上面3里面操作的
docker层面的来搞一下👇
# 转换harbor的crt证书为cert后缀,docker识别crt文件为CA证书,cert为客户端证书,这里的客户端应该说的是CA颁发给客户端也就是server服务器的证书,而非docker的客户端。而且全文也只有ca证书和server的证书。
# 不过其实这里是仅仅只是改了后缀而已,不存在转换一说
openssl x509 -inform PEM -in harbor.ming.org.crt -out harbor.ming.org.cert
# 所以仅仅等价于👇
cp -a harbor.ming.org.crt harbor.ming.org.cert
# 不相信可以对比两文件
diff harbor.ming.org.crt harbor.ming.org.cert
md5sum harbor.ming.org.crt harbor.ming.org.cert
# 默认的配置文件路径里创建
# 如果是docker就👇
mkdir -pv /etc/docker/certs.d/harbor.ming.org/
# 如果四containerd就👇
mkdir -pv /etc/containerd/certs.d/harobr.ming.org/
# 在docker客户端使用上面的证书文件
# 注意,官方介绍还需要同时复制harbor.ming.org.key和ca.crt,实际不需要
cp harbor.ming.org.cert 或 harbor.ming.org.crt harbor.ming.org.key ca.crt /etc/docker/certs.d/harbor.ming.org/
# 注意,实际只需要复制一个文件即可
# ①实际操作1
cp harbor.ming.org.crt /etc/docker/cert.d/harbor.ming.org/
# 无需重启服务,docker客户端即可上传下载镜像
# 新版如果无法登入,就重启docker服务
# ②实际操作2 就行了
systemctl restart docker
确实转的没意义👆
就是要重启docker的,但是docker重启后,harbor估计就不正常了
harbor是做成服务的,状态倒是OK,但是监听端口80没了
不得已重启harbor吧
然后就看到一开始提到的报错了
[root@realserver2 harbor]# docker login -u admin -p Harbor12345 harbor.ming.org
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Error response from daemon: Get "https://harbor.ming.org/v2/": Get "https://192.168.126.132/service/token?account=admin&client_id=docker&offline_token=true&service=harbor-registry": tls: failed to verify certificate: x509: cannot validate certificate for 192.168.126.132 because it doesn't contain any IP SANs
前文解决方法就是hostname写域名,但是这方法被我否掉了,因为HA没法做了。
当然你说做了HA,SSL就配置在nginx就行了,单机不做SSL。也行~
单机就hostname改为域名,然后不做HA,SSL也就OK了。
但是我就要既做HA--hostname就得IP,然后就要ngnix和后面得nodes都做ssl呢,你说神经病。我呸
就是要hostname写IP,正面解决这个报错,这个报错的本意还是证书里的信息选项不全。
cannot validate certificate for 192.168.126.132 because it doesn't contain any IP SANs
因为这个服务器证书里没有IP SANs信息,什么叫IP SANs
Subject Alternative Name (SAN) 这个熟悉吧,所以加一行就行了
[ alt_names ]
IP.1 = 192.168.126.132
DNS.1 = *.ming.org
DNS.2 = ming.org
将v3.ext优化为
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=*.ming.org
DNS.2=ming.org
重新颁发server的证书,服务器的证书啊,一些文章称之为客户端证书,其实是指CA的客户端,CA为其客户颁发的证书。哦,这是一个意思。
然后重新配置docker信任的ssl证书
再看最终效果
好了
搞定👆
搞定啥了?搞定了
1、HA
2、nginx的ssl证书不要讲了
3、HA环境下harbor.yml 的 hostname 必须写IP的情况下,每个单台harbor的ssl证书也做好了
4、操作逻辑如下
1、curl 的 ssl 信任路径和加载
2、docker的ssl信任路径和重启docker的必要性
3、重启docker对harbor的服务起来没影响,但是对可怜的监听端口有影响,需要重启harbor
4、harbor.yml这个初始化配置yml文件里hostname以后就记住必须写ip了
5、报错如果是refuse拒绝,一般可能就是监听端口没了
6、新版ssl要让浏览器也就是curl认可,需要SAN(subjectAltName)里有DNS1的域名,
7、新版ssl要让docker push的时候不报错IP SAN,就要让SAN(subjectAltName)里有IP1信息,就是配置为ssl服务器的IP就行了
差不多了,其他就是删改你乱七八糟但是又一个过程不拉的讨人厌的繁琐的操作记录了
tomcat那篇弄完再来👇
构建tomcat镜像运行jpress
1、ubuntu基础镜像: ubuntu22.04
2、jdk镜像: jdk-ubuntu22.04
3、tomcat镜像: tomcat-jdk-ubuntu22.04
4、最后一个jpress镜像也就是业务镜像: jpress-tomcat-jdk-ubuntu22.04
1 2 3 就是都属于基础镜像,4就是业务镜像会存在改动,所以变动就做4步就行了。
5、然后利用多阶段构建新开一个ubuntu然后二次构建,这样整体镜像就会小很多。如果是go不是java就直接用busybox来构建甚至用scratch空基础镜像来弄。 这步感觉要考虑插入上面哪一步里面,最好是第四步了。 # 就是能够脱离原环境到一个新的基础环境里运行得情况下就可以进行多阶段构建。还需要打几个常会用得检查工具 如 ping curl
7、上传到harbor上
8、从另外一台主机下载 docker run jpress
上传的jdk源码包,可以删掉,或者直接用ADD解压缩进去,但是还是有过程文件残留还是会占用空间,不一定能释放得掉,即使删掉一些,镜像可能也不会缩减。
案例
openssh升级高版本
以下未验证👇,思路应该使对的
用telnet上去编译安装openssl
openssl升级
直接换rocky9