Search code examples
pythonsslopensslssl-certificatepython-3.9

Compile custom OpenSSL-1.1.1t with source Python-3.9.17 in CentOS-7.9.2009 docker image


i am trying to compile Python-3.9.17 with custom OpenSSL-1.1.1t from source. I have followed steps mentioned in python openssl linking documention using --with-openssl=/path/to/ssl. After installation, I can see SSl module installed succesfully but for some website while using urllib.request.Request ssl certificate verify failed error is thrown urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)

Any help how to resolve the [SSL: CERTIFICATE_VERIFY_FAILED] issue.

FROM centos:centos7.9.2009

MAINTAINER kavin<[email protected]>

WORKDIR /root/install
SHELL ["/bin/bash", "-c"]

RUN yes "yes" | yum update --nogpgcheck
RUN yes "yes" | yum install wget --nogpgcheck
RUN yes "yes" | yum update --nogpgcheck
RUN yes "yes" | yum install libffi-devel --nogpgcheck
RUN yes "yes" | yum install make --nogpgcheck
RUN yes "yes" | yum install gcc --nogpgcheck
RUN yes "yes" | yum install zlib-devel --nogpgcheck


RUN wget https://ftp.openssl.org/source/old/1.1.1/openssl-1.1.1t.tar.gz
RUN wget https://www.python.org/ftp/python/3.9.17/Python-3.9.17.tgz
RUN wget https://www.cpan.org/src/5.0/perl-5.38.0.tar.gz
RUN wget https://bootstrap.pypa.io/pip/get-pip.py


RUN tar -zxf perl-5.38.0.tar.gz
WORKDIR perl-5.38.0
RUN sh Configure -de
RUN make && make install


WORKDIR /root/install/
RUN tar -zxf openssl-1.1.1t.tar.gz
WORKDIR openssl-1.1.1t
RUN ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib
RUN make clean
RUN make && make install
RUN printf "/usr/local/ssl/lib" > /etc/ld.so.conf.d/openssl.conf
RUN ldconfig
ENV PATH="$PATH:/usr/local/ssl/bin"
RUN printf PATH=\"$PATH\" > /etc/environment
RUN source /etc/environment


WORKDIR /root/install
RUN tar -zxf Python-3.9.17.tgz
WORKDIR Python-3.9.17

# Configure Setup for Custom OpenSSl
RUN sed -i "/SSL=\/usr\/local\/ssl/c\SSL=/usr/local/ssl" Modules/Setup
RUN sed -i "/_ssl _ssl.c/c\_ssl _ssl.c \\\\" Modules/Setup
RUN sed -i '/-DUSE_SSL/c\   -DUSE_SSL -I\$(SSL)/include -I\$(SSL)/include/openssl \\' Modules/Setup
RUN sed -i '/-L$(SSL)\/lib/c\   -L\$(SSL)\/lib -lssl -lcrypto' Modules/Setup
RUN sed -i '/_socket socketmodule.c/c\_socket socketmodule.c' Modules/Setup
RUN sed -i '/_md5 md5module.c/c\_md5 md5module.c' Modules/Setup
RUN sed -i '/_sha1 sha1module.c/c\_sha1 sha1module.c' Modules/Setup
RUN sed -i '/_sha256 sha256module.c/c\_sha256 sha256module.c -DPy_BUILD_CORE_BUILTIN' Modules/Setup
RUN sed -i '/_sha512 sha512module.c/c\_sha512 sha512module.c -DPy_BUILD_CORE_BUILTIN' Modules/Setup
RUN sed -i '/_sha3 _sha3\/sha3module.c/c\_sha3 _sha3\/sha3module.c' Modules/Setup
RUN sed -i '/zlib zlibmodule/c\zlib zlibmodule.c -I\$(prefix)\/include -L\$(exec_prefix)\/lib -lz' Modules/Setup

WORKDIR /root/install
WORKDIR Python-3.9.17

ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/ssl/lib"
RUN ./configure --with-openssl=/usr/local/ssl
RUN make clean
RUN make && make install
RUN ldconfig


WORKDIR /root/install/
RUN python3.9 get-pip.py


WORKDIR /
RUN printf "import urllib.request\n" > test_ssl.py
RUN printf "req = urllib.request.Request('https://stackoverflow.com/')\n" >> test_ssl.py
RUN printf "resp = urllib.request.urlopen(req)\n" >> test_ssl.py
RUN printf "print(resp.headers)\n" >> test_ssl.py
RUN printf "print(resp.read())\n" >> test_ssl.py

RUN python3 test_ssl.py

Solution

  • Since you've build your Python against an OpenSSL in /usr/local/ssl it will check by default for the trust store in /usr/local/ssl/cert.pem and in directory /usr/local/ssl/certs. Probably your trust store isn't there though, but instead in /usr/lib/ssl/certs/ca-certificates.crt or similar, depending on your docker image.

    Therefore you need to make it available for your custom OpenSSL, like with (assuming that there is a trust store in /usr/lib/ssl/certs/ca-certificates.crt):

    ln -s /usr/lib/ssl/certs/ca-certificates.crt /usr/local/ssl/cert.pem