Realm Configuration

Concept

A realm is a fully isolated PKI environment within an OpenXPKI instance. Each realm has its own CA, certificate profiles, authentication configuration, and workflows. A single OpenXPKI instance can run multiple realms simultaneously (e.g. democa and rootca).

Creating a Realm

Add the Realm Definition

Add a new entry to config.d/system/realms.yaml:

myca:
    label: My Production CA
    baseurl: https://pki.example.com/webui/myca/
    description: Production CA for Example Corp

The key (myca here) is the internal name and must consist only of alphanumeric characters and underscores.

Set Up the Directory Structure

The easiest approach is to create symlinks to the realm.tpl template and only copy the files that need customization:

mkdir -p config.d/realm/myca/{workflow/def,profile,notification}
cd config.d/realm/myca

# Shared configurations as symlinks
ln -s ../../realm.tpl/api/
ln -s ../../realm.tpl/auth/
ln -s ../../realm.tpl/crl/
ln -s ../../realm.tpl/crypto.yaml
ln -s ../../realm.tpl/uicontrol/

# Profiles: copy default (customizable), symlink template dir
cp ../../realm.tpl/profile/default.yaml profile/
ln -s ../../../realm.tpl/profile/template/ profile/

# Notifications: copy sample and adjust
cp ../../realm.tpl/notification/smtp.yaml.sample notification/smtp.yaml

# Workflows: global components as symlinks
ln -s ../../../realm.tpl/workflow/global workflow/
ln -s ../../../realm.tpl/workflow/persister.yaml workflow/

# Link all workflow definitions
(cd workflow/def && find ../../../../realm.tpl/workflow/def/ -type f | xargs -L1 ln -s)

# Remove unused workflows (optional)
cd workflow/def
rm est_* scep_*   # if EST/SCEP is not needed

Add the Realm to the WebUI Realm Map

In client.d/service/webui/default.yaml, add the new realm to realm.map (mode path):

realm:
    mode: path
    map:
        democa: democa
        rootca: rootca
        myca: myca      # new entry

The key on the left is the URL path segment, the value on the right is the internal realm name. The realm is then reachable at https://yourhost/webui/myca/.


Authentication

Authentication consists of two layers: handlers (the authentication mechanism) and stacks (the login options visible on the login page).

Handlers (auth/handler.yaml)

A handler defines how credentials are verified:

Anonymous — no login required:

Anonymous:
    type: Anonymous
    label: Guest User

System — for internal processes (hidden in the UI):

System:
    type: Anonymous
    role: System

ClientX509 — authentication with a TLS client certificate:

Certificate:
    type: ClientX509
    role: User
    arg: CN              # which DN component is used as username
    trust_anchor:
        realm: democa    # only accept certificates from this realm

Password (YAML file) — password authentication against a local user file:

LocalPassword:
    type: Password
    user@: connector:auth.connector.userdb

With this connector definition in auth/connector.yaml:

userdb:
    class: Connector::Proxy::YAML
    LOCATION: /etc/openxpki/local/userdb.yaml

The user file has the following structure:

alice:
    digest: "{ssha}JQ2BAoHQZQgecmNjGF143k4U2st6bE5B"
    role: User
    name: Anderson
    gname: Alice
    email: alice@example.com

You can also use argon2 or crypt based digest notation starting with the dollar sign $.

LDAP/Active Directory — authentication via an external directory service:

raop-ad:
    class: Connector::Builtin::Authentication::LDAP
    LOCATION: ldap://ad.company.com
    base: dc=company,dc=loc
    binddn: cn=binduser
    password: secret
    filter: "(&(mail=[% LOGIN %])(memberOf=CN=RA Operator,OU=Groups,DC=company,DC=loc))"

Stacks (auth/stack.yaml)

Stacks define the login options shown on the login page:

Anonymous:
    label: Anonymous
    description: Access as guest without credentials
    handler: Anonymous
    type: anon

LocalPassword:
    label: User Login
    description: Login with username and password
    handler: LocalPassword
    type: passwd

Certificate:
    label: Client certificate
    description: Login using a client certificate
    handler: Certificate
    type: x509

# Internal, hidden in the UI
_System:
    handler: System

Crypto Configuration

The token definition is done per realm in config.d/realm/<realm>/crypto.yaml.

The default configuration reads the PEM blocks of all required asymmetric keys from the database so there is no need to handle any key files on the nodes themselves.

The internal database encryption token is provided directly as AES secret inside the configuration.

For a standard setup using software keys, there is no need to change any of the settings in the token section.

Passphrases and Secrets

The secret management can be done per realm via the secret section in the crypto.yaml file.

Secrets can either be provided literally in the configuration or provided after system startup via the WebUI.

literal — password stored directly in the configuration:

secret:
    default:
        label: Global secret group
        method: literal
        value: my_passphrase

plain/cache — password is entered interactively after startup and cached:

secret:
    default:
        label: CA signing key password
        method: plain
        cache: daemon
        kcv: $argon2id$v=19$...   # optional key check value for verification

The secrets are linked to the token layer via the secret parameter in the token section, the default configuration uses three secrets:

default

Protects the CA signing token

ratoken

Protects the SCEP / RA token - must have export: 1 set to allow the secret to be handed over to the SCEP layer.

svault

Secret used as symmetric encryption key - must be a 64-character hex key (generate with: openssl rand -hex 32)

Secret sharing across realms

It is common to share the secrets across realms, in this case you can add the secret definitions in system/crypto.yaml and import them into the realm:

secret:
    default:
        import: 1

This imports the secret from the global settings into the realm, non-literal secrets need to be entered once after startup in any realm and are afterwards available across all realms that reference it.


CRL Configuration

The CRL configuration is in crl/default.yaml:

validity:
    nextupdate: "+000014"   # CRL valid for 14 days
    renewal: "+000003"      # Issue a new CRL 3 days before the current one expires

digest: sha256

extensions:
    authority_key_identifier:
        critical: 0
        keyid: 1
        issuer: 0

Create a cronjob/timer to call oxi workflow create --realm democa --type crl_issuance in regular intervals to trigger CRL generation.


Publishing

Publication of certificates and CRLs is configured via connector classes (publishing.yaml):

entity:
    disk@: connector:publishing.connectors.local

crl:
    crl@: connector:publishing.connectors.cdp

cacert:
    disk-pem@: connector:publishing.connectors.cacert-pem
    disk-der@: connector:publishing.connectors.cacert-der

connectors:
    local:
        class: Connector::Builtin::File::Path
        LOCATION: /tmp/
        file: "[% ARGS.0.replace('[^\\w-]','_') %].crt"
        content: "[% pem %]"

    cdp:
        class: Connector::Builtin::File::Path
        LOCATION: /var/www/download/
        file: "[% ARGS.0.replace('[^\\w-]','_') %].crl"
        content: "[% der %]"

The ARGS parameter receives an array with one element which holds the CN of the certificate / CRL.

For LDAP publishing, use the class Connector::Proxy::Net::LDAP::Single.


Email Notifications

Notifications are triggered from within workflows and configured in notification/smtp.yaml:

backend:
    class: OpenXPKI::Server::Notification::SMTP
    host: localhost
    port: 25
    starttls: 0
    use_html: 1

default:
    to: "[% data.notify_to %]"
    from: no-reply@mycompany.local
    reply: helpdesk@mycompany.local

template:
    dir: /etc/openxpki/template/email/

message:
    csr_created:
        default:
            template: csr_created_user
            subject: CSR for [% cert_subject %]
        raop:
            template: csr_created_raop
            to: reg-office@mycompany.local
            subject: CSR for [% cert_subject %]

    cert_issued:
        default:
            template: cert_issued
            subject: Certificate issued for [% cert_subject %]

Email templates are stored as .txt (and optionally .html) files in the configured template directory. Template Toolkit is used for variable substitution.