如何让 Docker 中的 GitLab Runner 看到自定义 CA 根证书
How to make GitLab Runner in Docker see a custom CA Root certificate
我已经安装并配置:
- 本地 GitLab Omnibus 在 ServerA 运行 在 HTTPS
- 本地 GitLab-Runner 作为 Docker 服务安装在 ServerB
服务器证书由自定义 CA Root 生成
配置
我已将 CA 根证书放在 ServerB 上:
/srv/gitlab-runner/config/certs/ca.crt
已按照 Run GitLab Runner in a container - Docker image installation and configuration:
中所述在 ServerB 上安装了 Runner
docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
已按照 Registering Runners - One-line registration command 中所述注册 Runner:
docker run --rm -t -i
-v /srv/gitlab-runner/config:/etc/gitlab-runner
--name gitlab-docker-runner gitlab/gitlab-runner register \
--non-interactive \
--executor "docker" \
--docker-image alpine:latest \
--url "https://MY_PRIVATE_REPO_URL_HERE/" \
--registration-token "MY_PRIVATE_TOKEN_HERE" \
--description "MyDockerServer-Runner" \
--tag-list "TAG_1,TAG_2,TAG_3" \
--run-untagged \
--locked="false"
此命令给出了以下输出:
Updating CA certificates...
Runtime platform arch=amd64 os=linux pid=5 revision=cf91d5e1 version=11.4.2
Running in system-mode.
Registering runner... succeeded runner=8UtcUXCY
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
我检查过
$ docker exec -it gitlab-runner bash
并且一次在容器中
$ awk -v cmd='openssl x509 -noout -subject' '
/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt
并且自定义 CA 根正确存在。
问题
当来自 GitLab-CI 的 运行 Gitlab-Runner 时,管道悲惨地失败告诉我:
$ git clone https://gitlab-ci-token:${CI_BUILD_TOKEN}@ServerA/foo/bar/My-Project.wiki.git
Cloning into 'My-Project.wiki'...
fatal: unable to access 'https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@ServerA/foo/bar/My-Project.wiki.git/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
ERROR: Job failed: exit code 1
它无法识别 Issuer(我的自定义 CA Root),但根据 The self-signed certificates or custom Certification Authorities,第 n.1 点,它应该开箱即用:
Default: GitLab Runner reads system certificate store and verifies the GitLab server against the CA’s stored in system.
然后我尝试了第 n.3 点的解决方案,编辑
/srv/gitlab-runner/config/config.toml:
并添加:
[[runners]]
tls-ca-file = "/srv/gitlab-runner/config/certs/ca.crt"
但是还是不行。
如何让Gitlab Runner读取CA根证书?
您有两个选择:
忽略 SSL 验证
把这个放在你的 .gitlab-ci.yml
的顶部:
variables:
GIT_SSL_NO_VERIFY: "1"
将 GitLab-Runner 指向正确的证书
如 official documentation 中所述,您可以使用 tls-*-file 选项来设置您的证书,例如:
[[runners]]
...
tls-ca-file = "/etc/gitlab-runner/ssl/ca-bundle.crt"
[runners.docker]
...
如 documentation 所述,"this file will be read every time when runner tries to access the GitLab server."
其他选项包括 tls-cert-file
以定义在需要时使用的证书。
根据您提供的输出,我认为证书可能没问题,但您缺少 CRL 文件:server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
CRL 文件用于验证即使证书有效也未被 CA 所有者吊销。然后你应该需要:
1) 根据您的 CA 生成 CRL 文件:
openssl ca -gencrl -keyfile ca.key -cert ca.crt -out crl.pem
来源:https://blog.didierstevens.com/2013/05/08/howto-make-your-own-cert-and-revocation-list-with-openssl/
2) 指示跑步者使用它:
[[runners]]
...
tls-ca-file = "/etc/gitlab-runner/ssl/ca-bundle.crt"
crl-file = "/etc/gitlab-runner/ssl/ca.crl"
3) 当然设置GIT_SSL_NO_VERIFY
会起作用,但是你会对中间人攻击更加敏感
虽然我仍然不明白为什么它不能开箱即用,我找到了哥伦布蛋:
Gitlab-Runner配置:
[[runners]]
name = "MyDockerServer-Runner"
url = "https://MY_PRIVATE_REPO_URL_HERE/"
token = "MY_TOKEN_HERE"
executor = "docker"
...
[runners.docker]
image = "ubuntu:latest"
# The trick is the following:
volumes = ["/cache","/srv/gitlab-runner/config:/etc/gitlab-runner"]
...
Gitlab-ci.yml管道:
MyJob:
image: ubuntu:latest
script:
- awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt
- git clone https://gitlab-ci-token:${CI_BUILD_TOKEN}@ServerA/foo/bar/My-Project.wiki.git
- wget -O foo.png https://ServerA/foo/bar/foo.png
before_script:
- apt-get update -y >/dev/null
- apt-get install -y apt-utils dialog >/dev/null
- apt-get install -y git >/dev/null
- apt-get install -y wget >/dev/null
# The trick is the following:
- cp /etc/gitlab-runner/certs/ca.crt /usr/local/share/ca-certificates/ca.crt
- update-ca-certificates
就是这样:
- 挂载卷一次(根据 Docker 执行程序)
- 更新 CA 证书一次(根据 工作)
一切都会按预期工作:git clone
、wget https
,等等...
一个很好的解决方法,直到 GitLab 的某人修复它或向我解释我错在哪里(做我的客人!)
不确定这是最好的方法,但至少它对我有用。您可以创建一个自定义的 gitlab runner 图像并在其中添加您的根 CA:
├── Dockerfile
└── myca.crt
# Dockerfile
FROM gitlab/gitlab-runner:latest
COPY myca.crt /usr/local/share/ca-certificates
RUN update-ca-certificates
构建它:
docker build -t custom-gitlab-runner .
然后重新运行所有命令,只记得使用这个新的图像名称。
题外话,但相关且可能有用
Docker 化的 gitlab-runner 似乎也会忽略你的 /etc/hosts
中的条目,所以如果你在自定义域上启动了 Gitlab,例如https://gitlab.local.net
,当launching/registering gitlab runner:
时,你需要传递/etc/hosts
的值
docker run -d --name gitlab-runner --restart always \
--add-host="gitlab.local.net:192.168.1.100" \
...
如果要启动 docker:dind
(docker 服务中的 docker)容器来构建 docker 图像,您还需要在 /srv/gitlab-runner/config/config.toml
:
中设置这些值
[[runners]]
url = "https://gitlab.local.net/"
executor = "docker"
pre_clone_script = "echo '192.168.1.100 gitlab.local.net registry.local.net' >> /etc/hosts"
...
我已经安装并配置:
- 本地 GitLab Omnibus 在 ServerA 运行 在 HTTPS
- 本地 GitLab-Runner 作为 Docker 服务安装在 ServerB
服务器证书由自定义 CA Root 生成
配置
我已将 CA 根证书放在 ServerB 上:
/srv/gitlab-runner/config/certs/ca.crt
已按照 Run GitLab Runner in a container - Docker image installation and configuration:
中所述在 ServerB 上安装了 Runnerdocker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest
已按照 Registering Runners - One-line registration command 中所述注册 Runner:
docker run --rm -t -i
-v /srv/gitlab-runner/config:/etc/gitlab-runner
--name gitlab-docker-runner gitlab/gitlab-runner register \
--non-interactive \
--executor "docker" \
--docker-image alpine:latest \
--url "https://MY_PRIVATE_REPO_URL_HERE/" \
--registration-token "MY_PRIVATE_TOKEN_HERE" \
--description "MyDockerServer-Runner" \
--tag-list "TAG_1,TAG_2,TAG_3" \
--run-untagged \
--locked="false"
此命令给出了以下输出:
Updating CA certificates...
Runtime platform arch=amd64 os=linux pid=5 revision=cf91d5e1 version=11.4.2
Running in system-mode.Registering runner... succeeded runner=8UtcUXCY
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
我检查过
$ docker exec -it gitlab-runner bash
并且一次在容器中
$ awk -v cmd='openssl x509 -noout -subject' '
/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt
并且自定义 CA 根正确存在。
问题
当来自 GitLab-CI 的 运行 Gitlab-Runner 时,管道悲惨地失败告诉我:
$ git clone https://gitlab-ci-token:${CI_BUILD_TOKEN}@ServerA/foo/bar/My-Project.wiki.git
Cloning into 'My-Project.wiki'...
fatal: unable to access 'https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@ServerA/foo/bar/My-Project.wiki.git/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
ERROR: Job failed: exit code 1
它无法识别 Issuer(我的自定义 CA Root),但根据 The self-signed certificates or custom Certification Authorities,第 n.1 点,它应该开箱即用:
Default: GitLab Runner reads system certificate store and verifies the GitLab server against the CA’s stored in system.
然后我尝试了第 n.3 点的解决方案,编辑
/srv/gitlab-runner/config/config.toml:
并添加:
[[runners]]
tls-ca-file = "/srv/gitlab-runner/config/certs/ca.crt"
但是还是不行。
如何让Gitlab Runner读取CA根证书?
您有两个选择:
忽略 SSL 验证
把这个放在你的 .gitlab-ci.yml
的顶部:
variables:
GIT_SSL_NO_VERIFY: "1"
将 GitLab-Runner 指向正确的证书
如 official documentation 中所述,您可以使用 tls-*-file 选项来设置您的证书,例如:
[[runners]]
...
tls-ca-file = "/etc/gitlab-runner/ssl/ca-bundle.crt"
[runners.docker]
...
如 documentation 所述,"this file will be read every time when runner tries to access the GitLab server."
其他选项包括 tls-cert-file
以定义在需要时使用的证书。
根据您提供的输出,我认为证书可能没问题,但您缺少 CRL 文件:server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
CRL 文件用于验证即使证书有效也未被 CA 所有者吊销。然后你应该需要:
1) 根据您的 CA 生成 CRL 文件:
openssl ca -gencrl -keyfile ca.key -cert ca.crt -out crl.pem
来源:https://blog.didierstevens.com/2013/05/08/howto-make-your-own-cert-and-revocation-list-with-openssl/
2) 指示跑步者使用它:
[[runners]]
...
tls-ca-file = "/etc/gitlab-runner/ssl/ca-bundle.crt"
crl-file = "/etc/gitlab-runner/ssl/ca.crl"
3) 当然设置GIT_SSL_NO_VERIFY
会起作用,但是你会对中间人攻击更加敏感
虽然我仍然不明白为什么它不能开箱即用,我找到了哥伦布蛋:
Gitlab-Runner配置:
[[runners]]
name = "MyDockerServer-Runner"
url = "https://MY_PRIVATE_REPO_URL_HERE/"
token = "MY_TOKEN_HERE"
executor = "docker"
...
[runners.docker]
image = "ubuntu:latest"
# The trick is the following:
volumes = ["/cache","/srv/gitlab-runner/config:/etc/gitlab-runner"]
...
Gitlab-ci.yml管道:
MyJob:
image: ubuntu:latest
script:
- awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/ssl/certs/ca-certificates.crt
- git clone https://gitlab-ci-token:${CI_BUILD_TOKEN}@ServerA/foo/bar/My-Project.wiki.git
- wget -O foo.png https://ServerA/foo/bar/foo.png
before_script:
- apt-get update -y >/dev/null
- apt-get install -y apt-utils dialog >/dev/null
- apt-get install -y git >/dev/null
- apt-get install -y wget >/dev/null
# The trick is the following:
- cp /etc/gitlab-runner/certs/ca.crt /usr/local/share/ca-certificates/ca.crt
- update-ca-certificates
就是这样:
- 挂载卷一次(根据 Docker 执行程序)
- 更新 CA 证书一次(根据 工作)
一切都会按预期工作:git clone
、wget https
,等等...
一个很好的解决方法,直到 GitLab 的某人修复它或向我解释我错在哪里(做我的客人!)
不确定这是最好的方法,但至少它对我有用。您可以创建一个自定义的 gitlab runner 图像并在其中添加您的根 CA:
├── Dockerfile
└── myca.crt
# Dockerfile
FROM gitlab/gitlab-runner:latest
COPY myca.crt /usr/local/share/ca-certificates
RUN update-ca-certificates
构建它:
docker build -t custom-gitlab-runner .
然后重新运行所有命令,只记得使用这个新的图像名称。
题外话,但相关且可能有用
Docker 化的 gitlab-runner 似乎也会忽略你的 /etc/hosts
中的条目,所以如果你在自定义域上启动了 Gitlab,例如https://gitlab.local.net
,当launching/registering gitlab runner:
/etc/hosts
的值
docker run -d --name gitlab-runner --restart always \
--add-host="gitlab.local.net:192.168.1.100" \
...
如果要启动 docker:dind
(docker 服务中的 docker)容器来构建 docker 图像,您还需要在 /srv/gitlab-runner/config/config.toml
:
[[runners]]
url = "https://gitlab.local.net/"
executor = "docker"
pre_clone_script = "echo '192.168.1.100 gitlab.local.net registry.local.net' >> /etc/hosts"
...