certapi 0.4.5__tar.gz → 0.4.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-0.4.5/src/certapi.egg-info → certapi-0.4.7}/PKG-INFO +12 -12
- {certapi-0.4.5 → certapi-0.4.7}/README.md +11 -11
- {certapi-0.4.5 → certapi-0.4.7}/setup.py +1 -1
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/__init__.py +1 -1
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/acme/Acme.py +0 -1
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/cloudflare/cloudflare_challenge_solver.py +1 -1
- {certapi-0.4.5 → certapi-0.4.7/src/certapi.egg-info}/PKG-INFO +12 -12
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi.egg-info/SOURCES.txt +0 -1
- certapi-0.4.5/src/certapi/keystore/FileSystemKeystore.py +0 -102
- {certapi-0.4.5 → certapi-0.4.7}/MANIFEST.in +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/pyproject.toml +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/setup.cfg +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/acme/AcmeError.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/acme/Challenge.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/acme/Order.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/acme/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/acme/http.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/ChallengeSolver.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/FileSystemChallengeSolver.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/InmemoryChallengeSolver.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/cloudflare/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/cloudflare/cloudflare_client.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/digitalocean/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/digitalocean/digitalocean_challenge_solver.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/digitalocean/digitalocean_client.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/client/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/client/cert_manager_client.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/crypto/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/crypto/crypto.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/crypto/crypto_classes.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/errors.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/http/HttpClientBase.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/http/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/http/types.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/issuers/AcmeCertIssuer.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/issuers/SelfCertIssuer.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/issuers/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/issuers/abstract_certissuer.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/keystore/FileSystemKeyStore.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/keystore/KeyStore.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/keystore/PostgresqlKeyStore.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/keystore/RemoteKeyStore.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/keystore/SqliteKeyStore.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/keystore/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/manager/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/manager/acme_cert_manager.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/server/__init__.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/server/api.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/server/cert_api.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/server/key_api.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/util.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi/utils.py +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi.egg-info/dependency_links.txt +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi.egg-info/requires.txt +0 -0
- {certapi-0.4.5 → certapi-0.4.7}/src/certapi.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: certapi
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.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
|
|
@@ -26,27 +26,21 @@ You can install CertApi using pip
|
|
|
26
26
|
pip install certapi
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Example: Obtain Certificate with Cloudflare
|
|
30
30
|
|
|
31
31
|
```python
|
|
32
32
|
import json
|
|
33
|
-
import
|
|
34
|
-
from certapi import FileSystemKeyStore, CertApiException, CloudflareChallengeSolver, AcmeCertManager, AcmeCertIssuer
|
|
33
|
+
from certapi import CertApiException, CloudflareChallengeSolver, Key, AcmeCertIssuer
|
|
35
34
|
|
|
36
35
|
|
|
37
|
-
# Initialize the key store and create acme account key
|
|
38
|
-
key_store = FileSystemKeyStore("data")
|
|
39
|
-
|
|
40
|
-
acme_key = key_store._get_or_generate_key("acme_account", "rsa")[0]
|
|
41
|
-
|
|
42
36
|
# Initialize the Cloudflare challenge solver
|
|
43
37
|
# The API key is read from the CLOUDFLARE_API_KEY environment variable, or you can set it below.
|
|
44
38
|
challenge_solver = CloudflareChallengeSolver(api_key=None)
|
|
45
39
|
|
|
46
|
-
## initialize cert issuer
|
|
47
|
-
cert_issuer = AcmeCertIssuer(
|
|
40
|
+
## initialize cert issuer with a new account key
|
|
41
|
+
cert_issuer = AcmeCertIssuer(Key.generate('rsa'), challenge_solver)
|
|
48
42
|
|
|
49
|
-
#
|
|
43
|
+
# Preform setup i.e. fetching directory and registering ACME account
|
|
50
44
|
cert_issuer.setup()
|
|
51
45
|
|
|
52
46
|
try:
|
|
@@ -61,3 +55,9 @@ except CertApiException as e:
|
|
|
61
55
|
print(f"An error occurred:", json.dumps(e.json_obj(), indent=2))
|
|
62
56
|
|
|
63
57
|
```
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## Example: Use High Leve API
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
```
|
|
@@ -13,27 +13,21 @@ You can install CertApi using pip
|
|
|
13
13
|
pip install certapi
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Example: Obtain Certificate with Cloudflare
|
|
17
17
|
|
|
18
18
|
```python
|
|
19
19
|
import json
|
|
20
|
-
import
|
|
21
|
-
from certapi import FileSystemKeyStore, CertApiException, CloudflareChallengeSolver, AcmeCertManager, AcmeCertIssuer
|
|
20
|
+
from certapi import CertApiException, CloudflareChallengeSolver, Key, AcmeCertIssuer
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
# Initialize the key store and create acme account key
|
|
25
|
-
key_store = FileSystemKeyStore("data")
|
|
26
|
-
|
|
27
|
-
acme_key = key_store._get_or_generate_key("acme_account", "rsa")[0]
|
|
28
|
-
|
|
29
23
|
# Initialize the Cloudflare challenge solver
|
|
30
24
|
# The API key is read from the CLOUDFLARE_API_KEY environment variable, or you can set it below.
|
|
31
25
|
challenge_solver = CloudflareChallengeSolver(api_key=None)
|
|
32
26
|
|
|
33
|
-
## initialize cert issuer
|
|
34
|
-
cert_issuer = AcmeCertIssuer(
|
|
27
|
+
## initialize cert issuer with a new account key
|
|
28
|
+
cert_issuer = AcmeCertIssuer(Key.generate('rsa'), challenge_solver)
|
|
35
29
|
|
|
36
|
-
#
|
|
30
|
+
# Preform setup i.e. fetching directory and registering ACME account
|
|
37
31
|
cert_issuer.setup()
|
|
38
32
|
|
|
39
33
|
try:
|
|
@@ -48,3 +42,9 @@ except CertApiException as e:
|
|
|
48
42
|
print(f"An error occurred:", json.dumps(e.json_obj(), indent=2))
|
|
49
43
|
|
|
50
44
|
```
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## Example: Use High Leve API
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .acme.Acme import Acme, Order, AcmeNetworkError, AcmeHttpError, Challenge
|
|
1
|
+
from .acme.Acme import Acme, Order, AcmeNetworkError, AcmeHttpError,AcmeError, Challenge
|
|
2
2
|
from .manager.acme_cert_manager import AcmeCertManager
|
|
3
3
|
from .http.types import CertificateResponse, IssuedCert
|
|
4
4
|
from .errors import CertApiException
|
|
@@ -29,7 +29,6 @@ class Acme:
|
|
|
29
29
|
# json web key format for public key
|
|
30
30
|
self.jwk = account_key.jwk()
|
|
31
31
|
self.alg_name = account_key.algorithm_name()
|
|
32
|
-
print(self.jwk)
|
|
33
32
|
self.nonce = []
|
|
34
33
|
self.acme_url = url if url else os.environ.get("ACME_API_URL", self.URL_STAGING)
|
|
35
34
|
self.key_id = None
|
|
@@ -33,7 +33,7 @@ class CloudflareChallengeSolver(ChallengeSolver):
|
|
|
33
33
|
|
|
34
34
|
record_id = self.cloudflare.create_record(name=key, data=value, domain=domain)
|
|
35
35
|
self.challenges_map[key] = record_id
|
|
36
|
-
print(f"CloudflareChallengeSolver[{domain}]: Added Record {key}")
|
|
36
|
+
print(f"CloudflareChallengeSolver [ {domain} ]: Added Record {key}")
|
|
37
37
|
|
|
38
38
|
def get_challenge(self, key: str, domain: str) -> str:
|
|
39
39
|
if domain is None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: certapi
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.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
|
|
@@ -26,27 +26,21 @@ You can install CertApi using pip
|
|
|
26
26
|
pip install certapi
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Example: Obtain Certificate with Cloudflare
|
|
30
30
|
|
|
31
31
|
```python
|
|
32
32
|
import json
|
|
33
|
-
import
|
|
34
|
-
from certapi import FileSystemKeyStore, CertApiException, CloudflareChallengeSolver, AcmeCertManager, AcmeCertIssuer
|
|
33
|
+
from certapi import CertApiException, CloudflareChallengeSolver, Key, AcmeCertIssuer
|
|
35
34
|
|
|
36
35
|
|
|
37
|
-
# Initialize the key store and create acme account key
|
|
38
|
-
key_store = FileSystemKeyStore("data")
|
|
39
|
-
|
|
40
|
-
acme_key = key_store._get_or_generate_key("acme_account", "rsa")[0]
|
|
41
|
-
|
|
42
36
|
# Initialize the Cloudflare challenge solver
|
|
43
37
|
# The API key is read from the CLOUDFLARE_API_KEY environment variable, or you can set it below.
|
|
44
38
|
challenge_solver = CloudflareChallengeSolver(api_key=None)
|
|
45
39
|
|
|
46
|
-
## initialize cert issuer
|
|
47
|
-
cert_issuer = AcmeCertIssuer(
|
|
40
|
+
## initialize cert issuer with a new account key
|
|
41
|
+
cert_issuer = AcmeCertIssuer(Key.generate('rsa'), challenge_solver)
|
|
48
42
|
|
|
49
|
-
#
|
|
43
|
+
# Preform setup i.e. fetching directory and registering ACME account
|
|
50
44
|
cert_issuer.setup()
|
|
51
45
|
|
|
52
46
|
try:
|
|
@@ -61,3 +55,9 @@ except CertApiException as e:
|
|
|
61
55
|
print(f"An error occurred:", json.dumps(e.json_obj(), indent=2))
|
|
62
56
|
|
|
63
57
|
```
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## Example: Use High Leve API
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
```
|
|
@@ -41,7 +41,6 @@ src/certapi/issuers/SelfCertIssuer.py
|
|
|
41
41
|
src/certapi/issuers/__init__.py
|
|
42
42
|
src/certapi/issuers/abstract_certissuer.py
|
|
43
43
|
src/certapi/keystore/FileSystemKeyStore.py
|
|
44
|
-
src/certapi/keystore/FileSystemKeystore.py
|
|
45
44
|
src/certapi/keystore/KeyStore.py
|
|
46
45
|
src/certapi/keystore/PostgresqlKeyStore.py
|
|
47
46
|
src/certapi/keystore/RemoteKeyStore.py
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Tuple, Optional, Union, List
|
|
3
|
-
|
|
4
|
-
from certapi.crypto import certs_from_pem
|
|
5
|
-
from .KeyStore import KeyStore
|
|
6
|
-
from certapi.crypto import Key, Certificate
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class FileSystemKeyStore(KeyStore):
|
|
10
|
-
"""
|
|
11
|
-
Important nuance of using filesystem keystores is that id and name means same thing.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
def __init__(self, base_dir=".", keys_dir_name="keys", certs_dir_name="certs"):
|
|
15
|
-
self.keys_dir = os.path.join(base_dir, keys_dir_name)
|
|
16
|
-
self.certs_dir = os.path.join(base_dir, certs_dir_name)
|
|
17
|
-
os.makedirs(self.keys_dir, exist_ok=True)
|
|
18
|
-
os.makedirs(self.certs_dir, exist_ok=True)
|
|
19
|
-
|
|
20
|
-
def save_key(self, key: Key, name: str | None) -> str:
|
|
21
|
-
name = str(name)
|
|
22
|
-
key_path = os.path.join(self.keys_dir, f"{name}.key")
|
|
23
|
-
with open(key_path, "wb") as f:
|
|
24
|
-
f.write(key.to_pem())
|
|
25
|
-
return name
|
|
26
|
-
|
|
27
|
-
def find_key_by_id(self, id: str | int) -> Union[None, Key]:
|
|
28
|
-
name = str(id)
|
|
29
|
-
key_path = os.path.join(self.keys_dir, f"{name}.key")
|
|
30
|
-
if os.path.exists(key_path):
|
|
31
|
-
with open(key_path, "rb") as f:
|
|
32
|
-
key_data = f.read()
|
|
33
|
-
try:
|
|
34
|
-
return Key.from_pem(key_data)
|
|
35
|
-
except:
|
|
36
|
-
pass
|
|
37
|
-
return None
|
|
38
|
-
|
|
39
|
-
def find_key_by_name(self, name: str) -> Optional[Key]:
|
|
40
|
-
return self.find_key_by_id(name)
|
|
41
|
-
|
|
42
|
-
def save_cert(
|
|
43
|
-
self, private_key_id: str, cert: Certificate | str | List[Certificate], domains: list, name: str = None
|
|
44
|
-
) -> int:
|
|
45
|
-
cert_pem = self._get_cert_as_pem_bytes(cert)
|
|
46
|
-
|
|
47
|
-
if name:
|
|
48
|
-
cert_path = os.path.join(self.certs_dir, f"{name}.crt")
|
|
49
|
-
with open(cert_path, "wb") as f:
|
|
50
|
-
f.write(cert_pem)
|
|
51
|
-
|
|
52
|
-
key_content = None
|
|
53
|
-
key_path = os.path.join(self.keys_dir, f"{private_key_id}.key")
|
|
54
|
-
with open(key_path, "rb") as f:
|
|
55
|
-
key_content = f.read()
|
|
56
|
-
|
|
57
|
-
for domain in domains:
|
|
58
|
-
domain_name = domain
|
|
59
|
-
if name is not None and name.endswith(".selfsigned"):
|
|
60
|
-
domain_name += ".selfsigned"
|
|
61
|
-
|
|
62
|
-
if domain_name != private_key_id:
|
|
63
|
-
with open(os.path.join(self.keys_dir, f"{domain_name}.key"), "wb") as f:
|
|
64
|
-
f.write(key_content)
|
|
65
|
-
|
|
66
|
-
domain_cert_path = os.path.join(self.certs_dir, f"{domain_name}.crt")
|
|
67
|
-
with open(domain_cert_path, "wb") as f:
|
|
68
|
-
f.write(cert_pem)
|
|
69
|
-
|
|
70
|
-
return name
|
|
71
|
-
|
|
72
|
-
def find_key_and_cert_by_domain(self, domain: str) -> None | Tuple[str, Key, List[Certificate]]:
|
|
73
|
-
return self._get_key_and_cert_by_name(domain)
|
|
74
|
-
|
|
75
|
-
def find_key_and_cert_by_cert_id(self, id: str) -> None | Tuple[Key, List[Certificate]]:
|
|
76
|
-
|
|
77
|
-
key_path = os.path.join(self.keys_dir, f"{id}.key")
|
|
78
|
-
cert_path = os.path.join(self.certs_dir, f"{id}.crt")
|
|
79
|
-
key = None
|
|
80
|
-
cert = None
|
|
81
|
-
if os.path.exists(key_path):
|
|
82
|
-
try:
|
|
83
|
-
with open(key_path, "rb") as f:
|
|
84
|
-
key = Key.from_pem(f.read())
|
|
85
|
-
except ValueError:
|
|
86
|
-
pass
|
|
87
|
-
|
|
88
|
-
if os.path.exists(cert_path):
|
|
89
|
-
try:
|
|
90
|
-
with open(cert_path, "rb") as f:
|
|
91
|
-
cert = certs_from_pem(f.read())
|
|
92
|
-
except ValueError:
|
|
93
|
-
pass
|
|
94
|
-
|
|
95
|
-
if cert is None or key is None:
|
|
96
|
-
return None
|
|
97
|
-
return (key, cert)
|
|
98
|
-
|
|
99
|
-
def _get_key_and_cert_by_name(self, name: str) -> None | Tuple[str, Key, List[Certificate]]:
|
|
100
|
-
result = self.find_key_and_cert_by_cert_id(name)
|
|
101
|
-
if result is not None:
|
|
102
|
-
return (name, result[0], result[1])
|
|
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-0.4.5 → certapi-0.4.7}/src/certapi/challenge_solver/dns/cloudflare/cloudflare_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{certapi-0.4.5 → certapi-0.4.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
|