【问题标题】:How to make Python use CA certificates from Mac OS TrustStore?如何让 Python 使用来自 Mac OS TrustStore 的 CA 证书?
【发布时间】:2016-11-18 19:20:37
【问题描述】:

我需要在公司 Intranet 上使用 curtom 根证书并将它们加载到 Mac OS TrustStore (KeyChain) 中确实可以解决所有浏览器和 GUI 应用程序的问题。

似乎它甚至适用于 Mac OS X 附带的 curl 版本,但它不适用于 python,即使是 Mac OS 10.12 Sierra 附带的版本(Python 2.7.10)

不过,我似乎会被击中:

urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>

我该如何解决这个问题?

因为我在很多 Python 工具中都遇到过这个问题,如果我能找到一种方法来避免它而无需修补它们,我将不胜感激。

自己提供自定义 CA 证书不是一种选择,因为我无法修补我使用的数十种 Python 工具。

大多数工具都使用 requests 库,但也有一些工具直接使用 Python 中的原生 ssl 支持。

【问题讨论】:

标签: python macos ssl truststore


【解决方案1】:

这也是带有 MacOS Sierra 的 Python 3.6 中的一个问题。我知道你的用例是不同的。但是我在调​​查这个问题时偶然发现了这个线程。所以如果有人也有这篇文章值得一看:

http://www.cdotson.com/2017/01/sslerror-with-python-3-6-x-on-macos-sierra/

简而言之:Python 3.6 不再依赖 MacOS 的 openSSL。它捆绑了自己的 openSSL,并且无法访问 MacOS 的根证书。

你有两个选择:

运行 Python 3.6 附带的安装命令

cd /Applications/Python\ 3.6/
./Install\ Certificates.command

安装certifi package
pip install certifi

我选择了第一个选项,并且成功了。

【讨论】:

  • 还有从自制软件中获取python的选项,它会自动为您完成。
  • 第二个选项不够;还需要在 OpenSSL 目录中创建符号链接,这就是第一个选项中的命令所做的。详情请见this issue
  • 此解决方案停止在 OSX Catalina 中使用 Python 3.7 工作。没有 /Applications/Python 3.7 目录并且安装证书命令不存在。安装认证也不再解决这个问题。 #卡住!! gggrrrrr .... 有人在 Catalina 上解决了这个问题吗?
  • 这行得通。如果您有自定义 CA 证书,请将它们添加到 /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/certifi/cacert.pem 然后重新运行 /Applications/Python\ 3.7/Install \ Certificates.command
  • 我认为这个解决方案很好,但对于使用 pyenv 或直接构建 python 的人来说还不够。安装certifi后,我们需要关注stackoverflow.com/a/57795811/7412781
【解决方案2】:

运行它来设置适当的变量。这是这里已经给出的答案的组合。将其放入您的 ~/.bash_profile 中以使其永久化。

CERT_PATH=$(python -m certifi)
export SSL_CERT_FILE=${CERT_PATH}
export REQUESTS_CA_BUNDLE=${CERT_PATH}

【讨论】:

  • 太棒了!这个答案与在 Python 3.8 virtualenv 设置中解决我的问题最相关,其中 Jupyter notebook 遇到了证书错误。我在环境中采购了“.bash_profile”。就是这样。
  • @Shanti 看来你已经解决了我正在努力解决的问题......请在这里快速查看我的问题:stackoverflow.com/questions/64590535/…
  • 对我不起作用。在 Mac OS Big Sur 11.2.3 上通过 brew 安装的 Python 3.9.2
  • @MarcelloRomani 我使用 Mac OS Big Sur 11.2.3 并且成功了。
【解决方案3】:

Mac brew 安装 python 环境。

$ python3
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 16:52:21) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import certifi
>>> certifi.where()
'/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/certifi/cacert.pem'
>>> 

或者从命令行:

$ python -m certifi

然后需要链接 cacert.pem 作为 cert.pem

$ ln -s /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/certifi/cacert.pem cert.pem
$ pwd
/Library/Frameworks/Python.framework/Versions/3.7/etc/openssl

rehash

然后工作正常。

【讨论】:

  • 尝试了很多东西,但这是唯一有效的。荣誉
  • 为我工作,谢谢!
【解决方案4】:

如果您将其他证书放在 PEM 捆绑文件中,您可以使用这两个环境变量来覆盖 Python openssl 和 requests 使用的默认证书存储。

SSL_CERT_FILE=/System/Library/OpenSSL/cert.pem
REQUESTS_CA_BUNDLE=/System/Library/OpenSSL/cert.pem

请注意,此文件不存在,需要您自己构建。

【讨论】:

  • 我的位于 /Library/Frameworks/Python.framework/Versions/2.7/etc/openssl/cert.pem
  • // ,将REQUESTS_CA_BUNDLE 设置为我生成的堆叠.pem 解决了我对内部根CA 的请求的问题。谢谢,@Sorin。
【解决方案5】:

作为更新和数据点,我在 macOS 10.13.4 上运行 Python 3.7.0 时遇到了这个问题:

$ ipython
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.0.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import bokeh.sampledata

In [2]: bokeh.sampledata.download()
Using data directory: /Users/me/.bokeh/data

...
SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1045)

解决问题的说明在/Applications/Python\ 3.7/ReadMe.rtf

按照那里的建议并运行/Applications/Python\ 3.7/Install\ Certificates.command 解决了问题:

从终端:

$ /Applications/Python\ 3.7/Install\ Certificates.command

重新启动 IPython...

$ ipython
>>> import bokeh.sampledata

>>> bokeh.sampledata.download()
Using data directory: /Users/me/.bokeh/data
Downloading: CGM.csv (1589982 bytes)
   1589982 [100.00%]
...

【讨论】:

    【解决方案6】:

    对于我来说,/Applications/Python\ 3.6/./Install\ Certificates 命令在 pip certifi 安装时失败。我在 mac High Sierra 上使用 python3,所以 pip 有点失败,我必须改用 pip3。

    所以我做了什么:

    1. 在 shell 中手动运行 pip3 install --update certify
    2. 从命令脚本中删除安装证书行
    3. 重新运行脚本,一切正常。

    请注意,您最终会得到一个 cert.pem 符号链接:/Library/Frameworks/Python.framework/Versions/3.6/etc/openssl/

    【讨论】:

      【解决方案7】:

      我看到很多答案建议关闭证书验证或使用certifi.where。 虽然关闭 SSL 是明显的风险。 certifi.where 也是一种风险,主要是如果您打算将此代码制作为将在客户环境中运行的生产代码。

      PEP 描述错误的原因。 ssl.create_default_context 很好地与 linux 和 windows trustStore 集成。问题是,就像你的mac一样。 我通过使用集成的安全命令行工具加载证书来解决这个问题

      def create_macos_ssl_context():
          import subprocess
          import ssl
          import tempfile
          ctx = ssl.create_default_context()
          macos_ca_certs = subprocess.run(["security", "find-certificate", "-a", "-p",
                                           "/System/Library/Keychains/SystemRootCertificates.keychain"],
                                          stdout=subprocess.PIPE).stdout
      
          with tempfile.NamedTemporaryFile('w+b') as tmp_file:
              tmp_file.write(macos_ca_certs)
              ctx.load_verify_locations(tmp_file.name)
          print(ctx.get_ca_certs())
      

      请注意,这将为您提供 systemRoot 证书。如果您需要用户而不是简单地更改安全命令中的值

      【讨论】:

        【解决方案8】:

        MacOS 或 Linux 解决方案,最新 Python 版本作为独立或通过端口或 brew 安装

        https://github.com/certifi/python-certifi/blob/master/certifi/cacert.pem 的 Certifi 项目下载证书。 FYI Certifi 是一个第三方库,它提供 Mozilla 精选的根证书集合,用于验证 SSL 证书的可信度,同时验证 TLS 主机的身份。

        然后在最新的 MacOS 上添加到您的 ~/.zshrc~/.bash_profile 或类似的:

        export SSL_CERT_FILE=/pathtodownloadedfile/cacert.pem
        export REQUESTS_CA_BUNDLE=/pathtodownloadedfile/cacert.pem
        

        【讨论】:

          猜你喜欢
          • 2010-09-25
          • 1970-01-01
          • 1970-01-01
          • 2020-03-19
          • 2010-10-16
          • 2021-01-09
          • 2021-07-22
          • 1970-01-01
          • 2018-05-06
          相关资源
          最近更新 更多