sysnet-apikeys
Sdílená knihovna pro správu API klíčů FastAPI služeb SYSNET. Rozhodnutí a zdůvodnění: ADR 006 v CML
(docs/adr/006-sdilena-knihovna-sysnet-apikeys.md).
Stav: 0.2.0. Jádro, úložiště (paměť, SQL, Mongo, starý YAML jen pro čtení), vazba na FastAPI, admin router a CLI.
Není zatím nasazeno v žádné službě (pilot: taxonomy).
Co řeší
- Klíč se ukládá jako SHA-256, otevřený klíč se vrací jednou při vydání.
- Klient má víc klíčů; rotace vydá nový klíč a starému zkrátí platnost na
nyní + grace. Oba platí souběžně. - Chybějící, neznámý, zrušený i propadlý klíč dává stejnou chybu (nic se nenapovídá útočníkovi).
- Identita se vrací hodnotou (
Principal). Nesdílí se stav mezi požadavky, na rozdíl odContext.check_api_keyvsysnet-pyutils, který ho v souběhu zaměňuje. - Nové klíče mají tvar
snk_<public_id>_<tajemství>;public_idje bezpečné uvádět v logu a v tiketu.
Instalace
pip install "sysnet-apikeys[fastapi,mongo]" # nebo [fastapi,sql]; CLI: přidejte cli
Příklad (ověřený spuštěním)
import asyncio
from datetime import timedelta
from typing import Annotated
import httpx
from fastapi import Depends, FastAPI
from sysnet_apikeys import ApiKeyService, InMemoryStore, Principal
from sysnet_apikeys.fastapi import ApiKeyAuth, install_error_handlers
service = ApiKeyService(InMemoryStore())
auth = ApiKeyAuth(service)
app = FastAPI()
install_error_handlers(app)
@app.get("/dokumenty")
async def dokumenty(principal: Annotated[Principal, Depends(auth)]) -> dict[str, str]:
return {"volá": principal.client}
async def main() -> None:
old = await service.issue("ippc-docs", scopes=["read"])
new = await service.rotate("ippc-docs", grace=timedelta(days=1))
async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://t") as c:
for key in (old.key, new.key):
print((await c.get("/dokumenty", headers={"X-API-KEY": key})).status_code)
asyncio.run(main())
Výstup: 200 a 200. Starý i nový klíč platí do konce překryvu.
Úložiště
| Úložiště | Extra | Poznámka |
|---|---|---|
MongoStore(db, collection=...) |
mongo |
pymongo.AsyncMongoClient; _id = hash, unikátní public_id |
SqlStore(engine, table=...) |
sql |
PostgreSQL (asyncpg); create_schema() vytvoří tabulku |
LegacyYamlStore |
(jádro) | jen pro čtení, pro migraci |
InMemoryStore |
(jádro) | testy a malé nástroje |
Admin API a CLI
app.include_router(make_admin_router(service, admin_key=os.environ.get("APIKEYS_ADMIN_KEY")), prefix="/admin")
Bez admin_key vrací admin API 503. CLI čte úložiště z proměnných APIKEYS_STORE (mongo|sql) a
APIKEYS_MONGO_URL/APIKEYS_MONGO_DB nebo APIKEYS_SQL_URL; otevřený klíč tiskne jen issue a rotate.
sysnet-apikeys import-yaml conf/x.yml je dry-run, --apply zapíše hashe (klienti se nemění).
Migrace ze starého YAML
LegacyYamlStore.from_file("conf/xyz.yml") čte stávající api_keys: [{klíč: jméno}]. Klíče dostanou oprávnění *
a Principal.agenda a Principal.client odpovídají dnešnímu agenda a user_name. Úložiště je jen pro čtení.
Vývoj
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest && .venv/bin/ruff check . && .venv/bin/mypy
Testy úložišť potřebují PostgreSQL a MongoDB (APIKEYS_TEST_PG, APIKEYS_TEST_MONGO); bez nich padají, nepřeskakují se.
Verzování: pyproject.toml a sysnet_apikeys/__init__.py musí mít stejnou verzi, tag vX.Y.Z spustí release.
Licence: AGPL-3.0 (stejně jako ostatní sdílené knihovny SYSNET).
Metadata
Release files for sysnet-apikeys 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| sysnet_apikeys-0.2.0.tar.gz | 37.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sysnet_apikeys-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.2 kB
Release files / sysnet_apikeys-0.2.0.tar.gz
| Download URL | sysnet_apikeys-0.2.0.tar.gz |
|---|---|
| Size | 37.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c265ad48dd768165639691152ce101bd1f98abeb932fcad5a04d7ffe9519b85
|
|
BLAKE2b-256 checksum How to use checksums |
359bb1208010bc15c6bca1ad18c1f894a834b5252e7c7d7f468776030ad4abec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / sysnet_apikeys-0.2.0-py3-none-any.whl
| Download URL | sysnet_apikeys-0.2.0-py3-none-any.whl |
|---|---|
| Size | 33.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87cb69713de409115d5321ad9496992fd6431939a354a0281e8de661976dad4c
|
|
BLAKE2b-256 checksum How to use checksums |
296a9239fa2fb99550861abc87ddd50136d991da4a2c6de0d1232f4eba10bd68
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Security for sysnet-apikeys 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.