Hierarchical key provider for Swarmauri
Project description
Swarmauri Hierarchical Key Provider
Plugin providing a policy-driven composite key provider capable of routing
key operations across multiple child providers. It implements the
IKeyProvider interface and exposes a single HierarchicalKeyProvider
class.
Overview
HierarchicalKeyProvider composes a mapping of named child providers and
routes every key operation to the correct child according to declarative
policies. It offers:
- Create/import routing – specify ordered
CreateRuleobjects that match key class, algorithm, usage, or export policy. The first rule that matches aKeySpecwins. - Automatic discovery – when looking up an unknown key identifier (KID) the provider probes each child until it finds the owning provider and caches the association for future calls.
- Persistent indexing – optionally persist the learned KID → provider map
to JSON via the
index_fileargument so the routing cache survives process restarts. - Capability passthrough – rotate, destroy, list, JWKS, HKDF, and random byte requests are forwarded transparently to the owning (or designated) child provider. JWKS responses are merged across children while avoiding duplicate KIDs.
- Heuristic fallback – if no policy matches a create/import request the provider falls back to sensible defaults: asymmetric keys prefer children named like KMS/PKCS#11, symmetric keys prefer local/file providers, and otherwise the first registered child is used.
Installation
Choose the installer that matches your workflow.
pip
pip install swarmauri_keyprovider_hierarchical
Poetry
poetry add swarmauri_keyprovider_hierarchical
uv
uv venv # create (or reuse) a virtual environment
source .venv/bin/activate
uv pip install swarmauri_keyprovider_hierarchical
If you are already inside a uv-managed environment you can shorten the last
two steps to uv pip install swarmauri_keyprovider_hierarchical.
Quickstart
The example below wires two LocalKeyProvider instances behind a
HierarchicalKeyProvider. Symmetric keys are routed to a local provider while
asymmetric keys land on a provider named kms. The composite provider also
serves random bytes and JWKS responses for all children.
"""Create keys across multiple providers with policy-driven routing."""
import asyncio
from swarmauri_keyprovider_hierarchical import HierarchicalKeyProvider, CreateRule
from swarmauri_keyprovider_local import LocalKeyProvider
from swarmauri_core.key_providers.types import (
ExportPolicy,
KeyAlg,
KeyClass,
KeySpec,
KeyUse,
)
async def main() -> None:
children = {
"kms": LocalKeyProvider(),
"local": LocalKeyProvider(),
}
provider = HierarchicalKeyProvider(
children,
create_policy=[
CreateRule(provider="kms", klass=KeyClass.asymmetric),
CreateRule(provider="local", klass=KeyClass.symmetric),
],
randomness_provider="local", # designate a child for random_bytes
)
symmetric_spec = KeySpec(
klass=KeyClass.symmetric,
alg=KeyAlg.AES256_GCM,
uses=(KeyUse.ENCRYPT, KeyUse.DECRYPT),
export_policy=ExportPolicy.SECRET_WHEN_ALLOWED,
)
asymmetric_spec = KeySpec(
klass=KeyClass.asymmetric,
alg=KeyAlg.ED25519,
uses=(KeyUse.SIGN, KeyUse.VERIFY),
export_policy=ExportPolicy.PUBLIC_ONLY,
)
symmetric_ref = await provider.create_key(symmetric_spec)
asymmetric_ref = await provider.create_key(asymmetric_spec)
random_token = await provider.random_bytes(16)
jwks = await provider.jwks()
print(f"Symmetric key kid: {symmetric_ref.kid}")
print(f"Asymmetric key kid: {asymmetric_ref.kid}")
print(f"Random token length: {len(random_token)} bytes")
print(f"JWKS entries: {len(jwks['keys'])}")
if __name__ == "__main__":
asyncio.run(main())
Running the script prints the generated key identifiers, confirms the random token length, and shows how many public keys were merged into the JWKS document.
Routing policy
CreateRule is a dataclass that narrows matching by any combination of
attributes:
provider(required): the name of the child provider to route to.klass: limit matches to a specificKeyClass(symmetric or asymmetric).algs: iterable of allowedKeyAlgvalues.uses: iterable of desiredKeyUsevalues; at least one requested use must intersect with the spec.export_policies: iterable ofExportPolicyvalues.
Rules are evaluated in order, and the first match wins. When an import policy is not supplied, create rules are re-used for imports.
Index persistence & discovery
Pass index_file to persist the in-memory KID → provider cache as JSON. On
startup, any known mappings are re-loaded (invalid provider names are skipped).
When a lookup is made for an unknown KID the provider probes each child with a
get_key call; if a child recognizes the KID the mapping is remembered and
future calls avoid probing. Destroying a key (without specifying a version)
removes the cached entry.
Randomness & key derivation
Use the randomness_provider and derivation_provider keyword arguments to
pin those helper methods to a specific child. If they are omitted the first
registered provider is used for both random bytes and HKDF requests.
Want to help?
If you want to contribute to swarmauri-sdk, read up on our guidelines for contributing that will help you get started.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file swarmauri_keyprovider_hierarchical-0.3.0.dev46.tar.gz.
File metadata
- Download URL: swarmauri_keyprovider_hierarchical-0.3.0.dev46.tar.gz
- Upload date:
- Size: 11.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fbb26001ee5ed5fef45b870f74388cf0af0d992ef5165c79f11c2476ad16870
|
|
| MD5 |
566fc54860da3dcc4f9b21d29030d54a
|
|
| BLAKE2b-256 |
5e5b7109a958a2aca133a2bc703f48e5a5ff64a34d16e8a34324a0caccd82954
|
File details
Details for the file swarmauri_keyprovider_hierarchical-0.3.0.dev46-py3-none-any.whl.
File metadata
- Download URL: swarmauri_keyprovider_hierarchical-0.3.0.dev46-py3-none-any.whl
- Upload date:
- Size: 12.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.12 {"installer":{"name":"uv","version":"0.10.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e255fa21fe96e638120feeaec3fa837eae2bc2f2a1409b4ea2078cbaa8df03bb
|
|
| MD5 |
bfe55bf39736ffe956d43d78be3b4fa9
|
|
| BLAKE2b-256 |
022333da9f31214360b1a1ab3f472ac97ede76ff9f108058b970e13d31484db7
|