Skip to content
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

Merged
merged 18 commits into from
Oct 4, 2018

Conversation

jkakavas
Copy link
Member

@jkakavas jkakavas commented Sep 25, 2018

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 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.
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security

@jkakavas
Copy link
Member Author

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
Copy link
Member Author

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 )

Copy link
Member

@jaymode jaymode left a 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
Copy link
Member

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");
Copy link
Member

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.

Copy link
Member Author

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
@jkakavas
Copy link
Member Author

Failed to get resource: HEAD. [HTTP HTTP/1.1 504 Gateway Time-out: https://plugins.gradle.org/m2/org/apache/apache/13/apache-13.pom]

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
Copy link
Member Author

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.

Copy link
Member

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?

@jkakavas
Copy link
Member Author

@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) {
Copy link
Member

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) {
Copy link
Member

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
Copy link
Member

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";
Copy link
Member

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();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extra line

@jkakavas
Copy link
Member Author

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?

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.

@jaymode
Copy link
Member

jaymode commented Sep 28, 2018

I guess we can return them all and adjust the documentation for the get certificates API

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) {
Copy link
Member Author

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.

Copy link
Member

@jaymode jaymode left a 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/Elasticsearch/{es}

@jkakavas
Copy link
Member Author

jkakavas commented Oct 3, 2018

Thanks @jaymode , I'm running a final CI run with the master merged for due diligence and will merge this on green

@jkakavas jkakavas merged commit 2c82b80 into elastic:master Oct 4, 2018
jkakavas added a commit that referenced this pull request Oct 4, 2018
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.
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Oct 4, 2018
* 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)
  ...
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Oct 4, 2018
* 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)
  ...
jkakavas added a commit that referenced this pull request Oct 5, 2018
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.
kcm pushed a commit that referenced this pull request Oct 30, 2018
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants