如何让 Docker 中的 GitLab Runner 看到自定义 CA 根证书
Posted
技术标签:
【中文标题】如何让 Docker 中的 GitLab Runner 看到自定义 CA 根证书【英文标题】:How to make GitLab Runner in Docker see a custom CA Root certificate 【发布时间】:2019-04-09 02:23:44 【问题描述】:我已经安装并配置好了:
-
在 ServerA 上运行在 HTTPS 上的本地 GitLab Omnibus
在 ServerB 中作为 Docker 服务安装的本地 GitLab-Runner
ServerA 证书由自定义 CA Root 生成
配置
我已将 CA 根证书放在 ServerB 上:
/srv/gitlab-runner/config/certs/ca.crt
在 ServerB 上安装了 Runner,如 Run GitLab Runner in a container - Docker image installation and configuration 中所述:
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"
此命令给出以下输出:
正在更新 CA 证书... 运行平台arch=amd64 os=linux pid=5 revision=cf91d5e1 version=11.4.2 在系统模式下运行。
正在注册跑步者...成功跑步者=8UtcUXCY Runner注册成功。随意启动它,但如果它已经在运行,配置应该会自动重新加载!
我检查过
$ 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
克隆到“My-Project.wiki”...
致命:无法访问“https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@ServerA/foo/bar/My-Project.wiki.git/”:服务器证书验证失败。 CAfile:/etc/ssl/certs/ca-certificates.crt CRLfile:无
错误:作业失败:退出代码 1
它无法识别颁发者(我的自定义 CA Root),但根据The self-signed certificates or custom Certification Authorities,第 n.1 点,它应该是开箱即用的:
默认值:GitLab Runner 读取系统证书存储并根据系统中存储的 CA 验证 GitLab 服务器。
然后我尝试了第 n.3 点的解决方案,正在编辑
/srv/gitlab-runner/config/config.toml:
并添加:
[[runners]]
tls-ca-file = "/srv/gitlab-runner/config/certs/ca.crt"
但还是不行。
如何让 Gitlab Runner 读取 CA Root 证书?
【问题讨论】:
【参考方案1】:不确定这是不是最好的方法,但至少它对我有用。您可以创建一个自定义的 gitlab 运行器映像并在其中添加您的根 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 .
然后重新运行所有命令,记住使用这个新的图像名称。
离题,但相关且可能有用
Dockerized gitlab-runner 似乎也忽略了/etc/hosts
中的条目,所以如果你在自定义域上启动了 Gitlab,例如https://gitlab.local.net
,您需要在启动/注册 gitlab runner 时传递来自 /etc/hosts
的值:
docker run -d --name gitlab-runner --restart always \
--add-host="gitlab.local.net:192.168.1.100" \
...
如果你想启动docker:dind
(docker in docker service)容器来构建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"
...
【讨论】:
感谢您的宝贵回答!我会尽快尝试的【参考方案2】:你有两个选择:
忽略 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 所说,“每次运行者尝试访问 GitLab 服务器时都会读取此文件。”
其他选项包括tls-cert-file
,用于定义需要时使用的证书。
【讨论】:
@AndreaLigios 检查 gitlab-runner 进程的日志输出;也许您可以合并有关您的设置的更多信息 - 您选择了几种安装跑步者的方法中的哪一种,等等。 你的意思是/srv/gitlab-runner/config/certs
我猜。无论哪种方式,它都不起作用……这件事让我发疯。我可以清楚地看到作为 Docker 服务安装的 Gitlab-Runner 正在接受 CA 根并更新其证书;记录它并检查,它就在那里。问题是 GitLab-CI 生成的 Runner 不是。 My configuration is the default one for a containerized GitLab-Runner,如果我让它从 gitlab-ci 打印 CA,则自定义 CA 不存在:/
我重新编辑了问题,添加了所有详细信息和文档链接。您的答案中的 tls-ca-file 应该在 [[runners]]
部分,而不是在 [runners.docker]
部分,但它的工作方式不同:(
我怀疑文档中缺少一些东西,需要在 config.toml 中进行一些调整(例如 tls_verify 应该有什么值,什么 priviledge_mode 等等),单独的 tls-ca-file 恕我直言还不够。并且没有提到根据该页面,一切都应该在不做任何事情的情况下工作:/
即使您的解决方案不起作用,我也已授予您的答案,因为您已经花了一些时间,而且我讨厌浪费东西。享受吧。【参考方案3】:
虽然我仍然不明白为什么它不能开箱即用,我找到了哥伦布之蛋:
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 有人修复它或向我解释我错在哪里(做我的客人!)
【讨论】:
我已经按照您所说的“诀窍如下”的部分进行了操作,现在它似乎可以正常工作了! :) 我只是想知道,真的有必要指定卷吗?它的目的是什么?那部分实际上是做什么的? 您正在使用 Docker Runner 运行管道,该管道在 Docker 容器中运行。要复制/usr/local/share/ca-certificates
下的证书文件,您需要使证书文件在容器中可用。为此,您将本地路径(在我的情况下为/srv/gitlab-runner/config
)映射到容器路径(/etc/gitlab-runner
),这样当您在容器内执行cp /etc/gitlab-runner/certs/ca.crt ...
时,您就可以在后台从主机路径/srv/gitlab-runner/config/certs
。如果不安装卷,cp
将找不到任何要复制的内容
@NewteqDeveloper,这是我写的一篇小文章,它以一种简单的方式涵盖了这个 Docker 概念:baeldung.com/docker-compose。
@AndreaLigios 不确定为什么这可以解决您的问题,看起来 Runner 图像已经在 init script 中做同样的事情。唯一的区别似乎是您没有将--fresh
标志传递给update-ca-certificates
。有什么想法吗?
我应该指定它是 Runner Helper 图像正在执行此操作,而您正在做的是在 Runner 容器(而不是 Helper 容器)中运行相同的逻辑。通常,它是负责执行常见操作(例如 Git 提取等)的辅助映像。所以,是的,如果您需要在构建脚本中执行相同类型的操作(或 wget),那么您需要挂载/安装您的自定义 CA。【参考方案4】:
根据您提供的输出,我认为证书可能没问题,但您缺少 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
会起作用,但你会对中间人攻击更敏感
【讨论】:
感谢您的回答,我会尽快尝试(尽管我不相信 CRL 是强制性的)。正如在另一个答案according to the docs 中所说,tls-ca-file 应该留在[[runners]]
而不是[runners.docker]
:)
另外,为什么要输出 DER 格式?这表示证书不支持 DER,所以我想 CRL 也不支持:docs.gitlab.com/runner/configuration/tls-self-signed.html
@AndreaLigios 我在上面剪切并粘贴了您的配置。如果 runners.docker 部分不是放置 tls-ca 文件的正确位置,请随时编辑问题以避免后续错误:-) 我相应地编辑了答案
@AndreaLigios :您对 DER 格式的看法是正确的。我相应地编辑了答案
您复制粘贴了另一个答案,而不是我的问题。根据文档,它应该是[[runners]] ... tls-ca-file = "" ... [docker.runners]
。看看吧:)以上是关于如何让 Docker 中的 GitLab Runner 看到自定义 CA 根证书的主要内容,如果未能解决你的问题,请参考以下文章
kubernetes/docker 上的 gitlab:管道失败:清理 configmap 时出错:资源名称可能不为空
如何将存储库中的文件复制到用于作业的 Docker 容器中,在 gitlab-ci.yml