theca 3.0.2__tar.gz → 3.0.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: theca
3
- Version: 3.0.2
3
+ Version: 3.0.3
4
4
  Summary: Python library to run your own private CA (devnull.cn/theca).
5
5
  Home-page: https://devnull.cn
6
6
  Author: Xizhen Du
@@ -20,9 +20,9 @@ Dynamic: summary
20
20
 
21
21
  # theca-sdk-python
22
22
 
23
- Run your own private CA at [devnull.cn](https://devnull.cn/pca): the service
24
- signs a per-account root CA and SAN certificates, and this package writes the
25
- PEM files to `~/.devnull/certs/`.
23
+ Run your own private CA at [devnull.cn](https://devnull.cn/pca): every account
24
+ gets its own self-signed root CA (no shared devnull root, no cross-account
25
+ trust), and this package writes the PEM files to `~/.devnull/certs/`.
26
26
 
27
27
  Requires `theid>=2` (theid 2.0 credentials; the service only accepts EdDSA
28
28
  access tokens).
@@ -52,6 +52,19 @@ Point at another environment with `DEVNULL_PCA_URL`
52
52
  (default `https://devnull.cn/pca`; the 3.0.1 name `DEVNULL_THECA_URL` is still read). The identity service is resolved by
53
53
  `theid` (`DEVNULL_BASE_URL` / `THEID_ISSUER`).
54
54
 
55
+ ## Revocation
56
+
57
+ ```python
58
+ from theca import revoke_cert, crl
59
+
60
+ revoke_cert('api.example.com') # idempotent; it stays in the CRL
61
+ open('ca.crl.pem', 'w').write(crl())
62
+ ```
63
+
64
+ New certificates carry a CRL distribution point
65
+ (`https://devnull.cn/getcrl/<orgid>`); verify with
66
+ `openssl verify -crl_check -CRLfile ca.crl.pem -CAfile ca.pem crt.pem`.
67
+
55
68
  ## What the service stores
56
69
 
57
70
  Per account: one RSA-4096 root CA (10 years) and up to 11 RSA-2048
@@ -1,8 +1,8 @@
1
1
  # theca-sdk-python
2
2
 
3
- Run your own private CA at [devnull.cn](https://devnull.cn/pca): the service
4
- signs a per-account root CA and SAN certificates, and this package writes the
5
- PEM files to `~/.devnull/certs/`.
3
+ Run your own private CA at [devnull.cn](https://devnull.cn/pca): every account
4
+ gets its own self-signed root CA (no shared devnull root, no cross-account
5
+ trust), and this package writes the PEM files to `~/.devnull/certs/`.
6
6
 
7
7
  Requires `theid>=2` (theid 2.0 credentials; the service only accepts EdDSA
8
8
  access tokens).
@@ -32,6 +32,19 @@ Point at another environment with `DEVNULL_PCA_URL`
32
32
  (default `https://devnull.cn/pca`; the 3.0.1 name `DEVNULL_THECA_URL` is still read). The identity service is resolved by
33
33
  `theid` (`DEVNULL_BASE_URL` / `THEID_ISSUER`).
34
34
 
35
+ ## Revocation
36
+
37
+ ```python
38
+ from theca import revoke_cert, crl
39
+
40
+ revoke_cert('api.example.com') # idempotent; it stays in the CRL
41
+ open('ca.crl.pem', 'w').write(crl())
42
+ ```
43
+
44
+ New certificates carry a CRL distribution point
45
+ (`https://devnull.cn/getcrl/<orgid>`); verify with
46
+ `openssl verify -crl_check -CRLfile ca.crl.pem -CAfile ca.pem crt.pem`.
47
+
35
48
  ## What the service stores
36
49
 
37
50
  Per account: one RSA-4096 root CA (10 years) and up to 11 RSA-2048
@@ -2,7 +2,7 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='theca',
5
- version='3.0.2',
5
+ version='3.0.3',
6
6
  author='Xizhen Du',
7
7
  author_email='xizhendu@gmail.com',
8
8
  url='https://devnull.cn',
@@ -9,6 +9,9 @@ from theid import account_id, authorization_headers, system_id
9
9
  # from .utils import _get_fqdn_id
10
10
  from ._utils import _create_ca
11
11
  from ._utils import _create_cert
12
+ from ._utils import _get_crl
13
+ from ._utils import _revoke_cert
14
+ from ._utils import _whoami
12
15
  # from .utils import _get_ca
13
16
  # from .utils import _get_certs
14
17
 
@@ -85,3 +88,22 @@ def create_cert():
85
88
  'rc': 205,
86
89
  'msg': 'unhealthy service.'
87
90
  }
91
+
92
+
93
+ def whoami():
94
+ """Current account's CA state: orgid, usage, ca_url, crl_url."""
95
+ return _whoami(request_headers=authorization_headers())
96
+
97
+
98
+ def revoke_cert(common_name=None):
99
+ """Revoke a certificate before expiry (it stays in the CA's CRL)."""
100
+ return _revoke_cert(request_headers=authorization_headers(), common_name=common_name)
101
+
102
+
103
+ def crl(orgid=None):
104
+ """Download the account CA's CRL as PEM text."""
105
+ if orgid is None:
106
+ orgid = whoami().get('orgid')
107
+ if not orgid:
108
+ raise ValueError('no CA yet: call create_cert() first')
109
+ return _get_crl(orgid=orgid)
@@ -10,6 +10,12 @@ THECA_URL = (os.environ.get('DEVNULL_PCA_URL')
10
10
  or os.environ.get('DEVNULL_THECA_URL')
11
11
  or 'https://devnull.cn/pca').rstrip('/')
12
12
 
13
+ # CRLs are served next to the API: https://devnull.cn/pca -> .../getcrl/<orgid>
14
+ CRL_URL = os.environ.get('DEVNULL_CRL_URL') or (
15
+ THECA_URL.rsplit('/', 1)[0] + '/getcrl' if THECA_URL.endswith(('/pca', '/theca'))
16
+ else 'https://devnull.cn/getcrl'
17
+ )
18
+
13
19
  def _get_private_ip():
14
20
  s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
15
21
  s.connect(('8.8.8.8', 80))
@@ -79,4 +85,24 @@ def _create_cert(request_headers=None, common_names=None):
79
85
  'common_names': common_names
80
86
  })
81
87
  response = requests.post(THECA_URL, headers=request_headers, data=payload)
82
- return response.json()
88
+ return response.json()
89
+
90
+ def _whoami(request_headers=None):
91
+ response = requests.get(THECA_URL + '/whoami', headers=request_headers)
92
+ return response.json()
93
+
94
+
95
+ def _revoke_cert(request_headers=None, common_name=None):
96
+ payload = json.dumps({
97
+ 'action_type': 'revoke',
98
+ 'cert_type': 'common',
99
+ 'common_name': common_name,
100
+ })
101
+ response = requests.post(THECA_URL, headers=request_headers, data=payload)
102
+ return response.json()
103
+
104
+
105
+ def _get_crl(orgid=None):
106
+ response = requests.get(f'{CRL_URL}/{orgid}')
107
+ response.raise_for_status()
108
+ return response.text
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: theca
3
- Version: 3.0.2
3
+ Version: 3.0.3
4
4
  Summary: Python library to run your own private CA (devnull.cn/theca).
5
5
  Home-page: https://devnull.cn
6
6
  Author: Xizhen Du
@@ -20,9 +20,9 @@ Dynamic: summary
20
20
 
21
21
  # theca-sdk-python
22
22
 
23
- Run your own private CA at [devnull.cn](https://devnull.cn/pca): the service
24
- signs a per-account root CA and SAN certificates, and this package writes the
25
- PEM files to `~/.devnull/certs/`.
23
+ Run your own private CA at [devnull.cn](https://devnull.cn/pca): every account
24
+ gets its own self-signed root CA (no shared devnull root, no cross-account
25
+ trust), and this package writes the PEM files to `~/.devnull/certs/`.
26
26
 
27
27
  Requires `theid>=2` (theid 2.0 credentials; the service only accepts EdDSA
28
28
  access tokens).
@@ -52,6 +52,19 @@ Point at another environment with `DEVNULL_PCA_URL`
52
52
  (default `https://devnull.cn/pca`; the 3.0.1 name `DEVNULL_THECA_URL` is still read). The identity service is resolved by
53
53
  `theid` (`DEVNULL_BASE_URL` / `THEID_ISSUER`).
54
54
 
55
+ ## Revocation
56
+
57
+ ```python
58
+ from theca import revoke_cert, crl
59
+
60
+ revoke_cert('api.example.com') # idempotent; it stays in the CRL
61
+ open('ca.crl.pem', 'w').write(crl())
62
+ ```
63
+
64
+ New certificates carry a CRL distribution point
65
+ (`https://devnull.cn/getcrl/<orgid>`); verify with
66
+ `openssl verify -crl_check -CRLfile ca.crl.pem -CAfile ca.pem crt.pem`.
67
+
55
68
  ## What the service stores
56
69
 
57
70
  Per account: one RSA-4096 root CA (10 years) and up to 11 RSA-2048
File without changes
File without changes
File without changes
File without changes