ol.clave.ext.common

Common utilities for Clave server extensions.

This namespace provides server-agnostic helpers for working with Clave’s automation layer, including keystore creation and event processing.

These helpers work with any server extension (Jetty, http-kit, etc.).

create-keystore

(create-keystore bundle)
(create-keystore bundle password)

Creates an in-memory PKCS12 KeyStore from a Clave certificate bundle.

bundle is a certificate bundle from ol.clave.automation/lookup-cert, and password protects the keystore (default "changeit"). There is no disk I/O; the keystore is built entirely in memory for TLS handshakes.

Returns a java.security.KeyStore ready for a TLS server, or nil when bundle is nil (no certificate available yet).

(create-keystore (auto/lookup-cert system "example.com"))
;; => #object[java.security.KeyStore ...]

certificate-event?

(certificate-event? evt)

Returns true when evt indicates a certificate change.

evt is an event from ol.clave.automation/subscribe-events. Certificate changes are the :certificate-obtained and :certificate-renewed event types.

(when (certificate-event? evt)
  (log/info "Certificate updated for" (event-domain evt)))

event-domain

(event-domain evt)

Returns the domain name from certificate event evt, or nil when absent.


wrap-redirect-https

(wrap-redirect-https handler)
(wrap-redirect-https handler {:keys [ssl-port] :or {ssl-port 443}})

Ring middleware that redirects HTTP requests on handler to HTTPS.

Requests that are already HTTPS pass through unchanged, detected by :scheme or an x-forwarded-proto header. Everything else receives a 301 redirect to the same host and path under https.

Options:

key description default

:ssl-port

HTTPS port for the redirect URL

443

Port 443 is left implicit in the URL; any other port, such as 8443, is included explicitly.

(wrap-redirect-https handler {:ssl-port 8443})

no-op-solver

(no-op-solver)

Creates a no-op ACME solver for testing.

The returned solver does nothing. It is useful with PEBBLE_VA_ALWAYS_VALID=1, where challenge validation is skipped.

{:solvers {:http-01 (no-op-solver)}}

missing-certificates

(missing-certificates system domains)

Returns the subset of domains without a currently available certificate.

system is a Clave automation system; ol.clave.automation/lookup-cert is the authoritative source of certificate state.


wait-for-certificates

(wait-for-certificates system domains event-queue timeout-ms poll-interval-ms)

Blocks until a certificate is available for every domain in domains.

Certificate state from ol.clave.automation/lookup-cert on system is authoritative. The loop rechecks that state at least every poll-interval-ms (a positive integer) and gives up after timeout-ms, or waits indefinitely when timeout-ms is nil. A terminal :certificate-failed event for a still-missing domain fails immediately rather than waiting out the timeout, and a :subscription-overflow event fails instead of silently degrading.

event-queue comes from ol.clave.automation/subscribe-events and must be created before ol.clave.automation/manage-domains, because subscriptions receive only live events. The caller must pass the same queue to ol.clave.automation/unsubscribe-events in a finally clause.

Returns nil once every certificate is available, and otherwise throws clojure.lang.ExceptionInfo on timeout, terminal failure, or overflow.

(let [events (auto/subscribe-events system)]
  (try
    (auto/manage-domains system ["example.com"])
    (wait-for-certificates system ["example.com"] events 120000 100)
    (finally
      (auto/unsubscribe-events system events))))