Juntai IAM Python
juntai-iam is the side-effect-free Python integration library for Juntai
identity and domain authorization. It validates Casdoor API access tokens and
Kubernetes projected workload tokens, evaluates the reviewed Casbin policy
model, installs trusted transaction-local KingbaseES context, and enforces
field-read and field-write decisions.
This repository does not contain an IAM service, HTTP listener, browser session, tenant administration API, secret backend, policy store, audit chain, database migration owner, provider runtime, deployment image, OpenAPI artifact, or generated TypeScript client. Casdoor remains authoritative for organizations, users, groups, roles, OIDC tokens, permissions, models, and Casbin records. Domain repositories remain authoritative for their resources, actions, fields, tables, ACLs, and RLS migrations.
Install
python -m pip install "juntai-iam>=1,<2"
The stable import root is juntai.iam. Importing it performs no discovery,
network request, token validation, database connection, migration, policy
synchronization, listener startup, or global middleware installation.
Compose a service boundary
from juntai.iam import (
JUNTAI_POLICY_MODEL_V1,
AuthorizationRequest,
CasdoorAccessTokenVerifier,
CasdoorPolicyEvaluator,
IamMiddleware,
iam_transaction_context,
project_allowed_fields,
)
verifier = CasdoorAccessTokenVerifier.from_discovery(
issuer=settings.oidc_issuer,
audiences={settings.api_audience},
required_scopes={"juntai.api"},
)
evaluator = CasdoorPolicyEvaluator(
model=JUNTAI_POLICY_MODEL_V1,
policy_source=policy_source,
)
iam = IamMiddleware(verifier=verifier, evaluator=evaluator)
Construct these objects once in the service composition root and inject them. The policy source reads a revisioned snapshot from the configured Casdoor policy integration; this package does not persist or mutate policy.
For a protected operation:
identity = iam.require_human_or_delegated(request)
decision = await iam.authorize(
identity,
AuthorizationRequest(
tenant=identity.tenant_id,
resource=f"axiom/workflows/{workflow_id}",
action="read",
requested_fields=("id", "name", "created_at", "secret_notes"),
),
)
with database.transaction() as transaction:
with iam_transaction_context(transaction, identity, decision):
row = repository.get(transaction, workflow_id)
return project_allowed_fields(row, decision)
Build tenant, resource, action, and requested fields from verified identity and the domain route. Never accept an authorization decision, tenant, group, role, resource, action, or field grant from an untrusted request.
Identity and token rules
IdentityContext is immutable. Human subjects are issuer-qualified Casdoor
subjects; the tenant is the verified Casdoor organization claim. Display name
and email are presentation-only attributes. API validation checks signature,
issuer, audience, authorized party, expiry, not-before, scopes, organization,
key identity, and the exact tokenType=access-token profile. Callers must
forward Casdoor's OAuth access_token response field. Casdoor 3.125 aliases
id_token to the same JWT bytes, so downstream code cannot infer response-field
provenance; any future distinct ID-token profile is rejected as an API
credential.
Discovery and JWKS are fetched lazily and cached. Unknown keys trigger at most
one bounded refresh and fail closed. Previously validated keys may survive a
configured short issuer outage; invalidate_keys() supplies the rotation and
emergency invalidation path.
Workloads use audience-bound projected ServiceAccount tokens validated through
the live Kubernetes TokenReview API. Namespace and ServiceAccount are mapped by
trusted service configuration. delegated_identity() accepts only independently
verified workload and user contexts and enforces same-tenant, shortest-expiry
binding. Delegated authorization uses workload-and-user policy intersection.
The TokenReview client may authenticate with a projected reviewer token or an
explicit Kubernetes client-certificate/key pair supplied by the composition
root; credential files are never read at import time.
Casbin conventions
The reviewed logical policy tuple is:
p = subject_or_role, tenant, resource_pattern, action_pattern, field_pattern, effect
g = subject, role, tenant
Evaluation is default deny and any matching deny overrides allows. Tenant is an
exact verified organization identifier and cannot be wildcarded. Resource,
action, and field patterns use literal slash segments, * for one segment, and
terminal ** for descendants. Regular expressions and executable matcher text
are rejected. Operation policies use field pattern *; requested fields are
evaluated separately through field.read or field.write policies.
AuthorizationDecision binds the result to the exact tenant, resource, action,
allowed fields, matched policy identifiers, revision, correlation-derived
decision identifier, and audit reason. Call invalidate() on the evaluator for
policy revocation, emergency deny, or revision notifications; cache TTL is the
bounded fallback.
KingbaseES integration
iam_transaction_context accepts a DB-API connection or cursor with autocommit
disabled. It uses parameterized set_config(..., true) calls for tenant,
subject, groups, roles, workload, delegation, policy revision, correlation, and
decision values. KingbaseES clears them at transaction end, including pooled
connection reuse.
Domain migrations—not this package—must:
- add
tenant_idto every protected table; - enable and force RLS;
- define tenant policy using
tenant_id = current_setting('juntai.iam.tenant_id', true); - grant runtime access to a dedicated non-superuser, non-owner role without
BYPASSRLS; and - add domain ACL tables for ownership and high-cardinality sharing.
assert_forced_rls() and assert_least_privileged_runtime_role() provide
acceptance checks. Missing transaction context yields NULL in the recommended
predicate and therefore denies every row.
Contracts and compatibility
contracts/identity-context.v1.schema.json and
contracts/authorization-request.v1.schema.json describe in-process data and
test fixtures. They are not network contracts and do not grant authorization.
The legacy juntai_iam_contracts.auth path contains only compatibility imports
for HumanOIDCVerifier and KubernetesTokenReviewer. No legacy service,
KESRepository, secret, policy, or HTTP API is retained. Consumers must migrate
to juntai.iam and domain-owned RLS/policy integrations.
Verification
python -m pip install -e '.[test]'
ruff check .
pytest -m 'not kes and not kubernetes and not casdoor'
python -m build
Real-dependency suites are opt-in and never substitute SQLite, in-memory authority, or fixture platform APIs:
tests/casdoorvalidates a native Casdoor-issued access token through live discovery and JWKS.tests/kubernetesvalidates a projected ServiceAccount token with live TokenReview.tests/kesproves forced RLS, missing-context denial, cross-tenant isolation, and pooled-connection cleanup against KingbaseES.
The deterministic HTTP/JWT and TokenReview test doubles under tests/unit are
unit evidence only.
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 juntai_iam-1.0.0.tar.gz.
File metadata
- Download URL: juntai_iam-1.0.0.tar.gz
- Upload date:
- Size: 27.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67f3f0883cbcd4089ec69af269c2a78c0511d209373de8941c01a17d65f8e437
|
|
| MD5 |
b3448fbaeb125dda97eafad67648ddfa
|
|
| BLAKE2b-256 |
d22a6805be1af3a0cb433760c2e9e8ff97486637d76daacab2f13d07cd12050e
|
Provenance
The following attestation bundles were made for juntai_iam-1.0.0.tar.gz:
Publisher:
publish-python.yml on zephytiju/JuntaiIAMPython
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
juntai_iam-1.0.0.tar.gz -
Subject digest:
67f3f0883cbcd4089ec69af269c2a78c0511d209373de8941c01a17d65f8e437 - Sigstore transparency entry: 2458053373
- Sigstore integration time:
-
Permalink:
zephytiju/JuntaiIAMPython@8e735b7f778a867ef181fd8bd35d1fb91dd3b185 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/zephytiju
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@8e735b7f778a867ef181fd8bd35d1fb91dd3b185 -
Trigger Event:
release
-
Statement type:
File details
Details for the file juntai_iam-1.0.0-py3-none-any.whl.
File metadata
- Download URL: juntai_iam-1.0.0-py3-none-any.whl
- Upload date:
- Size: 30.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7d7cc8a07030cefee95a2016107ed30dcebf95dac1429ac73308052b84ccec0
|
|
| MD5 |
ee4fce0eba84bb40a0c52202711fd3e9
|
|
| BLAKE2b-256 |
f5390e83d69739e1849d10b3989ee0e2f50a4904a724bea7eb981e45ec67fb29
|
Provenance
The following attestation bundles were made for juntai_iam-1.0.0-py3-none-any.whl:
Publisher:
publish-python.yml on zephytiju/JuntaiIAMPython
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
juntai_iam-1.0.0-py3-none-any.whl -
Subject digest:
a7d7cc8a07030cefee95a2016107ed30dcebf95dac1429ac73308052b84ccec0 - Sigstore transparency entry: 2458053632
- Sigstore integration time:
-
Permalink:
zephytiju/JuntaiIAMPython@8e735b7f778a867ef181fd8bd35d1fb91dd3b185 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/zephytiju
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@8e735b7f778a867ef181fd8bd35d1fb91dd3b185 -
Trigger Event:
release
-
Statement type: