Implement KCA: web reimplementation of XCA PKI workflows
- kaya backend with OIDC sessions, API tokens, Postgres/Tortoise models - AES-256-GCM private key storage and full certificate/CSR/CRL domain logic - Sycamore/WASM SPA for vaults, keys, requests, certificates, CRLs and templates - imports/exports, XCA .xdb migration, Docker Compose stack and tests
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
"""In-process HTTP client for the app."""
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
from typing import AsyncIterator
|
||||
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from kca.app import app, tortoise_mixin
|
||||
|
||||
|
||||
@contextlib.asynccontextmanager
|
||||
async def api_client() -> AsyncIterator[AsyncClient]:
|
||||
await tortoise_mixin.ensure_context()
|
||||
transport = ASGITransport(app=app)
|
||||
async with AsyncClient(transport=transport, base_url="http://127.0.0.1") as client:
|
||||
yield client
|
||||
@@ -0,0 +1,23 @@
|
||||
"""``async_test`` that closes the app's per-loop Tortoise context."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from functools import wraps
|
||||
from typing import Any, Callable, Coroutine
|
||||
|
||||
from kca.app import tortoise_mixin
|
||||
|
||||
|
||||
def async_test(coro: Callable[..., Coroutine[Any, Any, None]]) -> Callable[..., None]:
|
||||
@wraps(coro)
|
||||
def wrapper(*args: Any, **kwargs: Any) -> None:
|
||||
async def run() -> None:
|
||||
try:
|
||||
await coro(*args, **kwargs)
|
||||
finally:
|
||||
await tortoise_mixin.aclose()
|
||||
|
||||
with asyncio.Runner() as runner:
|
||||
runner.run(run())
|
||||
|
||||
return wrapper
|
||||
@@ -0,0 +1,35 @@
|
||||
"""Fake the OIDC-authenticated user during tests."""
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import unittest.mock as _mock
|
||||
from typing import Any, Iterator, Optional
|
||||
|
||||
from kaya.oidc import OIDCUser
|
||||
|
||||
from kca.app import oidc
|
||||
|
||||
_PROVIDER = next(iter(oidc.providers))
|
||||
|
||||
|
||||
def make_user(sub: str, name: Optional[str] = None, **claims: Any) -> OIDCUser:
|
||||
data: dict = {"sub": sub, "preferred_username": name or sub}
|
||||
data.update(claims)
|
||||
return OIDCUser(data)
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def oidc_user(
|
||||
sub: str,
|
||||
name: Optional[str] = None,
|
||||
**claims: Any,
|
||||
) -> Iterator[OIDCUser]:
|
||||
data: dict = {"sub": sub, "preferred_username": name or sub}
|
||||
data.update(claims)
|
||||
user = OIDCUser(data)
|
||||
patcher = _mock.patch.object(oidc, "get_users", return_value={_PROVIDER: user})
|
||||
patcher.start()
|
||||
try:
|
||||
yield user
|
||||
finally:
|
||||
patcher.stop()
|
||||
Reference in New Issue
Block a user