swarmauri_certs_self_signed 0.3.0.dev5__tar.gz → 0.11.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/PKG-INFO +15 -14
- {swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/README.md +8 -9
- {swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/pyproject.toml +7 -6
- {swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/swarmauri_certs_self_signed/SelfSignedCertificate.py +74 -24
- {swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/LICENSE +0 -0
- {swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/swarmauri_certs_self_signed/__init__.py +0 -0
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: swarmauri_certs_self_signed
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0.dev2
|
|
4
4
|
Summary: Self-signed certificate builder for Swarmauri
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: swarmauri,sdk,standards,certs,self,signed,certificates,self-signed-certificates,certificate-builder,development-certificates,x509-format
|
|
8
8
|
Author: Jacob Stewart
|
|
9
9
|
Author-email: jacob@swarmauri.com
|
|
10
|
-
Requires-Python: >=3.10,<3.
|
|
10
|
+
Requires-Python: >=3.10,<3.15
|
|
11
11
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
12
|
Classifier: Natural Language :: English
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
17
13
|
Classifier: Development Status :: 3 - Alpha
|
|
18
14
|
Classifier: Topic :: Security :: Cryptography
|
|
19
15
|
Classifier: Intended Audience :: Developers
|
|
20
16
|
Classifier: Programming Language :: Python
|
|
21
17
|
Classifier: Programming Language :: Python :: 3
|
|
22
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
24
|
Provides-Extra: ocsp
|
|
24
25
|
Requires-Dist: cryptography
|
|
25
26
|
Requires-Dist: pyopenssl ; extra == "ocsp"
|
|
@@ -27,23 +28,21 @@ Requires-Dist: swarmauri_base
|
|
|
27
28
|
Requires-Dist: swarmauri_core
|
|
28
29
|
Description-Content-Type: text/markdown
|
|
29
30
|
|
|
30
|
-

|
|
32
32
|
|
|
33
33
|
<p align="center">
|
|
34
|
-
<a href="https://
|
|
35
|
-
<img src="https://
|
|
34
|
+
<a href="https://pepy.tech/project/swarmauri_certs_self_signed/">
|
|
35
|
+
<img src="https://static.pepy.tech/badge/swarmauri_certs_self_signed/month" alt="PyPI - Downloads"/></a>
|
|
36
36
|
<a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_certs_self_signed/">
|
|
37
37
|
<img alt="Hits" src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_certs_self_signed.svg"/></a>
|
|
38
38
|
<a href="https://pypi.org/project/swarmauri_certs_self_signed/">
|
|
39
|
-
<img src="https://img.shields.io/
|
|
39
|
+
<img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue" alt="PyPI - Python Version"/></a>
|
|
40
40
|
<a href="https://pypi.org/project/swarmauri_certs_self_signed/">
|
|
41
41
|
<img src="https://img.shields.io/pypi/l/swarmauri_certs_self_signed" alt="PyPI - License"/></a>
|
|
42
42
|
<a href="https://pypi.org/project/swarmauri_certs_self_signed/">
|
|
43
43
|
<img src="https://img.shields.io/pypi/v/swarmauri_certs_self_signed?label=swarmauri_certs_self_signed&color=green" alt="PyPI - swarmauri_certs_self_signed"/></a>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
---
|
|
44
|
+
<a href="https://discord.gg/N4UpBuQv8T">
|
|
45
|
+
<img src="https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white" alt="Discord"/></a></p>
|
|
47
46
|
|
|
48
47
|
# Swarmauri Self-Signed Certificate Builder
|
|
49
48
|
|
|
@@ -123,3 +122,5 @@ This package registers `SelfSignedCertificate` under both the `swarmauri.cert_se
|
|
|
123
122
|
If you want to contribute to swarmauri-sdk, read up on our
|
|
124
123
|
[guidelines for contributing](https://github.com/swarmauri/swarmauri-sdk/blob/master/CONTRIBUTING.md)
|
|
125
124
|
that will help you get started.
|
|
125
|
+
|
|
126
|
+
|
{swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/README.md
RENAMED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-

|
|
3
2
|
|
|
4
3
|
<p align="center">
|
|
5
|
-
<a href="https://
|
|
6
|
-
<img src="https://
|
|
4
|
+
<a href="https://pepy.tech/project/swarmauri_certs_self_signed/">
|
|
5
|
+
<img src="https://static.pepy.tech/badge/swarmauri_certs_self_signed/month" alt="PyPI - Downloads"/></a>
|
|
7
6
|
<a href="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_certs_self_signed/">
|
|
8
7
|
<img alt="Hits" src="https://hits.sh/github.com/swarmauri/swarmauri-sdk/tree/master/pkgs/standards/swarmauri_certs_self_signed.svg"/></a>
|
|
9
8
|
<a href="https://pypi.org/project/swarmauri_certs_self_signed/">
|
|
10
|
-
<img src="https://img.shields.io/
|
|
9
|
+
<img src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-blue" alt="PyPI - Python Version"/></a>
|
|
11
10
|
<a href="https://pypi.org/project/swarmauri_certs_self_signed/">
|
|
12
11
|
<img src="https://img.shields.io/pypi/l/swarmauri_certs_self_signed" alt="PyPI - License"/></a>
|
|
13
12
|
<a href="https://pypi.org/project/swarmauri_certs_self_signed/">
|
|
14
13
|
<img src="https://img.shields.io/pypi/v/swarmauri_certs_self_signed?label=swarmauri_certs_self_signed&color=green" alt="PyPI - swarmauri_certs_self_signed"/></a>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
---
|
|
14
|
+
<a href="https://discord.gg/N4UpBuQv8T">
|
|
15
|
+
<img src="https://img.shields.io/badge/Discord-Join%20Chat-5865F2?logo=discord&logoColor=white" alt="Discord"/></a></p>
|
|
18
16
|
|
|
19
17
|
# Swarmauri Self-Signed Certificate Builder
|
|
20
18
|
|
|
@@ -93,4 +91,5 @@ This package registers `SelfSignedCertificate` under both the `swarmauri.cert_se
|
|
|
93
91
|
|
|
94
92
|
If you want to contribute to swarmauri-sdk, read up on our
|
|
95
93
|
[guidelines for contributing](https://github.com/swarmauri/swarmauri-sdk/blob/master/CONTRIBUTING.md)
|
|
96
|
-
that will help you get started.
|
|
94
|
+
that will help you get started.
|
|
95
|
+
|
{swarmauri_certs_self_signed-0.3.0.dev5 → swarmauri_certs_self_signed-0.11.0.dev2}/pyproject.toml
RENAMED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "swarmauri_certs_self_signed"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.11.0.dev2"
|
|
4
4
|
description = "Self-signed certificate builder for Swarmauri"
|
|
5
5
|
license = "Apache-2.0"
|
|
6
6
|
readme = "README.md"
|
|
7
|
-
requires-python = ">=3.10,<3.
|
|
7
|
+
requires-python = ">=3.10,<3.15"
|
|
8
8
|
authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
|
|
9
9
|
classifiers = [
|
|
10
10
|
"License :: OSI Approved :: Apache Software License",
|
|
11
11
|
"Natural Language :: English",
|
|
12
|
-
"Programming Language :: Python :: 3.10",
|
|
13
|
-
"Programming Language :: Python :: 3.11",
|
|
14
|
-
"Programming Language :: Python :: 3.12",
|
|
15
|
-
"Programming Language :: Python :: 3.13",
|
|
16
12
|
"Development Status :: 3 - Alpha",
|
|
17
13
|
"Topic :: Security :: Cryptography",
|
|
18
14
|
"Intended Audience :: Developers",
|
|
19
15
|
"Programming Language :: Python",
|
|
20
16
|
"Programming Language :: Python :: 3",
|
|
21
17
|
"Programming Language :: Python :: 3 :: Only",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
22
23
|
]
|
|
23
24
|
dependencies = [
|
|
24
25
|
"swarmauri_core",
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import ipaddress
|
|
3
4
|
from datetime import datetime, timedelta, timezone
|
|
4
5
|
from typing import Any, Dict, Iterable, Mapping, Optional, Sequence
|
|
5
6
|
|
|
@@ -39,15 +40,21 @@ def _name_from_subject(spec: SubjectSpec) -> x509.Name:
|
|
|
39
40
|
if "C" in spec and spec["C"]:
|
|
40
41
|
rdns.append(x509.NameAttribute(NameOID.COUNTRY_NAME, spec["C"]))
|
|
41
42
|
if "ST" in spec and spec["ST"]:
|
|
42
|
-
rdns.append(
|
|
43
|
+
rdns.append(
|
|
44
|
+
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, spec["ST"])
|
|
45
|
+
)
|
|
43
46
|
if "L" in spec and spec["L"]:
|
|
44
47
|
rdns.append(x509.NameAttribute(NameOID.LOCALITY_NAME, spec["L"]))
|
|
45
48
|
if "O" in spec and spec["O"]:
|
|
46
49
|
rdns.append(x509.NameAttribute(NameOID.ORGANIZATION_NAME, spec["O"]))
|
|
47
50
|
if "OU" in spec and spec["OU"]:
|
|
48
|
-
rdns.append(
|
|
51
|
+
rdns.append(
|
|
52
|
+
x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, spec["OU"])
|
|
53
|
+
)
|
|
49
54
|
if "emailAddress" in spec and spec["emailAddress"]:
|
|
50
|
-
rdns.append(
|
|
55
|
+
rdns.append(
|
|
56
|
+
x509.NameAttribute(NameOID.EMAIL_ADDRESS, spec["emailAddress"])
|
|
57
|
+
)
|
|
51
58
|
if "CN" in spec and spec["CN"]:
|
|
52
59
|
rdns.append(x509.NameAttribute(NameOID.COMMON_NAME, spec["CN"]))
|
|
53
60
|
|
|
@@ -57,21 +64,25 @@ def _name_from_subject(spec: SubjectSpec) -> x509.Name:
|
|
|
57
64
|
continue
|
|
58
65
|
rdns.append(
|
|
59
66
|
x509.NameAttribute(
|
|
60
|
-
x509.ObjectIdentifier(k)
|
|
67
|
+
x509.ObjectIdentifier(k)
|
|
68
|
+
if k.count(".") >= 2
|
|
69
|
+
else NameOID.COMMON_NAME,
|
|
61
70
|
v,
|
|
62
71
|
)
|
|
63
72
|
)
|
|
64
73
|
return x509.Name(rdns)
|
|
65
74
|
|
|
66
75
|
|
|
67
|
-
def _san_from_spec(
|
|
76
|
+
def _san_from_spec(
|
|
77
|
+
san: Optional[AltNameSpec],
|
|
78
|
+
) -> Optional[x509.SubjectAlternativeName]:
|
|
68
79
|
if not san:
|
|
69
80
|
return None
|
|
70
81
|
gns = []
|
|
71
82
|
for d in san.get("dns") or []:
|
|
72
83
|
gns.append(x509.DNSName(d))
|
|
73
84
|
for ip in san.get("ip") or []:
|
|
74
|
-
gns.append(x509.IPAddress(
|
|
85
|
+
gns.append(x509.IPAddress(ipaddress.ip_address(ip)))
|
|
75
86
|
for uri in san.get("uri") or []:
|
|
76
87
|
gns.append(x509.UniformResourceIdentifier(uri))
|
|
77
88
|
for email in san.get("email") or []:
|
|
@@ -120,7 +131,9 @@ def _bc_from_spec(
|
|
|
120
131
|
|
|
121
132
|
|
|
122
133
|
def _choose_sig_hash(private_key) -> Optional[hashes.HashAlgorithm]:
|
|
123
|
-
if isinstance(
|
|
134
|
+
if isinstance(
|
|
135
|
+
private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)
|
|
136
|
+
):
|
|
124
137
|
return None
|
|
125
138
|
return hashes.SHA256()
|
|
126
139
|
|
|
@@ -129,7 +142,9 @@ def _choose_sig_hash(private_key) -> Optional[hashes.HashAlgorithm]:
|
|
|
129
142
|
class SelfSignedCertificate(CertServiceBase):
|
|
130
143
|
"""Minimal self-signed certificate builder exposed as a cert service."""
|
|
131
144
|
|
|
132
|
-
subject: SubjectSpec = Field(
|
|
145
|
+
subject: SubjectSpec = Field(
|
|
146
|
+
default_factory=lambda: SubjectSpec(CN="localhost")
|
|
147
|
+
)
|
|
133
148
|
san: Optional[AltNameSpec] = None
|
|
134
149
|
extensions: Optional[CertExtensionSpec] = None
|
|
135
150
|
not_before: Optional[int] = None
|
|
@@ -163,7 +178,10 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
163
178
|
) -> bytes:
|
|
164
179
|
if key.material is None:
|
|
165
180
|
raise ValueError(
|
|
166
|
-
|
|
181
|
+
(
|
|
182
|
+
"Self-signed issuance requires a private key in "
|
|
183
|
+
"KeyRef.material (PEM)."
|
|
184
|
+
)
|
|
167
185
|
)
|
|
168
186
|
|
|
169
187
|
pwd = password if password is not None else self.password
|
|
@@ -178,7 +196,9 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
178
196
|
else key.tags["passphrase"]
|
|
179
197
|
)
|
|
180
198
|
|
|
181
|
-
private_key = serialization.load_pem_private_key(
|
|
199
|
+
private_key = serialization.load_pem_private_key(
|
|
200
|
+
key.material, password=pwd
|
|
201
|
+
)
|
|
182
202
|
public_key = private_key.public_key()
|
|
183
203
|
|
|
184
204
|
subject_spec = subject or self.subject
|
|
@@ -196,11 +216,17 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
196
216
|
if na_epoch is not None:
|
|
197
217
|
na = datetime.fromtimestamp(int(na_epoch), tz=timezone.utc)
|
|
198
218
|
else:
|
|
199
|
-
life =
|
|
219
|
+
life = (
|
|
220
|
+
lifetime_days
|
|
221
|
+
if lifetime_days is not None
|
|
222
|
+
else self.lifetime_days
|
|
223
|
+
)
|
|
200
224
|
na = nb + timedelta(days=int(life))
|
|
201
225
|
|
|
202
226
|
serial_number = (
|
|
203
|
-
serial
|
|
227
|
+
serial
|
|
228
|
+
if serial is not None
|
|
229
|
+
else self.serial or x509.random_serial_number()
|
|
204
230
|
)
|
|
205
231
|
|
|
206
232
|
builder = (
|
|
@@ -215,7 +241,11 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
215
241
|
|
|
216
242
|
ext_spec = extensions if extensions is not None else self.extensions
|
|
217
243
|
|
|
218
|
-
bc =
|
|
244
|
+
bc = (
|
|
245
|
+
_bc_from_spec(ext_spec.get("basic_constraints"))
|
|
246
|
+
if ext_spec
|
|
247
|
+
else None
|
|
248
|
+
)
|
|
219
249
|
if bc:
|
|
220
250
|
builder = builder.add_extension(bc, critical=True)
|
|
221
251
|
|
|
@@ -223,7 +253,11 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
223
253
|
if ku:
|
|
224
254
|
builder = builder.add_extension(ku, critical=True)
|
|
225
255
|
|
|
226
|
-
eku =
|
|
256
|
+
eku = (
|
|
257
|
+
_eku_from_spec(ext_spec.get("extended_key_usage"))
|
|
258
|
+
if ext_spec
|
|
259
|
+
else None
|
|
260
|
+
)
|
|
227
261
|
if eku:
|
|
228
262
|
builder = builder.add_extension(eku, critical=False)
|
|
229
263
|
|
|
@@ -243,16 +277,20 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
243
277
|
|
|
244
278
|
if ext_spec and ext_spec.get("name_constraints"):
|
|
245
279
|
nc = ext_spec["name_constraints"]
|
|
246
|
-
permitted_dns = [
|
|
247
|
-
|
|
280
|
+
permitted_dns = [
|
|
281
|
+
x509.DNSName(d) for d in (nc.get("permitted_dns") or [])
|
|
282
|
+
]
|
|
283
|
+
excluded_dns = [
|
|
284
|
+
x509.DNSName(d) for d in (nc.get("excluded_dns") or [])
|
|
285
|
+
]
|
|
248
286
|
permitted_ip = [
|
|
249
|
-
x509.IPAddress(
|
|
287
|
+
x509.IPAddress(ipaddress.ip_network(ip))
|
|
250
288
|
for ip in (nc.get("permitted_ip") or [])
|
|
251
|
-
]
|
|
289
|
+
]
|
|
252
290
|
excluded_ip = [
|
|
253
|
-
x509.IPAddress(
|
|
291
|
+
x509.IPAddress(ipaddress.ip_network(ip))
|
|
254
292
|
for ip in (nc.get("excluded_ip") or [])
|
|
255
|
-
]
|
|
293
|
+
]
|
|
256
294
|
permitted_uri = [
|
|
257
295
|
x509.UniformResourceIdentifier(u)
|
|
258
296
|
for u in (nc.get("permitted_uri") or [])
|
|
@@ -271,11 +309,17 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
271
309
|
builder = builder.add_extension(
|
|
272
310
|
x509.NameConstraints(
|
|
273
311
|
permitted_subtrees=(
|
|
274
|
-
permitted_dns
|
|
312
|
+
permitted_dns
|
|
313
|
+
+ permitted_ip
|
|
314
|
+
+ permitted_uri
|
|
315
|
+
+ permitted_email
|
|
275
316
|
)
|
|
276
317
|
or None,
|
|
277
318
|
excluded_subtrees=(
|
|
278
|
-
excluded_dns
|
|
319
|
+
excluded_dns
|
|
320
|
+
+ excluded_ip
|
|
321
|
+
+ excluded_uri
|
|
322
|
+
+ excluded_email
|
|
279
323
|
)
|
|
280
324
|
or None,
|
|
281
325
|
),
|
|
@@ -350,7 +394,10 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
350
394
|
subject_alt_name=san,
|
|
351
395
|
)
|
|
352
396
|
return cls(
|
|
353
|
-
subject=subject,
|
|
397
|
+
subject=subject,
|
|
398
|
+
san=san,
|
|
399
|
+
extensions=ext,
|
|
400
|
+
lifetime_days=lifetime_days,
|
|
354
401
|
)
|
|
355
402
|
|
|
356
403
|
@classmethod
|
|
@@ -379,5 +426,8 @@ class SelfSignedCertificate(CertServiceBase):
|
|
|
379
426
|
subject_alt_name=san,
|
|
380
427
|
)
|
|
381
428
|
return cls(
|
|
382
|
-
subject=subject,
|
|
429
|
+
subject=subject,
|
|
430
|
+
san=san,
|
|
431
|
+
extensions=ext,
|
|
432
|
+
lifetime_days=lifetime_days,
|
|
383
433
|
)
|
|
File without changes
|