pwm-project / pwm

pwm
Other
883 stars 248 forks source link

Allow TLS key pair to be sourced at runtime from a Kubernetes secret #700

Open klasen opened 1 year ago

klasen commented 1 year ago

If intra-cluster communication needs to be encrypted, the pwm must provide https service with a certificate trusted by the ingress controller.

In order to achieve this I'd like to provide the TLS key/cert pair at pod runtime using a Secret of type "kubernetes.io/tls", coming a tls.crt and tls.key files, and ca.crt secret for intermediate and root certificates.

Unfortunately, because of the current way certs are configured in pwm, I can't mount this secret to any pod folder and get the pair picked up by the container at runtime.

See https://kubernetes.github.io/ingress-nginx/examples/auth/client-certs/#creating-certificate-secrets

jrivard commented 1 year ago

Id like to see this added as well. In the meantime, just in case it's not clear, PWM will use the default Java truststore for certificate validation in cases where no certificate is configured in the corresponding setting.

So the approach to implement this would be to have the docker startup script:

1) generate a Java keystore using keytool 2) import any certs found in a defined path 3) set JAVA_OPTIONS parameter to have the jvm use the above keystore

I don't think any changes to PWM Java code are required.

klasen commented 1 year ago

PWM will use the default Java truststore for certificate validation in cases where no certificate is configured in the corresponding setting.

@jrivard Does this also apply to the HTTPS Private Key & Certificate setting? The comment on this setting is If this setting does not have a value, the SSPR HTTPS web server uses an auto-generated value based on Settings ⇨ Application ⇨ Application ⇨ Site URL and other current configuration data.

jrivard commented 1 year ago

@jrivard Does this also apply to the HTTPS Private Key & Certificate setting? The comment on this setting is If this setting does not have a value, the SSPR HTTPS web server uses an auto-generated value based on Settings ⇨ Application ⇨ Application ⇨ Site URL and other current configuration data.

@klasen Nope, only for certificate trusts. Though we could probably have it try to use a well-known alias name for the private cert and only auto-generate one if it can't find such a cert..... I'll think about it a bit...

klasen commented 1 year ago

Could we set javax.net.ssl.keyStore to a keystore generated by the container startup script and have tomcat use the default SSLContext?

This default SSLContext is initialized with a default KeyManager and a default TrustManager. If a keystore is specified by the javax.net.ssl.keyStore system property and an appropriate javax.net.ssl.keyStorePassword system property (see How to Specify a java.lang.System Property), then the KeyManager created by the default SSLContext will be a KeyManager implementation for managing the specified keystore. (The actual implementation will be as specified in Customizing the Default Key Managers and Trust Managers.) If no such system property is specified, then the keystore managed by the KeyManager will be a new empty keystore.

From https://docs.oracle.com/en/java/javase/11/security/java-secure-socket-extension-jsse-reference-guide.html#GUID-7D9F43B8-AABF-4C5B-93E6-3AFB18B66150

jrivard commented 1 year ago

Could we set javax.net.ssl.keyStore to a keystore generated by the container startup script and have tomcat use the default SSLContext?

I don't know. My guess is that if it worked it would probably break other things TLS. PWM doesn't change the default KeyManager as far as I know and just sets tomcat's keystore properties, so I don't know what magic happens inside tomcat. At that point your probably better off just making your own docker image with tomcat and the PWM war and configuring tomcat as desired... For reference this is the PWM code that does the embedded tomcat initialization:

https://github.com/pwm-project/pwm/blob/master/onejar/src/main/java/password/pwm/onejar/TomcatOnejarRunner.java