-
Notifications
You must be signed in to change notification settings - Fork 25.3k
Support PKCS#11 tokens as keystores and truststores #34063
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
Changes from all commits
9c18d80
6f6eb3a
430b998
8a0b64e
365d675
92248a1
5fda332
6dde2f7
2df67f4
c37c5e3
efe542c
60da02b
777554b
41c74ac
4ec50c6
ba90235
88f80c3
6604aa1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
|
||
import org.elasticsearch.ElasticsearchException; | ||
import org.elasticsearch.common.Nullable; | ||
import org.elasticsearch.common.settings.SecureString; | ||
import org.elasticsearch.env.Environment; | ||
import org.elasticsearch.xpack.core.ssl.cert.CertificateInfo; | ||
|
||
|
@@ -30,9 +31,14 @@ | |
*/ | ||
class DefaultJDKTrustConfig extends TrustConfig { | ||
|
||
static final DefaultJDKTrustConfig INSTANCE = new DefaultJDKTrustConfig(); | ||
private SecureString trustStorePassword; | ||
|
||
private DefaultJDKTrustConfig() { | ||
/** | ||
* @param trustStorePassword the password for the default jdk truststore defined either as a system property or in the Elasticsearch | ||
* configuration. It applies only when PKCS#11 tokens are user, is null otherwise | ||
*/ | ||
DefaultJDKTrustConfig(@Nullable SecureString trustStorePassword) { | ||
this.trustStorePassword = trustStorePassword; | ||
} | ||
|
||
@Override | ||
|
@@ -76,13 +82,14 @@ public int hashCode() { | |
/** | ||
* Merges the default trust configuration with the provided {@link TrustConfig} | ||
* @param trustConfig the trust configuration to merge with | ||
* @param trustStorePassword the password for the default jdk truststore. It applies only to PKCS#11 tokens | ||
* @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 commentThe 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? |
||
if (trustConfig == null) { | ||
return INSTANCE; | ||
return new DefaultJDKTrustConfig(trustStorePassword); | ||
} else { | ||
return new CombiningTrustConfig(Arrays.asList(INSTANCE, trustConfig)); | ||
return new CombiningTrustConfig(Arrays.asList(new DefaultJDKTrustConfig(trustStorePassword), trustConfig)); | ||
} | ||
} | ||
|
||
|
@@ -94,9 +101,10 @@ static TrustConfig merge(TrustConfig trustConfig) { | |
* @return the KeyStore used as truststore for PKCS#11 initialized with the password, null otherwise | ||
*/ | ||
private KeyStore getSystemTrustStore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { | ||
if (System.getProperty("javax.net.ssl.trustStoreType", "").equalsIgnoreCase("PKCS11")) { | ||
if (System.getProperty("javax.net.ssl.trustStoreType", "").equalsIgnoreCase("PKCS11") | ||
&& trustStorePassword != null) { | ||
KeyStore keyStore = KeyStore.getInstance("PKCS11"); | ||
keyStore.load(null, System.getProperty("javax.net.ssl.trustStorePassword", "").toCharArray()); | ||
keyStore.load(null, trustStorePassword.getChars()); | ||
return keyStore; | ||
} | ||
return null; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -212,12 +212,11 @@ private static TrustConfig createTrustConfig(Settings settings, KeyConfig keyCon | |
|
||
private static TrustConfig createCertChainTrustConfig(Settings settings, KeyConfig keyConfig, SSLConfiguration global) { | ||
String trustStorePath = SETTINGS_PARSER.truststorePath.get(settings).orElse(null); | ||
|
||
String trustStoreType = getKeyStoreType(SETTINGS_PARSER.truststoreType, settings, trustStorePath); | ||
List<String> caPaths = getListOrNull(SETTINGS_PARSER.caPaths, settings); | ||
if (trustStorePath != null && caPaths != null) { | ||
throw new IllegalArgumentException("you cannot specify a truststore and ca files"); | ||
} | ||
|
||
VerificationMode verificationMode = SETTINGS_PARSER.verificationMode.get(settings).orElseGet(() -> { | ||
if (global != null) { | ||
return global.verificationMode(); | ||
|
@@ -228,24 +227,39 @@ private static TrustConfig createCertChainTrustConfig(Settings settings, KeyConf | |
return TrustAllConfig.INSTANCE; | ||
} else if (caPaths != null) { | ||
return new PEMTrustConfig(caPaths); | ||
} else if (trustStorePath != null) { | ||
SecureString trustStorePassword = SETTINGS_PARSER.truststorePassword.get(settings); | ||
} else if (trustStorePath != null || trustStoreType.equalsIgnoreCase("pkcs11")) { | ||
String trustStoreAlgorithm = SETTINGS_PARSER.truststoreAlgorithm.get(settings); | ||
String trustStoreType = getKeyStoreType(SETTINGS_PARSER.truststoreType, settings, trustStorePath); | ||
SecureString trustStorePassword = SETTINGS_PARSER.truststorePassword.get(settings); | ||
return new StoreTrustConfig(trustStorePath, trustStoreType, trustStorePassword, trustStoreAlgorithm); | ||
} else if (global == null && System.getProperty("javax.net.ssl.trustStore") != null | ||
&& System.getProperty("javax.net.ssl.trustStore").equals("NONE") == false) { | ||
try (SecureString truststorePassword = new SecureString(System.getProperty("javax.net.ssl.trustStorePassword", ""))) { | ||
return new StoreTrustConfig(System.getProperty("javax.net.ssl.trustStore"), KeyStore.getDefaultType(), truststorePassword, | ||
System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm())); | ||
System.getProperty("ssl.TrustManagerFactory.algorithm", TrustManagerFactory.getDefaultAlgorithm())); | ||
} | ||
} else if (global != null && keyConfig == global.keyConfig()) { | ||
return global.trustConfig(); | ||
} else if (keyConfig != KeyConfig.NONE) { | ||
return DefaultJDKTrustConfig.merge(keyConfig); | ||
return DefaultJDKTrustConfig.merge(keyConfig, getDefaultTrustStorePassword(settings)); | ||
} else { | ||
return DefaultJDKTrustConfig.INSTANCE; | ||
return new DefaultJDKTrustConfig(getDefaultTrustStorePassword(settings)); | ||
} | ||
} | ||
|
||
private static SecureString getDefaultTrustStorePassword(Settings settings) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
// We only handle the default store password if it's a PKCS#11 token | ||
if (System.getProperty("javax.net.ssl.trustStoreType", "").equalsIgnoreCase("PKCS11")) { | ||
try (SecureString systemTrustStorePassword = | ||
new SecureString(System.getProperty("javax.net.ssl.trustStorePassword", "").toCharArray())) { | ||
if (systemTrustStorePassword.length() == 0) { | ||
try (SecureString trustStorePassword = SETTINGS_PARSER.truststorePassword.get(settings)) { | ||
return trustStorePassword; | ||
} | ||
} | ||
return systemTrustStorePassword; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
private static List<String> getListOrNull(Setting<List<String>> listSetting, 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.
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 )