Skip to content

Security & Authentication

LoomCache ships two orthogonal mechanisms: TLS (or mTLS) at the transport layer, and role- or CN-based authorization at the message-handler layer. Both are off by default; both are configured through TlsConfig and AuthConfig (or loomcache.tls.* / loomcache.auth.* in Spring Boot).

Zero-Trust Internal Network

mTLS Handshake + RBAC + Audit Logging

API Gateway
Validates JWT
X-Auth-Roles: admin
TcpServer
TLS 1.3 Terminated
Execution
RBAC + AuditLog
[Gateway] Received external request, verified JWT
TlsConfig tls = TlsConfig.builder()
.enabled(true)
.keyStorePath(Paths.get("/etc/loomcache/tls/keystore.p12"))
.keyStorePassword(System.getenv("KEYSTORE_PASSWORD"))
.keyStoreType("PKCS12")
.trustStorePath(Paths.get("/etc/loomcache/tls/truststore.p12"))
.trustStorePassword(System.getenv("TRUSTSTORE_PASSWORD"))
.trustStoreType("PKCS12")
.requireClientAuth(true) // mTLS
.protocols(List.of("TLSv1.3", "TLSv1.2"))
.provider(TlsProvider.JDK) // JSSE; required for FIPS-capable deployments
.revocationCheckingEnabled(true) // required in production
.revocationSoftFail(false) // fail closed on CRL/OCSP errors
.certExpirationWarningDays(30)
.certExpirationCriticalDays(7)
.build();

For deployments that need different TLS material per traffic role, EndpointTlsConfig carries member-to-member, member-to-client, and WAN endpoint configs:

EndpointTlsConfig endpointTls = EndpointTlsConfig.builder()
.defaults(tls)
.memberTlsConfig(memberTls)
.clientTlsConfig(clientTls)
.wanTlsConfig(wanTls)
.build();

Spring Boot exposes the same split as loomcache.tls.member.*, loomcache.tls.client.*, and loomcache.tls.wan.*. Each endpoint inherits the global loomcache.tls.* settings and overrides only the fields it sets. The current binary listener remains a single socket and uses the member endpoint config at runtime; client and WAN configs are parsed, validated, exposed through configuration, and preserved for deployments that split listeners or WAN transport.

CertificateWatcher polls the keystore and truststore paths; CertificateReloader rebuilds the SSLContext on change. ReloadableSslContext forwards socket creation to the current context so in-flight connections survive rotations.

LoomCache is not a FIPS-validated cryptographic module. It delegates TLS, keystore handling, random generation, signatures, and cipher operations to the configured Java security provider or Netty TLS provider. That means a FIPS-controlled deployment depends on the runtime cryptographic module and its CMVP certificate, not on a LoomCache product certificate.

NIST has moved validation work to FIPS 140-3. FIPS 140-3 superseded FIPS 140-2, and CMVP no longer accepts new FIPS 140-2 validation submissions. Active FIPS 140-2 modules remain usable for new systems until September 21, 2026; after that, the certificates move to the Historical list and are for existing systems only.

For FIPS-controlled environments:

  1. Use a JDK or JSSE security provider backed by a CMVP Active FIPS 140-3 module, or by an accepted FIPS 140-2 module before its September 21, 2026 transition date.
  2. Set TlsConfig.provider(TlsProvider.JDK) or loomcache.tls.provider=JDK.
  3. Do not use OPENSSL or OPENSSL_REFCNT unless your exact Netty/native TLS distribution is independently covered by the certificate and security policy you intend to cite.
  4. Configure provider order, FIPS mode, DRBG/random source, keystore type, disabled algorithms, protocols, and cipher suites according to the chosen module’s security policy.
  5. Keep the CMVP certificate number, module version, JVM build, operating system, provider files, JVM flags, and LoomCache TLS configuration in the deployment evidence package.

Primary references: NIST FIPS 140-3 transition and NIST CMVP.

Terminal window
openssl genrsa -out ca-key.pem 4096
openssl req -new -x509 -days 3650 -key ca-key.pem -out ca-cert.pem \
-subj "/O=LoomCache/CN=loomcache-ca"
openssl genrsa -out node-1-key.pem 4096
openssl req -new -key node-1-key.pem -out node-1.csr \
-subj "/O=LoomCache/CN=node-1.loomcache.local"
openssl x509 -req -in node-1.csr -CA ca-cert.pem -CAkey ca-key.pem \
-CAcreateserial -out node-1-cert.pem -days 365 -sha256
openssl pkcs12 -export -in node-1-cert.pem -inkey node-1-key.pem \
-out node-1.p12 -name node-1 -passout pass:$KEYSTORE_PASSWORD
keytool -import -file ca-cert.pem -alias ca \
-keystore truststore.p12 -storetype PKCS12 \
-storepass $TRUSTSTORE_PASSWORD -noprompt

Choose an enforcement style via AuthConfig:

Used when an authenticating reverse proxy sits in front of the cluster. The proxy forwards X-Auth-User and X-Auth-Roles; the server trusts those headers only if the connection comes from a listed gateway address and mTLS identifies it.

This gateway-trust mode is non-production only in the current release. Production preflight rejects gatewayTrust=true; use certificate-CN permissions or another direct authentication source for production clusters.

AuthConfig auth = AuthConfig.builder()
.enabled(true)
.gatewayTrust(true)
.trustedGatewayAddresses(Set.of("10.0.0.0/8"))
.userHeader("X-Auth-User")
.rolesHeader("X-Auth-Roles")
.rolePrefix("ROLE_")
.role("reader", Set.of("MAP_GET", "MAP_CONTAINS", "MAP_SIZE"))
.role("writer", Set.of("MAP_PUT", "MAP_DELETE", "MAP_GET"))
.role("admin", Set.of("*"))
.build();

When mTLS is on, authConfig.certPermissions maps CN patterns to a CertPermissionMapper.PermissionLevel:

LevelAllowed operations
READ_ONLYReads and cluster info queries.
READ_WRITEAll READ_ONLY operations plus writes, deletes, batches.
ADMINEverything including cluster management.

Patterns support exact matches and prefix-* wildcards; longest prefix wins when multiple patterns match.

  • BackpressureController rejects overflow with RESPONSE_SERVER_BUSY.
  • RateLimiter + PerClientRateLimiter cap global and per-client QPS.
  • ConnectionHealthMonitor enforces per-IP connection limits (TOO_MANY_CONNECTIONS).
  • REST inputs are validated by InputValidator in the Spring module and inline in the raw REST router.
  1. Generate a private CA; issue one keystore per node, one shared truststore.
  2. Enable TLS with requireClientAuth = true, revocationCheckingEnabled = true, and revocationSoftFail = false for production — Raft traffic is critical.
  3. Use CN-based certificate permissions, tokens, JAAS, LDAP, or Kerberos for production authorization; keep gateway-forwarded roles out of production.
  4. Store keystore passwords in a secret manager — never in git.
  5. Rotate certificates by overwriting the keystore file; CertificateWatcher picks it up without downtime.
  6. Alert on the tls.cert.expiration.days gauge below certExpirationCriticalDays.