Configuration Reference
Inmor is configured through multiple configuration files and environment variables.
Trust Anchor Configuration (taconfig.toml)
The Trust Anchor reads its configuration from taconfig.toml.
# Trust Anchor entity ID (must match public URL)
domain = "https://federation.example.com"
# Redis connection URI
redis_uri = "redis://redis:6379"
# TLS certificate and key (optional if behind reverse proxy)
tls_cert = "cert.pem"
tls_key = "key.pem"
Configuration Options:
Option |
Required |
Description |
|---|---|---|
|
Yes |
The Trust Anchor’s entity identifier URL. This must match the public URL where the TA is accessible. |
|
Yes |
Redis connection URI for storing federation data. |
|
No |
Path to TLS certificate file. Not required if running behind a reverse proxy. |
|
No |
Path to TLS private key file. Not required if running behind a reverse proxy. |
|
No |
Allow HTTP scheme and private/loopback IPs in outbound federation requests. Development only. Defaults to |
Admin Portal Configuration (settings.py)
The Admin Portal is configured through Django settings. Create admin/inmoradmin/localsettings.py
to override defaults.
Core Settings
# Trust Anchor entity ID (must match TA domain)
TA_DOMAIN = "https://federation.example.com"
# Endpoint for trust mark services (usually same as TA_DOMAIN)
TRUSTMARK_PROVIDER = "https://federation.example.com"
# Django security settings
DEBUG = False
SECRET_KEY = "your-production-secret-key"
ALLOWED_HOSTS = ["admin.federation.example.com"]
Federation Endpoints
These are automatically derived from TA_DOMAIN:
FEDERATION_ENTITY = {
"federation_fetch_endpoint": f"{TA_DOMAIN}/fetch",
"federation_list_endpoint": f"{TA_DOMAIN}/list",
"federation_resolve_endpoint": f"{TA_DOMAIN}/resolve",
"federation_trust_mark_status_endpoint": f"{TA_DOMAIN}/trust_mark_status",
"federation_trust_mark_list_endpoint": f"{TA_DOMAIN}/trust_mark_list",
"federation_trust_mark_endpoint": f"{TA_DOMAIN}/trust_mark",
"federation_historical_keys_endpoint": f"{TA_DOMAIN}/historical_keys",
}
Default Values
# Default validity for subordinate statements (in hours)
SUBORDINATE_DEFAULT_VALID_FOR = 8760 # 1 year
# Server entity statement expiry (in hours)
SERVER_EXPIRY = 8760 # 1 year
# Default values for new trust mark types and trust marks
TA_DEFAULTS = {
"trustmarktype": {
"autorenew": True,
"valid_for": 8760, # 1 year in hours
"renewal_time": 48, # Hours before expiry to renew
"active": True,
},
"trustmark": {
"autorenew": True,
"valid_for": 8760,
"renewal_time": 48,
"active": True,
},
}
Trust Marks for the TA
Configure trust marks issued to the TA itself by external issuers:
# Trust marks that appear in TA's entity configuration
TA_TRUSTMARKS = [
{
"trust_mark_type": "https://federation-operator.example.com/trustmarks/verified-ta",
"mark": "eyJhbGciOiJFUzI1NiIsInR5cCI6InRydXN0LW1hcmsrand0In0..."
},
]
# Trusted trust mark issuers
# Maps trust_mark_type URLs to lists of trusted issuer entity_ids
TA_TRUSTED_TRUSTMARK_ISSUERS = {
"https://accreditation-body.example.com/trustmarks/certified": [
"https://accreditation-body.example.com"
],
"https://industry-group.example.com/trustmarks/member": [
"https://industry-group.example.com",
"https://secondary-issuer.example.com"
],
}
Metadata Policy
Define metadata policy for subordinates:
# Policy applied to all subordinate metadata
POLICY_DOCUMENT = {
"metadata_policy": {
"openid_relying_party": {
"grant_types": {
"subset_of": ["authorization_code", "refresh_token"]
},
"response_types": {
"subset_of": ["code"]
}
},
"openid_provider": {
"subject_types_supported": {
"subset_of": ["public", "pairwise"]
}
}
}
}
Database Configuration
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "inmor",
"USER": "inmor",
"PASSWORD": "secure-password",
"HOST": "db.example.com",
"PORT": 5432,
}
}
Redis Configuration
REDIS_LOCATION = "redis://redis.example.com:6379/0"
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": REDIS_LOCATION,
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}
Historical Keys
# Directory containing historical/expired key files
HISTORICAL_KEYS_DIR = "./historical_keys"
Environment Variables
Trust Anchor (Rust)
Variable |
Description |
|---|---|
|
Log level: |
Admin Portal (Django)
Variable |
Description |
|---|---|
|
Set to |
|
PostgreSQL host (default: |
|
PostgreSQL port (default: |
|
Redis connection URI (default: |
|
Path to historical keys directory (default: |
Key Files
Signing Keys
Inmor uses JWK-formatted keys for signing:
inmor/
├── private.json # TA primary signing key
├── publickeys/ # Public keys (included in JWKS)
│ ├── key1.json
│ └── key2.json
└── admin/
└── private.json # Admin signing key
private.json Example:
{
"kty": "EC",
"crv": "P-256",
"x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
"y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
"d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
"kid": "key-1",
"use": "sig",
"alg": "ES256"
}
Historical Keys
Historical keys are stored in historical_keys/ with an exp field:
{
"kty": "EC",
"crv": "P-256",
"x": "...",
"y": "...",
"kid": "old-key-1",
"use": "sig",
"alg": "ES256",
"exp": 1704067200,
"revoked": {
"revoked_at": 1704067200,
"reason": "superseded"
}
}
Use the scripts/add_historical_key.py script to retire keys:
# Move a key to historical with expiry
python scripts/add_historical_key.py publickeys/old-key.json
# Mark as superseded
python scripts/add_historical_key.py publickeys/old-key.json --revoked superseded
# Mark as compromised
python scripts/add_historical_key.py publickeys/old-key.json --revoked compromised
Redis Key Structure
The Trust Anchor stores federation data in Redis:
Key |
Description |
|---|---|
|
TA’s entity configuration JWT |
|
Historical keys JWT |
|
Hash: entity_id → subordinate statement JWT |
|
Hash: entity_id → entity configuration JWT |
|
Set of Relying Party entity IDs |
|
Set of OpenID Provider entity IDs |
|
Set of TA/IA entity IDs |
|
Hash: trust_mark_type → JWT or “revoked” |
|
Set of entity IDs with this trust mark type |
|
Set of all trust mark SHA256 hashes (for validation) |
|
Hash: entity_id → JSON entity object (populated by |
|
Set of entity IDs of a given entity type |
|
Set of entity IDs with a verified trust mark of a given type |
|
Set: registry of indexed trust mark types |
|
Entity Identifier the collection was walked from |
|
Sorted set of entity IDs for consistent ordering |
|
Unix timestamp of the last collection walk |
Example Configuration Files
Production localsettings.py
# admin/inmoradmin/localsettings.py
DEBUG = False
SECRET_KEY = "your-very-secure-production-secret-key"
ALLOWED_HOSTS = ["admin.federation.example.com", "localhost"]
# Trust Anchor configuration
TA_DOMAIN = "https://federation.example.com"
TRUSTMARK_PROVIDER = "https://federation.example.com"
# For intermediate authorities
AUTHORITY_HINTS = []
# Trust marks issued to this TA
TA_TRUSTMARKS = [
{
"trust_mark_type": "https://root-ta.example.com/trustmarks/verified",
"mark": "eyJ..."
}
]
# Trusted issuers for trust mark validation
TA_TRUSTED_TRUSTMARK_ISSUERS = {
"https://accreditation.example.com/trustmarks/certified": [
"https://accreditation.example.com"
]
}
# Custom defaults
SUBORDINATE_DEFAULT_VALID_FOR = 4320 # 180 days
TA_DEFAULTS = {
"trustmarktype": {
"autorenew": True,
"valid_for": 4320, # 180 days
"renewal_time": 168, # 1 week
"active": True,
},
"trustmark": {
"autorenew": True,
"valid_for": 4320,
"renewal_time": 168,
"active": True,
},
}
# Metadata policy
POLICY_DOCUMENT = {
"metadata_policy": {
"openid_relying_party": {
"grant_types": {
"subset_of": ["authorization_code", "refresh_token"]
}
}
}
}
Production taconfig.toml
# taconfig.toml
domain = "https://federation.example.com"
redis_uri = "redis://redis:6379"
# TLS handled by reverse proxy, omit these
# tls_cert = "cert.pem"
# tls_key = "key.pem"
# NEVER set allow_http in production — it disables SSRF protection
# allow_http = false