Skip to content

Commit

Permalink
crypto: validate that generated certificate's name is unique (cherry-…
Browse files Browse the repository at this point in the history
…pick #12015) (#12016)

crypto: validate that generated certificate's name is unique (#12015)

Signed-off-by: Jens Langhammer <[email protected]>
Co-authored-by: Jens L. <[email protected]>
  • Loading branch information
gcp-cherry-pick-bot[bot] and BeryJu authored Nov 13, 2024
1 parent feb13c8 commit f49008b
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 4 deletions.
11 changes: 7 additions & 4 deletions authentik/crypto/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger

Expand Down Expand Up @@ -181,7 +182,10 @@ class CertificateDataSerializer(PassiveSerializer):
class CertificateGenerationSerializer(PassiveSerializer):
"""Certificate generation parameters"""

common_name = CharField()
common_name = CharField(
validators=[UniqueValidator(queryset=CertificateKeyPair.objects.all())],
source="name",
)
subject_alt_name = CharField(required=False, allow_blank=True, label=_("Subject-alt name"))
validity_days = IntegerField(initial=365)
alg = ChoiceField(default=PrivateKeyAlg.RSA, choices=PrivateKeyAlg.choices)
Expand Down Expand Up @@ -242,11 +246,10 @@ def list(self, request, *args, **kwargs):
def generate(self, request: Request) -> Response:
"""Generate a new, self-signed certificate-key pair"""
data = CertificateGenerationSerializer(data=request.data)
if not data.is_valid():
return Response(data.errors, status=400)
data.is_valid(raise_exception=True)
raw_san = data.validated_data.get("subject_alt_name", "")
sans = raw_san.split(",") if raw_san != "" else []
builder = CertificateBuilder(data.validated_data["common_name"])
builder = CertificateBuilder(data.validated_data["name"])
builder.alg = data.validated_data["alg"]
builder.build(
subject_alt_names=sans,
Expand Down
11 changes: 11 additions & 0 deletions authentik/crypto/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ def test_builder_api(self):
self.assertIsInstance(ext[1], DNSName)
self.assertEqual(ext[1].value, "baz")

def test_builder_api_duplicate(self):
"""Test Builder (via API)"""
cert = create_test_cert()
self.client.force_login(create_test_admin_user())
res = self.client.post(
reverse("authentik_api:certificatekeypair-generate"),
data={"common_name": cert.name, "subject_alt_name": "bar,baz", "validity_days": 3},
)
self.assertEqual(res.status_code, 400)
self.assertJSONEqual(res.content, {"common_name": ["This field must be unique."]})

def test_builder_api_empty_san(self):
"""Test Builder (via API)"""
self.client.force_login(create_test_admin_user())
Expand Down

0 comments on commit f49008b

Please sign in to comment.