tiny-ca-gateway 0.1.0__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.
Files changed (34) hide show
  1. tiny_ca_gateway-0.1.0/LICENSE +54 -0
  2. tiny_ca_gateway-0.1.0/PKG-INFO +233 -0
  3. tiny_ca_gateway-0.1.0/README.md +181 -0
  4. tiny_ca_gateway-0.1.0/pyproject.toml +288 -0
  5. tiny_ca_gateway-0.1.0/setup.cfg +4 -0
  6. tiny_ca_gateway-0.1.0/tiny_ca_gateway/aiohttp/api/v1/ca_routes.py +546 -0
  7. tiny_ca_gateway-0.1.0/tiny_ca_gateway/aiohttp/lifespan/manager.py +11 -0
  8. tiny_ca_gateway-0.1.0/tiny_ca_gateway/core/__init__.py +71 -0
  9. tiny_ca_gateway-0.1.0/tiny_ca_gateway/core/auth.py +26 -0
  10. tiny_ca_gateway-0.1.0/tiny_ca_gateway/core/base_manager.py +162 -0
  11. tiny_ca_gateway-0.1.0/tiny_ca_gateway/core/helpers.py +110 -0
  12. tiny_ca_gateway-0.1.0/tiny_ca_gateway/core/routes.py +41 -0
  13. tiny_ca_gateway-0.1.0/tiny_ca_gateway/core/schemas.py +179 -0
  14. tiny_ca_gateway-0.1.0/tiny_ca_gateway/core/summary.py +26 -0
  15. tiny_ca_gateway-0.1.0/tiny_ca_gateway/db.py +63 -0
  16. tiny_ca_gateway-0.1.0/tiny_ca_gateway/django/api/v1/ca_router.py +594 -0
  17. tiny_ca_gateway-0.1.0/tiny_ca_gateway/django/lifespan/manager.py +5 -0
  18. tiny_ca_gateway-0.1.0/tiny_ca_gateway/fastapi/api/v1/__init__.py +1 -0
  19. tiny_ca_gateway-0.1.0/tiny_ca_gateway/fastapi/api/v1/ca_routes.py +580 -0
  20. tiny_ca_gateway-0.1.0/tiny_ca_gateway/fastapi/api/v1/utils.py +87 -0
  21. tiny_ca_gateway-0.1.0/tiny_ca_gateway/fastapi/auth/__init__.py +0 -0
  22. tiny_ca_gateway-0.1.0/tiny_ca_gateway/fastapi/auth/verify.py +61 -0
  23. tiny_ca_gateway-0.1.0/tiny_ca_gateway/fastapi/lifespan/__init__.py +3 -0
  24. tiny_ca_gateway-0.1.0/tiny_ca_gateway/fastapi/lifespan/manager.py +7 -0
  25. tiny_ca_gateway-0.1.0/tiny_ca_gateway/flask/api/v1/ca_blueprint.py +629 -0
  26. tiny_ca_gateway-0.1.0/tiny_ca_gateway/flask/lifespan/manager.py +5 -0
  27. tiny_ca_gateway-0.1.0/tiny_ca_gateway/models.py +79 -0
  28. tiny_ca_gateway-0.1.0/tiny_ca_gateway/openapi.py +536 -0
  29. tiny_ca_gateway-0.1.0/tiny_ca_gateway/utils/singleton.py +27 -0
  30. tiny_ca_gateway-0.1.0/tiny_ca_gateway.egg-info/PKG-INFO +233 -0
  31. tiny_ca_gateway-0.1.0/tiny_ca_gateway.egg-info/SOURCES.txt +32 -0
  32. tiny_ca_gateway-0.1.0/tiny_ca_gateway.egg-info/dependency_links.txt +1 -0
  33. tiny_ca_gateway-0.1.0/tiny_ca_gateway.egg-info/requires.txt +28 -0
  34. tiny_ca_gateway-0.1.0/tiny_ca_gateway.egg-info/top_level.txt +1 -0
@@ -0,0 +1,54 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Denis Shchutskyi (Shchusia)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ ## Dependency Notice
26
+
27
+ This package is built on top of **tiny-ca** by Denis Shchutskyi (Shchusia),
28
+ also distributed under the MIT License.
29
+ See: https://github.com/Shchusia/tiny_ca
30
+
31
+ ---
32
+
33
+ ## Third-Party Licenses
34
+
35
+ This software uses the following open source dependencies:
36
+
37
+ ### Core
38
+ - **tiny-ca** (MIT) - https://github.com/Shchusia/tiny_ca
39
+ - **cryptography** (BSD 3-Clause) - https://github.com/pyca/cryptography
40
+ - **SQLAlchemy** (MIT) - https://github.com/sqlalchemy/sqlalchemy
41
+ - **Pydantic** (MIT) - https://github.com/pydantic/pydantic
42
+ - **aiosqlite** (MIT) - https://github.com/omnilib/aiosqlite
43
+ - **aiofiles** (Apache 2.0) - https://github.com/Tinche/aiofiles
44
+
45
+ ### Optional framework dependencies
46
+ - **FastAPI** (MIT) - https://github.com/tiangolo/fastapi
47
+ - **Starlette** (BSD 3-Clause) - https://github.com/encode/starlette
48
+ - **Uvicorn** (BSD 3-Clause) - https://github.com/encode/uvicorn
49
+ - **Flask** (BSD 3-Clause) - https://github.com/pallets/flask
50
+ - **Werkzeug** (BSD 3-Clause) - https://github.com/pallets/werkzeug
51
+ - **aiohttp** (Apache 2.0) - https://github.com/aio-libs/aiohttp
52
+ - **Django** (BSD 3-Clause) - https://github.com/django/django
53
+ - **django-ninja** (MIT) - https://github.com/vitalik/django-ninja
54
+ - **Gunicorn** (MIT) - https://github.com/benoitc/gunicorn
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.4
2
+ Name: tiny-ca-gateway
3
+ Version: 0.1.0
4
+ Summary: Framework-agnostic REST API routes for tiny-ca — supports FastAPI, Flask, aiohttp and Django Ninja
5
+ Author-email: Denis Shchutskyi <denisshchutskyi@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Shchusia/tiny-ca-gateway
8
+ Project-URL: Documentation, https://github.com/Shchusia/tiny-ca-gateway/blob/master/README.md
9
+ Project-URL: Bug Tracker, https://github.com/Shchusia/tiny-ca-gateway/issues
10
+ Project-URL: Changelog, https://github.com/Shchusia/tiny-ca-gateway/blob/master/CHANGELOG.md
11
+ Keywords: certificate-authority,pki,ca,tls,ssl,fastapi,flask,aiohttp,django,rest,api
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
19
+ Classifier: Topic :: Security :: Cryptography
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Framework :: FastAPI
22
+ Classifier: Framework :: Flask
23
+ Classifier: Framework :: Django
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.12
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: gunicorn>=26.0.0
29
+ Requires-Dist: pydantic>=2.13.3
30
+ Requires-Dist: pydantic-settings>=2.14.0
31
+ Requires-Dist: tiny-ca[async]>=0.2.0
32
+ Requires-Dist: aiofiles>=23.0.0
33
+ Requires-Dist: cryptography>=42.0.0
34
+ Provides-Extra: fastapi
35
+ Requires-Dist: fastapi>=0.136.1; extra == "fastapi"
36
+ Requires-Dist: uvicorn[standard]>=0.29.0; extra == "fastapi"
37
+ Provides-Extra: django
38
+ Requires-Dist: django>=6.0.5; extra == "django"
39
+ Requires-Dist: django-ninja>=1.6.2; extra == "django"
40
+ Provides-Extra: flask
41
+ Requires-Dist: flask>=3.1.3; extra == "flask"
42
+ Provides-Extra: aiohttp
43
+ Requires-Dist: aiohttp>=3.13.5; extra == "aiohttp"
44
+ Provides-Extra: all
45
+ Requires-Dist: fastapi>=0.136.1; extra == "all"
46
+ Requires-Dist: uvicorn[standard]>=0.29.0; extra == "all"
47
+ Requires-Dist: django>=6.0.5; extra == "all"
48
+ Requires-Dist: django-ninja>=1.6.2; extra == "all"
49
+ Requires-Dist: flask>=3.1.3; extra == "all"
50
+ Requires-Dist: aiohttp>=3.13.5; extra == "all"
51
+ Dynamic: license-file
52
+
53
+ # tiny-ca-gateway
54
+
55
+ [![PyPI](https://img.shields.io/pypi/v/tiny-ca-gateway)](https://pypi.org/project/tiny-ca-gateway/)
56
+ [![Python](https://img.shields.io/pypi/pyversions/tiny-ca-gateway)](https://pypi.org/project/tiny-ca-gateway/)
57
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
58
+
59
+ **tiny-ca-gateway** provides ready-to-use REST API routes for [tiny-ca](https://github.com/Shchusia/tiny_ca) — a lightweight Python Certificate Authority library. Mount a full-featured CA HTTP API into any of your existing applications in minutes.
60
+
61
+ > **Built on top of [tiny-ca](https://github.com/Shchusia/tiny_ca).** This package only provides the HTTP layer. For CA internals, certificate issuance logic, and database models, see the [tiny-ca documentation](https://github.com/Shchusia/tiny_ca).
62
+
63
+ ---
64
+
65
+ ## Features
66
+
67
+ - **22 REST endpoints** — issue, revoke, renew, rotate, verify, download certificates and more
68
+ - **4 framework adapters** — drop into an existing app without rewriting anything
69
+ - **Shared core** — identical behaviour across all frameworks; integration tests run against all of them
70
+ - **Bearer token auth** — optional, zero-config when `CA_API_TOKEN` is empty
71
+ - **OpenAPI / Swagger UI** — built-in for FastAPI & Django Ninja; CDN-based for Flask & aiohttp
72
+ - **Async-native** — FastAPI, aiohttp and Django (ASGI) run fully async; Flask uses an asyncio bridge
73
+
74
+ ---
75
+
76
+ ## Supported frameworks
77
+
78
+ | Framework | Adapter | Integration guide |
79
+ |-----------|---------|------------------|
80
+ | **FastAPI** | `tiny_ca_gateway.fastapi` | [docs/fastapi.md](docs/fastapi.md) |
81
+ | **Flask** | `tiny_ca_gateway.flask` | [docs/flask.md](docs/flask.md) |
82
+ | **aiohttp** | `tiny_ca_gateway.aiohttp` | [docs/aiohttp.md](docs/aiohttp.md) |
83
+ | **Django Ninja** | `tiny_ca_gateway.django` | [docs/django.md](docs/django.md) |
84
+
85
+ ---
86
+
87
+ ## Quick install
88
+
89
+ Install only what you need:
90
+
91
+ ```bash
92
+ # FastAPI
93
+ pip install "tiny-ca-gateway[fastapi]"
94
+
95
+ # Flask
96
+ pip install "tiny-ca-gateway[flask]"
97
+
98
+ # aiohttp
99
+ pip install "tiny-ca-gateway[aiohttp]"
100
+
101
+ # Django + Django Ninja
102
+ pip install "tiny-ca-gateway[django]"
103
+
104
+ # Everything
105
+ pip install "tiny-ca-gateway[all]"
106
+ ```
107
+
108
+ ---
109
+
110
+ ## 60-second example
111
+
112
+ ### FastAPI
113
+
114
+ ```python
115
+ from fastapi import FastAPI
116
+ from contextlib import asynccontextmanager
117
+ from tiny_ca_gateway.fastapi.lifespan.manager import FastAPILifespanManager
118
+ from tiny_ca_gateway.fastapi.api.v1.ca_routes import router
119
+
120
+ @asynccontextmanager
121
+ async def lifespan(app: FastAPI):
122
+ await FastAPILifespanManager(common_name="My CA").on_startup()
123
+ yield
124
+
125
+ app = FastAPI(lifespan=lifespan)
126
+ app.include_router(router, prefix="/api/v1")
127
+ ```
128
+
129
+ ### Flask
130
+
131
+ ```python
132
+ from flask import Flask
133
+ from tiny_ca_gateway.flask.lifespan.manager import FlaskCAManager
134
+ from tiny_ca_gateway.flask.api.v1.ca_blueprint import ca_bp
135
+
136
+ def create_app():
137
+ app = Flask(__name__)
138
+ FlaskCAManager(common_name="My CA").init_sync()
139
+ app.register_blueprint(ca_bp, url_prefix="/api/v1/ca")
140
+ return app
141
+ ```
142
+
143
+ ### aiohttp
144
+
145
+ ```python
146
+ from aiohttp import web
147
+ from tiny_ca_gateway.aiohttp.lifespan.manager import AiohttpCAManager
148
+ from tiny_ca_gateway.aiohttp.api.v1.ca_routes import routes
149
+
150
+ async def lifespan(app):
151
+ await AiohttpCAManager(common_name="My CA").on_startup()
152
+ yield
153
+
154
+ app = web.Application()
155
+ app.cleanup_ctx.append(lifespan)
156
+ app.add_subapp("/api/v1/ca", web.Application())
157
+ app.router.add_routes(routes)
158
+ ```
159
+
160
+ ### Django Ninja
161
+
162
+ ```python
163
+ # urls.py
164
+ from ninja import NinjaAPI
165
+ from tiny_ca_gateway.django.api.v1.ca_router import ca_router
166
+
167
+ api = NinjaAPI()
168
+ api.add_router("/ca", ca_router)
169
+
170
+ urlpatterns = [path("api/v1/", api.urls)]
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Environment variables
176
+
177
+ | Variable | Default | Description |
178
+ |----------|---------|-------------|
179
+ | `CA_CERT_PATH` | `certs/ca.pem` | Path to the CA certificate |
180
+ | `CA_KEY_PATH` | `certs/ca.key` | Path to the CA private key |
181
+ | `CA_CRL_PATH` | `certs/crl.pem` | Path to the CRL file |
182
+ | `CA_CERTS_DIR` | `certs/` | Directory for issued certificates |
183
+ | `CA_DB_URL` | `sqlite+aiosqlite:///ca.db` | SQLAlchemy async database URL |
184
+ | `CA_API_TOKEN` | `""` | Bearer token — empty = open access |
185
+
186
+ ---
187
+
188
+ ## API reference
189
+
190
+ All adapters expose the same 22 endpoints under the configured prefix:
191
+
192
+ | Method | Path | Auth | Description |
193
+ |--------|------|------|-------------|
194
+ | `GET` | `/cert` | ✗ | Download CA public certificate |
195
+ | `GET` | `/crl` | ✗ | Download CRL (DER or `?pem=true`) |
196
+ | `GET` | `/` | ✓ | List certificates |
197
+ | `GET` | `/expiring` | ✓ | Certificates expiring soon |
198
+ | `POST` | `/root` | ✓ | Bootstrap / replace root CA |
199
+ | `POST` | `/intermediate` | ✓ | Issue intermediate CA |
200
+ | `POST` | `/issue` | ✓ | Issue leaf certificate |
201
+ | `POST` | `/maintenance/expire` | ✓ | Mark expired certificates |
202
+ | `POST` | `/crl/refresh` | ✓ | Regenerate CRL |
203
+ | `POST` | `/crl/verify` | ✓ | Verify a CRL |
204
+ | `POST` | `/verify` | ✓ | Verify a certificate |
205
+ | `POST` | `/cosign` | ✓ | Co-sign an external certificate |
206
+ | `POST` | `/export-p12/{serial}` | ✓ | Export PKCS#12 bundle |
207
+ | `PATCH` | `/revoke` | ✓ | Revoke a certificate |
208
+ | `POST` | `/rotate/{serial}` | ✓ | Rotate (new key) |
209
+ | `POST` | `/renew/{serial}` | ✓ | Renew (same key, new validity) |
210
+ | `DELETE` | `/{serial}` | ✓ | Hard-delete certificate |
211
+ | `GET` | `/status/{serial}` | ✓ | Lifecycle status |
212
+ | `GET` | `/inspect/{serial}` | ✓ | Structured details |
213
+ | `GET` | `/chain/{serial}` | ✓ | Full PEM chain |
214
+ | `GET` | `/stream/{uuid}` | ✓ | Stream artefact (pem / key / csr) |
215
+ | `GET` | `/{uuid}` | ✓ | Download artefact |
216
+
217
+ ---
218
+
219
+ ## Running the integration tests
220
+
221
+ ```bash
222
+ # Start any backend first, then:
223
+ python tests/ca_integration_test.py --base-url http://localhost:8000
224
+
225
+ # Run against all frameworks automatically:
226
+ task run-all-tests TOKEN=mysecret
227
+ ```
228
+
229
+ ---
230
+
231
+ ## License
232
+
233
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,181 @@
1
+ # tiny-ca-gateway
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/tiny-ca-gateway)](https://pypi.org/project/tiny-ca-gateway/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/tiny-ca-gateway)](https://pypi.org/project/tiny-ca-gateway/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+
7
+ **tiny-ca-gateway** provides ready-to-use REST API routes for [tiny-ca](https://github.com/Shchusia/tiny_ca) — a lightweight Python Certificate Authority library. Mount a full-featured CA HTTP API into any of your existing applications in minutes.
8
+
9
+ > **Built on top of [tiny-ca](https://github.com/Shchusia/tiny_ca).** This package only provides the HTTP layer. For CA internals, certificate issuance logic, and database models, see the [tiny-ca documentation](https://github.com/Shchusia/tiny_ca).
10
+
11
+ ---
12
+
13
+ ## Features
14
+
15
+ - **22 REST endpoints** — issue, revoke, renew, rotate, verify, download certificates and more
16
+ - **4 framework adapters** — drop into an existing app without rewriting anything
17
+ - **Shared core** — identical behaviour across all frameworks; integration tests run against all of them
18
+ - **Bearer token auth** — optional, zero-config when `CA_API_TOKEN` is empty
19
+ - **OpenAPI / Swagger UI** — built-in for FastAPI & Django Ninja; CDN-based for Flask & aiohttp
20
+ - **Async-native** — FastAPI, aiohttp and Django (ASGI) run fully async; Flask uses an asyncio bridge
21
+
22
+ ---
23
+
24
+ ## Supported frameworks
25
+
26
+ | Framework | Adapter | Integration guide |
27
+ |-----------|---------|------------------|
28
+ | **FastAPI** | `tiny_ca_gateway.fastapi` | [docs/fastapi.md](docs/fastapi.md) |
29
+ | **Flask** | `tiny_ca_gateway.flask` | [docs/flask.md](docs/flask.md) |
30
+ | **aiohttp** | `tiny_ca_gateway.aiohttp` | [docs/aiohttp.md](docs/aiohttp.md) |
31
+ | **Django Ninja** | `tiny_ca_gateway.django` | [docs/django.md](docs/django.md) |
32
+
33
+ ---
34
+
35
+ ## Quick install
36
+
37
+ Install only what you need:
38
+
39
+ ```bash
40
+ # FastAPI
41
+ pip install "tiny-ca-gateway[fastapi]"
42
+
43
+ # Flask
44
+ pip install "tiny-ca-gateway[flask]"
45
+
46
+ # aiohttp
47
+ pip install "tiny-ca-gateway[aiohttp]"
48
+
49
+ # Django + Django Ninja
50
+ pip install "tiny-ca-gateway[django]"
51
+
52
+ # Everything
53
+ pip install "tiny-ca-gateway[all]"
54
+ ```
55
+
56
+ ---
57
+
58
+ ## 60-second example
59
+
60
+ ### FastAPI
61
+
62
+ ```python
63
+ from fastapi import FastAPI
64
+ from contextlib import asynccontextmanager
65
+ from tiny_ca_gateway.fastapi.lifespan.manager import FastAPILifespanManager
66
+ from tiny_ca_gateway.fastapi.api.v1.ca_routes import router
67
+
68
+ @asynccontextmanager
69
+ async def lifespan(app: FastAPI):
70
+ await FastAPILifespanManager(common_name="My CA").on_startup()
71
+ yield
72
+
73
+ app = FastAPI(lifespan=lifespan)
74
+ app.include_router(router, prefix="/api/v1")
75
+ ```
76
+
77
+ ### Flask
78
+
79
+ ```python
80
+ from flask import Flask
81
+ from tiny_ca_gateway.flask.lifespan.manager import FlaskCAManager
82
+ from tiny_ca_gateway.flask.api.v1.ca_blueprint import ca_bp
83
+
84
+ def create_app():
85
+ app = Flask(__name__)
86
+ FlaskCAManager(common_name="My CA").init_sync()
87
+ app.register_blueprint(ca_bp, url_prefix="/api/v1/ca")
88
+ return app
89
+ ```
90
+
91
+ ### aiohttp
92
+
93
+ ```python
94
+ from aiohttp import web
95
+ from tiny_ca_gateway.aiohttp.lifespan.manager import AiohttpCAManager
96
+ from tiny_ca_gateway.aiohttp.api.v1.ca_routes import routes
97
+
98
+ async def lifespan(app):
99
+ await AiohttpCAManager(common_name="My CA").on_startup()
100
+ yield
101
+
102
+ app = web.Application()
103
+ app.cleanup_ctx.append(lifespan)
104
+ app.add_subapp("/api/v1/ca", web.Application())
105
+ app.router.add_routes(routes)
106
+ ```
107
+
108
+ ### Django Ninja
109
+
110
+ ```python
111
+ # urls.py
112
+ from ninja import NinjaAPI
113
+ from tiny_ca_gateway.django.api.v1.ca_router import ca_router
114
+
115
+ api = NinjaAPI()
116
+ api.add_router("/ca", ca_router)
117
+
118
+ urlpatterns = [path("api/v1/", api.urls)]
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Environment variables
124
+
125
+ | Variable | Default | Description |
126
+ |----------|---------|-------------|
127
+ | `CA_CERT_PATH` | `certs/ca.pem` | Path to the CA certificate |
128
+ | `CA_KEY_PATH` | `certs/ca.key` | Path to the CA private key |
129
+ | `CA_CRL_PATH` | `certs/crl.pem` | Path to the CRL file |
130
+ | `CA_CERTS_DIR` | `certs/` | Directory for issued certificates |
131
+ | `CA_DB_URL` | `sqlite+aiosqlite:///ca.db` | SQLAlchemy async database URL |
132
+ | `CA_API_TOKEN` | `""` | Bearer token — empty = open access |
133
+
134
+ ---
135
+
136
+ ## API reference
137
+
138
+ All adapters expose the same 22 endpoints under the configured prefix:
139
+
140
+ | Method | Path | Auth | Description |
141
+ |--------|------|------|-------------|
142
+ | `GET` | `/cert` | ✗ | Download CA public certificate |
143
+ | `GET` | `/crl` | ✗ | Download CRL (DER or `?pem=true`) |
144
+ | `GET` | `/` | ✓ | List certificates |
145
+ | `GET` | `/expiring` | ✓ | Certificates expiring soon |
146
+ | `POST` | `/root` | ✓ | Bootstrap / replace root CA |
147
+ | `POST` | `/intermediate` | ✓ | Issue intermediate CA |
148
+ | `POST` | `/issue` | ✓ | Issue leaf certificate |
149
+ | `POST` | `/maintenance/expire` | ✓ | Mark expired certificates |
150
+ | `POST` | `/crl/refresh` | ✓ | Regenerate CRL |
151
+ | `POST` | `/crl/verify` | ✓ | Verify a CRL |
152
+ | `POST` | `/verify` | ✓ | Verify a certificate |
153
+ | `POST` | `/cosign` | ✓ | Co-sign an external certificate |
154
+ | `POST` | `/export-p12/{serial}` | ✓ | Export PKCS#12 bundle |
155
+ | `PATCH` | `/revoke` | ✓ | Revoke a certificate |
156
+ | `POST` | `/rotate/{serial}` | ✓ | Rotate (new key) |
157
+ | `POST` | `/renew/{serial}` | ✓ | Renew (same key, new validity) |
158
+ | `DELETE` | `/{serial}` | ✓ | Hard-delete certificate |
159
+ | `GET` | `/status/{serial}` | ✓ | Lifecycle status |
160
+ | `GET` | `/inspect/{serial}` | ✓ | Structured details |
161
+ | `GET` | `/chain/{serial}` | ✓ | Full PEM chain |
162
+ | `GET` | `/stream/{uuid}` | ✓ | Stream artefact (pem / key / csr) |
163
+ | `GET` | `/{uuid}` | ✓ | Download artefact |
164
+
165
+ ---
166
+
167
+ ## Running the integration tests
168
+
169
+ ```bash
170
+ # Start any backend first, then:
171
+ python tests/ca_integration_test.py --base-url http://localhost:8000
172
+
173
+ # Run against all frameworks automatically:
174
+ task run-all-tests TOKEN=mysecret
175
+ ```
176
+
177
+ ---
178
+
179
+ ## License
180
+
181
+ MIT — see [LICENSE](LICENSE).