A common security procedure for DB access is to require mutual TLS for the
DB connection.
This involves specifying a server certificate, client certificate, and
client key when connecting.
Django already supports this configuration, it looks like this:
{{{
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('POSTGRES_DB_NAME'),
'USER': os.environ.get('POSTGRES_DB_USER'),
'HOST': 'postgres',
'PORT': '5432',
'SCHEMA': os.environ.get('POSTGRES_DB_SCHEMA'),
'OPTIONS': {
'sslmode': 'verify-ca',
'sslrootcert': os.environ.get('POSTGRES_CLI_SSL_CA',
'ca.crt'),
'sslcert': os.environ.get('POSTGRES_CLI_SSL_CRT',
'client_cert_chain.crt'),
'sslkey': os.environ.get('POSTGRES_CLI_SSL_KEY',
'client_key.key')
}
}
}
}}}
However the dbshell command does not support the client cert params.
Should be a trivial fix to add in support for the other 'ssl' parameters
required here.
--
Ticket URL: <https://code.djangoproject.com/ticket/30370>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* type: Bug => Cleanup/optimization
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:1>
* version: 2.2 => master
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:2>
* owner: nobody => Oleh Mykytyuk
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:3>
Comment (by Oleh Mykytyuk):
Added pull request: https://github.com/django/django/pull/11239/
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:4>
* has_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:5>
* needs_better_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:6>
* needs_better_patch: 1 => 0
* stage: Accepted => Ready for checkin
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:7>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"177fa08339c4908afbefbda5dceabe72641ec915" 177fa083]:
{{{
#!CommitTicketReference repository=""
revision="177fa08339c4908afbefbda5dceabe72641ec915"
Fixed #30370 -- Added dbshell support for client TLS certificates on
PostgreSQL.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:8>
Comment (by Robert Kisteleki):
I'd like to ask for reconsideration of the severity of this from
"optimization" to "security" or such.
As it stands, users connecting to a Postgres server with the CLI (psql),
if configured properly, will connect verifiably using TLS, giving the
impression that the setup is correct the connection is secured. However,
this is a false impression as even if the configuration is perfect, Django
settings are such that these options are specified, the actual working
*code* will not use a secure channel.
As a consequence, passwords, keys, PII and the like will travel in clear
text between the application and the database.
Ultimately, I'd like this patch to be added to the 2.2 LTS release too.
Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:9>
Comment (by Oleh Mykytyuk):
Replying to [comment:9 Robert Kisteleki]:
> I'd like to ask for reconsideration of the severity of this from
"optimization" to "security" or such.
>
> As it stands, users connecting to a Postgres server with the CLI (psql),
if configured properly, will connect verifiably using TLS, giving the
impression that the setup is correct the connection is secured. However,
this is a false impression as even if the configuration is perfect, Django
settings are such that these options are specified, the actual working
*code* will not use a secure channel.
>
> As a consequence, passwords, keys, PII and the like will travel in clear
text between the application and the database.
>
> Ultimately, I'd like this patch to be added to the 2.2 LTS release too.
>
> Thanks!
I can't change from optimization to security. Available options for the
severity are "normal", "release blocker". Available options for type are:
uncategorized/new feature/bug/cleanup/optimization. Can I ask you to
advise me on what I have to change?
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:10>
* type: Cleanup/optimization => Bug
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:11>
Comment (by Oleh Mykytyuk):
I've changed type to 'bug'
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:12>
* type: Bug => New feature
Comment:
That's not a bug, it's a new feature. I don't see a security issue in this
behavior. `dbshell` is a utility tool and passwords, keys, etc. will
travel in clear text only if your database allows non-ssl connections.
It's also [https://docs.djangoproject.com/en/3.0/ref/django-admin/#dbshell
documented] that ''not all options set in the `OPTIONS` part of your
database configuration in `DATABASES` are passed to the command-line
client''.
> As it stands, users connecting to a Postgres server with the CLI (psql),
if configured properly, will connect verifiably using TLS, giving the
impression that the setup is correct the connection is secured. However,
this is a false impression as even if the configuration is perfect, ....
`dbshell` uses a subprocess with
[https://github.com/django/django/blob/7d8df4ad032c6241776c2b3ec6c76af9dd84fda3/django/db/backends/postgresql/client.py#L34
a copy of the current environment], so if you set `PGSSLMODE`,
`PGSSLROOTCERT`, etc. in your current environment you will connect using
TLS even without this change.
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:13>
Comment (by Robert Kisteleki):
Replying to [comment:13 felixxm]:
> That's not a bug, it's a new feature. I don't see a security issue in
this behavior. `dbshell` is a utility tool and passwords, keys, etc. will
travel in clear text only if your database allows non-ssl connections.
It's also [https://docs.djangoproject.com/en/3.0/ref/django-admin/#dbshell
documented] that ''not all options set in the `OPTIONS` part of your
database configuration in `DATABASES` are passed to the command-line
client''.
I understand your argument for considering it a feature instead. My point
is that it's a security feature.
> > As it stands, users connecting to a Postgres server with the CLI
(psql), if configured properly, will connect verifiably using TLS, giving
the impression that the setup is correct the connection is secured.
However, this is a false impression as even if the configuration is
perfect, ....
>
> `dbshell` uses a subprocess with
[https://github.com/django/django/blob/7d8df4ad032c6241776c2b3ec6c76af9dd84fda3/django/db/backends/postgresql/client.py#L34
a copy of the current environment], so if you set `PGSSLMODE`,
`PGSSLROOTCERT`, etc. in your current environment you will connect using
TLS even without this change.
That is true. However, that requires devs (and/or users) to understand
that even though Djanog is configured properly and every day use (via wsgi
and such) is fine, if they *ever* ask for a dbshell and not consciously
set ENV variables, auth tokens and perhaps PII can be captured on the
wire. IMO it's a basic security requirement never to send your password in
the clear... So this has vast consequences in environments where you don't
control the network.
--
Ticket URL: <https://code.djangoproject.com/ticket/30370#comment:14>