Summary
rekor-server serve can only expose the API over plaintext HTTP. go-swagger, which generates Rekor's server, already implements an HTTPS listener and a configureTLS hook, but Rekor never enables the former or populates the latter. This issues asks for both, serving TLS on the API listener, and a way to set a minimum TLS version and TLS 1.2 cipher suites on it.
Current behaviour
The listener scheme is hardcoded in , so https can never be enabled:
// cmd/rekor-server/app/serve.go
server.EnabledListeners = []string{"http"}
Certificate material can already be supplied today:
- Via CLI flag:
--tls-certificate, --tls-key, --tls-ca, --tls-port are registered in pkg/generated/restapi/server.go's init(). Cobra picks these up automatically, so they already show up in rekor-server --help.
- Via env var, as a fallback:
TLS_CERTIFICATE, TLS_PRIVATE_KEY, TLS_CA_CERTIFICATE, TLS_PORT.
Either way, the value correctly lands on the server struct but with no https listener enabled, it's inert.
The same applies to --scheme: it does populate EnabledListeners when restapi.NewServer builds the server, but serve.go immediately overwrites it with ["http"], discarding whatever scheme was requested. So the gap isn't that the flags don't reach the CLI, it's that hardcoded assignment always wins.
There's also no flag or config key feeding go-swagger's TLS policy hook:
// pkg/generated/restapi/configure_rekor_server.go
func configureTLS(_ *tls.Config) {
// Make all necessary changes to the TLS configuration here.
}
Note: trillian_log_server.tls and redis_server.enable-tls configure Rekor as a client to those backends; neither affects the API listener above.
Motivation
- The final hop to the Rekor process is unavoidably plaintext in reencrypt/passthrough load-balancing setups without a service mesh.
- Compliance baselines (FIPS 140-x, FedRAMP, PCI-DSS) require a stated TLS version/cipher floor on the listener itself, not just "TLS somewhere in front of it."
- On an untrusted internal network, a plaintext listener exposes log traffic to passive observation and lets an on-path attacker tamper with requests/responses in flight (detectable by a correct client via inclusion proofs, but still a confidentiality/availability gap worth closing).
Proposed change
- Make the listener scheme configurable (e.g.
--scheme), feeding go-swagger's existing EnabledListeners/TLSCertificate/TLSCertificateKey/TLSCACertificate fields from Rekor's own config, instead of hardcoding http.
- Wire a TLS policy — add
--tls-min-version and --tls-cipher-suites, applied inside configureTLS. Cipher-suite selection only affects TLS 1.2 handshakes (TLS 1.3 suites aren't configurable in Go); the min-version flag mainly matters for pinning 1.3 or making the floor explicit and auditable.
Defaults to current behaviour (HTTP only), so no impact on existing deployments.
Scope
- In: serving TLS on the API listener; min-version and TLS 1.2 cipher-suite configuration.
- Optional: mTLS via
--tls-ca, already supported by go-swagger once the listener exists.
- Out: the separate
:2112 metrics endpoint; Rekor's outbound TLS to Trillian/Redis (already configurable); certificate rotation (go-swagger loads the key pair once at startup).
Acceptance criteria
- No config change → behaves exactly as today (plaintext HTTP).
- Scheme + cert/key configured. HTTPS served on the configured port; plaintext rejected on it.
- Configured min version / TLS 1.2 cipher list is enforced against a client that doesn't meet it.
https with no certificate fails fast with a clear error, not a broken listener.
- New flags and the TLS 1.3 cipher-suite caveat are documented with the other rekor-server settings.
Prior art
sigstore/timestamp-authority also uses go-swagger and doesn't hardcode the listener. scheme := viper.GetStringSlice("scheme") feeds EnabledListeners directly (Viper-only, no registered flag). This request goes one step further and makes the scheme and TLS policy first-class rekor-server configuration.
Summary
rekor-server servecan only expose the API over plaintext HTTP. go-swagger, which generates Rekor's server, already implements an HTTPS listener and aconfigureTLShook, but Rekor never enables the former or populates the latter. This issues asks for both, serving TLS on the API listener, and a way to set a minimum TLS version and TLS 1.2 cipher suites on it.Current behaviour
The listener scheme is hardcoded in , so
httpscan never be enabled:Certificate material can already be supplied today:
--tls-certificate,--tls-key,--tls-ca,--tls-portare registered inpkg/generated/restapi/server.go'sinit(). Cobra picks these up automatically, so they already show up inrekor-server --help.TLS_CERTIFICATE,TLS_PRIVATE_KEY,TLS_CA_CERTIFICATE,TLS_PORT.Either way, the value correctly lands on the server struct but with no
httpslistener enabled, it's inert.The same applies to
--scheme: it does populateEnabledListenerswhenrestapi.NewServerbuilds the server, butserve.goimmediately overwrites it with["http"], discarding whatever scheme was requested. So the gap isn't that the flags don't reach the CLI, it's that hardcoded assignment always wins.There's also no flag or config key feeding go-swagger's TLS policy hook:
Note:
trillian_log_server.tlsandredis_server.enable-tlsconfigure Rekor as a client to those backends; neither affects the API listener above.Motivation
Proposed change
--scheme), feeding go-swagger's existingEnabledListeners/TLSCertificate/TLSCertificateKey/TLSCACertificatefields from Rekor's own config, instead of hardcodinghttp.--tls-min-versionand--tls-cipher-suites, applied insideconfigureTLS. Cipher-suite selection only affects TLS 1.2 handshakes (TLS 1.3 suites aren't configurable in Go); the min-version flag mainly matters for pinning 1.3 or making the floor explicit and auditable.Defaults to current behaviour (HTTP only), so no impact on existing deployments.
Scope
--tls-ca, already supported by go-swagger once the listener exists.:2112metrics endpoint; Rekor's outbound TLS to Trillian/Redis (already configurable); certificate rotation (go-swagger loads the key pair once at startup).Acceptance criteria
httpswith no certificate fails fast with a clear error, not a broken listener.Prior art
sigstore/timestamp-authorityalso uses go-swagger and doesn't hardcode the listener.scheme := viper.GetStringSlice("scheme")feedsEnabledListenersdirectly (Viper-only, no registered flag). This request goes one step further and makes the scheme and TLS policy first-classrekor-serverconfiguration.