crypto: add command to import certificates

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>

#3544
This commit is contained in:
Jens Langhammer 2022-09-06 19:39:01 +02:00
parent c2cb804ace
commit 03a3f1bd6f
3 changed files with 65 additions and 1 deletions

View File

@ -12,10 +12,11 @@ from django_filters.filters import BooleanFilter
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, DateTimeField, IntegerField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, ValidationError
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger

View File

@ -0,0 +1,51 @@
"""Import certificate"""
from sys import exit as sys_exit
from django.core.management.base import BaseCommand, no_translations
from rest_framework.exceptions import ValidationError
from structlog.stdlib import get_logger
from authentik.crypto.api import CertificateKeyPairSerializer
from authentik.crypto.models import CertificateKeyPair
LOGGER = get_logger()
class Command(BaseCommand):
"""Import certificate"""
@no_translations
def handle(self, *args, **options):
"""Import certificate"""
keypair = CertificateKeyPair.objects.filter(name=options["name"]).first()
dirty = False
if not keypair:
keypair = CertificateKeyPair(name=options["name"])
dirty = True
with open(options["certificate"], mode="r", encoding="utf-8") as _cert:
cert_data = _cert.read()
if keypair.certificate_data != cert_data:
dirty = True
keypair.certificate_data = cert_data
if options["private_key"]:
with open(options["private_key"], mode="r", encoding="utf-8") as _key:
key_data = _key.read()
if keypair.key_data != key_data:
dirty = True
keypair.key_data = key_data
# Validate that cert and key are actually PEM and valid
serializer = CertificateKeyPairSerializer(instance=keypair)
try:
serializer.validate_certificate_data(keypair.certificate_data)
if keypair.key_data != "":
serializer.validate_certificate_data(keypair.key_data)
except ValidationError as exc:
self.stderr.write(exc)
sys_exit(1)
if dirty:
keypair.save()
def add_arguments(self, parser):
parser.add_argument("--certificate", type=str, required=True)
parser.add_argument("--private-key", type=str, required=False)
parser.add_argument("--name", type=str, required=True)

View File

@ -57,6 +57,18 @@ certs/
Files are checked every 5 minutes, and will trigger an Outpost refresh if the files differ.
#### Manual imports
Starting with authentik 2022.9, you can also import certificates with any folder structure directly. To do this, run the following command within the worker container:
```shell
ak import_certificate --certificate /certs/mycert.pem --private-key /certs/something.pem --name test
# --private-key can be omitted to only import a certificate, i.e. to trust other connections
# ak import_certificate --certificate /certs/othercert.pem --name test2
```
This will import the certificate into authentik under the given name. This command is idempotent, meaning you can run it via a cron-job and authentik will only update the certificate when it changes.
## Web certificates
Starting with authentik 2021.12.4, you can configure the certificate authentik uses for its core webserver. For most deployments this will not be relevant and reverse proxies are used, but this can be used to create a very compact and self-contained authentik install.