正在 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 证书,现在我有点困惑这意味着什么。似乎有两个选择:
- 只需安装
ca-certificates
包。它应该为大多数 CA 提供必要的 public 密钥。
- 安装您自己的(可能是自签名的)证书:将其复制到您的 docker 容器中并通过调用
update-ca-certificates
将其告知 ca-certificates 包。 (您也可以将它安装在 windows 全局证书存储中,根据 github 上的 this issue,它应该可以与 docker 开箱即用)
不幸的是,第一种方法似乎对我不起作用。它会引发与上述相同的验证错误。更糟糕的是,由于我不知道哪个 .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 容器 运行。
这并不像预期的那么简单。这是最终起作用的方法:
使用.pem格式的公司证书开头。
重命名它们以 .crt 结尾。不要使用任何 openssl .pem 到 .crt 的转换。就我而言,我在网上找到的每个 .crt 文件的编码方式使得 Notepad++、Vim 等无法读取它。另一方面,.pem 文件看起来不错。
将重命名的证书复制到 OS 上正确的 ca 证书位置。
通过 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
我正在尝试从 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 证书,现在我有点困惑这意味着什么。似乎有两个选择:
- 只需安装
ca-certificates
包。它应该为大多数 CA 提供必要的 public 密钥。 - 安装您自己的(可能是自签名的)证书:将其复制到您的 docker 容器中并通过调用
update-ca-certificates
将其告知 ca-certificates 包。 (您也可以将它安装在 windows 全局证书存储中,根据 github 上的 this issue,它应该可以与 docker 开箱即用)
不幸的是,第一种方法似乎对我不起作用。它会引发与上述相同的验证错误。更糟糕的是,由于我不知道哪个 .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 容器 运行。
这并不像预期的那么简单。这是最终起作用的方法:
使用.pem格式的公司证书开头。
重命名它们以 .crt 结尾。不要使用任何 openssl .pem 到 .crt 的转换。就我而言,我在网上找到的每个 .crt 文件的编码方式使得 Notepad++、Vim 等无法读取它。另一方面,.pem 文件看起来不错。
将重命名的证书复制到 OS 上正确的 ca 证书位置。
通过
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