Skip to main content

Running Ory Polis in FIPS 140-3 mode

Ory Polis for OEL has a second container image, polis-oel-fips, which runs with an OpenSSL FIPS provider active. In this image every cryptographic operation Polis performs is served by that provider, and algorithms outside the FIPS-approved set are unavailable rather than merely discouraged.

The application code is identical to the standard image. Only the base image, the OpenSSL FIPS provider, and the behaviour that follows from restricting Polis to approved algorithms differ.

info

The FIPS image is preview work. It is built and security-scanned on every release, but it is not published to the enterprise registry or Cloudsmith, and the release pipeline's runtime tests do not yet cover it. Reach out to Ory if you want to evaluate it.

What is and is not being claimed

FIPS 140-3 validates cryptographic modules, not applications. The polis-oel-fips image:

  • performs all cryptography inside an OpenSSL FIPS provider,
  • uses only FIPS-approved algorithms for security functions, and
  • runs in FIPS mode unconditionally — this cannot be turned off at runtime, and it does not depend on the host kernel being booted with fips=1.

The FIPS provider in this image is compiled from upstream OpenSSL source. It is therefore not a CMVP-validated cryptographic module, and the image must not be represented as FIPS 140-2 or FIPS 140-3 validated. The CMVP certificates published for OpenSSL cover specific vendor-built binaries on specific tested operational environments. If your programme requires a certificate number that covers the running binary, contact us before deploying.

The datastore keyspace differs from the standard image

Polis derives every datastore key — and from it every SSO connection clientID, setup-link ID, identity federation app ID, directory-sync group membership ID, and the idHash claim — from a hash of the record's identifying parts.

ImageDigestLength
polis-oelRIPEMD-16040 hex characters
polis-oel-fipsSHA-25664 hex characters

RIPEMD-160 is not FIPS-approved at any implementation, so the FIPS image cannot use it. Each digest is used at its full width, so identifiers the FIPS image issues — connection clientIDs, setup-link IDs, identity federation app IDs and the idHash claim — are 64 characters rather than 40. The schema accommodates both; check anywhere your own systems store a Polis-issued identifier for a fixed-width column or validation.

warning

A database written by one image cannot be read by the other. The two digests produce different keys for the same record, so switching an existing deployment between polis-oel and polis-oel-fips makes its existing records unreachable. Choose one image per deployment.

Polis logs the digest it is using on every start, so you can confirm which keyspace a running process is on:

FIPS 140-3 mode is active (Node.js crypto backed by an OpenSSL FIPS provider). Datastore keys use SHA-256.
FIPS 140-3 mode is not active. Datastore keys use RIPEMD-160.

Choosing an image, and moving between them

The two images are deliberately separate deployments. There is no automatic migration and no dual-read mode, by design: a FIPS deployment and a non-FIPS deployment do not share a datastore.

For a new deployment, start on the image you intend to keep — nothing further is required.

Migrating an existing deployment is a manual re-key, not a schema migration, and everything Polis stores under a digest-derived key has to be re-established. That includes:

  • SSO connections. Each clientID is derived from the digest, so it changes value and length. Anything that stored a clientID needs updating, as does the idHash claim if your application correlates users on it — the id claim is unaffected.
  • Identity federation apps, setup links, and directory-sync group memberships, for the same reason.
  • The SAML signing certificate, if you let Polis generate one. It is stored under a digest-derived key, so a FIPS deployment cannot read a certificate a non-FIPS deployment wrote, and mints a new key pair instead. Identity providers holding the old certificate will then reject signed authentication requests, and assertions encrypted to the old public key cannot be decrypted. Deployments that set PUBLIC_KEY and PRIVATE_KEY are not affected: an operator-supplied certificate never goes through the datastore.
  • In-flight state. Ephemeral records such as OAuth state are not carried over, so migrate during a maintenance window.

Contact us before migrating an existing deployment. We plan the re-key with you, including the signing certificate, rather than leaving it to a self-service procedure.

Microsoft SQL Server is not supported

The MSSQL driver authenticates with NTLM, which depends on MD4. MD4 cannot be used under FIPS 140-3, so the FIPS image refuses to start when DB_TYPE=mssql, and its database migration job refuses to run:

FIPS mode: the mssql database engine is not supported because its NTLM authentication relies on MD4.
It is the only one FIPS rules out: set DB_TYPE to postgres, cockroachdb, yugabytedb, mysql, mariadb, or
sqlite, or use a non-SQL DB_ENGINE.

MSSQL is the only database Polis supports that FIPS rules out. PostgreSQL, CockroachDB, YugabyteDB, MySQL, MariaDB and SQLite all work, as do the non-SQL engines (MongoDB, Redis, DynamoDB, PlanetScale). The standard image is unaffected.

Identity provider requirements

The FIPS provider does not implement algorithms that some identity providers still default to. Under the FIPS image your IdP must:

  • sign SAML responses with RSA-SHA256. RSA-SHA1 signatures cannot be verified.
  • use RSA-OAEP for key transport if it encrypts assertions. RSA-PKCS#1 v1.5 (rsa-1_5) key transport is unavailable.
  • use AES for assertion encryption. 3DES is unavailable.

Polis reports these failures with a message naming the likely cause and the fix rather than the underlying OpenSSL error, so a misconfigured IdP is identifiable from the SSO trace.

Polis warns at start-up, without refusing to run, about two settings that weaken the posture of an otherwise FIPS deployment:

  • Set DB_ENCRYPTION_KEY. Without it, records are stored without encryption at rest.
  • Supply PUBLIC_KEY and PRIVATE_KEY. Without them Polis generates a self-signed SAML signing certificate on first start. That is convenient for evaluation, but the key material is not under your control and it does not survive a move between the two images. Certificates Polis generates itself use RSA-3072.

Everything else is configured exactly as for the standard image; see Environment Variables.