Skip to content

Commit

Permalink
Add system checks to verify proper config exist
Browse files Browse the repository at this point in the history
  • Loading branch information
marteinn committed Dec 14, 2022
1 parent 7c24f03 commit b14dcb6
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 0 deletions.
7 changes: 7 additions & 0 deletions pgcrypto/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.apps import AppConfig

from . import checks # NOQA


class PgcryptoConfig(AppConfig):
name = "pgcrypto"
74 changes: 74 additions & 0 deletions pgcrypto/checks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import django.apps
from django.conf import settings
from django.core.checks import Error, register

from .mixins import PGPPublicKeyFieldMixin, PGPSymmetricKeyFieldMixin


@register()
def check_required_settings_exist(app_configs, **kwargs):
"""Make sure PGCRYPTO_KEY/PUBLIC_PGP_KEY/PRIVATE_PGP_KEY are set."""
all_models = django.apps.apps.get_models()
errors = []

has_pgp_symmetric_field = _contains_pgp_symmetric_field(all_models)
if has_pgp_symmetric_field:
found_keys = [
getattr(settings, "PGCRYPTO_KEY", None),
]

db_settings = [*settings.DATABASES.values()]
found_keys = found_keys + [x.get("PGCRYPTO_KEY", None) for x in db_settings]
found_keys = list(filter(bool, found_keys))

if len(found_keys) == 0:
errors = [
*errors,
Error(
"Missing PGCRYPTO_KEY setting",
id="pgcrypto.E001",
),
]

has_pgp_public_field = _contains_pgp_public_key_field(all_models)
if has_pgp_public_field:
found_keys = [
(
getattr(settings, "PUBLIC_PGP_KEY", None),
getattr(settings, "PRIVATE_PGP_KEY", None),
)
]

db_settings = [*settings.DATABASES.values()]
found_keys = found_keys + [
(x.get("PUBLIC_PGP_KEY", None), x.get("PRIVATE_PGP_KEY", None))
for x in db_settings
]
found_keys = list(filter(lambda x: bool(x[0]) and bool(x[1]), found_keys))

if len(found_keys) == 0:
errors = [
*errors,
Error(
"Missing PGCRYPTO_KEY setting",
id="pgcrypto.E001",
),
]

return errors


def _contains_pgp_symmetric_field(models):
for model in models:
for field in model._meta.fields:
if isinstance(field, PGPSymmetricKeyFieldMixin):
return True
return False


def _contains_pgp_public_key_field(models):
for model in models:
for field in model._meta.fields:
if isinstance(field, PGPPublicKeyFieldMixin):
return True
return False
72 changes: 72 additions & 0 deletions tests/test_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# flake8: noqa
from django.conf import settings
from django.test import override_settings, TestCase

from pgcrypto.checks import check_required_settings_exist


class TestChecks(TestCase):
# noqa: D103
def test_pgcrypto_key_exist(self):
errors = check_required_settings_exist(None)
self.assertEqual(len(errors), 0)

@override_settings()
def test_missing_pgcrypto_key_raises_error(self):
del settings.PGCRYPTO_KEY

key_value = settings.DATABASES["diff_keys"]["PGCRYPTO_KEY"]
del settings.DATABASES["diff_keys"]["PGCRYPTO_KEY"]

errors = check_required_settings_exist(None)
self.assertEqual(errors[0].id, "pgcrypto.E001")

settings.DATABASES["diff_keys"]["PGCRYPTO_KEY"] = key_value

@override_settings()
def test_error_not_raised_if_key_is_in_db_settings(self):
del settings.PGCRYPTO_KEY

errors = check_required_settings_exist(None)
self.assertEqual(len(errors), 0)

@override_settings()
def test_empty_pgcrypto_raises_error(self):
settings.PGCRYPTO_KEY = None
key_value = settings.DATABASES["diff_keys"]["PGCRYPTO_KEY"]
del settings.DATABASES["diff_keys"]["PGCRYPTO_KEY"]

errors = check_required_settings_exist(None)
self.assertEqual(len(errors), 1)
self.assertEqual(errors[0].id, "pgcrypto.E001")

settings.DATABASES["diff_keys"]["PGCRYPTO_KEY"] = key_value

def test_public_key_exist(self):
errors = check_required_settings_exist(None)
self.assertEqual(len(errors), 0)

@override_settings()
def test_missing_public_pgp_key_raises_error(self):
del settings.PUBLIC_PGP_KEY

key_value = settings.DATABASES["diff_keys"]["PUBLIC_PGP_KEY"]
del settings.DATABASES["diff_keys"]["PUBLIC_PGP_KEY"]

errors = check_required_settings_exist(None)
self.assertEqual(errors[0].id, "pgcrypto.E001")

settings.DATABASES["diff_keys"]["PUBLIC_PGP_KEY"] = key_value

@override_settings()
def test_missing_private_pgp_key_raises_error(self):
del settings.PRIVATE_PGP_KEY

key_value = settings.DATABASES["diff_keys"]["PRIVATE_PGP_KEY"]
del settings.DATABASES["diff_keys"]["PRIVATE_PGP_KEY"]

errors = check_required_settings_exist(None)
self.assertEqual(len(errors), 1)
self.assertEqual(errors[0].id, "pgcrypto.E001")

settings.DATABASES["diff_keys"]["PRIVATE_PGP_KEY"] = key_value

0 comments on commit b14dcb6

Please sign in to comment.