From 4c81a5667657fdcd2f448c28dbd31c954e9dd69a Mon Sep 17 00:00:00 2001 From: Karol Hrdina Date: Fri, 17 Jul 2026 10:21:28 +0200 Subject: [PATCH 01/11] docs: add OTPKI Connector integration guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Administrator-facing guide for the OTPKI Connector — an ILM Authority Provider v3 connector that fronts the OTPKI backend over Connect-RPC. Covers deployment (environment variables, Docker, Kubernetes), connector registration, authority and RA-profile configuration, the certificate lifecycle (issue, renew, register, revoke, discover, CRL), the Attributes v2 interface, constraints, and troubleshooting. Also lists the connector in the available-connectors catalog. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../connectors/available-connectors.md | 1 + .../otpki-connector/_category_.json | 8 + .../otpki-connector/integration-guide.md | 290 ++++++++++++++++++ 3 files changed, 299 insertions(+) create mode 100644 docs/certificate-key/integration-guides/otpki-connector/_category_.json create mode 100644 docs/certificate-key/integration-guides/otpki-connector/integration-guide.md diff --git a/docs/certificate-key/connectors/available-connectors.md b/docs/certificate-key/connectors/available-connectors.md index d2ccd5ea9..de986edbd 100644 --- a/docs/certificate-key/connectors/available-connectors.md +++ b/docs/certificate-key/connectors/available-connectors.md @@ -25,6 +25,7 @@ The following `Connectors` are officially available: | HashiCorp Vault Connector | Authority Provider | HVault | | | Discovery Provider | HVault | | | Secret Provider | | +| OTPKI Connector | Authority Provider | | | Keystore Entity Provider | Entity Provider | Keystore | | PyADCS Connector | Authority Provider | PyADCS-WinRM | | | Discovery Provider | PyADCS-WinRM | diff --git a/docs/certificate-key/integration-guides/otpki-connector/_category_.json b/docs/certificate-key/integration-guides/otpki-connector/_category_.json new file mode 100644 index 000000000..180f625b0 --- /dev/null +++ b/docs/certificate-key/integration-guides/otpki-connector/_category_.json @@ -0,0 +1,8 @@ +{ + "position": 22, + "label": "OTPKI Connector", + "link": { + "type": "doc", + "id": "integration-guide" + } +} diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md new file mode 100644 index 000000000..87a894a95 --- /dev/null +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -0,0 +1,290 @@ +--- +sidebar_position: 1 +--- + +# Integration Guide + +:::info +This integration guide assumes basic knowledge of ILM [`Connectors`](../../concept-design/architecture/connector.md), [`Authorities`](../../concept-design/core-components/authority.md), and [`RA Profiles`](../../concept-design/core-components/ra-profile.md), and that you already have a running OTPKI installation. It focuses on the steps needed to connect OTPKI to ILM through the OTPKI Connector. +::: + +This document explains how to deploy the OTPKI Connector, register it with ILM, and configure an `Authority` and `RA Profiles` so you can issue, renew, revoke, and discover certificates from OTPKI through ILM. + +The OTPKI Connector is an ILM **Authority Provider** connector. It exposes the ILM Authority Provider v3 REST interface to ILM `Core` and translates each request into calls to an OTPKI backend over Connect-RPC. The connector is **stateless** — it keeps no data of its own — and a single instance can serve any number of OTPKI authorities, because every request carries the details of the OTPKI installation it applies to. + +Through its `/v2/info` endpoint the connector advertises the following interfaces: + +| Interface | Version | Purpose | +|------------|---------|--------------------------------------------------------------------| +| `authority`| v3 | Certificate issuance, renewal, registration, revocation, discovery | +| `info` | v2 | Connector identity and supported interfaces | +| `health` | v2 | Liveness and readiness health checks | +| `metrics` | v1 | Prometheus metrics | + +:::info[OTPKI installation] +This guide assumes that OTPKI is already installed, running, and reachable from where the connector runs. Installing and operating OTPKI itself is out of scope of this document. +::: + +## How the connector works + +ILM `Core` never talks to OTPKI directly. It calls the connector's Authority Provider v3 endpoints, and the connector calls OTPKI's `EnrollmentService`, `IssuanceService`, and `ValidationService` over Connect-RPC. A certificate issuance, for example, flows like this: + +```plantuml +@startuml +autonumber +actor Client +participant "ILM Core" as Core +participant "OTPKI Connector" as Conn +participant "OTPKI" as PKI + +Client -> Core : Issue certificate (CSR via RA profile) +Core -> Conn : POST /v3/authorityProvider/certificates/issue +Conn -> PKI : Create end entity, submit enrollment (Connect-RPC) +PKI --> Conn : Issued certificate +Conn --> Core : Certificate + tracking metadata +Core --> Client : Issued certificate +@enduml +``` + +Configuration is split into two independent planes, and it is important to keep them apart: + +- **Process configuration** — how the connector *runs*: listen port, logging, TLS trust bundle, tracing, and the password key. This is set through **environment variables** on the connector process (see [Deploy the connector](#deploy-the-connector)). +- **OTPKI connection** — *which* OTPKI installation to talk to and how to authenticate to it: base URL, token URL, OAuth2 credentials, TLS trust, timeouts, and retries. This is **not** set through environment variables. It is entered in ILM as `Authority` attributes (see [Create an authority](#create-an-authority)) and travels with every request. A freshly deployed connector has no OTPKI target until ILM sends it a request. + +## Prerequisites + +Before you begin, make sure you have: + +- A running ILM instance with permission to register connectors and create authorities and RA profiles. +- A running OTPKI installation, reachable over the network from the connector. +- OAuth2 **client credentials** for OTPKI: a token endpoint (Token URL) and a client id / client secret that OTPKI accepts through the `client_credentials` grant. Scope and audience are optional and only needed if your identity provider requires them. +- A host (container runtime or Kubernetes cluster) to run the connector, reachable from ILM `Core`. +- If OTPKI is served by a private CA, the CA certificate(s) so the connector can trust the OTPKI endpoint. + +## Deploy the connector + +The connector is distributed as the container image `ilm/otpki-connector`. It is a single static binary, runs as the non-root user `ilm` (UID/GID `10001`), needs no database or writable volumes, and listens for **plain HTTP** on the port given by `PORT` (default `8080`). Terminate TLS at an ingress or service mesh in front of it and restrict inbound access to ILM `Core`. + +### Configuration (environment variables) + +The connector *process* is configured entirely through the environment variables below. Note that none of them point the connector at OTPKI — the OTPKI connection is configured later as `Authority` attributes. + +| Variable | Default | Required | Purpose | +|---------------------------------|-------------------|----------|----------------------------------------------------------------------------------------------------------| +| `PORT` | `8080` | No | HTTP listen port. | +| `LOG_LEVEL` | `INFO` | No | Log level: `DEBUG`, `INFO`, `WARN`, or `ERROR`. | +| `TRUSTED_CERTIFICATES` | _(unset)_ | No | PEM bundle (concatenated `CERTIFICATE` blocks) added to the base TLS trust pool for outbound calls. | +| `OTPKI_LOGIN_PASSWORD_KEY` | _(unset)_ | Yes (production) | HMAC-SHA256 key used to derive OTPKI end-entity passwords. See the warning below. | +| `OTEL_SERVICE_NAME` | `otpki-connector` | No | OpenTelemetry service name. | +| `OTEL_EXPORTER_OTLP_ENDPOINT` | _(unset)_ | No | OTLP/HTTP trace exporter endpoint. Traces are sampled and propagated regardless, but only exported when set. | +| `TRACING_SAMPLING_PROBABILITY` | `1.0` | No | Trace sampling ratio, `0.0`–`1.0`. | +| `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` | _(unset)_ | No | Standard Go proxy configuration for all outbound OTPKI and token calls. | + +:::warning[Set OTPKI_LOGIN_PASSWORD_KEY in production] +For every certificate it issues, the connector creates or reuses an OTPKI end entity and needs a password for it. That password is derived deterministically from the end entity's login id using `HMAC-SHA256(OTPKI_LOGIN_PASSWORD_KEY, loginId)`, so nothing has to be stored. If `OTPKI_LOGIN_PASSWORD_KEY` is left unset, the connector falls back to using the login id itself as the password and logs a one-time warning. **Always set a strong, secret `OTPKI_LOGIN_PASSWORD_KEY` in production**, and keep it stable — changing it changes the derived passwords for existing end entities. +::: + +### Run with Docker + +```sh +docker run --rm \ + -p 8080:8080 \ + -e PORT=8080 \ + -e LOG_LEVEL=INFO \ + -e OTPKI_LOGIN_PASSWORD_KEY=change-me \ + ilm/otpki-connector +``` + +Add `-e TRUSTED_CERTIFICATES="$(cat ca-bundle.pem)"` if outbound calls need extra trust roots, and `-e OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318` to export traces. + +### Run on Kubernetes + +No Helm chart or manifests ship with the connector — deploy it as a standard stateless `Deployment` and `Service`. A minimal, hardened pod spec looks like this: + +```yaml title="otpki-connector.yaml" +apiVersion: apps/v1 +kind: Deployment +metadata: + name: otpki-connector +spec: + replicas: 2 + selector: + matchLabels: + app: otpki-connector + template: + metadata: + labels: + app: otpki-connector + spec: + securityContext: + runAsNonRoot: true + runAsUser: 10001 + runAsGroup: 10001 + containers: + - name: otpki-connector + image: ilm/otpki-connector + ports: + - containerPort: 8080 + env: + - name: PORT + value: "8080" + - name: OTPKI_LOGIN_PASSWORD_KEY + valueFrom: + secretKeyRef: + name: otpki-connector + key: loginPasswordKey + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + livenessProbe: + httpGet: + path: /v2/health/liveness + port: 8080 + readinessProbe: + httpGet: + path: /v2/health/readiness + port: 8080 +``` + +:::info[Readiness does not test OTPKI] +The connector's liveness and readiness probes report the status of the connector process only — they return healthy as long as the process is up and do **not** check that OTPKI is reachable. To verify the OTPKI connection, use the authority **connect** action in ILM (see [Create an authority](#create-an-authority)). +::: + +### Endpoints, health, and metrics + +The connector serves these routes: + +| Route | Purpose | +|-----------------------------------------|---------------------------------------------------------------| +| `GET /v2/info` | Connector identity and supported interfaces. | +| `GET /v2/health` | Aggregate health. | +| `GET /v2/health/liveness` | Liveness probe. | +| `GET /v2/health/readiness` | Readiness probe. | +| `GET /v1/metrics` | Prometheus / OpenMetrics. | +| `/v3/authorityProvider/*` | Authority Provider v3 operations. | +| `/v2/attributes`, `/v2/attributes/{uuid}`, `/v2/attributes/callback` | Attribute discovery (see [Attribute discovery](#attribute-discovery)). | + +Logs are written as JSON to standard output, with bearer tokens, passwords, client secrets, and CSRs redacted. Tracing uses the OpenTelemetry environment variables above. For background on these interfaces, see the connector [common interfaces](../../connectors/common-interfaces/overview.md) documentation ([health](../../connectors/common-interfaces/health-interface.md), [metrics](../../connectors/common-interfaces/metrics-interface.md), [info](../../connectors/common-interfaces/info-interface.md)). + +## Register the connector in ILM + +Once the connector is running and reachable from ILM `Core`, register it as a connector. The connector requires **no inbound authentication**, so register it with authentication type `none` and the connector's base URL, for example `http://otpki-connector:8080`. + +ILM reads `/v2/info` during registration to learn the connector's identity and supported interfaces. For the full registration flow (Web UI and API), see [Register connectors](../../quick-start/certificate-management/register-connectors.mdx). + +## Create an authority + +Create an `Authority` that uses the registered OTPKI Connector. The authority attributes are the OTPKI connection details. + +Before you start, create the supporting objects in ILM: + +- A **Basic Authentication** credential holding the OTPKI OAuth2 client — its **username** is the OAuth client id and its **password** is the OAuth client secret. It is selected in the **OAuth client** attribute. +- If OTPKI uses a private CA, upload the CA certificate(s) so they can be selected in the **TLS trust** attribute. + +The authority attributes are: + +| Attribute | Required | Default | Description | +|----------------------|----------|---------|---------------------------------------------------------------------------------------------------------------| +| **Base URL** | Yes | — | Address of the OTPKI server, for example `https://otpki.example.com:15580`. | +| **Token URL** | Yes | — | OAuth2 token endpoint that issues access tokens for OTPKI, for example `https://auth.example.com/realms/otpki/protocol/openid-connect/token`. | +| **OAuth client** | Yes | — | A stored **Basic Authentication** credential. Its username is the OAuth client id; its password is the OAuth client secret. | +| **OAuth scope** | No | — | Scope sent when requesting access tokens. Leave blank unless your identity provider requires one. | +| **OAuth audience** | No | — | Audience sent when requesting access tokens. Leave blank unless your identity provider requires one. | +| **TLS trust** | No | — | One or more **Root CA** or **Intermediate CA** certificates to trust the OTPKI endpoint. Leave empty to use only the system trust store. | +| **Call deadline (ms)** | No | `30000` | Maximum time to wait for a single call to OTPKI before timing out. | +| **Retry max attempts** | No | `3` | How many times a safe, read-only call is retried when OTPKI is briefly unavailable. State-changing calls are never retried. | +| **Retry initial backoff (ms)** | No | `500` | Wait before the first retry. | +| **Retry max backoff (ms)** | No | `5000` | Upper bound on the wait between retries. | + +The connector authenticates to OTPKI with the OAuth2 `client_credentials` grant and reuses access tokens until shortly before they expire. There is no mutual TLS to OTPKI; authentication is by bearer token only. + +When you create or update the authority, ILM runs a **connect** action that lists the OTPKI certificate authorities as a connectivity and credential check. If it fails, verify the Base URL, Token URL, OAuth client, and TLS trust. For the general flow, see [Create an authority](../../quick-start/certificate-management/create-authority.mdx). + +## Create an RA profile + +Create one or more `RA Profiles` against the OTPKI authority. An RA profile decides which OTPKI templates and CA are used and how each issued end entity is named. + +**Select the End Entity Profile first.** The **Certificate Profile** and **Certificate Authority** dropdowns are then populated by a callback that returns only the options the selected end-entity profile allows. + +| Attribute | Required | Description | +|-------------------------|----------|------------------------------------------------------------------------------------------------------| +| **End Entity Profile** | Yes | OTPKI end-entity profile that defines the allowed certificate profiles and CAs. Populated from OTPKI. | +| **Certificate Profile** | Yes | OTPKI certificate template to issue from. Populated from the selected end-entity profile. | +| **Certificate Authority** | Yes | OTPKI CA that signs the certificates. Populated from the selected end-entity profile. | +| **Login ID strategy** | Yes | How the OTPKI end-entity username is derived for each issued certificate (see below). | +| **Login ID DN attribute** | No | Subject DN attribute to use as the login id. Required only when the strategy is *Login ID from DN attribute*, for example `UID`. | +| **Login ID custom value** | No | Fixed login id value. Required only when the strategy is *Custom login ID*. | +| **Username prefix** | No | Text added before the derived login id, for example `otpki-`. | +| **Username postfix** | No | Text added after the derived login id, for example `-prod`. | + +The **Login ID strategy** options are: + +| Option | Meaning | +|----------------------------|-------------------------------------------------------------------------------| +| **Login ID from CN** | Use the CN from the certificate request. | +| **Login ID from DN attribute** | Use a specific subject DN attribute (set *Login ID DN attribute*). | +| **Custom login ID** | Always use the same value (set *Login ID custom value*). | +| **Random login ID** | Generate a unique value for each certificate. | + +The derived login id (including any prefix and postfix) must be between 3 and 64 characters long. For the general flow, see [Create an RA profile](../../quick-start/certificate-management/create-ra-profile.mdx). + +## Issue and manage certificates + +With an authority and RA profile in place, certificates can be managed through ILM as with any other Authority Provider. No extra attributes are required at issuance, renewal, registration, or revocation time — everything comes from the RA profile, the certificate request, and (for revocation) the chosen reason. + +The connector stores tracking metadata on each certificate (the OTPKI end-entity id, certificate id, request ids, profile and CA ids). ILM round-trips this metadata back to the connector so that later renewal, revocation, and discovery can find the right OTPKI objects without the connector holding any state. + +### Issuing and renewing + +Issuance takes a CSR and the RA profile settings. The connector derives the login id from the request (per the RA profile's Login ID strategy), creates the OTPKI end entity if needed, and submits the enrollment. If OTPKI issues synchronously, the certificate is returned immediately; otherwise ILM polls until it completes. Renewal submits a new CSR for the existing end entity resolved from the certificate metadata. + +### Registering existing certificates + +Registration pre-creates an end-entity identity in OTPKI from a subject (no CSR, no enrollment) so the certificate can be managed through this authority later. + +### Revoking + +Revocation revokes the certificate in OTPKI using the reason chosen on the revocation form. The following ILM revocation reasons are supported: `unspecified`, `keyCompromise`, `cACompromise`, `affiliationChanged`, `superseded`, `cessationOfOperation`, `certificateHold`, `privilegeWithdrawn`, and `aACompromise`. Any other reason is rejected. + +### Discovering certificates + +Certificate identification looks up a certificate in OTPKI by its serial number and returns the tracking metadata needed to manage it. This is how certificates that were not issued through ILM become manageable through this authority. + +### CRL and CA certificates + +The connector serves the latest CRL and the CA certificate chain for the CA selected in the RA profile, which ILM uses for validation and chain building. + +## Attribute discovery + +The connector implements the common **Attributes v2** interface — a read-only, connector-wide catalog of every attribute it can request, so ILM `Core` can discover and resolve attribute definitions without keeping per-connector state. It exposes three routes: + +| Route | Purpose | +|--------------------------------|-----------------------------------------------------------------------------------------------------| +| `GET /v2/attributes` | The full attribute-definition registry (authority, RA profile, and per-operation attributes). | +| `GET /v2/attributes/{uuid}` | A single definition by UUID. Returns `ATTRIBUTE_DEFINITION_NOT_FOUND` (HTTP 404) when unknown. | +| `POST /v2/attributes/callback` | Resolves the cascading dropdowns (the certificate profiles and CAs allowed by a selected end-entity profile) statelessly, from the connection details supplied in the request. | + +You do not call these routes directly — ILM `Core` uses them when it builds the authority and RA profile forms. See the connector [attributes interface](../../connectors/common-interfaces/attributes-interface.md) documentation for background. + +## Constraints + +The following are known constraints of the OTPKI Connector: + +| Constraint | Note | +|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------| +| Issuance, registration, and revocation cannot be cancelled | OTPKI has no cancel operation; cancel requests are rejected. | +| CRMF requests require a Login ID strategy of **Custom** or **Random** | The subject cannot be read from an opaque CRMF body, so the login id cannot be derived from the CN or a DN attribute. | +| Renewal requires a CSR | CSR-less or key-reuse renewal is not supported. | +| The connector authenticates to OTPKI with an OAuth2 bearer token only | There is no mutual TLS to OTPKI. | +| The connector serves plain HTTP | Terminate TLS at an ingress or service mesh and restrict inbound access to ILM `Core`. | +| Readiness does not test OTPKI connectivity | Use the authority **connect** action to verify the OTPKI connection. | + +## Troubleshooting + +- **The authority connect action fails.** Check that the **Base URL** and **Token URL** are reachable from the connector, that the **OAuth client** credential holds a valid client id and secret, and that any private OTPKI CA is selected in **TLS trust** (or added through `TRUSTED_CERTIFICATES`). +- **Upstream authentication errors.** Confirm the OAuth client credentials, and add the **OAuth scope** and **OAuth audience** if your identity provider requires them. +- **TLS handshake errors reaching OTPKI.** Add the OTPKI CA certificate to the authority's **TLS trust** attribute, or to the connector's `TRUSTED_CERTIFICATES` bundle. +- **Login id errors.** Make sure the derived login id (with any prefix and postfix) is between 3 and 64 characters, and that CRMF requests use the **Custom** or **Random** strategy. +- **End-entity password issues after a redeploy.** Confirm `OTPKI_LOGIN_PASSWORD_KEY` is set and unchanged; changing it changes the passwords derived for existing end entities. + +Errors are returned as RFC 9457 `application/problem+json` responses whose `type` links to `https://docs.otilm.com/problems/common/`, with a machine-readable `errorCode` and a `retryable` flag. Increase detail by setting `LOG_LEVEL=DEBUG`, and enable tracing with `OTEL_EXPORTER_OTLP_ENDPOINT` to follow a request through to OTPKI. From b2748bad01d543c8d827ba25c005eee249dc63e2 Mon Sep 17 00:00:00 2001 From: Karol Hrdina Date: Fri, 17 Jul 2026 12:28:49 +0200 Subject: [PATCH 02/11] docs: focus OTPKI guide on OTPKI-side configuration and testing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework the OTPKI Connector integration guide per review: describe what must be configured in OTPKI (OAuth2 client, CA, certificate profile, end-entity profile) and how to test the integration, matching the other integration guides. Remove the connector deployment and internal API details — the connector is deployed with ILM through the Helm chart or operator. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../otpki-connector/integration-guide.md | 313 ++++-------------- 1 file changed, 72 insertions(+), 241 deletions(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index 87a894a95..c4a5b970a 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -5,286 +5,117 @@ sidebar_position: 1 # Integration Guide :::info -This integration guide assumes basic knowledge of ILM [`Connectors`](../../concept-design/architecture/connector.md), [`Authorities`](../../concept-design/core-components/authority.md), and [`RA Profiles`](../../concept-design/core-components/ra-profile.md), and that you already have a running OTPKI installation. It focuses on the steps needed to connect OTPKI to ILM through the OTPKI Connector. +This integration guide assumes basic knowledge of ILM [`Connectors`](../../concept-design/architecture/connector.md), [`Authorities`](../../concept-design/core-components/authority.md), and [`RA Profiles`](../../concept-design/core-components/ra-profile.md), and that you already have a running OTPKI installation. It focuses on what has to be configured in OTPKI so that ILM can manage certificates through it, and on how to test the integration. ::: -This document explains how to deploy the OTPKI Connector, register it with ILM, and configure an `Authority` and `RA Profiles` so you can issue, renew, revoke, and discover certificates from OTPKI through ILM. +ILM manages certificates in OTPKI through the **OTPKI Connector**, an Authority Provider connector. The connector is deployed together with ILM (through the ILM Helm chart or operator), so deploying it is not part of this guide. What you do need to prepare is the OTPKI side: an OAuth2 client the connector can authenticate as, and the certificate authority and templates it issues from. -The OTPKI Connector is an ILM **Authority Provider** connector. It exposes the ILM Authority Provider v3 REST interface to ILM `Core` and translates each request into calls to an OTPKI backend over Connect-RPC. The connector is **stateless** — it keeps no data of its own — and a single instance can serve any number of OTPKI authorities, because every request carries the details of the OTPKI installation it applies to. - -Through its `/v2/info` endpoint the connector advertises the following interfaces: - -| Interface | Version | Purpose | -|------------|---------|--------------------------------------------------------------------| -| `authority`| v3 | Certificate issuance, renewal, registration, revocation, discovery | -| `info` | v2 | Connector identity and supported interfaces | -| `health` | v2 | Liveness and readiness health checks | -| `metrics` | v1 | Prometheus metrics | +This document outlines the steps to take in OTPKI before the connector can be configured, how to connect an OTPKI authority in ILM, and how to test the integration. :::info[OTPKI installation] -This guide assumes that OTPKI is already installed, running, and reachable from where the connector runs. Installing and operating OTPKI itself is out of scope of this document. -::: - -## How the connector works - -ILM `Core` never talks to OTPKI directly. It calls the connector's Authority Provider v3 endpoints, and the connector calls OTPKI's `EnrollmentService`, `IssuanceService`, and `ValidationService` over Connect-RPC. A certificate issuance, for example, flows like this: - -```plantuml -@startuml -autonumber -actor Client -participant "ILM Core" as Core -participant "OTPKI Connector" as Conn -participant "OTPKI" as PKI - -Client -> Core : Issue certificate (CSR via RA profile) -Core -> Conn : POST /v3/authorityProvider/certificates/issue -Conn -> PKI : Create end entity, submit enrollment (Connect-RPC) -PKI --> Conn : Issued certificate -Conn --> Core : Certificate + tracking metadata -Core --> Client : Issued certificate -@enduml -``` - -Configuration is split into two independent planes, and it is important to keep them apart: - -- **Process configuration** — how the connector *runs*: listen port, logging, TLS trust bundle, tracing, and the password key. This is set through **environment variables** on the connector process (see [Deploy the connector](#deploy-the-connector)). -- **OTPKI connection** — *which* OTPKI installation to talk to and how to authenticate to it: base URL, token URL, OAuth2 credentials, TLS trust, timeouts, and retries. This is **not** set through environment variables. It is entered in ILM as `Authority` attributes (see [Create an authority](#create-an-authority)) and travels with every request. A freshly deployed connector has no OTPKI target until ILM sends it a request. - -## Prerequisites - -Before you begin, make sure you have: - -- A running ILM instance with permission to register connectors and create authorities and RA profiles. -- A running OTPKI installation, reachable over the network from the connector. -- OAuth2 **client credentials** for OTPKI: a token endpoint (Token URL) and a client id / client secret that OTPKI accepts through the `client_credentials` grant. Scope and audience are optional and only needed if your identity provider requires them. -- A host (container runtime or Kubernetes cluster) to run the connector, reachable from ILM `Core`. -- If OTPKI is served by a private CA, the CA certificate(s) so the connector can trust the OTPKI endpoint. - -## Deploy the connector - -The connector is distributed as the container image `ilm/otpki-connector`. It is a single static binary, runs as the non-root user `ilm` (UID/GID `10001`), needs no database or writable volumes, and listens for **plain HTTP** on the port given by `PORT` (default `8080`). Terminate TLS at an ingress or service mesh in front of it and restrict inbound access to ILM `Core`. - -### Configuration (environment variables) - -The connector *process* is configured entirely through the environment variables below. Note that none of them point the connector at OTPKI — the OTPKI connection is configured later as `Authority` attributes. - -| Variable | Default | Required | Purpose | -|---------------------------------|-------------------|----------|----------------------------------------------------------------------------------------------------------| -| `PORT` | `8080` | No | HTTP listen port. | -| `LOG_LEVEL` | `INFO` | No | Log level: `DEBUG`, `INFO`, `WARN`, or `ERROR`. | -| `TRUSTED_CERTIFICATES` | _(unset)_ | No | PEM bundle (concatenated `CERTIFICATE` blocks) added to the base TLS trust pool for outbound calls. | -| `OTPKI_LOGIN_PASSWORD_KEY` | _(unset)_ | Yes (production) | HMAC-SHA256 key used to derive OTPKI end-entity passwords. See the warning below. | -| `OTEL_SERVICE_NAME` | `otpki-connector` | No | OpenTelemetry service name. | -| `OTEL_EXPORTER_OTLP_ENDPOINT` | _(unset)_ | No | OTLP/HTTP trace exporter endpoint. Traces are sampled and propagated regardless, but only exported when set. | -| `TRACING_SAMPLING_PROBABILITY` | `1.0` | No | Trace sampling ratio, `0.0`–`1.0`. | -| `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` | _(unset)_ | No | Standard Go proxy configuration for all outbound OTPKI and token calls. | - -:::warning[Set OTPKI_LOGIN_PASSWORD_KEY in production] -For every certificate it issues, the connector creates or reuses an OTPKI end entity and needs a password for it. That password is derived deterministically from the end entity's login id using `HMAC-SHA256(OTPKI_LOGIN_PASSWORD_KEY, loginId)`, so nothing has to be stored. If `OTPKI_LOGIN_PASSWORD_KEY` is left unset, the connector falls back to using the login id itself as the password and logs a one-time warning. **Always set a strong, secret `OTPKI_LOGIN_PASSWORD_KEY` in production**, and keep it stable — changing it changes the derived passwords for existing end entities. -::: - -### Run with Docker - -```sh -docker run --rm \ - -p 8080:8080 \ - -e PORT=8080 \ - -e LOG_LEVEL=INFO \ - -e OTPKI_LOGIN_PASSWORD_KEY=change-me \ - ilm/otpki-connector -``` - -Add `-e TRUSTED_CERTIFICATES="$(cat ca-bundle.pem)"` if outbound calls need extra trust roots, and `-e OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318` to export traces. - -### Run on Kubernetes - -No Helm chart or manifests ship with the connector — deploy it as a standard stateless `Deployment` and `Service`. A minimal, hardened pod spec looks like this: - -```yaml title="otpki-connector.yaml" -apiVersion: apps/v1 -kind: Deployment -metadata: - name: otpki-connector -spec: - replicas: 2 - selector: - matchLabels: - app: otpki-connector - template: - metadata: - labels: - app: otpki-connector - spec: - securityContext: - runAsNonRoot: true - runAsUser: 10001 - runAsGroup: 10001 - containers: - - name: otpki-connector - image: ilm/otpki-connector - ports: - - containerPort: 8080 - env: - - name: PORT - value: "8080" - - name: OTPKI_LOGIN_PASSWORD_KEY - valueFrom: - secretKeyRef: - name: otpki-connector - key: loginPasswordKey - securityContext: - readOnlyRootFilesystem: true - allowPrivilegeEscalation: false - livenessProbe: - httpGet: - path: /v2/health/liveness - port: 8080 - readinessProbe: - httpGet: - path: /v2/health/readiness - port: 8080 -``` - -:::info[Readiness does not test OTPKI] -The connector's liveness and readiness probes report the status of the connector process only — they return healthy as long as the process is up and do **not** check that OTPKI is reachable. To verify the OTPKI connection, use the authority **connect** action in ILM (see [Create an authority](#create-an-authority)). +Installing and operating OTPKI is out of scope of this document. This guide assumes OTPKI is installed, running, and reachable from ILM. Refer to the OTPKI documentation for the exact administration steps referenced below. ::: -### Endpoints, health, and metrics - -The connector serves these routes: - -| Route | Purpose | -|-----------------------------------------|---------------------------------------------------------------| -| `GET /v2/info` | Connector identity and supported interfaces. | -| `GET /v2/health` | Aggregate health. | -| `GET /v2/health/liveness` | Liveness probe. | -| `GET /v2/health/readiness` | Readiness probe. | -| `GET /v1/metrics` | Prometheus / OpenMetrics. | -| `/v3/authorityProvider/*` | Authority Provider v3 operations. | -| `/v2/attributes`, `/v2/attributes/{uuid}`, `/v2/attributes/callback` | Attribute discovery (see [Attribute discovery](#attribute-discovery)). | - -Logs are written as JSON to standard output, with bearer tokens, passwords, client secrets, and CSRs redacted. Tracing uses the OpenTelemetry environment variables above. For background on these interfaces, see the connector [common interfaces](../../connectors/common-interfaces/overview.md) documentation ([health](../../connectors/common-interfaces/health-interface.md), [metrics](../../connectors/common-interfaces/metrics-interface.md), [info](../../connectors/common-interfaces/info-interface.md)). +## What the connector needs from OTPKI -## Register the connector in ILM +The connector authenticates to OTPKI with an OAuth2 access token and calls OTPKI to look up profiles and CAs, create end entities, enroll and issue certificates, download CA certificates and CRLs, and revoke certificates. For that to work, OTPKI must provide: -Once the connector is running and reachable from ILM `Core`, register it as a connector. The connector requires **no inbound authentication**, so register it with authentication type `none` and the connector's base URL, for example `http://otpki-connector:8080`. +- an **OAuth2 client** the connector authenticates as, +- a **certificate authority**, a **certificate profile**, and an **end-entity profile** to issue from, +- **network reachability** from ILM. -ILM reads `/v2/info` during registration to learn the connector's identity and supported interfaces. For the full registration flow (Web UI and API), see [Register connectors](../../quick-start/certificate-management/register-connectors.mdx). +The sections below describe what each of these must look like. The exact steps to create them depend on your OTPKI version — follow the OTPKI documentation; this guide describes what must exist and how the connector uses it. -## Create an authority +## Configure an OAuth2 client for the connector -Create an `Authority` that uses the registered OTPKI Connector. The authority attributes are the OTPKI connection details. +The connector authenticates using the OAuth2 **client credentials** grant against your OTPKI identity provider's token endpoint (a Keycloak realm in a typical deployment, for example `https:///realms/otpki/protocol/openid-connect/token`). -Before you start, create the supporting objects in ILM: +In the identity provider, configure a confidential client for the connector and: -- A **Basic Authentication** credential holding the OTPKI OAuth2 client — its **username** is the OAuth client id and its **password** is the OAuth client secret. It is selected in the **OAuth client** attribute. -- If OTPKI uses a private CA, upload the CA certificate(s) so they can be selected in the **TLS trust** attribute. +- enable the **client credentials** grant, +- note the **client id** and **client secret** — you will store these in ILM, +- if your identity provider requires a **scope** or **audience** on the token, note them as well; otherwise leave them unset. -The authority attributes are: +The client's account must be allowed to perform the operations the connector uses in OTPKI: -| Attribute | Required | Default | Description | -|----------------------|----------|---------|---------------------------------------------------------------------------------------------------------------| -| **Base URL** | Yes | — | Address of the OTPKI server, for example `https://otpki.example.com:15580`. | -| **Token URL** | Yes | — | OAuth2 token endpoint that issues access tokens for OTPKI, for example `https://auth.example.com/realms/otpki/protocol/openid-connect/token`. | -| **OAuth client** | Yes | — | A stored **Basic Authentication** credential. Its username is the OAuth client id; its password is the OAuth client secret. | -| **OAuth scope** | No | — | Scope sent when requesting access tokens. Leave blank unless your identity provider requires one. | -| **OAuth audience** | No | — | Audience sent when requesting access tokens. Leave blank unless your identity provider requires one. | -| **TLS trust** | No | — | One or more **Root CA** or **Intermediate CA** certificates to trust the OTPKI endpoint. Leave empty to use only the system trust store. | -| **Call deadline (ms)** | No | `30000` | Maximum time to wait for a single call to OTPKI before timing out. | -| **Retry max attempts** | No | `3` | How many times a safe, read-only call is retried when OTPKI is briefly unavailable. State-changing calls are never retried. | -| **Retry initial backoff (ms)** | No | `500` | Wait before the first retry. | -| **Retry max backoff (ms)** | No | `5000` | Upper bound on the wait between retries. | +| OTPKI resource | Access the connector needs | +|-----------------------|----------------------------| +| Certificate authority | Read | +| Certificate profile | Read | +| End-entity profile | Read | +| End entity | Create | +| Enrollment request | Create | +| Certificate | Issue, revoke, read | -The connector authenticates to OTPKI with the OAuth2 `client_credentials` grant and reuses access tokens until shortly before they expire. There is no mutual TLS to OTPKI; authentication is by bearer token only. +The connector never deletes OTPKI objects and never manages OTPKI roles or users, so the client does not need delete or administration permissions. -When you create or update the authority, ILM runs a **connect** action that lists the OTPKI certificate authorities as a connectivity and credential check. If it fails, verify the Base URL, Token URL, OAuth client, and TLS trust. For the general flow, see [Create an authority](../../quick-start/certificate-management/create-authority.mdx). +## Configure a CA and certificate templates -## Create an RA profile +The connector issues certificates using OTPKI **end-entity profiles**, **certificate profiles**, and **certificate authorities**. In OTPKI, make sure the following exist and are associated with each other: -Create one or more `RA Profiles` against the OTPKI authority. An RA profile decides which OTPKI templates and CA are used and how each issued end entity is named. +- at least one **certificate authority** to sign the certificates, +- at least one **certificate profile** (the certificate template), +- at least one **end-entity profile** whose list of allowed certificate profiles and CAs includes the ones above. -**Select the End Entity Profile first.** The **Certificate Profile** and **Certificate Authority** dropdowns are then populated by a callback that returns only the options the selected end-entity profile allows. +When you create an RA profile in ILM you pick an end-entity profile first; ILM then offers only the certificate profiles and CAs that the selected end-entity profile allows. -| Attribute | Required | Description | -|-------------------------|----------|------------------------------------------------------------------------------------------------------| -| **End Entity Profile** | Yes | OTPKI end-entity profile that defines the allowed certificate profiles and CAs. Populated from OTPKI. | -| **Certificate Profile** | Yes | OTPKI certificate template to issue from. Populated from the selected end-entity profile. | -| **Certificate Authority** | Yes | OTPKI CA that signs the certificates. Populated from the selected end-entity profile. | -| **Login ID strategy** | Yes | How the OTPKI end-entity username is derived for each issued certificate (see below). | -| **Login ID DN attribute** | No | Subject DN attribute to use as the login id. Required only when the strategy is *Login ID from DN attribute*, for example `UID`. | -| **Login ID custom value** | No | Fixed login id value. Required only when the strategy is *Custom login ID*. | -| **Username prefix** | No | Text added before the derived login id, for example `otpki-`. | -| **Username postfix** | No | Text added after the derived login id, for example `-prod`. | +The end-entity profile also has to: -The **Login ID strategy** options are: +- **permit API enrollment** for the connector's client — the connector always enrolls over OTPKI's API. If the profile does not allow programmatic enrollment, issuance fails with an `enrollment request data is invalid` error. +- **accept a supplied end-entity password** rather than forcing an auto-generated one — the connector sets a password for each end entity it creates. -| Option | Meaning | -|----------------------------|-------------------------------------------------------------------------------| -| **Login ID from CN** | Use the CN from the certificate request. | -| **Login ID from DN attribute** | Use a specific subject DN attribute (set *Login ID DN attribute*). | -| **Custom login ID** | Always use the same value (set *Login ID custom value*). | -| **Random login ID** | Generate a unique value for each certificate. | +## Allow network access -The derived login id (including any prefix and postfix) must be between 3 and 64 characters long. For the general flow, see [Create an RA profile](../../quick-start/certificate-management/create-ra-profile.mdx). +Allow the connector (running alongside ILM) to reach OTPKI: -## Issue and manage certificates +- the OTPKI **base URL** used for the certificate services, for example `https://otpki.example.com:15580`, +- the identity provider's **token endpoint**. -With an authority and RA profile in place, certificates can be managed through ILM as with any other Authority Provider. No extra attributes are required at issuance, renewal, registration, or revocation time — everything comes from the RA profile, the certificate request, and (for revocation) the chosen reason. +If OTPKI or the identity provider is served by a private CA, make that CA trusted — either per authority through the **TLS trust** attribute (below), or for the whole connector through its trusted-certificates bundle. -The connector stores tracking metadata on each certificate (the OTPKI end-entity id, certificate id, request ids, profile and CA ids). ILM round-trips this metadata back to the connector so that later renewal, revocation, and discovery can find the right OTPKI objects without the connector holding any state. +## Connect OTPKI in ILM -### Issuing and renewing +With OTPKI prepared, connect it in ILM. -Issuance takes a CSR and the RA profile settings. The connector derives the login id from the request (per the RA profile's Login ID strategy), creates the OTPKI end entity if needed, and submits the enrollment. If OTPKI issues synchronously, the certificate is returned immediately; otherwise ILM polls until it completes. Renewal submits a new CSR for the existing end entity resolved from the certificate metadata. +1. Create a **Basic Authentication** credential that holds the OAuth2 client — its **username** is the OAuth client id and its **password** is the OAuth client secret. +2. Create an **Authority** that uses the OTPKI Connector and fill in the connection attributes: -### Registering existing certificates + | Attribute | Required | Description | + |----------------|----------|--------------------------------------------------------------------------------| + | **Base URL** | Yes | Address of the OTPKI server, for example `https://otpki.example.com:15580`. | + | **Token URL** | Yes | OAuth2 token endpoint that issues access tokens for OTPKI. | + | **OAuth client** | Yes | The Basic Authentication credential created above. | + | **OAuth scope** | No | Only if your identity provider requires a specific scope. | + | **OAuth audience** | No | Only if your identity provider requires a specific audience. | + | **TLS trust** | No | Root or Intermediate CA certificate(s) to trust a private OTPKI endpoint. | -Registration pre-creates an end-entity identity in OTPKI from a subject (no CSR, no enrollment) so the certificate can be managed through this authority later. + The connector authenticates to OTPKI with the OAuth2 bearer token only; there is no mutual TLS. The remaining authority attributes (call deadline and retry settings) can be left at their defaults. -### Revoking +3. Create one or more **RA Profiles** against the authority. Select the **End Entity Profile** first, then the **Certificate Profile** and **Certificate Authority** (ILM populates these from the selected end-entity profile), and choose a **Login ID strategy** that decides how each OTPKI end entity is named: -Revocation revokes the certificate in OTPKI using the reason chosen on the revocation form. The following ILM revocation reasons are supported: `unspecified`, `keyCompromise`, `cACompromise`, `affiliationChanged`, `superseded`, `cessationOfOperation`, `certificateHold`, `privilegeWithdrawn`, and `aACompromise`. Any other reason is rejected. + | Login ID strategy | Meaning | + |-------------------|----------------------------------------------------------------| + | From CN | Use the CN from the certificate request. | + | From DN attribute | Use a specific subject DN attribute. | + | Custom | Always use the same configured value. | + | Random | Generate a unique value for each certificate. | -### Discovering certificates +For the general authority and RA-profile flow in ILM, see [Create an authority](../../quick-start/certificate-management/create-authority.mdx) and [Create an RA profile](../../quick-start/certificate-management/create-ra-profile.mdx). -Certificate identification looks up a certificate in OTPKI by its serial number and returns the tracking metadata needed to manage it. This is how certificates that were not issued through ILM become manageable through this authority. +## Test the integration -### CRL and CA certificates +1. Creating or updating the authority runs a **connect** check that lists the OTPKI certificate authorities. A successful result confirms the connector can reach OTPKI and authenticate with the OAuth2 client. +2. Through an RA profile, **issue a test certificate** from a CSR. A successful issuance exercises the whole path — creating the end entity, enrolling, and issuing. +3. Optionally confirm that **revocation** works and that the **CRL** and **CA certificate** downloads succeed for the selected CA. -The connector serves the latest CRL and the CA certificate chain for the CA selected in the RA profile, which ILM uses for validation and chain building. - -## Attribute discovery - -The connector implements the common **Attributes v2** interface — a read-only, connector-wide catalog of every attribute it can request, so ILM `Core` can discover and resolve attribute definitions without keeping per-connector state. It exposes three routes: - -| Route | Purpose | -|--------------------------------|-----------------------------------------------------------------------------------------------------| -| `GET /v2/attributes` | The full attribute-definition registry (authority, RA profile, and per-operation attributes). | -| `GET /v2/attributes/{uuid}` | A single definition by UUID. Returns `ATTRIBUTE_DEFINITION_NOT_FOUND` (HTTP 404) when unknown. | -| `POST /v2/attributes/callback` | Resolves the cascading dropdowns (the certificate profiles and CAs allowed by a selected end-entity profile) statelessly, from the connection details supplied in the request. | - -You do not call these routes directly — ILM `Core` uses them when it builds the authority and RA profile forms. See the connector [attributes interface](../../connectors/common-interfaces/attributes-interface.md) documentation for background. +If issuance fails with `enrollment request data is invalid`, the selected end-entity profile does not permit API enrollment for the connector's client — adjust the profile in OTPKI. ## Constraints -The following are known constraints of the OTPKI Connector: - -| Constraint | Note | -|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------| -| Issuance, registration, and revocation cannot be cancelled | OTPKI has no cancel operation; cancel requests are rejected. | -| CRMF requests require a Login ID strategy of **Custom** or **Random** | The subject cannot be read from an opaque CRMF body, so the login id cannot be derived from the CN or a DN attribute. | -| Renewal requires a CSR | CSR-less or key-reuse renewal is not supported. | -| The connector authenticates to OTPKI with an OAuth2 bearer token only | There is no mutual TLS to OTPKI. | -| The connector serves plain HTTP | Terminate TLS at an ingress or service mesh and restrict inbound access to ILM `Core`. | -| Readiness does not test OTPKI connectivity | Use the authority **connect** action to verify the OTPKI connection. | - -## Troubleshooting - -- **The authority connect action fails.** Check that the **Base URL** and **Token URL** are reachable from the connector, that the **OAuth client** credential holds a valid client id and secret, and that any private OTPKI CA is selected in **TLS trust** (or added through `TRUSTED_CERTIFICATES`). -- **Upstream authentication errors.** Confirm the OAuth client credentials, and add the **OAuth scope** and **OAuth audience** if your identity provider requires them. -- **TLS handshake errors reaching OTPKI.** Add the OTPKI CA certificate to the authority's **TLS trust** attribute, or to the connector's `TRUSTED_CERTIFICATES` bundle. -- **Login id errors.** Make sure the derived login id (with any prefix and postfix) is between 3 and 64 characters, and that CRMF requests use the **Custom** or **Random** strategy. -- **End-entity password issues after a redeploy.** Confirm `OTPKI_LOGIN_PASSWORD_KEY` is set and unchanged; changing it changes the passwords derived for existing end entities. +The following are known constraints of the OTPKI integration: -Errors are returned as RFC 9457 `application/problem+json` responses whose `type` links to `https://docs.otilm.com/problems/common/`, with a machine-readable `errorCode` and a `retryable` flag. Increase detail by setting `LOG_LEVEL=DEBUG`, and enable tracing with `OTEL_EXPORTER_OTLP_ENDPOINT` to follow a request through to OTPKI. +| Constraint | Note | +|-----------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| +| Issuance, registration, and revocation cannot be cancelled | OTPKI has no cancel operation, so cancel requests are rejected. | +| CRMF requests require a **Custom** or **Random** Login ID strategy | The subject cannot be read from an opaque CRMF body, so the login id cannot be derived from the CN or a DN attribute. | +| Renewal requires a CSR | CSR-less or key-reuse renewal is not supported. | From 9a1d37d70a970185bda28af9933de7fba73fd09f Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sat, 1 Aug 2026 21:41:55 +0200 Subject: [PATCH 03/11] docs: align OTPKI guide with delivered connector Cross-referenced the reworked guide against the otpki-connector implementation and folded in review feedback: - Use the real Login ID strategy labels (Login ID from CN / from DN attribute / Custom login ID / Random login ID) and note the extra field each one reveals. - Document the Username prefix/postfix wrappers and the 3-64 character derived login-ID limit. - Add the end-entity-profile requirement that the connector supplies the login id rather than OTPKI auto-generating it. - Fix Login ID casing in the constraints table and match the CRMF row to the strategy labels. - Pad the OTPKI catalog row to the table width. --- .../connectors/available-connectors.md | 2 +- .../otpki-connector/integration-guide.md | 26 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/certificate-key/connectors/available-connectors.md b/docs/certificate-key/connectors/available-connectors.md index de986edbd..d5adb0674 100644 --- a/docs/certificate-key/connectors/available-connectors.md +++ b/docs/certificate-key/connectors/available-connectors.md @@ -25,7 +25,7 @@ The following `Connectors` are officially available: | HashiCorp Vault Connector | Authority Provider | HVault | | | Discovery Provider | HVault | | | Secret Provider | | -| OTPKI Connector | Authority Provider | | +| OTPKI Connector | Authority Provider | | | Keystore Entity Provider | Entity Provider | Keystore | | PyADCS Connector | Authority Provider | PyADCS-WinRM | | | Discovery Provider | PyADCS-WinRM | diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index c4a5b970a..4f79742eb 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -62,6 +62,7 @@ When you create an RA profile in ILM you pick an end-entity profile first; ILM t The end-entity profile also has to: - **permit API enrollment** for the connector's client — the connector always enrolls over OTPKI's API. If the profile does not allow programmatic enrollment, issuance fails with an `enrollment request data is invalid` error. +- **let the connector supply the login id** rather than auto-generating it — the connector derives each end entity's login id from the RA profile's Login ID strategy and creates the end entity under that name. - **accept a supplied end-entity password** rather than forcing an auto-generated one — the connector sets a password for each end entity it creates. ## Allow network access @@ -93,12 +94,14 @@ With OTPKI prepared, connect it in ILM. 3. Create one or more **RA Profiles** against the authority. Select the **End Entity Profile** first, then the **Certificate Profile** and **Certificate Authority** (ILM populates these from the selected end-entity profile), and choose a **Login ID strategy** that decides how each OTPKI end entity is named: - | Login ID strategy | Meaning | - |-------------------|----------------------------------------------------------------| - | From CN | Use the CN from the certificate request. | - | From DN attribute | Use a specific subject DN attribute. | - | Custom | Always use the same configured value. | - | Random | Generate a unique value for each certificate. | + | Login ID strategy | Meaning | + |----------------------------|--------------------------------------------------------------------------------------------| + | Login ID from CN | Use the CN from the certificate request. | + | Login ID from DN attribute | Use a specific subject DN attribute; picking it reveals a **Login ID DN attribute** field. | + | Custom login ID | Always use the same configured value; picking it reveals a **Login ID custom value** field. | + | Random login ID | Generate a unique value for each certificate. | + + Optionally set a **Username prefix** and **Username postfix** — they wrap whichever login id the strategy produces. The resulting login id must be 3–64 characters long. For the general authority and RA-profile flow in ILM, see [Create an authority](../../quick-start/certificate-management/create-authority.mdx) and [Create an RA profile](../../quick-start/certificate-management/create-ra-profile.mdx). @@ -114,8 +117,9 @@ If issuance fails with `enrollment request data is invalid`, the selected end-en The following are known constraints of the OTPKI integration: -| Constraint | Note | -|-----------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| -| Issuance, registration, and revocation cannot be cancelled | OTPKI has no cancel operation, so cancel requests are rejected. | -| CRMF requests require a **Custom** or **Random** Login ID strategy | The subject cannot be read from an opaque CRMF body, so the login id cannot be derived from the CN or a DN attribute. | -| Renewal requires a CSR | CSR-less or key-reuse renewal is not supported. | +| Constraint | Note | +|-----------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------| +| Issuance, registration, and revocation cannot be cancelled | OTPKI has no cancel operation, so cancel requests are rejected. | +| CRMF requests require a **Custom login ID** or **Random login ID** strategy | The subject cannot be read from an opaque CRMF body, so the login ID cannot be derived from the CN or a DN attribute. | +| Renewal requires a CSR | CSR-less or key-reuse renewal is not supported. | +| Derived login ID must be 3–64 characters | The Username prefix, derived value, and postfix together must stay within OTPKI's login-ID length limits, or issuance fails. | From e0df490ee059805d3ac79f52c0868596aa093f96 Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sat, 1 Aug 2026 23:34:31 +0200 Subject: [PATCH 04/11] docs: add concrete OTPKI-side setup steps and doc links Expand the OTPKI-side sections into step-by-step procedures grounded in the OTPKI admin console, mirroring the EJBCA guide: - OAuth2 client via client_credentials against the OTPKI Keycloak realm, mapped to an OTPKI identity through the token's claims. - Create a role and grant the exact Resource/Action cells the connector uses, on the Roles and Permissions screens. - Link a CA, certificate profile, and end-entity profile, and set the end-entity profile so the connector supplies the login id and password. - Link each step to the relevant docs.otpki.com page. - Correct the token URL (/kc/realms/otpki) and drop the unverified port from the base-URL examples. --- .../otpki-connector/integration-guide.md | 71 ++++++++++--------- 1 file changed, 38 insertions(+), 33 deletions(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index 4f79742eb..4274fe833 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -13,63 +13,68 @@ ILM manages certificates in OTPKI through the **OTPKI Connector**, an Authority This document outlines the steps to take in OTPKI before the connector can be configured, how to connect an OTPKI authority in ILM, and how to test the integration. :::info[OTPKI installation] -Installing and operating OTPKI is out of scope of this document. This guide assumes OTPKI is installed, running, and reachable from ILM. Refer to the OTPKI documentation for the exact administration steps referenced below. +Installing and operating OTPKI is out of scope of this document. This guide assumes OTPKI is installed, running, and reachable from ILM. Refer to the [OTPKI documentation](https://docs.otpki.com/) for the exact administration steps referenced below. ::: ## What the connector needs from OTPKI -The connector authenticates to OTPKI with an OAuth2 access token and calls OTPKI to look up profiles and CAs, create end entities, enroll and issue certificates, download CA certificates and CRLs, and revoke certificates. For that to work, OTPKI must provide: +The connector authenticates to OTPKI with an OAuth2 access token and calls OTPKI to look up profiles and CAs, create end entities, enroll and issue certificates, download CA certificates and CRLs, and revoke certificates. Before the connector can be configured, prepare the following in OTPKI: -- an **OAuth2 client** the connector authenticates as, +- an **OAuth2 client** the connector authenticates as, mapped to an OTPKI identity that holds the right permissions, - a **certificate authority**, a **certificate profile**, and an **end-entity profile** to issue from, - **network reachability** from ILM. -The sections below describe what each of these must look like. The exact steps to create them depend on your OTPKI version — follow the OTPKI documentation; this guide describes what must exist and how the connector uses it. +The sections below give the OTPKI-side steps. They follow the OTPKI administration console; for background on each screen, see the [OTPKI documentation](https://docs.otpki.com/). -## Configure an OAuth2 client for the connector +## Create the OAuth2 client and map it to an OTPKI identity -The connector authenticates using the OAuth2 **client credentials** grant against your OTPKI identity provider's token endpoint (a Keycloak realm in a typical deployment, for example `https:///realms/otpki/protocol/openid-connect/token`). +The connector authenticates using the OAuth2 **client credentials** grant against the token endpoint of the identity provider OTPKI uses — a Keycloak realm in the standard deployment, for example `https:///kc/realms/otpki/protocol/openid-connect/token`. -In the identity provider, configure a confidential client for the connector and: +1. In that identity provider, create a **confidential client** for the connector with the **client credentials** grant enabled. Note its **client id** and **client secret** — you store these in ILM. If the provider requires a **scope** or **audience** on the token, note them too; otherwise leave them unset. +2. Make sure the client's token maps to an **OTPKI identity** (a user) that OTPKI can resolve from the token. OTPKI links a token to a user through its `sub`/`iss` claims and can assign roles from a `roles` claim — see [Identity Providers](https://docs.otpki.com/docs/operations/administration/identity/identity-providers/) and [Users](https://docs.otpki.com/docs/operations/administration/identity/users/). That identity must hold the role created in the next step (either let OTPKI create it from the token's claims, or pre-create the user and assign the role). -- enable the **client credentials** grant, -- note the **client id** and **client secret** — you will store these in ILM, -- if your identity provider requires a **scope** or **audience** on the token, note them as well; otherwise leave them unset. +## Grant the connector's identity the required permissions -The client's account must be allowed to perform the operations the connector uses in OTPKI: +Create a role for the connector and grant it exactly the resource/action permissions it uses — nothing more. -| OTPKI resource | Access the connector needs | -|-----------------------|----------------------------| -| Certificate authority | Read | -| Certificate profile | Read | -| End-entity profile | Read | -| End entity | Create | -| Enrollment request | Create | -| Certificate | Issue, revoke, read | +1. Go to **Operations > Administration > Identity > Roles**, click **Create**, and name the role (for example `ilm-connector`). See [Roles](https://docs.otpki.com/docs/operations/administration/identity/roles/). +2. Go to **Operations > Administration > Permissions**, select the role, and set these cells to **Allow** (click a cell to cycle Allow / Deny / Unset, then **Save**). See [Permissions](https://docs.otpki.com/docs/operations/administration/permissions/). -The connector never deletes OTPKI objects and never manages OTPKI roles or users, so the client does not need delete or administration permissions. + | Resource | Actions | + |-----------------------|---------------------| + | Certificate authority | Read | + | Certificate profile | Read | + | End-entity profile | Read | + | End entity | Create, Read | + | Enrollment request | Create | + | Certificate | Issue, Revoke, Read | -## Configure a CA and certificate templates +3. Assign the role to the connector's identity — through the user form, or the Permissions screen's **User Assignments** tab. -The connector issues certificates using OTPKI **end-entity profiles**, **certificate profiles**, and **certificate authorities**. In OTPKI, make sure the following exist and are associated with each other: +The connector never deletes OTPKI objects and never manages roles or users, so grant it no **Delete** or administration permissions. -- at least one **certificate authority** to sign the certificates, -- at least one **certificate profile** (the certificate template), -- at least one **end-entity profile** whose list of allowed certificate profiles and CAs includes the ones above. +## Configure a CA, certificate profile, and end-entity profile -When you create an RA profile in ILM you pick an end-entity profile first; ILM then offers only the certificate profiles and CAs that the selected end-entity profile allows. +The connector issues through an OTPKI **end-entity profile**, which ties a **certificate profile** (the template) to a **certificate authority**. Make sure all three exist and are linked: + +1. A **certificate authority** to sign the certificates — see [Certificate Authorities](https://docs.otpki.com/docs/operations/issuance-and-revocation/certificate-authorities/). +2. A **certificate profile** for the certificates you issue — see [Certificate Profiles](https://docs.otpki.com/docs/operations/issuance-and-revocation/certificate-profiles/). +3. An **end-entity profile** (**Operations > Enrollment > End Entity Profiles**) configured so the connector can enroll through it: + - under **Certificate & CA binding**, include the certificate profile and CA above in the available lists and set a default for each, + - set **Login ID** so the connector supplies it rather than OTPKI auto-generating it — the connector names each end entity from the RA profile's Login ID strategy, + - set **Password** to accept a supplied password rather than auto-generating one — the connector sets a password for each end entity it creates. -The end-entity profile also has to: + See [End Entity Profiles](https://docs.otpki.com/docs/operations/enrollment/end-entity-profiles/). + +When you create an RA profile in ILM you pick an end-entity profile first; ILM then offers only the certificate profiles and CAs that the selected end-entity profile allows. -- **permit API enrollment** for the connector's client — the connector always enrolls over OTPKI's API. If the profile does not allow programmatic enrollment, issuance fails with an `enrollment request data is invalid` error. -- **let the connector supply the login id** rather than auto-generating it — the connector derives each end entity's login id from the RA profile's Login ID strategy and creates the end entity under that name. -- **accept a supplied end-entity password** rather than forcing an auto-generated one — the connector sets a password for each end entity it creates. +If issuance later fails with an `enrollment request data is invalid` error, the end-entity profile is rejecting the connector's request — most often because it forces an auto-generated login id or password, or does not allow the selected CA or certificate profile. Adjust the profile in OTPKI. ## Allow network access Allow the connector (running alongside ILM) to reach OTPKI: -- the OTPKI **base URL** used for the certificate services, for example `https://otpki.example.com:15580`, +- the OTPKI **base URL** used for the certificate services, for example `https://otpki.example.com`, - the identity provider's **token endpoint**. If OTPKI or the identity provider is served by a private CA, make that CA trusted — either per authority through the **TLS trust** attribute (below), or for the whole connector through its trusted-certificates bundle. @@ -83,7 +88,7 @@ With OTPKI prepared, connect it in ILM. | Attribute | Required | Description | |----------------|----------|--------------------------------------------------------------------------------| - | **Base URL** | Yes | Address of the OTPKI server, for example `https://otpki.example.com:15580`. | + | **Base URL** | Yes | Address of the OTPKI server, for example `https://otpki.example.com`. | | **Token URL** | Yes | OAuth2 token endpoint that issues access tokens for OTPKI. | | **OAuth client** | Yes | The Basic Authentication credential created above. | | **OAuth scope** | No | Only if your identity provider requires a specific scope. | @@ -111,7 +116,7 @@ For the general authority and RA-profile flow in ILM, see [Create an authority]( 2. Through an RA profile, **issue a test certificate** from a CSR. A successful issuance exercises the whole path — creating the end entity, enrolling, and issuing. 3. Optionally confirm that **revocation** works and that the **CRL** and **CA certificate** downloads succeed for the selected CA. -If issuance fails with `enrollment request data is invalid`, the selected end-entity profile does not permit API enrollment for the connector's client — adjust the profile in OTPKI. +If issuance fails with `enrollment request data is invalid`, the selected end-entity profile is rejecting the connector's enrollment — see [Configure a CA, certificate profile, and end-entity profile](#configure-a-ca-certificate-profile-and-end-entity-profile) and adjust the profile in OTPKI. ## Constraints From 33cee21330149b6204e81ce2421c43967a1314b7 Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sun, 2 Aug 2026 06:01:03 +0200 Subject: [PATCH 05/11] docs: refine OTPKI guide intro, links, and dedup - Lead with what OTPKI is and link its docs, instead of the ILM-centric opener. - Point the confidential-client step at ILM's Keycloak guide (Create Realm and Client / dedicated scope) for the client-creation mechanics. - Link the OTPKI User Assignments section for role assignment. - Drop the duplicated "enrollment request data is invalid" note, keeping the self-contained one in the test section. --- .../otpki-connector/integration-guide.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index 4274fe833..0fabdae61 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -8,9 +8,9 @@ sidebar_position: 1 This integration guide assumes basic knowledge of ILM [`Connectors`](../../concept-design/architecture/connector.md), [`Authorities`](../../concept-design/core-components/authority.md), and [`RA Profiles`](../../concept-design/core-components/ra-profile.md), and that you already have a running OTPKI installation. It focuses on what has to be configured in OTPKI so that ILM can manage certificates through it, and on how to test the integration. ::: -ILM manages certificates in OTPKI through the **OTPKI Connector**, an Authority Provider connector. The connector is deployed together with ILM (through the ILM Helm chart or operator), so deploying it is not part of this guide. What you do need to prepare is the OTPKI side: an OAuth2 client the connector can authenticate as, and the certificate authority and templates it issues from. +[OTPKI](https://docs.otpki.com/) (OmniTrust PKI) is a modern, cloud-native PKI service for operating certificate authorities and managing the full certificate lifecycle through an API-first interface. For installing and operating OTPKI itself, see the [OTPKI documentation](https://docs.otpki.com/). -This document outlines the steps to take in OTPKI before the connector can be configured, how to connect an OTPKI authority in ILM, and how to test the integration. +The **OTPKI Connector** that ILM uses to manage certificates in OTPKI ships with ILM (through the Helm chart or operator), so deploying it is not part of this guide. This document outlines the steps to take in OTPKI before the connector can be configured, how to connect an OTPKI authority in ILM, and how to test the integration. :::info[OTPKI installation] Installing and operating OTPKI is out of scope of this document. This guide assumes OTPKI is installed, running, and reachable from ILM. Refer to the [OTPKI documentation](https://docs.otpki.com/) for the exact administration steps referenced below. @@ -30,7 +30,7 @@ The sections below give the OTPKI-side steps. They follow the OTPKI administrati The connector authenticates using the OAuth2 **client credentials** grant against the token endpoint of the identity provider OTPKI uses — a Keycloak realm in the standard deployment, for example `https:///kc/realms/otpki/protocol/openid-connect/token`. -1. In that identity provider, create a **confidential client** for the connector with the **client credentials** grant enabled. Note its **client id** and **client secret** — you store these in ILM. If the provider requires a **scope** or **audience** on the token, note them too; otherwise leave them unset. +1. In that identity provider, create a **confidential client** for the connector and enable the **client credentials** (service-account) grant. Note its **client id** and **client secret** — you store these in ILM. If the provider requires a **scope** or **audience** on the token, note them too; otherwise leave them unset. The client-creation mechanics match ILM's own Keycloak setup — see [Create Realm and Client](../keycloak/create-realm.md#create-oidc-client) (for the connector, turn on the client credentials grant rather than the login redirect flow, and add an audience mapper as in [Configure the dedicated scope](../keycloak/create-realm.md#configure-the-dedicated-scope) if OTPKI expects an audience). 2. Make sure the client's token maps to an **OTPKI identity** (a user) that OTPKI can resolve from the token. OTPKI links a token to a user through its `sub`/`iss` claims and can assign roles from a `roles` claim — see [Identity Providers](https://docs.otpki.com/docs/operations/administration/identity/identity-providers/) and [Users](https://docs.otpki.com/docs/operations/administration/identity/users/). That identity must hold the role created in the next step (either let OTPKI create it from the token's claims, or pre-create the user and assign the role). ## Grant the connector's identity the required permissions @@ -49,7 +49,7 @@ Create a role for the connector and grant it exactly the resource/action permiss | Enrollment request | Create | | Certificate | Issue, Revoke, Read | -3. Assign the role to the connector's identity — through the user form, or the Permissions screen's **User Assignments** tab. +3. Assign the role to the connector's identity — through the user form, or the Permissions screen's [**User Assignments**](https://docs.otpki.com/docs/operations/administration/permissions/#user-assignments) tab. The connector never deletes OTPKI objects and never manages roles or users, so grant it no **Delete** or administration permissions. @@ -68,8 +68,6 @@ The connector issues through an OTPKI **end-entity profile**, which ties a **cer When you create an RA profile in ILM you pick an end-entity profile first; ILM then offers only the certificate profiles and CAs that the selected end-entity profile allows. -If issuance later fails with an `enrollment request data is invalid` error, the end-entity profile is rejecting the connector's request — most often because it forces an auto-generated login id or password, or does not allow the selected CA or certificate profile. Adjust the profile in OTPKI. - ## Allow network access Allow the connector (running alongside ILM) to reach OTPKI: @@ -116,7 +114,7 @@ For the general authority and RA-profile flow in ILM, see [Create an authority]( 2. Through an RA profile, **issue a test certificate** from a CSR. A successful issuance exercises the whole path — creating the end entity, enrolling, and issuing. 3. Optionally confirm that **revocation** works and that the **CRL** and **CA certificate** downloads succeed for the selected CA. -If issuance fails with `enrollment request data is invalid`, the selected end-entity profile is rejecting the connector's enrollment — see [Configure a CA, certificate profile, and end-entity profile](#configure-a-ca-certificate-profile-and-end-entity-profile) and adjust the profile in OTPKI. +If issuance fails with `enrollment request data is invalid`, the selected end-entity profile is rejecting the connector's enrollment — most often because it forces an auto-generated login id or password, or does not allow the selected CA or certificate profile. Adjust the profile in OTPKI. ## Constraints From 9d375f759e8646493e34bf93253314636bec459a Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sun, 2 Aug 2026 06:06:51 +0200 Subject: [PATCH 06/11] docs: drop the Connect-in-ILM section from OTPKI guide The ILM-side authority and RA-profile attribute walkthrough is stale-prone and belongs in the ILM quick-start, not the integration guide (matching the EJBCA guide, which stops at provider-side setup). A pointer to Create an authority / Create an RA profile stays in the intro. --- .../otpki-connector/integration-guide.md | 33 +------------------ 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index 0fabdae61..ed0775fdc 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -10,7 +10,7 @@ This integration guide assumes basic knowledge of ILM [`Connectors`](../../conce [OTPKI](https://docs.otpki.com/) (OmniTrust PKI) is a modern, cloud-native PKI service for operating certificate authorities and managing the full certificate lifecycle through an API-first interface. For installing and operating OTPKI itself, see the [OTPKI documentation](https://docs.otpki.com/). -The **OTPKI Connector** that ILM uses to manage certificates in OTPKI ships with ILM (through the Helm chart or operator), so deploying it is not part of this guide. This document outlines the steps to take in OTPKI before the connector can be configured, how to connect an OTPKI authority in ILM, and how to test the integration. +The **OTPKI Connector** that ILM uses to manage certificates in OTPKI ships with ILM (through the Helm chart or operator), so deploying it is not part of this guide. This document outlines the steps to take in OTPKI before the connector can be configured, and how to test the integration. For connecting the prepared OTPKI as an authority in ILM, follow [Create an authority](../../quick-start/certificate-management/create-authority.mdx) and [Create an RA profile](../../quick-start/certificate-management/create-ra-profile.mdx). :::info[OTPKI installation] Installing and operating OTPKI is out of scope of this document. This guide assumes OTPKI is installed, running, and reachable from ILM. Refer to the [OTPKI documentation](https://docs.otpki.com/) for the exact administration steps referenced below. @@ -77,37 +77,6 @@ Allow the connector (running alongside ILM) to reach OTPKI: If OTPKI or the identity provider is served by a private CA, make that CA trusted — either per authority through the **TLS trust** attribute (below), or for the whole connector through its trusted-certificates bundle. -## Connect OTPKI in ILM - -With OTPKI prepared, connect it in ILM. - -1. Create a **Basic Authentication** credential that holds the OAuth2 client — its **username** is the OAuth client id and its **password** is the OAuth client secret. -2. Create an **Authority** that uses the OTPKI Connector and fill in the connection attributes: - - | Attribute | Required | Description | - |----------------|----------|--------------------------------------------------------------------------------| - | **Base URL** | Yes | Address of the OTPKI server, for example `https://otpki.example.com`. | - | **Token URL** | Yes | OAuth2 token endpoint that issues access tokens for OTPKI. | - | **OAuth client** | Yes | The Basic Authentication credential created above. | - | **OAuth scope** | No | Only if your identity provider requires a specific scope. | - | **OAuth audience** | No | Only if your identity provider requires a specific audience. | - | **TLS trust** | No | Root or Intermediate CA certificate(s) to trust a private OTPKI endpoint. | - - The connector authenticates to OTPKI with the OAuth2 bearer token only; there is no mutual TLS. The remaining authority attributes (call deadline and retry settings) can be left at their defaults. - -3. Create one or more **RA Profiles** against the authority. Select the **End Entity Profile** first, then the **Certificate Profile** and **Certificate Authority** (ILM populates these from the selected end-entity profile), and choose a **Login ID strategy** that decides how each OTPKI end entity is named: - - | Login ID strategy | Meaning | - |----------------------------|--------------------------------------------------------------------------------------------| - | Login ID from CN | Use the CN from the certificate request. | - | Login ID from DN attribute | Use a specific subject DN attribute; picking it reveals a **Login ID DN attribute** field. | - | Custom login ID | Always use the same configured value; picking it reveals a **Login ID custom value** field. | - | Random login ID | Generate a unique value for each certificate. | - - Optionally set a **Username prefix** and **Username postfix** — they wrap whichever login id the strategy produces. The resulting login id must be 3–64 characters long. - -For the general authority and RA-profile flow in ILM, see [Create an authority](../../quick-start/certificate-management/create-authority.mdx) and [Create an RA profile](../../quick-start/certificate-management/create-ra-profile.mdx). - ## Test the integration 1. Creating or updating the authority runs a **connect** check that lists the OTPKI certificate authorities. A successful result confirms the connector can reach OTPKI and authenticate with the OAuth2 client. From 40e307c69b509bce0c4811c5ad96c516ca880325 Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sun, 2 Aug 2026 06:14:20 +0200 Subject: [PATCH 07/11] docs: rename OTPKI guide overview section to OTPKI prerequisites --- .../integration-guides/otpki-connector/integration-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index ed0775fdc..cea994d06 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -16,7 +16,7 @@ The **OTPKI Connector** that ILM uses to manage certificates in OTPKI ships with Installing and operating OTPKI is out of scope of this document. This guide assumes OTPKI is installed, running, and reachable from ILM. Refer to the [OTPKI documentation](https://docs.otpki.com/) for the exact administration steps referenced below. ::: -## What the connector needs from OTPKI +## OTPKI prerequisites The connector authenticates to OTPKI with an OAuth2 access token and calls OTPKI to look up profiles and CAs, create end entities, enroll and issue certificates, download CA certificates and CRLs, and revoke certificates. Before the connector can be configured, prepare the following in OTPKI: From 821221d5aa9884b6125c480ed68cd88be84c00f8 Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sun, 2 Aug 2026 06:19:39 +0200 Subject: [PATCH 08/11] docs: shorten OTPKI guide section headings --- .../integration-guides/otpki-connector/integration-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index cea994d06..e7cb61aa9 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -26,14 +26,14 @@ The connector authenticates to OTPKI with an OAuth2 access token and calls OTPKI The sections below give the OTPKI-side steps. They follow the OTPKI administration console; for background on each screen, see the [OTPKI documentation](https://docs.otpki.com/). -## Create the OAuth2 client and map it to an OTPKI identity +## Set up the OAuth2 client The connector authenticates using the OAuth2 **client credentials** grant against the token endpoint of the identity provider OTPKI uses — a Keycloak realm in the standard deployment, for example `https:///kc/realms/otpki/protocol/openid-connect/token`. 1. In that identity provider, create a **confidential client** for the connector and enable the **client credentials** (service-account) grant. Note its **client id** and **client secret** — you store these in ILM. If the provider requires a **scope** or **audience** on the token, note them too; otherwise leave them unset. The client-creation mechanics match ILM's own Keycloak setup — see [Create Realm and Client](../keycloak/create-realm.md#create-oidc-client) (for the connector, turn on the client credentials grant rather than the login redirect flow, and add an audience mapper as in [Configure the dedicated scope](../keycloak/create-realm.md#configure-the-dedicated-scope) if OTPKI expects an audience). 2. Make sure the client's token maps to an **OTPKI identity** (a user) that OTPKI can resolve from the token. OTPKI links a token to a user through its `sub`/`iss` claims and can assign roles from a `roles` claim — see [Identity Providers](https://docs.otpki.com/docs/operations/administration/identity/identity-providers/) and [Users](https://docs.otpki.com/docs/operations/administration/identity/users/). That identity must hold the role created in the next step (either let OTPKI create it from the token's claims, or pre-create the user and assign the role). -## Grant the connector's identity the required permissions +## Grant permissions Create a role for the connector and grant it exactly the resource/action permissions it uses — nothing more. @@ -53,7 +53,7 @@ Create a role for the connector and grant it exactly the resource/action permiss The connector never deletes OTPKI objects and never manages roles or users, so grant it no **Delete** or administration permissions. -## Configure a CA, certificate profile, and end-entity profile +## Configure the CA and profiles The connector issues through an OTPKI **end-entity profile**, which ties a **certificate profile** (the template) to a **certificate authority**. Make sure all three exist and are linked: From 648e8ef531d210cc064c658cb1c96c9d1efe0d0e Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sun, 2 Aug 2026 06:57:56 +0200 Subject: [PATCH 09/11] docs: address OTPKI guide review findings - Warn that OTPKI_LOGIN_PASSWORD_KEY (Helm otpki.loginPasswordKey) defaults to empty, making the end-entity password the predictable login id; require it for production. - State the OAuth client is stored as a Basic Authentication secret (username = client id, password = client secret) and selected as the authority's OAuth client. - Replace the MS ADCS-specific quick-start links with the connector- neutral Authority and RA Profile concept pages. - Reword the CRMF and login-ID-length constraints so they no longer rely on the removed Login ID strategy enumeration. --- .../otpki-connector/integration-guide.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index e7cb61aa9..6b404a181 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -10,7 +10,11 @@ This integration guide assumes basic knowledge of ILM [`Connectors`](../../conce [OTPKI](https://docs.otpki.com/) (OmniTrust PKI) is a modern, cloud-native PKI service for operating certificate authorities and managing the full certificate lifecycle through an API-first interface. For installing and operating OTPKI itself, see the [OTPKI documentation](https://docs.otpki.com/). -The **OTPKI Connector** that ILM uses to manage certificates in OTPKI ships with ILM (through the Helm chart or operator), so deploying it is not part of this guide. This document outlines the steps to take in OTPKI before the connector can be configured, and how to test the integration. For connecting the prepared OTPKI as an authority in ILM, follow [Create an authority](../../quick-start/certificate-management/create-authority.mdx) and [Create an RA profile](../../quick-start/certificate-management/create-ra-profile.mdx). +The **OTPKI Connector** that ILM uses to manage certificates in OTPKI ships with ILM (through the Helm chart or operator), so deploying it is not part of this guide. This document outlines the steps to take in OTPKI before the connector can be configured, and how to test the integration. For connecting the prepared OTPKI as an authority in ILM, create an [`Authority`](../../concept-design/core-components/authority.md) and an [`RA Profile`](../../concept-design/core-components/ra-profile.md) that use the OTPKI Connector. + +:::warning[Production hardening] +The connector derives each end entity's OTPKI password from an HMAC key supplied through `OTPKI_LOGIN_PASSWORD_KEY` (Helm value `otpki.loginPasswordKey`). Left unset — the default — the connector falls back to using the login id itself as the password, which is predictable. Set this key for any production deployment. +::: :::info[OTPKI installation] Installing and operating OTPKI is out of scope of this document. This guide assumes OTPKI is installed, running, and reachable from ILM. Refer to the [OTPKI documentation](https://docs.otpki.com/) for the exact administration steps referenced below. @@ -30,7 +34,7 @@ The sections below give the OTPKI-side steps. They follow the OTPKI administrati The connector authenticates using the OAuth2 **client credentials** grant against the token endpoint of the identity provider OTPKI uses — a Keycloak realm in the standard deployment, for example `https:///kc/realms/otpki/protocol/openid-connect/token`. -1. In that identity provider, create a **confidential client** for the connector and enable the **client credentials** (service-account) grant. Note its **client id** and **client secret** — you store these in ILM. If the provider requires a **scope** or **audience** on the token, note them too; otherwise leave them unset. The client-creation mechanics match ILM's own Keycloak setup — see [Create Realm and Client](../keycloak/create-realm.md#create-oidc-client) (for the connector, turn on the client credentials grant rather than the login redirect flow, and add an audience mapper as in [Configure the dedicated scope](../keycloak/create-realm.md#configure-the-dedicated-scope) if OTPKI expects an audience). +1. In that identity provider, create a **confidential client** for the connector and enable the **client credentials** (service-account) grant. Note its **client id** and **client secret** — in ILM you store them as a **Basic Authentication** secret (username = client id, password = client secret) and select it as the authority's **OAuth client**. If the provider requires a **scope** or **audience** on the token, note them too; otherwise leave them unset. The client-creation mechanics match ILM's own Keycloak setup — see [Create Realm and Client](../keycloak/create-realm.md#create-oidc-client) (for the connector, turn on the client credentials grant rather than the login redirect flow, and add an audience mapper as in [Configure the dedicated scope](../keycloak/create-realm.md#configure-the-dedicated-scope) if OTPKI expects an audience). 2. Make sure the client's token maps to an **OTPKI identity** (a user) that OTPKI can resolve from the token. OTPKI links a token to a user through its `sub`/`iss` claims and can assign roles from a `roles` claim — see [Identity Providers](https://docs.otpki.com/docs/operations/administration/identity/identity-providers/) and [Users](https://docs.otpki.com/docs/operations/administration/identity/users/). That identity must hold the role created in the next step (either let OTPKI create it from the token's claims, or pre-create the user and assign the role). ## Grant permissions @@ -92,6 +96,6 @@ The following are known constraints of the OTPKI integration: | Constraint | Note | |-----------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------| | Issuance, registration, and revocation cannot be cancelled | OTPKI has no cancel operation, so cancel requests are rejected. | -| CRMF requests require a **Custom login ID** or **Random login ID** strategy | The subject cannot be read from an opaque CRMF body, so the login ID cannot be derived from the CN or a DN attribute. | +| CRMF requests need a fixed or random login ID | The subject cannot be read from an opaque CRMF body, so the login ID cannot be derived from the certificate's CN or a DN attribute — configure the RA profile to use a custom or random login ID instead. | | Renewal requires a CSR | CSR-less or key-reuse renewal is not supported. | -| Derived login ID must be 3–64 characters | The Username prefix, derived value, and postfix together must stay within OTPKI's login-ID length limits, or issuance fails. | +| Derived login ID must be 3–64 characters | The login ID the RA profile derives for each end entity (including any prefix or suffix) must stay within OTPKI's 3–64 character limit, or issuance fails. | From cd4bac882c7280f587db95688eed92cc8427e89a Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sun, 2 Aug 2026 07:05:44 +0200 Subject: [PATCH 10/11] docs: normalize login ID casing in OTPKI guide --- .../integration-guides/otpki-connector/integration-guide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md index 6b404a181..d5381ebe7 100644 --- a/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md +++ b/docs/certificate-key/integration-guides/otpki-connector/integration-guide.md @@ -13,7 +13,7 @@ This integration guide assumes basic knowledge of ILM [`Connectors`](../../conce The **OTPKI Connector** that ILM uses to manage certificates in OTPKI ships with ILM (through the Helm chart or operator), so deploying it is not part of this guide. This document outlines the steps to take in OTPKI before the connector can be configured, and how to test the integration. For connecting the prepared OTPKI as an authority in ILM, create an [`Authority`](../../concept-design/core-components/authority.md) and an [`RA Profile`](../../concept-design/core-components/ra-profile.md) that use the OTPKI Connector. :::warning[Production hardening] -The connector derives each end entity's OTPKI password from an HMAC key supplied through `OTPKI_LOGIN_PASSWORD_KEY` (Helm value `otpki.loginPasswordKey`). Left unset — the default — the connector falls back to using the login id itself as the password, which is predictable. Set this key for any production deployment. +The connector derives each end entity's OTPKI password from an HMAC key supplied through `OTPKI_LOGIN_PASSWORD_KEY` (Helm value `otpki.loginPasswordKey`). Left unset — the default — the connector falls back to using the login ID itself as the password, which is predictable. Set this key for any production deployment. ::: :::info[OTPKI installation] @@ -87,7 +87,7 @@ If OTPKI or the identity provider is served by a private CA, make that CA truste 2. Through an RA profile, **issue a test certificate** from a CSR. A successful issuance exercises the whole path — creating the end entity, enrolling, and issuing. 3. Optionally confirm that **revocation** works and that the **CRL** and **CA certificate** downloads succeed for the selected CA. -If issuance fails with `enrollment request data is invalid`, the selected end-entity profile is rejecting the connector's enrollment — most often because it forces an auto-generated login id or password, or does not allow the selected CA or certificate profile. Adjust the profile in OTPKI. +If issuance fails with `enrollment request data is invalid`, the selected end-entity profile is rejecting the connector's enrollment — most often because it forces an auto-generated login ID or password, or does not allow the selected CA or certificate profile. Adjust the profile in OTPKI. ## Constraints From bf3052abd114d0d2587072232a0e7520ef830156 Mon Sep 17 00:00:00 2001 From: lubomirw <76479559+lubomirw@users.noreply.github.com> Date: Sun, 2 Aug 2026 07:08:38 +0200 Subject: [PATCH 11/11] docs: mark OTPKI connector kind as not applicable The OTPKI Connector is a v3 stateless Authority Provider that advertises no kind (empty /v2/info kinds, no {kind} segment in the v3 API path). Mark the catalog Kinds cell with an em dash and add a footnote, rather than leave it ambiguously blank. --- docs/certificate-key/connectors/available-connectors.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/certificate-key/connectors/available-connectors.md b/docs/certificate-key/connectors/available-connectors.md index d5adb0674..0209f8c8a 100644 --- a/docs/certificate-key/connectors/available-connectors.md +++ b/docs/certificate-key/connectors/available-connectors.md @@ -25,10 +25,12 @@ The following `Connectors` are officially available: | HashiCorp Vault Connector | Authority Provider | HVault | | | Discovery Provider | HVault | | | Secret Provider | | -| OTPKI Connector | Authority Provider | | +| OTPKI Connector | Authority Provider | — | | Keystore Entity Provider | Entity Provider | Keystore | | PyADCS Connector | Authority Provider | PyADCS-WinRM | | | Discovery Provider | PyADCS-WinRM | | Network Discovery Provider | Discovery Provider | IP-Hostname | | Software Cryptography Provider | Cryptography Provider | SOFT | | X.509 Compliance Provider | Compliance Provider | x509 | + +— The OTPKI Connector is a v3 stateless connector and advertises no kind.