Skip to content

Commit 258f227

Browse files
committed
tmp
1 parent 1f8cc0b commit 258f227

File tree

6 files changed

+13
-190
lines changed

6 files changed

+13
-190
lines changed

ca/django_ca/ca_settings.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ def _get_hash_algorithm(setting: str, default: "HashAlgorithms") -> "AllowedHash
184184
"description": _(
185185
"A certificate for an enduser, allows client authentication, code and email signing."
186186
),
187-
"cn_in_san": False,
188187
"extensions": {
189188
"key_usage": {
190189
"critical": True,
@@ -206,7 +205,6 @@ def _get_hash_algorithm(setting: str, default: "HashAlgorithms") -> "AllowedHash
206205
},
207206
"ocsp": {
208207
"description": _("A certificate for an OCSP responder."),
209-
"cn_in_san": False, # CAs frequently use human-readable name as CN
210208
"add_ocsp_url": False,
211209
"autogenerated": True,
212210
"subject": False,
@@ -290,7 +288,6 @@ def _get_hash_algorithm(setting: str, default: "HashAlgorithms") -> "AllowedHash
290288

291289
for profile_name, profile in CA_PROFILES.items():
292290
profile.setdefault("subject", CA_DEFAULT_SUBJECT)
293-
profile.setdefault("cn_in_san", True)
294291

295292
if subject := profile.get("subject"):
296293
profile["subject"] = _normalize_x509_name(subject, f"subject in {profile_name} profile.")

ca/django_ca/managers.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -605,10 +605,6 @@ def create_cert( # noqa: PLR0913
605605
Passed to :py:func:`Profiles.create_cert() <django_ca.profiles.Profile.create_cert>`.
606606
extensions : list or of :py:class:`~cg:cryptography.x509.Extension`
607607
Passed to :py:func:`Profiles.create_cert() <django_ca.profiles.Profile.create_cert>`.
608-
cn_in_san : bool, optional
609-
Passed to :py:func:`Profiles.create_cert() <django_ca.profiles.Profile.create_cert>`.
610-
cn_in_san : bool, optional
611-
Passed to :py:func:`Profiles.create_cert() <django_ca.profiles.Profile.create_cert>`.
612608
add_crl_url : bool, optional
613609
Passed to :py:func:`Profiles.create_cert() <django_ca.profiles.Profile.create_cert>`.
614610
add_ocsp_url : bool, optional
@@ -633,7 +629,6 @@ def create_cert( # noqa: PLR0913
633629
expires=expires,
634630
algorithm=algorithm,
635631
extensions=extensions,
636-
cn_in_san=False,
637632
add_crl_url=add_crl_url,
638633
add_ocsp_url=add_ocsp_url,
639634
add_issuer_url=add_issuer_url,

ca/django_ca/models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -792,8 +792,7 @@ def sign(
792792
793793
Required extensions are added if not provided. Unless already included in `extensions`, this function
794794
will add the AuthorityKeyIdentifier, BasicConstraints and SubjectKeyIdentifier extensions with values
795-
coming from the certificate authority. The common names in `subject` are added to
796-
SubjectAlternativeName if `cn_in_san` is ``True``.
795+
coming from the certificate authority.
797796
798797
Parameters
799798
----------

ca/django_ca/profiles.py

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
SerializedProfile,
4242
SerializedPydanticName,
4343
)
44-
from django_ca.utils import get_cert_builder, merge_x509_names, parse_expires, parse_general_name, x509_name
44+
from django_ca.utils import get_cert_builder, merge_x509_names, parse_expires, x509_name
4545

4646
if typing.TYPE_CHECKING:
4747
from django_ca.models import CertificateAuthority
@@ -115,7 +115,12 @@ def __init__( # noqa: PLR0913
115115
except KeyError as ex:
116116
raise ValueError(f"{algorithm}: Unknown hash algorithm.") from ex
117117

118-
self.cn_in_san = cn_in_san
118+
if cn_in_san is not None: # pragma: no cover
119+
warnings.warn(
120+
"cn_in_san: Support for this flag has been removed.",
121+
RemovedInDjangoCA128Warning,
122+
stacklevel=2,
123+
)
119124
self.expires = expires or ca_settings.CA_DEFAULT_EXPIRES
120125
self.add_crl_url = add_crl_url
121126
self.add_issuer_url = add_issuer_url
@@ -148,7 +153,6 @@ def __eq__(self, value: object) -> bool:
148153
and self.subject == value.subject
149154
and algo
150155
and self.extensions == value.extensions
151-
and self.cn_in_san == value.cn_in_san
152156
and self.expires == value.expires
153157
and self.add_crl_url == value.add_crl_url
154158
and self.add_issuer_url == value.add_issuer_url
@@ -179,7 +183,6 @@ def create_cert( # noqa: PLR0913
179183
expires: Expires = None,
180184
algorithm: Optional[AllowedHashTypes] = None,
181185
extensions: Optional[Iterable[x509.Extension[x509.ExtensionType]]] = None,
182-
cn_in_san: Optional[bool] = None,
183186
add_crl_url: Optional[bool] = None,
184187
add_ocsp_url: Optional[bool] = None,
185188
add_issuer_url: Optional[bool] = None,
@@ -229,9 +232,6 @@ def create_cert( # noqa: PLR0913
229232
:py:class:`~cg:cryptography.x509.IssuerAlternativeName` extension, *add_issuer_alternative_name*
230233
is ``True`` and the passed CA has an IssuerAlternativeName set, that value will be appended to the
231234
extension you pass here.
232-
cn_in_san : bool, optional
233-
Override if the commonName should be added as an SubjectAlternativeName. If not passed, the value
234-
set in the profile is used.
235235
add_crl_url : bool, optional
236236
Override if any CRL URLs from the CA should be added to the CA. If not passed, the value set in
237237
the profile is used.
@@ -253,8 +253,6 @@ def create_cert( # noqa: PLR0913
253253
The signed certificate.
254254
"""
255255
# Get overrides values from profile if not passed as parameter
256-
if cn_in_san is None:
257-
cn_in_san = self.cn_in_san
258256
if add_crl_url is None:
259257
add_crl_url = self.add_crl_url
260258
if add_ocsp_url is None:
@@ -302,9 +300,6 @@ def create_cert( # noqa: PLR0913
302300
# Make sure that expires is a fixed timestamp
303301
expires = self.get_expires(expires)
304302

305-
# Finally, add the commonName as a subjectAlternativeName if not already present.
306-
self._update_san_from_cn(cn_in_san, subject=subject, extensions=cert_extensions)
307-
308303
if not subject.get_attributes_for_oid(NameOID.COMMON_NAME) and not cert_extensions.get(
309304
ExtensionOID.SUBJECT_ALTERNATIVE_NAME
310305
):
@@ -526,40 +521,6 @@ def _update_cn_from_san(
526521

527522
return subject
528523

529-
def _update_san_from_cn(self, cn_in_san: bool, subject: x509.Name, extensions: ExtensionMapping) -> None:
530-
if cn_in_san is False:
531-
return
532-
533-
if not (common_name_attributes := subject.get_attributes_for_oid(NameOID.COMMON_NAME)):
534-
return
535-
536-
common_name_value = typing.cast(str, common_name_attributes[0].value)
537-
try:
538-
common_name = parse_general_name(common_name_value)
539-
except ValueError as ex:
540-
raise ValueError(
541-
f"{common_name_value}: Could not parse CommonName as subjectAlternativeName."
542-
) from ex
543-
544-
if ExtensionOID.SUBJECT_ALTERNATIVE_NAME in extensions:
545-
san_ext = typing.cast(
546-
x509.Extension[x509.SubjectAlternativeName],
547-
extensions[ExtensionOID.SUBJECT_ALTERNATIVE_NAME],
548-
)
549-
550-
if common_name not in san_ext.value:
551-
extensions[ExtensionOID.SUBJECT_ALTERNATIVE_NAME] = x509.Extension(
552-
oid=ExtensionOID.SUBJECT_ALTERNATIVE_NAME,
553-
critical=san_ext.critical,
554-
value=x509.SubjectAlternativeName([*san_ext.value, common_name]),
555-
)
556-
else:
557-
extensions[ExtensionOID.SUBJECT_ALTERNATIVE_NAME] = x509.Extension(
558-
oid=ExtensionOID.SUBJECT_ALTERNATIVE_NAME,
559-
critical=False,
560-
value=x509.SubjectAlternativeName([common_name]),
561-
)
562-
563524

564525
def get_profile(name: Optional[str] = None) -> Profile:
565526
"""Get profile by the given name.

ca/django_ca/tests/test_models.py

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,8 @@
6666
basic_constraints,
6767
crl_distribution_points,
6868
distribution_point,
69-
dns,
7069
issuer_alternative_name,
7170
override_tmpcadir,
72-
subject_alternative_name,
7371
subject_key_identifier,
7472
uri,
7573
)
@@ -1032,28 +1030,6 @@ def test_non_default_extensions(self) -> None:
10321030
self.assertBasicCert(cert)
10331031
self.assertExtensionDict(cert, [ski, basic_constraints(critical=False), aki])
10341032

1035-
@override_tmpcadir()
1036-
@freeze_time(TIMESTAMPS["everything_valid"])
1037-
def test_cn_not_in_san(self) -> None:
1038-
"""Test the cn_in_san option."""
1039-
cn = "example.com"
1040-
csr = CERT_DATA["child-cert"]["csr"]["parsed"]
1041-
subject = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)])
1042-
san = subject_alternative_name(dns("example.net"))
1043-
with self.assertSignCertSignals():
1044-
cert = self.ca.sign(csr, subject=subject, extensions=[san])
1045-
1046-
self.assertBasicCert(cert)
1047-
self.assertExtensionDict(
1048-
cert,
1049-
[
1050-
subject_key_identifier(cert),
1051-
san,
1052-
basic_constraints(),
1053-
self.ca.get_authority_key_identifier_extension(),
1054-
],
1055-
)
1056-
10571033
def test_create_ca(self) -> None:
10581034
"""Try passing a BasicConstraints extension that allows creating a CA."""
10591035
csr = CERT_DATA["child-cert"]["csr"]["parsed"]

ca/django_ca/tests/test_profiles.py

Lines changed: 5 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,7 @@ def test_python_intro(self) -> None:
8484
class ProfileTestCase(TestCaseMixin, TestCase):
8585
"""Main tests for the profile class."""
8686

87-
def create_cert( # type: ignore[override]
88-
self, prof: Profile, ca: CertificateAuthority, *args: Any, **kwargs: Any
89-
) -> Certificate:
87+
def create_cert(self, prof: Profile, ca: CertificateAuthority, *args: Any, **kwargs: Any) -> Certificate:
9088
"""Shortcut to create a cert with the given profile."""
9189
cert = Certificate(ca=ca)
9290
cert.update_certificate(prof.create_cert(ca, *args, **kwargs))
@@ -108,10 +106,7 @@ def test_create_cert_minimal(self) -> None:
108106
add_issuer_alternative_name=False,
109107
)
110108
self.assertEqual(pre.call_count, 1)
111-
self.assertExtensions(
112-
cert,
113-
[ca.get_authority_key_identifier_extension(), subject_alternative_name(dns(self.hostname))],
114-
)
109+
self.assertExtensions(cert, [ca.get_authority_key_identifier_extension()])
115110

116111
@override_tmpcadir()
117112
def test_alternative_values(self) -> None:
@@ -175,7 +170,6 @@ def test_overrides(self) -> None:
175170
subject_key_identifier(cert),
176171
ca.get_authority_key_identifier_extension(),
177172
basic_constraints(),
178-
subject_alternative_name(dns(self.hostname)),
179173
],
180174
expect_defaults=False,
181175
)
@@ -199,7 +193,6 @@ def test_overrides(self) -> None:
199193
[
200194
ca.get_authority_key_identifier_extension(),
201195
basic_constraints(),
202-
subject_alternative_name(dns(self.hostname)),
203196
],
204197
)
205198

@@ -215,78 +208,6 @@ def test_none_extension(self) -> None:
215208
self.assertEqual(pre.call_count, 1)
216209
self.assertNotIn(ExtensionOID.OCSP_NO_CHECK, cert.x509_extensions)
217210

218-
@override_tmpcadir()
219-
def test_cn_in_san(self) -> None:
220-
"""Test writing the common name into the SAN."""
221-
ca = self.load_ca(name="root", parsed=CERT_DATA["root"]["pub"]["parsed"])
222-
csr = CERT_DATA["child-cert"]["csr"]["parsed"]
223-
224-
prof = Profile("example", subject=False, add_issuer_alternative_name=False, cn_in_san=False)
225-
with self.mockSignal(pre_sign_cert) as pre:
226-
cert = self.create_cert(prof, ca, csr, subject=self.subject)
227-
self.assertEqual(pre.call_count, 1)
228-
self.assertEqual(cert.subject, self.subject)
229-
self.assertExtensions(cert, [ca.get_authority_key_identifier_extension()])
230-
231-
# Create the same cert, but pass cn_in_san=True to create_cert
232-
with self.mockSignal(pre_sign_cert) as pre:
233-
cert = self.create_cert(prof, ca, csr, subject=self.subject, cn_in_san=True)
234-
self.assertEqual(pre.call_count, 1)
235-
self.assertEqual(cert.subject, self.subject)
236-
self.assertExtensions(
237-
cert,
238-
[ca.get_authority_key_identifier_extension(), subject_alternative_name(dns(self.hostname))],
239-
)
240-
241-
# test that cn_in_san=True with a SAN that already contains the CN does not lead to a duplicate
242-
with self.mockSignal(pre_sign_cert) as pre:
243-
cert = self.create_cert(
244-
prof,
245-
ca,
246-
csr,
247-
subject=self.subject,
248-
cn_in_san=True,
249-
extensions=[subject_alternative_name(dns(self.hostname))],
250-
)
251-
self.assertEqual(pre.call_count, 1)
252-
self.assertEqual(cert.subject, self.subject)
253-
self.assertExtensions(
254-
cert,
255-
[ca.get_authority_key_identifier_extension(), subject_alternative_name(dns(self.hostname))],
256-
)
257-
258-
# test that cn_in_san=True with a SAN that does NOT yet contain the CN, so it's added
259-
with self.mockSignal(pre_sign_cert) as pre:
260-
cert = self.create_cert(
261-
prof,
262-
ca,
263-
csr,
264-
subject=self.subject,
265-
cn_in_san=True,
266-
extensions=[subject_alternative_name(dns(self.hostname + ".added"))],
267-
)
268-
self.assertEqual(pre.call_count, 1)
269-
self.assertEqual(cert.subject, self.subject)
270-
self.assertExtensions(
271-
cert,
272-
[
273-
ca.get_authority_key_identifier_extension(),
274-
subject_alternative_name(dns(self.hostname + ".added"), dns(self.hostname)),
275-
],
276-
)
277-
278-
# test that the first SAN is added as CN if we don't have A CN
279-
with self.mockSignal(pre_sign_cert) as pre:
280-
cert = self.create_cert(
281-
prof, ca, csr, cn_in_san=True, extensions=[subject_alternative_name(dns(self.hostname))]
282-
)
283-
self.assertEqual(pre.call_count, 1)
284-
self.assertEqual(cert.subject, self.subject)
285-
self.assertExtensions(
286-
cert,
287-
[ca.get_authority_key_identifier_extension(), subject_alternative_name(dns(self.hostname))],
288-
)
289-
290211
@override_tmpcadir()
291212
def test_override_ski(self) -> None:
292213
"""Test overriding the subject key identifier."""
@@ -314,12 +235,7 @@ def test_override_ski(self) -> None:
314235
self.assertEqual(pre.call_count, 1)
315236
self.assertExtensions(
316237
cert,
317-
[
318-
ca.get_authority_key_identifier_extension(),
319-
basic_constraints(),
320-
subject_alternative_name(dns(self.hostname)),
321-
ski,
322-
],
238+
[ca.get_authority_key_identifier_extension(), basic_constraints(), ski],
323239
expect_defaults=False,
324240
)
325241

@@ -357,7 +273,6 @@ def test_add_distribution_point_with_ca_crldp(self) -> None:
357273
ca.get_authority_key_identifier_extension(),
358274
basic_constraints(),
359275
x509.Extension(oid=ExtensionOID.SUBJECT_KEY_IDENTIFIER, critical=False, value=ski),
360-
subject_alternative_name(dns(self.hostname)),
361276
added_crldp,
362277
],
363278
expect_defaults=False,
@@ -422,7 +337,6 @@ def test_issuer_alternative_name_override(self) -> None:
422337
ca.get_authority_key_identifier_extension(),
423338
basic_constraints(),
424339
x509.Extension(oid=ExtensionOID.SUBJECT_KEY_IDENTIFIER, critical=False, value=ski),
425-
subject_alternative_name(dns(self.hostname)),
426340
issuer_alternative_name(added_ian_uri),
427341
],
428342
expect_defaults=False,
@@ -468,7 +382,6 @@ def test_merge_authority_information_access_existing_values(self) -> None:
468382
ca.get_authority_key_identifier_extension(),
469383
basic_constraints(),
470384
x509.Extension(oid=ExtensionOID.SUBJECT_KEY_IDENTIFIER, critical=False, value=ski),
471-
subject_alternative_name(dns(self.hostname)),
472385
authority_information_access(
473386
ca_issuers=[cert_issuers, cert_issuers2],
474387
ocsp=[cert_ocsp],
@@ -496,12 +409,7 @@ def test_extension_as_cryptography(self) -> None:
496409
self.assertEqual(pre.call_count, 1)
497410
self.assertExtensions(
498411
cert,
499-
[
500-
ca.get_authority_key_identifier_extension(),
501-
basic_constraints(),
502-
ocsp_no_check(),
503-
subject_alternative_name(dns(self.hostname)),
504-
],
412+
[ca.get_authority_key_identifier_extension(), basic_constraints(), ocsp_no_check()],
505413
)
506414

507415
@override_tmpcadir()
@@ -643,22 +551,9 @@ def test_no_valid_cn_in_san(self) -> None:
643551
san = subject_alternative_name(x509.RegisteredID(ExtensionOID.OCSP_NO_CHECK))
644552

645553
with self.mockSignal(pre_sign_cert) as pre:
646-
self.create_cert(prof, ca, csr, cn_in_san=True, extensions=[san])
554+
self.create_cert(prof, ca, csr, extensions=[san])
647555
self.assertEqual(pre.call_count, 1)
648556

649-
@override_tmpcadir()
650-
def test_unparsable_cn(self) -> None:
651-
"""Try creating a profile with an unparsable Common Name."""
652-
ca = self.load_ca(name="root", parsed=CERT_DATA["root"]["pub"]["parsed"])
653-
csr = CERT_DATA["child-cert"]["csr"]["parsed"]
654-
cname = "foo bar"
655-
656-
prof = Profile("example", subject=x509.Name([x509.NameAttribute(x509.NameOID.COMMON_NAME, cname)]))
657-
msg = rf"^{cname}: Could not parse CommonName as subjectAlternativeName\.$"
658-
with self.mockSignal(pre_sign_cert) as pre, self.assertRaisesRegex(ValueError, msg):
659-
self.create_cert(prof, ca, csr)
660-
self.assertEqual(pre.call_count, 0)
661-
662557
def test_unknown_signature_hash_algorithm(self) -> None:
663558
"""Test passing an unknown hash algorithm."""
664559
with self.assertRaisesRegex(ValueError, r"^foo: Unknown hash algorithm\.$"):

0 commit comments

Comments
 (0)