Getting Started
Python Quickstart
Add CoreSDK to a FastAPI, Flask, or Django service.
Python Quickstart
Prerequisites
- Python 3.10+
- A running
coresdk-sidecar(or setfail_mode = "open"to develop without one)
Install
# FastAPI
pip install "coresdk[fastapi]" uvicorn
# Flask
pip install "coresdk[flask]" gunicorn
# Django
pip install "coresdk[django]"
# All frameworks
pip install "coresdk[fastapi,flask,django]"Configure
Create coresdk.toml in your project root:
[sdk]
sidecar_addr = "[::1]:50051"
tenant_id = "acme-corp"
service_name = "my-api"
fail_mode = "open" # "open" = allow on sidecar error; "closed" = deny
dev_mode = true
[observability]
service_version = "0.1.0"
otel_endpoint = "" # set to http://localhost:4317 for trace export
[[tenants.acme-corp]]
display_name = "Acme Corp"All [sdk] keys can be overridden with CORESDK_* env vars:
CORESDK_SIDECAR_ADDR=[::1]:50051 \
CORESDK_TENANT_ID=acme-corp \
CORESDK_FAIL_MODE=closed \
uvicorn main:appInitialize the SDK
import os, tomllib
from pathlib import Path
from coresdk import CoreSDKClient, SDKConfig
# Load from coresdk.toml (with env var overrides)
with open("coresdk.toml", "rb") as f:
cfg = tomllib.load(f)
sdk_cfg = cfg["sdk"]
_sdk = CoreSDKClient(SDKConfig(
sidecar_addr = os.getenv("CORESDK_SIDECAR_ADDR", sdk_cfg["sidecar_addr"]),
tenant_id = os.getenv("CORESDK_TENANT_ID", sdk_cfg["tenant_id"]),
service_name = os.getenv("CORESDK_SERVICE_NAME", sdk_cfg["service_name"]),
fail_mode = os.getenv("CORESDK_FAIL_MODE", sdk_cfg["fail_mode"]),
))Or load entirely from env vars:
from coresdk import CoreSDKClient, SDKConfig
_sdk = CoreSDKClient(SDKConfig.from_env())FastAPI
Add middleware
from fastapi import FastAPI, Request
from coresdk.middleware.fastapi import CoreSDKMiddleware
class SDKAdapter:
config = _sdk.config
def authorize_sync(self, token, **kw):
return _sdk.validate_token(token, **kw)
app = FastAPI()
app.add_middleware(
CoreSDKMiddleware,
sdk=SDKAdapter(),
exclude_paths=["/healthz", "/docs", "/openapi.json"],
)Read claims in your routes
from fastapi import Request
@app.get("/me")
async def me(request: Request):
# CoreSDKMiddleware sets request.state.coresdk_user after auth
user = getattr(request.state, "coresdk_user", None) or {}
return {"sub": user.get("sub"), "tenant": user.get("tenant_id")}Role-based access control
from fastapi import Depends, HTTPException, Request
def require_role(role: str):
def _check(request: Request):
user = getattr(request.state, "coresdk_user", None) or {}
if role not in user.get("roles", []):
raise HTTPException(status_code=403, detail={
"type": "https://coresdk.io/errors/forbidden",
"title": "Forbidden",
"status": 403,
"detail": f"Role '{role}' required",
})
return user
return Depends(_check)
@app.post("/products")
async def create_product(body: dict, _=require_role("editor")):
...
@app.delete("/products/{id}")
async def delete_product(id: int, _=require_role("admin")):
...Multi-tenant isolation
def get_tenant(request: Request) -> str:
user = getattr(request.state, "coresdk_user", None) or {}
return user.get("tenant_id") or "default"
@app.get("/products")
async def list_products(request: Request):
tenant = get_tenant(request)
return db.products.for_tenant(tenant) # always scoped to caller's tenantRego policy evaluation (ABAC)
@app.get("/documents/{doc_id}")
async def get_document(doc_id: str, request: Request):
user = getattr(request.state, "coresdk_user", None) or {}
tenant = get_tenant(request)
doc = db.get_document(doc_id, tenant)
allowed = _sdk.evaluate_policy("data.authz.allow", {
"tenant_id": tenant,
"subject": user.get("sub"),
"action": "read",
"resource": f"documents/{doc_id}",
"resource_owner": doc["owner"],
"context": {"roles": user.get("roles", [])},
})
if not allowed:
raise HTTPException(status_code=403, detail={
"type": "https://coresdk.io/errors/forbidden",
"title": "Forbidden", "status": 403,
})
return docPII-safe tracing
from coresdk.tracing.decorator import trace
@app.get("/products")
@trace(intent="list-products") # creates OTel span; PII scrubbed before export
async def list_products(request: Request):
...RFC 9457 error handler
from fastapi.responses import JSONResponse
from coresdk.errors._rfc9457 import ProblemDetailError
@app.exception_handler(ProblemDetailError)
async def problem_detail_handler(request: Request, exc: ProblemDetailError):
return JSONResponse(
status_code=exc.status,
content=exc.to_dict(),
media_type="application/problem+json",
)Flask
from flask import Flask, g
from coresdk.middleware.flask import CoreSDKFlask
from coresdk.tracing.decorator import trace
app = Flask(__name__)
CoreSDKFlask(_sdk, app) # registers before_request hook + ProblemDetailError handler
@app.get("/me")
@trace(intent="get-current-user")
def me():
# Flask middleware stores claims on flask.g.claims
return (g.claims or {"sub": "anonymous"}), 200
@app.post("/products")
def create_product():
user = g.claims or {}
if "editor" not in user.get("roles", []):
return {"type": "https://coresdk.io/errors/forbidden",
"title": "Forbidden", "status": 403}, 403, \
{"Content-Type": "application/problem+json"}
...Django
# settings.py
MIDDLEWARE = [
"coresdk.django.CoreSDKMiddleware",
"django.middleware.common.CommonMiddleware",
# ...
]
CORESDK = {
"sidecar_addr": "[::1]:50051",
"tenant_id": "acme-corp",
"fail_mode": "open",
"service_name": "my-django-api",
}# views.py
from django.http import JsonResponse
from coresdk.tracing.decorator import trace
@trace(intent="get-current-user")
def me(request):
# Django middleware stores claims on request.coresdk_claims
claims = getattr(request, "coresdk_claims", None) or {}
return JsonResponse({"sub": claims.get("sub"), "tenant": claims.get("tenant_id")})
def require_role(role):
def decorator(view):
def wrapper(request, *args, **kwargs):
claims = getattr(request, "coresdk_claims", None) or {}
if role not in claims.get("roles", []):
return JsonResponse({
"type": "https://coresdk.io/errors/forbidden",
"title": "Forbidden", "status": 403,
}, status=403, content_type="application/problem+json")
return view(request, *args, **kwargs)
return wrapper
return decoratorWhere claims live by framework
| Framework | Claims location |
|---|---|
| FastAPI | request.state.coresdk_user |
| Flask | flask.g.claims |
| Django | request.coresdk_claims |
Full working examples
python/fastapi-app/— full project with ABAC, RBAC, multi-tenancy, 13 testspython/flask-app/— Flask edition, 11 testspython/django-app/— Django DRF edition, 11 tests