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

domain

Yes

The Trust Anchor’s entity identifier URL. This must match the public URL where the TA is accessible.

redis_uri

Yes

Redis connection URI for storing federation data.

tls_cert

No

Path to TLS certificate file. Not required if running behind a reverse proxy.

tls_key

No

Path to TLS private key file. Not required if running behind a reverse proxy.

allow_http

No

Allow HTTP scheme and private/loopback IPs in outbound federation requests. Development only. Defaults to false. When disabled (production), all outbound requests enforce HTTPS and reject targets that resolve to private IP ranges (SSRF protection).

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,
    },
}

Authority Hints

For intermediate authorities, configure parent authorities:

# List of parent Trust Anchors/Intermediates
AUTHORITY_HINTS = [
    "https://parent-ta.example.com",
]

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

RUST_LOG

Log level: error, warn, info, debug, trace

Admin Portal (Django)

Variable

Description

INSIDE_CONTAINER

Set to true when running in Docker

DB_HOST

PostgreSQL host (default: db)

DB_PORT

PostgreSQL port (default: 5432)

REDIS_LOCATION

Redis connection URI (default: redis://redis:6379/0)

HISTORICAL_KEYS_DIR

Path to historical keys directory (default: ./historical_keys)

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

inmor:entity_id

TA’s entity configuration JWT

inmor:historical_keys

Historical keys JWT

inmor:subordinates

Hash: entity_id → subordinate statement JWT

inmor:subordinates:jwt

Hash: entity_id → entity configuration JWT

inmor:rp

Set of Relying Party entity IDs

inmor:op

Set of OpenID Provider entity IDs

inmor:taia

Set of TA/IA entity IDs

inmor:tm:{domain}

Hash: trust_mark_type → JWT or “revoked”

inmor:tmtype:{type}

Set of entity IDs with this trust mark type

inmor:tm:alltime

Set of all trust mark SHA256 hashes (for validation)

inmor:collection:entities

Hash: entity_id → JSON entity object (populated by inmor-collection)

inmor:collection:by_type:{type}

Set of entity IDs of a given entity type

inmor:collection:by_trustmark:{type}

Set of entity IDs with a verified trust mark of a given type

inmor:collection:trustmark_types

Set: registry of indexed trust mark types

inmor:collection:trust_anchor

Entity Identifier the collection was walked from

inmor:collection:all_sorted

Sorted set of entity IDs for consistent ordering

inmor:collection:last_updated

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