如何在 docker 映像中添加 CA 根证书?



我在 Ubuntu 14.04 上的 Docker 1.13.1 容器中运行 ASP.NET Core 1.1 Web API。

当代码尝试从HTTPS服务器检索某些数据时,我收到以下证书身份验证错误:

An error occurred while sending the request. ---> System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates
at System.Net.Http.CurlHandler.ThrowIfCURLEError(CURLcode error)
at System.Net.Http.CurlHandler.MultiAgent.FinishRequest(StrongToWeakReference`1 easyWrapper, CURLcode messageResult)

HTTPS 服务器是内部服务器,证书由我们的公司 CA 签名,因此我知道我可能需要注册内部 CA。

到目前为止,我发现的有关此错误的所有内容以及 Docker 都谈到了让 docker 本身运行、连接到存储库等。 我的 Docker 工作正常,Web API 在容器之外的 Ubuntu 服务器上运行没有问题。

1) 我需要在 docker 镜像中添加 CA 根证书吗?

2)如果是这样,我该怎么做?

3) 如果没有,我该如何解决这个问题?

任务本身并不特定于 docker,因为您也需要在普通系统上添加该 CA。在askubuntu社区上有一个关于如何做到这一点的答案。

因此,在 Dockerfile 中,您将执行以下操作(如果您使用非 root 用户运行容器,请不要忘记 chmod):

ADD your_ca_root.crt /usr/local/share/ca-certificates/foo.crt
RUN chmod 644 /usr/local/share/ca-certificates/foo.crt && update-ca-certificates

为了简化/标准化所有容器构建,我们现在将证书托管在中央 HTTPS 服务器上,并将它们构建到我们的容器中,如下所示:

# Debian stretch based container
RUN curl -ks 'https://cert.host.server/ssl_certs/EnterpriseRootCA.crt' -o '/usr/local/share/ca-certificates/EnterpriseRootCA.crt'
RUN /usr/sbin/update-ca-certificates

基于 Alpine 的容器没有立即可用的工具,因此需要更多的工作来实现相同的目标:

# Alpine based containers
RUN apk update && apk add curl
WORKDIR /usr/local/share/ca-certificates
RUN curl -ks 'https://cert.host.server/ssl_certs/EnterpriseRootCA.crt' -o '/usr/local/share/ca-certificates/EnterpriseRootCA.crt'
RUN /usr/sbin/update-ca-certificates

如果您还想更新 Java 信任库(与在任何计算机上相同):

RUN keytool -keystore /usr/lib/jvm/java-8-oracle/jre/lib/security/cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias EnterpriseRootCA -file EnterpriseRootCA.crt

还值得注意的是,这肯定需要使用.crt扩展名。我最初尝试使用 .pem 证书文件(我认为它们是可以互换的,所以其他人也可以),该文件没有通过update-ca-certificates链接。

安装ca-certificatescert_file_name.crt文件与 Dockerfile 位于同一目录中。

# Install ca-certificates
# Please locate cert_file_name.crt file in the same directory as Dockerfile.
COPY cert_file_name.crt /usr/share/ca-certificates/
RUN echo cert_file_name.crt >> /etc/ca-certificates.conf
RUN update-ca-certificates

这将更新 Dockerfile 中的证书。

另一种选择是使用OpenSSL.将domain_name替换为可以检索 CA 的 URL

RUN openssl s_client -connect <domain_name>:443 -showcerts </dev/null 2>/dev/null | sed -e '/-----BEGIN/,/-----END/!d' | tee "/usr/local/share/ca-certificates/ca.crt" >/dev/null && 
update-ca-certificates

如果你像我一样,并且真的不想在构建 docker 映像中包含 root-ca,那么

您可以在运行时将证书作为文件挂载,只需将挂载的 CA-cert 文件路径作为参数传递给您将要访问的任何服务

例如,在 e Kubernetes Pod 中使用卷曲,它看起来像

curl --cacert path/to/ca-root.pem https://<service>.<namespace>.svc.cluster.local:4000/

sudo apt -y install ca-certificates curl gnupg lsb-release

curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o/usr/share/keyrings/docker-archive-keyring.gpg apt update

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee/etc/apt/sources.list.d/docker.list>/dev/null

sudo apt -y install docker-ce docker-ce-cli containerd.io

sudo systemctl enable --now docker

Dockefile:

来自 nginx:最新复制索引.html/usr/share/nginx/html/index.html

sudo docker build -t mywebapp .

sudo docker run -d -p 80:80 MyWebApp

最新更新