luc luc - 28 days ago 12
Python Question

Why do I get a "SSL error: called a function you should not call" with Django

I have a

Python 3.5
/
Django 1.10
app served by
Apache
/
mod_wsgi
over SSL. It is connected to a
Postgres 9.5.2
database (with
psycopg2==2.6.2
) and is running on a server at
AlwaysData


It works fine most of time but I have sometimes an error that I don't understand.

(SSL error: called a function you should not call)


If I put the following database settings : The error seems to happen every time

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'db',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'host',
'PORT': '',
'OPTIONS': {
'sslmode': 'require',
},
}
}


It seems to occur while querying the database.

# django/db/backends/utils.py line 64
return self.cursor.execute(sql, params)


The problem occurs when REST api (made using django-rest-framework) is called by a Angular2 app.

I have activated the following settings:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True


Why does it happen? How to fix this problem in my Django project.

Note : This question looks similar but I don't manage the OpenSSL layer directly so it is not very helpful.

EDIT : here is the full traceback

File "proj/env/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
39. response = get_response(request)

File "proj/env/lib/python3.5/site-packages/django/core/handlers/base.py" in _legacy_get_response
249. response = self._get_response(request)

File "proj/env/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)

File "proj/env/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "proj/env/lib/python3.5/site-packages/django/views/decorators/csrf.py" in wrapped_view
58. return view_func(*args, **kwargs)

File "proj/env/lib/python3.5/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)

File "proj/env/lib/python3.5/site-packages/rest_framework/views.py" in dispatch
474. response = self.handle_exception(exc)

File "proj/env/lib/python3.5/site-packages/rest_framework/views.py" in handle_exception
434. self.raise_uncaught_exception(exc)

File "proj/env/lib/python3.5/site-packages/rest_framework/views.py" in dispatch
471. response = handler(request, *args, **kwargs)

File "proj/apps/costs/apis.py" in get
296. data = self.get_spends_stats(cost_items, perimeter, start_date, end_date)

File "proj/apps/costs/apis.py" in get_spends_stats
306. for building in buildings:

File "proj/env/lib/python3.5/site-packages/django/db/models/query.py" in __iter__
256. self._fetch_all()

File "proj/env/lib/python3.5/site-packages/django/db/models/query.py" in _fetch_all
1087. self._result_cache = list(self.iterator())

File "proj/env/lib/python3.5/site-packages/django/db/models/query.py" in __iter__
54. results = compiler.execute_sql()

File "proj/env/lib/python3.5/site-packages/django/db/models/sql/compiler.py" in execute_sql
835. cursor.execute(sql, params)

File "proj/env/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
64. return self.cursor.execute(sql, params)

File "proj/env/lib/python3.5/site-packages/django/db/utils.py" in __exit__
94. six.reraise(dj_exc_type, dj_exc_value, traceback)

File "proj/env/lib/python3.5/site-packages/django/utils/six.py" in reraise
685. raise value.with_traceback(tb)

File "proj/env/lib/python3.5/site-packages/django/db/backends/utils.py" in execute
64. return self.cursor.execute(sql, params)

Exception Type: OperationalError at /costs/api/benchmark/cost-center/3/38/2016-01/2017-12/
Exception Value: SSL error: called a function you should not call

luc luc
Answer

The problem seems to be solved by changing the database settings

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'name',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'host',
        'PORT': '',
        'OPTIONS': {
            'sslmode': 'disable',
        },
    }
}

If not set the option is using prefer as default (see https://www.postgresql.org/docs/9.5/static/libpq-ssl.html) which seems to have unpredicted behavior.

I guess that the root cause is an OpenSSL mismatch between Apache and Postgres. It has to be investigated.

The current fix makes the database connection not secured but this is another story.

Comments