正在 Windows 上的 docker 容器安装 SSL CA 证书

Installing SSL CA certificates for docker container on Windows

我正在尝试从 docker 容器中发出 https 请求。这是在我的 Windows 10 主机上运行良好的 python 代码:

import certifi
import ssl
import urllib.request


tmp_filename = "penguin.jpg"
pingu_link = "https://i.pinimg.com/originals/cc/3a/1a/cc3a1ae4beafdd5ac2293824f1fb0437.jpg"

print(certifi.where())
default = ssl.create_default_context()
https_handler = urllib.request.HTTPSHandler(context=ssl.create_default_context())
opener = urllib.request.build_opener(https_handler)
# add user agent headers to avoid 403 response
opener.addheaders = [
    (
        "User-agent",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0",
    )]
urllib.request.install_opener(opener)
r = urllib.request.urlretrieve(pingu_link, tmp_filename)

如果我没理解错的话,certifi 带有自己的一组 CA 证书,这些证书包含在您可以通过调用 certifi.where() 找到的 .pem 文件中。但是,如果我将此文件转换为 .crt 并通过调用

告诉请求使用它
https_handler = urllib.request.HTTPSHandler(context=ssl.create_default_context(cafile="cacert.crt"))

验证失败:ssl.SSLCertVerificationError:[SSL:CERTIFICATE_VERIFY_FAILED] 证书验证失败:无法获取本地颁发者证书 (_ssl.c:1129)。正如 this post 所解释的那样,certifi 还会自动从 windows 证书库中导入证书文件。 如果您想在 docker 容器中验证 SSL 证书,现在我有点困惑这意味着什么。似乎有两个选择:

不幸的是,第一种方法似乎对我不起作用。它会引发与上述相同的验证错误。更糟糕的是,由于我不知道哪个 .crt 文件用于在没有 docker 的情况下验证证书,因此第二个选项也不可行。这是 Dockerfile:

# start with a python env that already has urllib3 installed
FROM company_harbor/base_py3_container 

ENV HTTP_PROXY="my_company_proxy"
ENV HTTPS_PROXY="my_company_proxy"
# install ca certificates
RUN apt-get update && \ 
    apt-get install ca-certificates -y && \
    apt-get clean

RUN pip install --upgrade certifi --trusted-host=pypi.org --trusted-host=files.pythonhosted.org
# what I would do if I found the right .crt file
# COPY cacert.crt /usr/share/ca-certificates/cacert.crt
# RUN chmod 644 /usr/share/ca-certificates/cacert.crt
RUN update-ca-certificates
COPY ./download_penguin.py ./download_penguin.py

CMD [ "python", "download_penguin.py" ]

要在 docker 中使用 python 验证 SSL 证书,您需要做什么?

事实证明,公司代理可以在 Man-in-the-middle manner 中交换 SSL 证书。 apt-get install ca-certificates 或 python 的 certifi 包中的标准证书不会包含这些公司证书。此外,这不是具体的 Docker 相关问题,而是“如何在 Linux 上安装根证书”的问题。 Debian 更准确地说,因为默认情况下 Docker 容器 运行。

这并不像预期的那么简单。这是最终起作用的方法:

  1. 使用.pem格式的公司证书开头。

  2. 重命名它们以 .crt 结尾。不要使用任何 openssl .pem 到 .crt 的转换。就我而言,我在网上找到的每个 .crt 文件的编码方式使得 Notepad++、Vim 等无法读取它。另一方面,.pem 文件看起来不错。

  3. 将重命名的证书复制到 OS 上正确的 ca 证书位置。

  4. 通过 update-ca-certificates 安装证书。

翻译成Docker文件,这里是重要的部分:

COPY root.pem /usr/local/share/ca-certificates/root.crt
COPY proxy.pem /usr/local/share/ca-certificates/proxy.crt
RUN update-ca-certificates