certapi 1.1.6__tar.gz → 1.1.7__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.
- {certapi-1.1.6/src/certapi.egg-info → certapi-1.1.7}/PKG-INFO +2 -2
- {certapi-1.1.6 → certapi-1.1.7}/setup.py +2 -2
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/client/renewal_manager.py +15 -12
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/issuers/AcmeCertIssuer.py +1 -1
- {certapi-1.1.6 → certapi-1.1.7/src/certapi.egg-info}/PKG-INFO +2 -2
- certapi-1.1.7/src/certapi.egg-info/requires.txt +2 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_renewal_manager.py +16 -3
- certapi-1.1.6/src/certapi.egg-info/requires.txt +0 -2
- {certapi-1.1.6 → certapi-1.1.7}/MANIFEST.in +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/README.md +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/pyproject.toml +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/setup.cfg +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/acme/Acme.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/acme/AcmeError.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/acme/Challenge.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/acme/Order.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/acme/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/acme/http.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/ChallengeSolver.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/FileSystemChallengeSolver.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/InmemoryChallengeSolver.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/cloudflare/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/cloudflare/cloudflare_challenge_solver.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/cloudflare/cloudflare_client.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/digitalocean/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/digitalocean/digitalocean_challenge_solver.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/digitalocean/digitalocean_client.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/cli.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/client/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/client/cert_manager_client.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/crypto/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/crypto/crypto.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/crypto/crypto_classes.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/domain_batching.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/errors.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/http/HttpClientBase.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/http/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/http/types.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/issuers/SelfCertIssuer.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/issuers/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/issuers/abstract_certissuer.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/keystore/FileSystemKeyStore.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/keystore/KeyStore.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/keystore/PostgresqlKeyStore.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/keystore/RemoteKeyStore.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/keystore/SqliteKeyStore.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/keystore/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/manager/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/manager/acme_cert_manager.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/server/__init__.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/server/api.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/server/cert_api.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/server/key_api.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/util.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi/utils.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi.egg-info/SOURCES.txt +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi.egg-info/dependency_links.txt +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi.egg-info/entry_points.txt +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/src/certapi.egg-info/top_level.txt +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_acme_cert_manager_batching.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_acme_error_handling.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_cert_issuer_generic.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_certs_with_key_types.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_cli.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_domain_batching_boulder_cases.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_http_error_handling.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_keystores.py +0 -0
- {certapi-1.1.6 → certapi-1.1.7}/tests/test_obtain_interface.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: certapi
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.7
|
|
4
4
|
Summary: Python Package for managing keys, request SSL certificates from ACME.
|
|
5
5
|
Home-page: https://github.com/mesudip/certapi
|
|
6
6
|
Author: Sudip Bhattarai
|
|
@@ -10,7 +10,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Requires-Python: >=3.6
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
|
-
Requires-Dist: cryptography
|
|
13
|
+
Requires-Dist: cryptography>=39.0.0
|
|
14
14
|
Requires-Dist: requests
|
|
15
15
|
Dynamic: author
|
|
16
16
|
Dynamic: author-email
|
|
@@ -2,11 +2,11 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="certapi",
|
|
5
|
-
version="1.1.
|
|
5
|
+
version="1.1.7",
|
|
6
6
|
packages=find_packages(where="src"),
|
|
7
7
|
package_dir={"": "src"},
|
|
8
8
|
install_requires=[
|
|
9
|
-
"cryptography",
|
|
9
|
+
"cryptography>=39.0.0",
|
|
10
10
|
"requests",
|
|
11
11
|
],
|
|
12
12
|
include_package_data=True,
|
|
@@ -419,8 +419,8 @@ class RenewalManager:
|
|
|
419
419
|
if (expiry - now).total_seconds() < due_window:
|
|
420
420
|
due_domains.append(domain)
|
|
421
421
|
|
|
422
|
-
|
|
423
|
-
self.
|
|
422
|
+
if due_domains:
|
|
423
|
+
self._renew_domains(due_domains, now)
|
|
424
424
|
|
|
425
425
|
return len(due_domains)
|
|
426
426
|
|
|
@@ -463,10 +463,12 @@ class RenewalManager:
|
|
|
463
463
|
self._cache[domain] = expiry
|
|
464
464
|
self._lock.notify_all()
|
|
465
465
|
|
|
466
|
-
def
|
|
467
|
-
|
|
466
|
+
def _renew_domains(self, domains: List[str], now: datetime):
|
|
467
|
+
domains_with_cached_entries = []
|
|
468
468
|
with self._lock:
|
|
469
|
-
|
|
469
|
+
for domain in domains:
|
|
470
|
+
if domain in self._cache:
|
|
471
|
+
domains_with_cached_entries.append(domain)
|
|
470
472
|
|
|
471
473
|
try:
|
|
472
474
|
renew_threshold_days = self.cert_min_renew_threshold_secs // (24 * 3600)
|
|
@@ -475,7 +477,7 @@ class RenewalManager:
|
|
|
475
477
|
"expiry_days": self.expiry_days,
|
|
476
478
|
"renew_threshold_days": renew_threshold_days,
|
|
477
479
|
"skip_failing": False,
|
|
478
|
-
"batch_domains":
|
|
480
|
+
"batch_domains": True,
|
|
479
481
|
"self_verify": self.self_verify,
|
|
480
482
|
"country": self.country,
|
|
481
483
|
"state": self.state,
|
|
@@ -485,7 +487,7 @@ class RenewalManager:
|
|
|
485
487
|
}
|
|
486
488
|
res = self._call_certificate_backend(
|
|
487
489
|
self.cert_manager_client.obtain,
|
|
488
|
-
|
|
490
|
+
domains,
|
|
489
491
|
obtain_options,
|
|
490
492
|
)
|
|
491
493
|
if res is None:
|
|
@@ -493,11 +495,12 @@ class RenewalManager:
|
|
|
493
495
|
self._update_expiry_cache(res.issued + res.existing)
|
|
494
496
|
except Exception as e:
|
|
495
497
|
self._set_error(e)
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
self.
|
|
499
|
-
|
|
500
|
-
|
|
498
|
+
for domain in domains:
|
|
499
|
+
self._add_to_blacklist(domain, now)
|
|
500
|
+
if domain in domains_with_cached_entries or self._has_local_certificate(domain):
|
|
501
|
+
self._schedule_existing_certificate_retry(domain, now)
|
|
502
|
+
else:
|
|
503
|
+
self._register_self_signed(domain)
|
|
501
504
|
|
|
502
505
|
def _schedule_existing_certificate_retry(self, domain: str, now: datetime):
|
|
503
506
|
retry_interval_seconds = min(self.renew_retry_interval_seconds, 24 * 3600)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: certapi
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.7
|
|
4
4
|
Summary: Python Package for managing keys, request SSL certificates from ACME.
|
|
5
5
|
Home-page: https://github.com/mesudip/certapi
|
|
6
6
|
Author: Sudip Bhattarai
|
|
@@ -10,7 +10,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Requires-Python: >=3.6
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
|
-
Requires-Dist: cryptography
|
|
13
|
+
Requires-Dist: cryptography>=39.0.0
|
|
14
14
|
Requires-Dist: requests
|
|
15
15
|
Dynamic: author
|
|
16
16
|
Dynamic: author-email
|
|
@@ -25,7 +25,7 @@ class DummyClient:
|
|
|
25
25
|
|
|
26
26
|
def obtain(self, hosts, **kwargs):
|
|
27
27
|
host = hosts[0] if isinstance(hosts, list) else hosts
|
|
28
|
-
self.calls.append({"host": host, "kwargs": kwargs})
|
|
28
|
+
self.calls.append({"host": host, "hosts": hosts, "kwargs": kwargs})
|
|
29
29
|
handler = self._handlers.get(host)
|
|
30
30
|
if handler is None:
|
|
31
31
|
return CertificateResponse()
|
|
@@ -47,12 +47,12 @@ class DummyClientWithObtain(DummyClient):
|
|
|
47
47
|
|
|
48
48
|
def obtain(self, hosts, **kwargs):
|
|
49
49
|
host = hosts[0] if isinstance(hosts, list) else hosts
|
|
50
|
-
self.obtain_calls.append({"host": host, "kwargs": kwargs})
|
|
50
|
+
self.obtain_calls.append({"host": host, "hosts": hosts, "kwargs": kwargs})
|
|
51
51
|
return super().obtain(hosts, **kwargs)
|
|
52
52
|
|
|
53
53
|
def issue_certificate(self, hosts, **kwargs):
|
|
54
54
|
host = hosts[0] if isinstance(hosts, list) else hosts
|
|
55
|
-
self.issue_calls.append({"host": host, "kwargs": kwargs})
|
|
55
|
+
self.issue_calls.append({"host": host, "hosts": hosts, "kwargs": kwargs})
|
|
56
56
|
return super().obtain(hosts, **kwargs)
|
|
57
57
|
|
|
58
58
|
|
|
@@ -702,3 +702,16 @@ def test_stop_does_not_wait_for_hung_remote_request_thread():
|
|
|
702
702
|
|
|
703
703
|
assert not mgr._thread.is_alive()
|
|
704
704
|
release.set()
|
|
705
|
+
|
|
706
|
+
|
|
707
|
+
def test_renewal_manager_batches_due_domains():
|
|
708
|
+
now = datetime(2026, 1, 1, tzinfo=UTC)
|
|
709
|
+
client = DummyClientWithObtain()
|
|
710
|
+
client.set_handler("domain1.com", CertificateResponse())
|
|
711
|
+
|
|
712
|
+
mgr = RenewalManager(client, renew_threshold_days=30, clock_fn=lambda: now, batch_domains=True)
|
|
713
|
+
mgr.update_watch_domains(["domain1.com", "domain2.com"])
|
|
714
|
+
|
|
715
|
+
assert len(client.obtain_calls) == 1
|
|
716
|
+
assert "domain1.com" in client.obtain_calls[0]["hosts"]
|
|
717
|
+
assert "domain2.com" in client.obtain_calls[0]["hosts"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/cloudflare/cloudflare_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{certapi-1.1.6 → certapi-1.1.7}/src/certapi/challenge_solver/dns/digitalocean/digitalocean_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|