crypto: add additional validation before importing a certificate
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
54f893b84f
commit
32ace1bece
|
@ -11,10 +11,13 @@ from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||||
from cryptography.x509 import Certificate, load_pem_x509_certificate
|
from cryptography.x509 import Certificate, load_pem_x509_certificate
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
from authentik.lib.models import CreatedUpdatedModel
|
from authentik.lib.models import CreatedUpdatedModel
|
||||||
from authentik.managed.models import ManagedModel
|
from authentik.managed.models import ManagedModel
|
||||||
|
|
||||||
|
LOGGER = get_logger()
|
||||||
|
|
||||||
|
|
||||||
class CertificateKeyPair(ManagedModel, CreatedUpdatedModel):
|
class CertificateKeyPair(ManagedModel, CreatedUpdatedModel):
|
||||||
"""CertificateKeyPair that can be used for signing or encrypting if `key_data`
|
"""CertificateKeyPair that can be used for signing or encrypting if `key_data`
|
||||||
|
@ -62,7 +65,8 @@ class CertificateKeyPair(ManagedModel, CreatedUpdatedModel):
|
||||||
password=None,
|
password=None,
|
||||||
backend=default_backend(),
|
backend=default_backend(),
|
||||||
)
|
)
|
||||||
except ValueError:
|
except ValueError as exc:
|
||||||
|
LOGGER.warning(exc)
|
||||||
return None
|
return None
|
||||||
return self._private_key
|
return self._private_key
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
from glob import glob
|
from glob import glob
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from cryptography.hazmat.backends import default_backend
|
||||||
|
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
||||||
|
from cryptography.x509.base import load_pem_x509_certificate
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from structlog.stdlib import get_logger
|
from structlog.stdlib import get_logger
|
||||||
|
|
||||||
|
@ -20,6 +23,22 @@ LOGGER = get_logger()
|
||||||
MANAGED_DISCOVERED = "goauthentik.io/crypto/discovered/%s"
|
MANAGED_DISCOVERED = "goauthentik.io/crypto/discovered/%s"
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_private_key_valid(body: str):
|
||||||
|
"""Attempt loading of an RSA Private key without password"""
|
||||||
|
load_pem_private_key(
|
||||||
|
str.encode("\n".join([x.strip() for x in body.split("\n")])),
|
||||||
|
password=None,
|
||||||
|
backend=default_backend(),
|
||||||
|
)
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_certificate_valid(body: str):
|
||||||
|
"""Attempt loading of a PEM-encoded certificate"""
|
||||||
|
load_pem_x509_certificate(body.encode("utf-8"), default_backend())
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
@CELERY_APP.task(bind=True, base=MonitoredTask)
|
@CELERY_APP.task(bind=True, base=MonitoredTask)
|
||||||
@prefill_task
|
@prefill_task
|
||||||
def certificate_discovery(self: MonitoredTask):
|
def certificate_discovery(self: MonitoredTask):
|
||||||
|
@ -42,11 +61,11 @@ def certificate_discovery(self: MonitoredTask):
|
||||||
with open(path, "r+", encoding="utf-8") as _file:
|
with open(path, "r+", encoding="utf-8") as _file:
|
||||||
body = _file.read()
|
body = _file.read()
|
||||||
if "BEGIN RSA PRIVATE KEY" in body:
|
if "BEGIN RSA PRIVATE KEY" in body:
|
||||||
private_keys[cert_name] = body
|
private_keys[cert_name] = ensure_private_key_valid(body)
|
||||||
else:
|
else:
|
||||||
certs[cert_name] = body
|
certs[cert_name] = ensure_certificate_valid(body)
|
||||||
except OSError as exc:
|
except (OSError, ValueError) as exc:
|
||||||
LOGGER.warning("Failed to open file", exc=exc, file=path)
|
LOGGER.warning("Failed to open file or invalid format", exc=exc, file=path)
|
||||||
discovered += 1
|
discovered += 1
|
||||||
for name, cert_data in certs.items():
|
for name, cert_data in certs.items():
|
||||||
cert = CertificateKeyPair.objects.filter(managed=MANAGED_DISCOVERED % name).first()
|
cert = CertificateKeyPair.objects.filter(managed=MANAGED_DISCOVERED % name).first()
|
||||||
|
|
Reference in New Issue