Merge pull request #4357 from rtfd/humitos/ssh/encrypted
Encrypt SSHKey.private_key database fieldhumitos/ssh/management
commit
07fc45d5dc
|
@ -90,6 +90,7 @@ class CommunityBaseSettings(Settings):
|
|||
'django_extensions',
|
||||
'messages_extends',
|
||||
'tastypie',
|
||||
'encrypted_model_fields',
|
||||
|
||||
# our apps
|
||||
'readthedocs.projects',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
default_app_config = 'readthedocs.ssh.apps.SshConfig'
|
|
@ -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
|
||||
|
|
|
@ -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')),
|
||||
],
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue