Merge pull request #4357 from rtfd/humitos/ssh/encrypted

Encrypt SSHKey.private_key database field
humitos/ssh/management
Manuel Kaufmann 2018-07-23 16:19:37 -03:00 committed by GitHub
commit 07fc45d5dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 59 additions and 2 deletions

View File

@ -90,6 +90,7 @@ class CommunityBaseSettings(Settings):
'django_extensions',
'messages_extends',
'tastypie',
'encrypted_model_fields',
# our apps
'readthedocs.projects',

View File

@ -48,6 +48,11 @@ class CommunityDevSettings(CommunityBaseSettings):
'test:8000',
)
# Encryption
FIELD_ENCRYPTION_KEY = [
'P98DEYWoSuLmgXdRGzJkbo1JWeiHf4ghpFI8QvV3hRI=', # only for development
]
@property
def LOGGING(self): # noqa - avoid pep8 N802
logging = super(CommunityDevSettings, self).LOGGING

View File

@ -0,0 +1 @@
default_app_config = 'readthedocs.ssh.apps.SshConfig'

View File

@ -3,6 +3,8 @@
from __future__ import division, print_function, unicode_literals
from django.apps import AppConfig
from django.core.checks import Error, register
from django.conf import settings
class SshConfig(AppConfig):
@ -11,3 +13,48 @@ class SshConfig(AppConfig):
name = 'readthedocs.ssh'
verbose_name = 'SSH Keys'
@register()
def check_valid_encryption_key(app_configs, **kwargs):
from encrypted_model_fields.fields import parse_key
errors = []
keys = getattr(settings, 'FIELD_ENCRYPTION_KEY', None)
if not keys:
errors.append(
Error(
'FIELD_ENCRYPTION_KEY must be defined in settings',
hint='Use the "generate_encryption_key" management command to generate a valid one ', # noqa
id='ssh.E001',
),
)
else:
default_key = 'P98DEYWoSuLmgXdRGzJkbo1JWeiHf4ghpFI8QvV3hRI='
if not isinstance(keys, (tuple, list)):
keys = [keys]
for key in keys:
try:
parse_key(key)
except Exception:
errors.append(
Error(
'FIELD_ENCRYPTION_KEY setting has an incorrect padding',
hint='Use the "generate_encryption_key" management command to generate a valid one ', # noqa
id='ssh.E002',
),
)
# Check against the default value to prevent users to run the
# instance in production with a shared encryption key
if key == default_key and not settings.DEBUG:
errors.append(
Error(
'You are using the default value for FIELD_ENCRYPTION_KEY',
hint='Change it by running the "generate_encryption_key" management command',
id='ssh.E003',
),
)
return errors

View File

@ -5,6 +5,7 @@ from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import readthedocs.ssh.mixins
import encrypted_model_fields.fields
class Migration(migrations.Migration):
@ -22,7 +23,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('create_date', models.DateTimeField(auto_now_add=True, verbose_name='Creation date')),
('public_key', models.TextField(help_text='Add this to your version control to give us access.', verbose_name='Public SSH Key')),
('private_key', models.TextField(verbose_name='Private SSH Key')),
('private_key', encrypted_model_fields.fields.EncryptedTextField(verbose_name='Private SSH Key')),
('json', models.TextField(blank=True, null=True, verbose_name='Serialized API response')),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sshkeys', to='projects.Project')),
],

View File

@ -15,6 +15,7 @@ import hashlib
import json
from builtins import zip # pylint: disable=redefined-builtin
from encrypted_model_fields.fields import EncryptedTextField
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
@ -41,7 +42,7 @@ class SSHKey(SSHKeyGenMixin, models.Model):
_('Public SSH Key'),
help_text='Add this to your version control to give us access.',
)
private_key = models.TextField(_('Private SSH Key'))
private_key = EncryptedTextField(_('Private SSH Key'))
project = models.ForeignKey(Project, related_name='sshkeys')
json = models.TextField(_('Serialized API response'), blank=True, null=True)

View File

@ -38,6 +38,7 @@ defusedxml==0.5.0
redis==2.10.6
celery==4.1.1
cryptography==2.2.2
django-encrypted-model-fields==0.5.5
# django-allauth 0.33.0 dropped support for Django 1.9
# https://django-allauth.readthedocs.io/en/latest/release-notes.html#backwards-incompatible-changes