CERTIFICATE_VERIFY_FAILED error
Exception Location: /usr/lib/python3.8/urllib/request.py, line 1357, in do_open Running: Python 3.8.10, Django 4.0.3, Ubuntu 20.04, Apache 2 I’m using Django for a simple contact form app, which currently works and throws no errors. The CERTIFICATE_VERIFY_FAILED error occurs when I use this Django library https://github.com/tiesjan/django-hcaptcha-field to add hCaptcha to the form. The issue doesn’t appear to be with django-hcaptcha-field; it appears to be Ubuntu and SSL certificates when the hCaptcha API is accessed. I’ve looked at multiple questions on SO (esp. https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error , even though it’s for OS X) and Ask Ubuntu Certificate problems . I’ve tried all these «fixes»:
pip install pyOpenSSL --upgrade apt-get install --reinstall python3-certifi pip install --upgrade certifi --force apt install --reinstall openssl apt install ca-certificates update-ca-certificates --fresh export SSL_CERT_DIR=/etc/ssl/certs
wget --quiet https://curl.haxx.se/ca/cacert.pem export SSL_CERT_FILE=$HOME/cacert.pem
Nothing in my Python code requires import ssl What else can I try? Diagnostic outputs: dpkg -l | grep cert returns
ica-certificates 20210119~20.04.2 all Common CA certificates certbot 0.40.0-1ubuntu0.1 all automatically configure HTTPS using Let's Encrypt dirmngr 2.2.19-3ubuntu2.1 amd64 GNU privacy guard - network certificate management service python-certbot-apache 0.36.0-1 all transitional dummy package python3-certbot 0.40.0-1ubuntu0.1 all main library for certbot python3-certbot-apache 0.39.0-1 all Apache plugin for Certbot ipython3-certifi 2019.11.28-1 all root certificates for validating SSL certs and verifying TLS hosts (python3) ssl-cert 1.0.39 all simple debconf wrapper for OpenSSL
libxmlsec1-openssl:amd64 1.2.28-2 amd64 Openssl engine for the XML security library openssl 1.1.1f-1ubuntu2.12 amd64 Secure Sockets Layer toolkit - cryptographic utility perl-openssl-defaults:amd64 4 amd64 version compatibility baseline for Perl OpenSSL packages python3-openssl 19.0.0-1build1 all Python 3 wrapper around the OpenSSL library
openssl: /usr/bin/openssl /usr/local/bin/openssl /usr/include/openssl /usr/share/man/man1/openssl.1ssl.gz
/usr/local/bin/openssl /usr/bin/openssl
linux-vdso.so.1 (0x00007ffd9f10f000) libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007efdb3e3d000) libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007efdb3e34000) libidn2.so.0 => /lib/x86_64-linux-gnu/libidn2.so.0 (0x00007efdb3e12000) libssl.so.1.1 => /usr/local/lib/libssl.so.1.1 (0x00007efdb3d7a000) libcrypto.so.1.1 => /usr/local/lib/libcrypto.so.1.1 (0x00007efdb3a8e000) libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007efdb3a72000) libpsl.so.5 => /lib/x86_64-linux-gnu/libpsl.so.5 (0x00007efdb3a5d000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efdb386b000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007efdb3848000) /lib64/ld-linux-x86-64.so.2 (0x00007efdb3f6b000) libunistring.so.2 => /lib/x86_64-linux-gnu/libunistring.so.2 (0x00007efdb36c6000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007efdb36c0000)
python3-certifi 2019.11.28-1 all root certificates for validating SSL certs and verifying TLS hosts (python3)
Request Method: POST Request URL: https://example.com/contact/contact/contact/ Django Version: 4.0.3 Python Version: 3.8.10 Installed Applications: ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'contactform.apps.ContactformConfig', 'encrypted_files', 'hcaptcha_field'] Installed Middleware: ['django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware'] Traceback (most recent call last): File "/usr/lib/python3.8/urllib/request.py", line 1354, in do_open h.request(req.get_method(), req.selector, req.data, headers, File "/usr/lib/python3.8/http/client.py", line 1256, in request self._send_request(method, url, body, headers, encode_chunked) File "/usr/lib/python3.8/http/client.py", line 1302, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "/usr/lib/python3.8/http/client.py", line 1251, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/usr/lib/python3.8/http/client.py", line 1011, in _send_output self.send(msg) File "/usr/lib/python3.8/http/client.py", line 951, in send self.connect() File "/usr/lib/python3.8/http/client.py", line 1425, in connect self.sock = self._context.wrap_socket(self.sock, File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket return self.sslsocket_class._create( File "/usr/lib/python3.8/ssl.py", line 1040, in _create self.do_handshake() File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake self._sslobj.do_handshake() During handling of the above exception ([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1131)), another exception occurred: File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/exception.py", line 55, in inner response = get_response(request) File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/base.py", line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) File "/var/www/html/example.com/public_html/contact/contactform/views.py", line 26, in contact if form.is_valid(): File "/usr/local/lib/python3.8/dist-packages/django/forms/forms.py", line 205, in is_valid return self.is_bound and not self.errors File "/usr/local/lib/python3.8/dist-packages/django/forms/forms.py", line 200, in errors self.full_clean() File "/usr/local/lib/python3.8/dist-packages/django/forms/forms.py", line 433, in full_clean self._clean_fields() File "/usr/local/lib/python3.8/dist-packages/django/forms/forms.py", line 445, in _clean_fields value = field.clean(value) File "/usr/local/lib/python3.8/dist-packages/django/forms/fields.py", line 199, in clean self.validate(value) File "/usr/local/lib/python3.8/dist-packages/hcaptcha_field/fields.py", line 129, in validate response = opener.open(request, timeout=hcaptcha_settings.TIMEOUT) File "/usr/lib/python3.8/urllib/request.py", line 525, in open response = self._open(req, data) File "/usr/lib/python3.8/urllib/request.py", line 542, in _open result = self._call_chain(self.handle_open, protocol, protocol + File "/usr/lib/python3.8/urllib/request.py", line 502, in _call_chain result = func(*args) File "/usr/lib/python3.8/urllib/request.py", line 1397, in https_open return self.do_open(http.client.HTTPSConnection, req, File "/usr/lib/python3.8/urllib/request.py", line 1357, in do_open raise URLError(err) Exception Type: URLError at /contact/contact/ Exception Value:
import json import logging import ssl # added ############# import certifi # added ############# from urllib.error import HTTPError from urllib.parse import urlencode from urllib.request import build_opener, Request, ProxyHandler from django import forms from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ from hcaptcha_field.settings import hcaptcha_settings from hcaptcha_field.widgets import hCaptchaWidget LOGGER = logging.getLogger('hcaptcha_field') DATA_ATTRIBUTE_CONFIG = frozenset([ 'theme', 'size', 'tabindex', 'callback', 'expired-callback', 'chalexpired-callback', 'open-callback', 'close-callback', 'error-callback', ]) QUERY_PARAMETER_CONFIG = frozenset([ 'onload', 'render', 'hl', 'recaptchacompat' ]) class hCaptchaField(forms.Field): widget = hCaptchaWidget default_error_messages = < 'error_hcaptcha': _( # Translators: Error shown when an internal server error occurred. 'Something went wrong while verifying the hCaptcha. ' 'Please try again.' ), 'invalid_hcaptcha': _( # Translators: Error shown when visitor did not pass the hCaptcha check. 'hCaptcha could not be verified.' ), 'required': _( # Translators: Error shown when visitor forgot to fill in the hCaptcha. 'Please prove you are human.' ), >def __init__(self, sitekey=None, **kwargs): """ Initializer for `hCaptchaField` class. It determines data attributes for the widget class and constructs a widget if none is given. This constructed widget receives the URL of the JavaScript resource for the hCaptcha integration and the `sitekey` of the site to protect. """ # Retrieve settings DEFAULT_CONFIG = hcaptcha_settings.DEFAULT_CONFIG JS_API_URL = hcaptcha_settings.JS_API_URL SITEKEY = hcaptcha_settings.SITEKEY # Determine widget data attributes self.widget_data_attrs = <> for setting in DATA_ATTRIBUTE_CONFIG: if setting in kwargs: self.widget_data_attrs[setting] = kwargs.pop(setting) elif setting in DEFAULT_CONFIG: self.widget_data_attrs[setting] = DEFAULT_CONFIG[setting] # If the `widget` argument is not given, instantiate `self.widget` with # the hCaptcha API url and the sitekey if 'widget' not in kwargs: # Determine hCaptcha API url query_params = <> for setting in QUERY_PARAMETER_CONFIG: if setting in kwargs: query_params[setting] = kwargs.pop(setting) elif setting in DEFAULT_CONFIG: query_params[setting] = DEFAULT_CONFIG[setting] if query_params: js_api_url = '%s?%s' % (JS_API_URL, urlencode(query_params)) else: js_api_url = JS_API_URL # Determine hCaptcha sitekey self.sitekey = sitekey or SITEKEY # Instantiate widget kwargs['widget'] = self.widget( js_api_url=js_api_url, sitekey=self.sitekey) super().__init__(**kwargs) def widget_attrs(self, widget): """ Returns the widget attributes, including all the data attributes determined in the initializer. """ attrs = super().widget_attrs(widget) for key, value in self.widget_data_attrs.items(): attrs['data-%s' % key] = value return attrs def validate(self, value): """ Validates the field by verifying the value of the hidden field `h-captcha-response` with their API endpoint. """ super().validate(value) # Build request opener = build_opener(ProxyHandler(hcaptcha_settings.PROXIES)) post_data = urlencode(< 'secret': hcaptcha_settings.SECRET, 'response': value, 'sitekey': self.sitekey, >).encode('utf-8') request = Request(hcaptcha_settings.VERIFY_URL, post_data) # Perform request try: context=ssl.create_default_context(cafile=certifi.where()) # added ############ response = opener.open(request, timeout=hcaptcha_settings.TIMEOUT) except HTTPError: LOGGER.exception("Failed to verify response with hCaptcha API.") raise ValidationError( self.error_messages['error_hcaptcha'], code='error_hcaptcha' ) # Check response response_data = json.loads(response.read().decode('utf-8')) if not response_data.get('success'): LOGGER.error("Failed to pass hCaptcha check: %s", response_data) raise ValidationError( self.error_messages['invalid_hcaptcha'], code='invalid_hcaptcha' )
SSL: CERTIFICATE_VERIFY_FAILED certificate verify failed (_ssl.c:852)
For this error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852) have already installed company proxy certificate on host machine. Do I have to add certificate inside container? Any idea what I’m missing here? Any help would be helpful. Thanks.
1 Answer 1
I tried to reproduce your issue with the following Dockerfile
FROM ubuntu:18.04 # If you need a proxy server e.g. at 192.168.0.1:3128 #RUN echo 'Acquire::http::proxy "http://192.168.0.1:3128/";' > /etc/apt/apt.conf.d/05proxy #RUN echo 'Acquire::https::proxy "http://192.168.0.1:3128/";' >> /etc/apt/apt.conf.d/05proxy RUN apt-get update RUN apt-get install --no-install-recommends --yes software-properties-common # Add the local proxy certificate inside container ADD Proxy-Certificate.crt /usr/local/share/ca-certificates/Proxy-Certificate.crt RUN update-ca-certificates RUN add-apt-repository ppa:webupd8team/y-ppa-manager RUN apt-get update RUN apt-get install --yes y-ppa-manager
. 0 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d. done. --> d62ad9911de STEP 4/6: RUN add-apt-repository ppa:webupd8team/y-ppa-manager Y PPA Manager Info: http://www.webupd8.org/2010/11/y-ppa-manager-easily-search-add-remove.html This PPA is for Y PPA Manager and also includes the latest YAD for the supported Ubuntu versions (YAD is a dependency for Y PPA Manager): http://sourceforge.net/p/yad-dialog/ More info: https://launchpad.net/~webupd8team/+archive/ubuntu/y-ppa-manager Get:1 http://ppa.launchpad.net/webupd8team/y-ppa-manager/ubuntu bionic InRelease [15.4 kB] Hit:2 http://archive.ubuntu.com/ubuntu bionic InRelease Hit:3 http://security.ubuntu.com/ubuntu bionic-security InRelease Hit:4 http://archive.ubuntu.com/ubuntu bionic-updates InRelease .
And it worked. Is it possible, that you did not use the official base image ubuntu:18.04 ?