-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support PKCS#11 tokens as keystores and truststores #34063
Conversation
This commit enables Elasticsearch to use the JVM-wide configured PKCS#11 token as a keystore or a truststore for its TLS configuration. The JVM is assumed to be configured accordingly with the appropriate Security Provider implementation that supports PKCS#11 tokens. For the PKCS#11 token to be used as a keystore or a truststore for an SSLConfiguration, the keystore.type or truststore.type must be explicitly set to pkcs11 accordingly in the configuration.
Pinging @elastic/es-security |
Not sure if the scope of this makes it a good candidate for 6.4.2, WDYT @jaymode ? |
@@ -400,8 +400,9 @@ The path to the Java Keystore file that contains a private key and certificate. | |||
`ssl.key` and `ssl.keystore.path` may not be used at the same time. | |||
|
|||
`ssl.keystore.type`:: | |||
The format of the keystore file. Should be either `jks` to use the Java |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for calling out PKCS11 in the settings is that the implementation now includes specific handling if this is set as the keystore.type ( As opposed to for instance BCFKS
which can be used with the BouncyCastle FIPS Security Provider if configured, but handled transparently )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a request for a simple test. Otherwise this LGTM. IMO this is a bugfix and should go to 6.4.x
@@ -1316,6 +1320,29 @@ a PKCS#12 container includes trusted certificate ("anchor") entries look for | |||
`openssl pkcs12 -info` output, or `trustedCertEntry` in the | |||
`keytool -list` output. | |||
|
|||
===== PKCS#11 tokens | |||
|
|||
When using a PKCS#11 cryptographic token, which contain the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/contain/contains ?
ks.load(null, storePassword.getChars()); | ||
return ks; | ||
} | ||
throw new IllegalArgumentException("keystore.path or truststore.path can only be empty when using a PKCS#11 token"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add unit tests for this method? At least one with an expectThrows for this IAE.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks
- Adds unit test for TrustConfig#getStore - Fix typo - Do not return the certificates in the PKCS#11 token when using the SSL Certificate API
|
final Certificate certificate = chain[i]; | ||
if (certificate instanceof X509Certificate) { | ||
certificates.add(new CertificateInfo(keyStorePath, keyStoreType, alias, i == 0, (X509Certificate) certificate)); | ||
// Do not return certificates from the PKCS#11 token, as it is also the JRE default store |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jaymode I wanted to point out this change ( to not return the certificates of the PKCS#11 token in the get certificates API responses ) since I introduced it after your LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, this seems odd since the idea is to be able to use this API to alert about certificate expiration. Wouldn't we want this if the cert in the PKCS11 token is going to expire?
@jaymode Can you please take a look at the additional changes? |
@@ -78,11 +80,11 @@ public int hashCode() { | |||
* @param trustConfig the trust configuration to merge with | |||
* @return a {@link TrustConfig} that represents a combination of both trust configurations | |||
*/ | |||
static TrustConfig merge(TrustConfig trustConfig) { | |||
static TrustConfig merge(TrustConfig trustConfig, SecureString trustStorePassword) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add the parameter to the javadocs and include that this password is for the default jdk store?
@@ -96,7 +98,10 @@ static TrustConfig merge(TrustConfig trustConfig) { | |||
private KeyStore getSystemTrustStore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { | |||
if (System.getProperty("javax.net.ssl.trustStoreType", "").equalsIgnoreCase("PKCS11")) { | |||
KeyStore keyStore = KeyStore.getInstance("PKCS11"); | |||
keyStore.load(null, System.getProperty("javax.net.ssl.trustStorePassword", "").toCharArray()); | |||
if (trustStorePassword.length() == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just to be paranoid add a null check?
final Certificate certificate = chain[i]; | ||
if (certificate instanceof X509Certificate) { | ||
certificates.add(new CertificateInfo(keyStorePath, keyStoreType, alias, i == 0, (X509Certificate) certificate)); | ||
// Do not return certificates from the PKCS#11 token, as it is also the JRE default store |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, this seems odd since the idea is to be able to use this API to alert about certificate expiration. Wouldn't we want this if the cert in the PKCS11 token is going to expire?
throw new IllegalArgumentException("the keystore [" + keyStorePath + "] does not contain a private key entry"); | ||
final String message = null != keyStorePath ? | ||
"the keystore [" + keyStorePath + "] does not contain a private key entry" : | ||
"the system wide configured PKCS#11 token does not contain a private key entry"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove system wide
?
|
||
public SSLContext sslContext(String context) { | ||
return sslContextHolder(super.getSSLConfiguration(context)).sslContext(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: extra line
You have a point. I got carried away by the fact that we used to filter all certs from the JDK default truststore. Returning everything will provide with all sorts of CA certs that the JDK ships with and/or irrelevant to Elasticsearch certificates that happened to be in the token so there is a chance of false positives. I guess we can return them all and adjust the documentation for the get certificates API ( https://www.elastic.co/guide/en/elasticsearch/reference/current/security-api-ssl.html ) so that users are aware and can filter the results as they see fit. |
That works for me since this is only for PKCS#11 |
- Return all certificates when using a PKCS11 token and adjust documentation to reflect that - Ensure that the truststore password defined in a system property takes precedence over the one defined in Elasticsearch config
} | ||
} | ||
|
||
private static SecureString getDefaultTrustStorePassword(Settings settings) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve the deafult JDK TrustStore password here for the case of PKCS11 tokens, so that we don't need to pass the trustStorePassword to the DefaultJDKTrustConfig
's constructor for all other truststore types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
fallback to use he appropriate JVM setting (`-Djavax.net.ssl.trustStorePassword`) | ||
if that s set. | ||
Since there can only be one PKCS#11 token configured, only one keystore and | ||
truststore will be usable for configuration in Elasticsearch. This in turn means |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/Elasticsearch/{es}
Thanks @jaymode , I'm running a final CI run with the master merged for due diligence and will merge this on green |
This enables Elasticsearch to use the JVM-wide configured PKCS#11 token as a keystore or a truststore for its TLS configuration. The JVM is assumed to be configured accordingly with the appropriate Security Provider implementation that supports PKCS#11 tokens. For the PKCS#11 token to be used as a keystore or a truststore for an SSLConfiguration, the .keystore.type or .truststore.type must be explicitly set to pkcs11 in the configuration. The fact that the PKCS#11 token configuration is JVM wide implies that there is only one available keystore and truststore that can be used by TLS configurations in Elasticsearch. The PIN for the PKCS#11 token can be set as a truststore parameter in Elasticsearch or as a JVM parameter ( -Djavax.net.ssl.trustStorePassword). The basic goal of enabling PKCS#11 token support is to allow PKCS#11-NSS in FIPS mode to be used as a FIPS 140-2 enabled Security Provider.
* master: (25 commits) HLRC: ML Adding get datafeed stats API (elastic#34271) Small fixes to the HLRC watcher documentation. (elastic#34306) Tasks: Document that status is not semvered (elastic#34270) HLRC: ML Add preview datafeed api (elastic#34284) [CI] Fix bogus ScheduleWithFixedDelayTests.testRunnableRunsAtMostOnceAfterCancellation Fix error in documentation for activete watch SCRIPTING: Terms set query expression (elastic#33856) Logging: Drop remaining Settings log ctor (elastic#34149) [ML] Remove unused last_data_time member from Job (elastic#34262) Docs: Allow skipping response assertions (elastic#34240) HLRC: Add activate watch action (elastic#33988) [Security] Multi Index Expression alias wildcard exclusion (elastic#34144) [ML] Label anomalies with multi_bucket_impact (elastic#34233) Document smtp.ssl.trust configuration option (elastic#34275) Support PKCS#11 tokens as keystores and truststores (elastic#34063) Fix sporadic failure in NestedObjectMapperTests [Authz] Allow update settings action for system user (elastic#34030) Replace version with reader cache key in IndicesRequestCache (elastic#34189) [TESTS] Set SO_LINGER and SO_REUSEADDR on the mock socket (elastic#34211) Security: upgrade unboundid ldapsdk to 4.0.8 (elastic#34247) ...
* rename-ccr-stats: (25 commits) HLRC: ML Adding get datafeed stats API (elastic#34271) Small fixes to the HLRC watcher documentation. (elastic#34306) Tasks: Document that status is not semvered (elastic#34270) HLRC: ML Add preview datafeed api (elastic#34284) [CI] Fix bogus ScheduleWithFixedDelayTests.testRunnableRunsAtMostOnceAfterCancellation Fix error in documentation for activete watch SCRIPTING: Terms set query expression (elastic#33856) Logging: Drop remaining Settings log ctor (elastic#34149) [ML] Remove unused last_data_time member from Job (elastic#34262) Docs: Allow skipping response assertions (elastic#34240) HLRC: Add activate watch action (elastic#33988) [Security] Multi Index Expression alias wildcard exclusion (elastic#34144) [ML] Label anomalies with multi_bucket_impact (elastic#34233) Document smtp.ssl.trust configuration option (elastic#34275) Support PKCS#11 tokens as keystores and truststores (elastic#34063) Fix sporadic failure in NestedObjectMapperTests [Authz] Allow update settings action for system user (elastic#34030) Replace version with reader cache key in IndicesRequestCache (elastic#34189) [TESTS] Set SO_LINGER and SO_REUSEADDR on the mock socket (elastic#34211) Security: upgrade unboundid ldapsdk to 4.0.8 (elastic#34247) ...
This enables Elasticsearch to use the JVM-wide configured PKCS#11 token as a keystore or a truststore for its TLS configuration. The JVM is assumed to be configured accordingly with the appropriate Security Provider implementation that supports PKCS#11 tokens. For the PKCS#11 token to be used as a keystore or a truststore for an SSLConfiguration, the .keystore.type or .truststore.type must be explicitly set to pkcs11 in the configuration. The fact that the PKCS#11 token configuration is JVM wide implies that there is only one available keystore and truststore that can be used by TLS configurations in Elasticsearch. The PIN for the PKCS#11 token can be set as a truststore parameter in Elasticsearch or as a JVM parameter ( -Djavax.net.ssl.trustStorePassword). The basic goal of enabling PKCS#11 token support is to allow PKCS#11-NSS in FIPS mode to be used as a FIPS 140-2 enabled Security Provider.
This enables Elasticsearch to use the JVM-wide configured PKCS#11 token as a keystore or a truststore for its TLS configuration. The JVM is assumed to be configured accordingly with the appropriate Security Provider implementation that supports PKCS#11 tokens. For the PKCS#11 token to be used as a keystore or a truststore for an SSLConfiguration, the .keystore.type or .truststore.type must be explicitly set to pkcs11 in the configuration. The fact that the PKCS#11 token configuration is JVM wide implies that there is only one available keystore and truststore that can be used by TLS configurations in Elasticsearch. The PIN for the PKCS#11 token can be set as a truststore parameter in Elasticsearch or as a JVM parameter ( -Djavax.net.ssl.trustStorePassword). The basic goal of enabling PKCS#11 token support is to allow PKCS#11-NSS in FIPS mode to be used as a FIPS 140-2 enabled Security Provider.
This enables Elasticsearch to use the JVM-wide configured
PKCS#11 token as a keystore or a truststore for its TLS configuration.
The JVM is assumed to be configured accordingly with the appropriate
Security Provider implementation that supports PKCS#11 tokens.
For the PKCS#11 token to be used as a keystore or a truststore for an
SSLConfiguration, the
.keystore.type
or.truststore.type
must beexplicitly set to
pkcs11
in the configuration.The fact that the PKCS#11 token configuration is JVM wide implies that
there is only one available keystore and truststore that can be used by TLS
configurations in Elasticsearch.
The PIN for the PKCS#11 token can be set as a
truststore
parameter inElasticsearch or as a JVM parameter (
-Djavax.net.ssl.trustStorePassword
).The basic goal of enabling PKCS#11 token support is to allow PKCS#11-NSS in
FIPS mode to be used as a FIPS 140-2 enabled Security Provider.