cert-utils 1.2.0__py3-none-any.whl

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.
Files changed (79) hide show
  1. cert_utils/__init__.py +8 -0
  2. cert_utils/compat/__init__.py +0 -0
  3. cert_utils/compat/cryptography.py +172 -0
  4. cert_utils/compat/openssl.py +860 -0
  5. cert_utils/compat/pyopenssl.py +207 -0
  6. cert_utils/compat/signatures.py +114 -0
  7. cert_utils/conditionals.py +121 -0
  8. cert_utils/convert.py +307 -0
  9. cert_utils/core.py +3075 -0
  10. cert_utils/errors.py +54 -0
  11. cert_utils/letsencrypt-certs/deprecated/e5-cross.pem +26 -0
  12. cert_utils/letsencrypt-certs/deprecated/e5.pem +17 -0
  13. cert_utils/letsencrypt-certs/deprecated/e6-cross.pem +26 -0
  14. cert_utils/letsencrypt-certs/deprecated/e6.pem +17 -0
  15. cert_utils/letsencrypt-certs/deprecated/e7-cross.pem +26 -0
  16. cert_utils/letsencrypt-certs/deprecated/e7.pem +17 -0
  17. cert_utils/letsencrypt-certs/deprecated/e8-cross.pem +26 -0
  18. cert_utils/letsencrypt-certs/deprecated/e8.pem +17 -0
  19. cert_utils/letsencrypt-certs/deprecated/e9-cross.pem +26 -0
  20. cert_utils/letsencrypt-certs/deprecated/e9.pem +17 -0
  21. cert_utils/letsencrypt-certs/deprecated/fakeleintermediatex1.pem +28 -0
  22. cert_utils/letsencrypt-certs/deprecated/fakelerootx1.pem +29 -0
  23. cert_utils/letsencrypt-certs/deprecated/isrg-root-ocsp-x1.pem +28 -0
  24. cert_utils/letsencrypt-certs/deprecated/isrg-root-x1-cross-signed.pem +31 -0
  25. cert_utils/letsencrypt-certs/deprecated/isrg-root-x2-cross-signed.pem +26 -0
  26. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-e1.pem +17 -0
  27. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-e2.pem +17 -0
  28. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r3-cross-signed.pem +26 -0
  29. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r3.pem +30 -0
  30. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r4-cross-signed.pem +26 -0
  31. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-r4.pem +30 -0
  32. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x1-cross-signed.pem +27 -0
  33. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x2-cross-signed.pem +27 -0
  34. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x3-cross-signed.pem +27 -0
  35. cert_utils/letsencrypt-certs/deprecated/lets-encrypt-x4-cross-signed.pem +27 -0
  36. cert_utils/letsencrypt-certs/deprecated/letsencrypt-stg-root-x2-signed-by-x1.pem +27 -0
  37. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx1.pem +32 -0
  38. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx2.pem +32 -0
  39. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx3.pem +32 -0
  40. cert_utils/letsencrypt-certs/deprecated/letsencryptauthorityx4.pem +32 -0
  41. cert_utils/letsencrypt-certs/deprecated/r10.pem +29 -0
  42. cert_utils/letsencrypt-certs/deprecated/r11.pem +29 -0
  43. cert_utils/letsencrypt-certs/deprecated/r12.pem +29 -0
  44. cert_utils/letsencrypt-certs/deprecated/r13.pem +29 -0
  45. cert_utils/letsencrypt-certs/deprecated/r14.pem +29 -0
  46. cert_utils/letsencrypt-certs/deprecated/trustid-x3-root.p7c +0 -0
  47. cert_utils/letsencrypt-certs/deprecated/trustid-x3-root.pem +20 -0
  48. cert_utils/letsencrypt-certs/int-ye1.pem +16 -0
  49. cert_utils/letsencrypt-certs/int-ye2.pem +16 -0
  50. cert_utils/letsencrypt-certs/int-ye3.pem +16 -0
  51. cert_utils/letsencrypt-certs/int-yr1.pem +28 -0
  52. cert_utils/letsencrypt-certs/int-yr2.pem +28 -0
  53. cert_utils/letsencrypt-certs/int-yr3.pem +28 -0
  54. cert_utils/letsencrypt-certs/isrg-root-x2.pem +14 -0
  55. cert_utils/letsencrypt-certs/isrgrootx1.pem +31 -0
  56. cert_utils/letsencrypt-certs/isrgrootx1.pkix +0 -0
  57. cert_utils/letsencrypt-certs/letsencrypt-stg-root-x1.pem +32 -0
  58. cert_utils/letsencrypt-certs/letsencrypt-stg-root-x2.pem +15 -0
  59. cert_utils/letsencrypt-certs/root-x2-by-x1.pem +26 -0
  60. cert_utils/letsencrypt-certs/root-ye-by-x2.pem +17 -0
  61. cert_utils/letsencrypt-certs/root-ye.pem +12 -0
  62. cert_utils/letsencrypt-certs/root-yr-by-x1.pem +34 -0
  63. cert_utils/letsencrypt-certs/root-yr.pem +30 -0
  64. cert_utils/letsencrypt_info/__init__.py +6 -0
  65. cert_utils/letsencrypt_info/certificates.py +1074 -0
  66. cert_utils/letsencrypt_info/rate_limits.py +414 -0
  67. cert_utils/letsencrypt_info/types.py +120 -0
  68. cert_utils/model.py +181 -0
  69. cert_utils/network.py +28 -0
  70. cert_utils/py.typed +0 -0
  71. cert_utils/scripts/__init__.py +0 -0
  72. cert_utils/scripts/cert_info.py +332 -0
  73. cert_utils/utils.py +388 -0
  74. cert_utils-1.2.0.dist-info/METADATA +259 -0
  75. cert_utils-1.2.0.dist-info/RECORD +79 -0
  76. cert_utils-1.2.0.dist-info/WHEEL +5 -0
  77. cert_utils-1.2.0.dist-info/entry_points.txt +2 -0
  78. cert_utils-1.2.0.dist-info/licenses/LICENSE.txt +224 -0
  79. cert_utils-1.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,414 @@
1
+ """Versioned public production policy snapshot, not a live quota counter.
2
+
3
+ Values are JSON-compatible. See docs/rate-limits.md for modelling decisions,
4
+ rounded refill figures, exemption boundaries and migration from schema 1.
5
+ Importing this module does not load the bundled CA certificates.
6
+ """
7
+
8
+ # local
9
+ from .types import Catalogue
10
+
11
+ RATE_LIMITS: Catalogue = {
12
+ "schema_version": 2,
13
+ "policy_environment": "production",
14
+ "source": {
15
+ "url": "https://letsencrypt.org/docs/rate-limits/",
16
+ "document_last_modified": "2026-08-05",
17
+ "checked_on": "2026-10-28",
18
+ "checkout": "bb7e7238",
19
+ "path": "content/en/docs/rate-limits.md",
20
+ },
21
+ "limits": {
22
+ "registrations_per_ip": {
23
+ "kind": "token_bucket",
24
+ "title": "New Registrations per IP Address",
25
+ "capacity": 10,
26
+ "unit": "account",
27
+ "scope": {
28
+ "dimensions": ["source_ip"],
29
+ "key_rules": {"source_ip": "exact IPv4 or IPv6 address"},
30
+ },
31
+ "nominal_window_seconds": 10800,
32
+ "refill": {
33
+ "tokens": 1,
34
+ "period_seconds": 1080,
35
+ "precision": "published",
36
+ },
37
+ "cost_per_event": 1,
38
+ "counted_event": "account_created",
39
+ "enforced_on": "new_account",
40
+ "renewal_exemptions": {
41
+ "ari_replacement": "not_applicable",
42
+ "same_identifier_set": "not_applicable",
43
+ },
44
+ "override_scopes": [],
45
+ "source_url": (
46
+ "https://letsencrypt.org/docs/rate-limits/#new-registrations-per-ip-address"
47
+ ),
48
+ },
49
+ "registrations_per_ipv6_range": {
50
+ "kind": "token_bucket",
51
+ "title": "New Registrations per IPv6 Range",
52
+ "capacity": 500,
53
+ "unit": "account",
54
+ "scope": {
55
+ "dimensions": ["source_ipv6_48"],
56
+ "key_rules": {
57
+ "source_ipv6_48": "IPv6 address masked to /48; additional to per-IP quota"
58
+ },
59
+ },
60
+ "nominal_window_seconds": 10800,
61
+ "refill": {
62
+ "tokens": 1,
63
+ "period_seconds": 22,
64
+ "precision": "published_rounded",
65
+ },
66
+ "cost_per_event": 1,
67
+ "counted_event": "account_created",
68
+ "enforced_on": "new_account",
69
+ "renewal_exemptions": {
70
+ "ari_replacement": "not_applicable",
71
+ "same_identifier_set": "not_applicable",
72
+ },
73
+ "override_scopes": [],
74
+ "source_url": (
75
+ "https://letsencrypt.org/docs/rate-limits/#new-registrations-per-ipv6-range"
76
+ ),
77
+ },
78
+ "orders_per_account": {
79
+ "kind": "token_bucket",
80
+ "title": "New Orders per Account",
81
+ "capacity": 300,
82
+ "unit": "order",
83
+ "scope": {"dimensions": ["account"], "key_rules": {}},
84
+ "nominal_window_seconds": 10800,
85
+ "refill": {
86
+ "tokens": 1,
87
+ "period_seconds": 36,
88
+ "precision": "published",
89
+ },
90
+ "cost_per_event": 1,
91
+ "counted_event": "order_created",
92
+ "enforced_on": "new_order",
93
+ "renewal_exemptions": {
94
+ "ari_replacement": "documented_exempt",
95
+ "same_identifier_set": "exempt",
96
+ },
97
+ "override_scopes": ["account"],
98
+ "source_url": (
99
+ "https://letsencrypt.org/docs/rate-limits/#new-orders-per-account"
100
+ ),
101
+ },
102
+ "certificates_per_registered_domain": {
103
+ "kind": "token_bucket",
104
+ "title": "New Certificates per Registered Domain",
105
+ "capacity": 50,
106
+ "unit": "certificate",
107
+ "scope": {
108
+ "dimensions": ["registered_domain_or_ip_range"],
109
+ "key_rules": {
110
+ "dns": (
111
+ "Public Suffix List registered "
112
+ "domain; not simply the last two labels"
113
+ ),
114
+ "ipv4": "exact address",
115
+ "ipv6": "/64 network",
116
+ "sharing": "global across accounts",
117
+ "multi_identifier": "evaluate each distinct registered-domain/IP-range bucket",
118
+ },
119
+ },
120
+ "nominal_window_seconds": 604800,
121
+ "refill": {
122
+ "tokens": 1,
123
+ "period_seconds": 12120,
124
+ "precision": "published_rounded",
125
+ },
126
+ "cost_per_event": 1,
127
+ "counted_event": "certificate_issued",
128
+ "enforced_on": "new_order",
129
+ "renewal_exemptions": {
130
+ "ari_replacement": "documented_exempt",
131
+ "same_identifier_set": "exempt",
132
+ },
133
+ "override_scopes": ["registered_domain", "account"],
134
+ "source_url": (
135
+ "https://letsencrypt.org/docs/rate-limits/#new-certificates-per-registered-domain"
136
+ ),
137
+ },
138
+ "certificates_per_exact_identifier_set": {
139
+ "kind": "token_bucket",
140
+ "title": "New Certificates per Exact Set of Identifiers",
141
+ "capacity": 5,
142
+ "unit": "certificate",
143
+ "scope": {
144
+ "dimensions": ["identifier_set"],
145
+ "key_rules": {
146
+ "normalization": "case-insensitive and order-independent identifiers",
147
+ "sharing": "global across accounts",
148
+ "ip_canonicalization": (
149
+ "not specified by this source; do "
150
+ "not infer string equivalence rules"
151
+ ),
152
+ },
153
+ },
154
+ "nominal_window_seconds": 604800,
155
+ "refill": {
156
+ "tokens": 1,
157
+ "period_seconds": 122400,
158
+ "precision": "published_rounded",
159
+ },
160
+ "cost_per_event": 1,
161
+ "counted_event": "certificate_issued",
162
+ "enforced_on": "new_order",
163
+ "renewal_exemptions": {
164
+ "ari_replacement": "documented_exempt",
165
+ "same_identifier_set": "not_exempt",
166
+ },
167
+ "override_scopes": [],
168
+ "source_url": (
169
+ "https://letsencrypt.org/docs/rate-limits/#new-certificates-per-exact-set-of-identifiers"
170
+ ),
171
+ },
172
+ "authorization_failures_per_identifier_account": {
173
+ "kind": "token_bucket",
174
+ "title": "Authorization Failures per Identifier per Account",
175
+ "capacity": 5,
176
+ "unit": "failure",
177
+ "scope": {
178
+ "dimensions": ["account", "identifier"],
179
+ "key_rules": {"identifier": "DNS name or IP address"},
180
+ },
181
+ "nominal_window_seconds": 3600,
182
+ "refill": {
183
+ "tokens": 1,
184
+ "period_seconds": 720,
185
+ "precision": "published",
186
+ },
187
+ "cost_per_event": 1,
188
+ "counted_event": "authorization_failed",
189
+ "enforced_on": "new_order",
190
+ "renewal_exemptions": {
191
+ "ari_replacement": "documented_exempt",
192
+ "same_identifier_set": "not_exempt",
193
+ },
194
+ "override_scopes": [],
195
+ "source_url": (
196
+ "https://letsencrypt.org/docs/rate-limits/#authorization-failures-per-identifier-per-account"
197
+ ),
198
+ },
199
+ "consecutive_authorization_failures": {
200
+ "kind": "consecutive_failure_guard",
201
+ "title": (
202
+ "Consecutive Authorization " "Failures per Identifier per Account"
203
+ ),
204
+ "capacity": 1152,
205
+ "unit": "failure",
206
+ "scope": {
207
+ "dimensions": ["account", "identifier"],
208
+ "key_rules": {"identifier": "DNS name or IP address"},
209
+ },
210
+ "nominal_window_seconds": None,
211
+ "refill": {
212
+ "tokens": 1,
213
+ "period_seconds": 86400,
214
+ "precision": "published",
215
+ },
216
+ "cost_per_event": 1,
217
+ "counted_event": "consecutive_authorization_failed",
218
+ "enforced_on": "new_order",
219
+ "renewal_exemptions": {
220
+ "ari_replacement": "documented_exempt",
221
+ "same_identifier_set": "not_exempt",
222
+ },
223
+ "override_scopes": [],
224
+ "source_url": (
225
+ "https://letsencrypt.org/docs/rate-limits/#consecutive-authorization-failures-per-identifier-per-account"
226
+ ),
227
+ "reset_on": "authorization_succeeded",
228
+ "exhaustion_action": "identifier_issuance_paused",
229
+ "recovery": (
230
+ "self_service_unpause_link; automatic "
231
+ "unpause semantics not specified"
232
+ ),
233
+ },
234
+ },
235
+ "endpoints": {
236
+ "/acme/new-nonce": {
237
+ "kind": "endpoint_bucket",
238
+ "unit": "request",
239
+ "cost_per_event": 1,
240
+ "scope": ["source_ip"],
241
+ "refill": {
242
+ "tokens": 20,
243
+ "period_seconds": 1,
244
+ "precision": "published",
245
+ },
246
+ "capacity": 10,
247
+ "exhaustion_http_status": 503,
248
+ "retry_after_header": True,
249
+ "source_url": (
250
+ "https://letsencrypt.org/docs/rate-limits/#overall-requests-limit"
251
+ ),
252
+ },
253
+ "/acme/new-account": {
254
+ "kind": "endpoint_bucket",
255
+ "unit": "request",
256
+ "cost_per_event": 1,
257
+ "scope": ["source_ip"],
258
+ "refill": {
259
+ "tokens": 5,
260
+ "period_seconds": 1,
261
+ "precision": "published",
262
+ },
263
+ "capacity": 15,
264
+ "exhaustion_http_status": 503,
265
+ "retry_after_header": True,
266
+ "source_url": (
267
+ "https://letsencrypt.org/docs/rate-limits/#overall-requests-limit"
268
+ ),
269
+ },
270
+ "/acme/new-order": {
271
+ "kind": "endpoint_bucket",
272
+ "unit": "request",
273
+ "cost_per_event": 1,
274
+ "scope": ["source_ip"],
275
+ "refill": {
276
+ "tokens": 300,
277
+ "period_seconds": 1,
278
+ "precision": "published",
279
+ },
280
+ "capacity": 200,
281
+ "exhaustion_http_status": 503,
282
+ "retry_after_header": True,
283
+ "source_url": (
284
+ "https://letsencrypt.org/docs/rate-limits/#overall-requests-limit"
285
+ ),
286
+ },
287
+ "/acme/revoke-cert": {
288
+ "kind": "endpoint_bucket",
289
+ "unit": "request",
290
+ "cost_per_event": 1,
291
+ "scope": ["source_ip"],
292
+ "refill": {
293
+ "tokens": 10,
294
+ "period_seconds": 1,
295
+ "precision": "published",
296
+ },
297
+ "capacity": 100,
298
+ "exhaustion_http_status": 503,
299
+ "retry_after_header": True,
300
+ "source_url": (
301
+ "https://letsencrypt.org/docs/rate-limits/#overall-requests-limit"
302
+ ),
303
+ },
304
+ "/acme/renewal-info": {
305
+ "kind": "endpoint_bucket",
306
+ "unit": "request",
307
+ "cost_per_event": 1,
308
+ "scope": ["source_ip"],
309
+ "refill": {
310
+ "tokens": 1000,
311
+ "period_seconds": 1,
312
+ "precision": "published",
313
+ },
314
+ "capacity": 100,
315
+ "exhaustion_http_status": 503,
316
+ "retry_after_header": True,
317
+ "source_url": (
318
+ "https://letsencrypt.org/docs/rate-limits/#overall-requests-limit"
319
+ ),
320
+ },
321
+ "/acme/*": {
322
+ "kind": "endpoint_bucket",
323
+ "unit": "request",
324
+ "cost_per_event": 1,
325
+ "scope": ["source_ip"],
326
+ "refill": {
327
+ "tokens": 250,
328
+ "period_seconds": 1,
329
+ "precision": "published",
330
+ },
331
+ "capacity": 125,
332
+ "exhaustion_http_status": 503,
333
+ "retry_after_header": True,
334
+ "source_url": (
335
+ "https://letsencrypt.org/docs/rate-limits/#overall-requests-limit"
336
+ ),
337
+ },
338
+ "/directory": {
339
+ "kind": "endpoint_bucket",
340
+ "unit": "request",
341
+ "cost_per_event": 1,
342
+ "scope": ["source_ip"],
343
+ "refill": {
344
+ "tokens": 40,
345
+ "period_seconds": 1,
346
+ "precision": "published",
347
+ },
348
+ "capacity": 40,
349
+ "exhaustion_http_status": 503,
350
+ "retry_after_header": True,
351
+ "source_url": (
352
+ "https://letsencrypt.org/docs/rate-limits/#overall-requests-limit"
353
+ ),
354
+ },
355
+ },
356
+ "endpoint_matching": {
357
+ "patterns": "literal paths and /acme/* prefix pattern",
358
+ "overlap_policy": (
359
+ "not specified by source; do not " "assume precedence or additive buckets"
360
+ ),
361
+ "renewal_exemption": (
362
+ "transport/load-balancer applicability not "
363
+ "specified; do not disable request pacing for ARI"
364
+ ),
365
+ },
366
+ "constraints": {
367
+ "identifiers_per_certificate": {
368
+ "kind": "profile_constraint",
369
+ "unit": "identifier",
370
+ "scope": ["certificate", "profile"],
371
+ "maximum_by_profile": {
372
+ "classic": 100,
373
+ "tlsserver": 25,
374
+ "shortlived": 25,
375
+ },
376
+ "source_url": "https://letsencrypt.org/docs/profiles/",
377
+ "checked_on": "2026-10-28",
378
+ }
379
+ },
380
+ "renewals": {
381
+ "ari_replacement": {
382
+ "conditions": [
383
+ "order explicitly replaces an existing certificate using ARI",
384
+ "at least one identifier overlaps the replaced certificate",
385
+ "certificate has not already been replaced using ARI",
386
+ ],
387
+ "exempt_from": (
388
+ "documented certificate-issuance rate "
389
+ "limits; not an arbitrary ARI-capable request"
390
+ ),
391
+ "server_decides_eligibility": True,
392
+ },
393
+ "same_identifier_set": {
394
+ "normalization": "ignore capitalization and identifier ordering",
395
+ "exempt_limit_ids": [
396
+ "orders_per_account",
397
+ "certificates_per_registered_domain",
398
+ ],
399
+ "other_limits": "still apply unless the server grants an exemption",
400
+ },
401
+ },
402
+ "retry_policy": {
403
+ "honor_retry_after": True,
404
+ "multiple_exhausted_limits": "wait until the latest applicable retry time",
405
+ "revocation_resets_quota": False,
406
+ "quota_is_shared": (
407
+ "local estimates cannot observe other "
408
+ "clients or account-specific overrides"
409
+ ),
410
+ },
411
+ }
412
+
413
+ # Public historical name, now explicitly schema version 2.
414
+ LIMITS = RATE_LIMITS
@@ -0,0 +1,120 @@
1
+ """Shared TypedDict definitions for certificate and rate-limit metadata."""
2
+
3
+ from typing import Dict
4
+ from typing import List
5
+ from typing import Optional
6
+ from typing import Tuple
7
+ from typing import Union
8
+
9
+ from typing_extensions import Literal
10
+ from typing_extensions import Required
11
+ from typing_extensions import TypedDict
12
+
13
+
14
+ class Source(TypedDict):
15
+ url: str
16
+ document_last_modified: str
17
+ checked_on: str
18
+ checkout: str
19
+ path: str
20
+
21
+
22
+ class Refill(TypedDict):
23
+ tokens: int
24
+ period_seconds: int
25
+ precision: str
26
+
27
+
28
+ class Scope(TypedDict):
29
+ dimensions: List[str]
30
+ key_rules: Dict[str, str]
31
+
32
+
33
+ class Limit(TypedDict, total=False):
34
+ kind: Required[Literal["token_bucket", "consecutive_failure_guard"]]
35
+ title: Required[str]
36
+ capacity: Required[int]
37
+ unit: Required[str]
38
+ scope: Required[Scope]
39
+ nominal_window_seconds: Required[Optional[int]]
40
+ refill: Required[Refill]
41
+ counted_event: Required[str]
42
+ cost_per_event: Required[int]
43
+ enforced_on: Required[str]
44
+ renewal_exemptions: Required[Dict[str, str]]
45
+ override_scopes: Required[List[str]]
46
+ source_url: Required[str]
47
+ reset_on: str
48
+ exhaustion_action: str
49
+ recovery: str
50
+
51
+
52
+ class Endpoint(TypedDict):
53
+ kind: str
54
+ unit: str
55
+ cost_per_event: int
56
+ scope: List[str]
57
+ refill: Refill
58
+ capacity: int
59
+ exhaustion_http_status: int
60
+ retry_after_header: bool
61
+ source_url: str
62
+
63
+
64
+ class Constraint(TypedDict):
65
+ kind: str
66
+ unit: str
67
+ scope: List[str]
68
+ maximum_by_profile: Dict[str, int]
69
+ source_url: str
70
+ checked_on: str
71
+
72
+
73
+ class Renewal(TypedDict, total=False):
74
+ conditions: List[str]
75
+ exempt_from: str
76
+ server_decides_eligibility: bool
77
+ normalization: str
78
+ exempt_limit_ids: List[str]
79
+ other_limits: str
80
+
81
+
82
+ class Catalogue(TypedDict):
83
+ schema_version: int
84
+ policy_environment: str
85
+ source: Source
86
+ limits: Dict[str, Limit]
87
+ endpoints: Dict[str, Endpoint]
88
+ endpoint_matching: Dict[str, str]
89
+ constraints: Dict[str, Constraint]
90
+ renewals: Dict[str, Renewal]
91
+ retry_policy: Dict[str, Union[str, bool]]
92
+
93
+
94
+ CERT_CA_PAYLOAD = TypedDict(
95
+ "CERT_CA_PAYLOAD",
96
+ {
97
+ "display_name": Required[str],
98
+ "url_pem": Required[str],
99
+ "is_trusted_root": Optional[bool],
100
+ "is_untrusted_root": Optional[bool],
101
+ "is_self_signed": Optional[bool],
102
+ "signed_by": Required[str],
103
+ "is_active": Required[bool],
104
+ "is_retired": Optional[bool],
105
+ "is_backup": Optional[bool],
106
+ "key_technology": Required[str],
107
+ "cert.fingerprints": Optional[Dict[str, str]],
108
+ ".enddate": Optional[Tuple[int, ...]],
109
+ "compatibility": Optional[
110
+ Dict[str, Tuple[str, Optional[str], Optional[str]]]
111
+ ], # platform: (min, max, note)
112
+ "alternates": Optional[List[str]],
113
+ "alternate_of": Optional[str],
114
+ "letsencrypt_serial": Optional[str],
115
+ # loaded via deprecated processors
116
+ "cert_pem": Optional[str],
117
+ "cert_pem_md5": Optional[str],
118
+ },
119
+ total=False,
120
+ )