-
Notifications
You must be signed in to change notification settings - Fork 24.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce fips_mode setting and associated checks (#32326)
* Introduce fips_mode setting and associated checks Introduce xpack.security.fips_mode.enabled setting ( default false) When it is set to true, a number of Bootstrap checks are performed: - Check that Secure Settings are of the latest version (3) - Check that no JKS keystores are configured - Check that compliant algorithms ( PBKDF2 family ) are used for password hashing
- Loading branch information
Showing
8 changed files
with
368 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
...rity/src/main/java/org/elasticsearch/xpack/security/FIPS140JKSKeystoreBootstrapCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.security; | ||
|
||
import org.elasticsearch.bootstrap.BootstrapCheck; | ||
import org.elasticsearch.bootstrap.BootstrapContext; | ||
import org.elasticsearch.common.settings.Settings; | ||
|
||
|
||
public class FIPS140JKSKeystoreBootstrapCheck implements BootstrapCheck { | ||
|
||
private final boolean fipsModeEnabled; | ||
|
||
FIPS140JKSKeystoreBootstrapCheck(Settings settings) { | ||
this.fipsModeEnabled = Security.FIPS_MODE_ENABLED.get(settings); | ||
} | ||
|
||
/** | ||
* Test if the node fails the check. | ||
* | ||
* @param context the bootstrap context | ||
* @return the result of the bootstrap check | ||
*/ | ||
@Override | ||
public BootstrapCheckResult check(BootstrapContext context) { | ||
|
||
if (fipsModeEnabled) { | ||
final Settings settings = context.settings; | ||
Settings keystoreTypeSettings = settings.filter(k -> k.endsWith("keystore.type")) | ||
.filter(k -> settings.get(k).equalsIgnoreCase("jks")); | ||
if (keystoreTypeSettings.isEmpty() == false) { | ||
return BootstrapCheckResult.failure("JKS Keystores cannot be used in a FIPS 140 compliant JVM. Please " + | ||
"revisit [" + keystoreTypeSettings.toDelimitedString(',') + "] settings"); | ||
} | ||
// Default Keystore type is JKS if not explicitly set | ||
Settings keystorePathSettings = settings.filter(k -> k.endsWith("keystore.path")) | ||
.filter(k -> settings.hasValue(k.replace(".path", ".type")) == false); | ||
if (keystorePathSettings.isEmpty() == false) { | ||
return BootstrapCheckResult.failure("JKS Keystores cannot be used in a FIPS 140 compliant JVM. Please " + | ||
"revisit [" + keystorePathSettings.toDelimitedString(',') + "] settings"); | ||
} | ||
|
||
} | ||
return BootstrapCheckResult.success(); | ||
} | ||
|
||
@Override | ||
public boolean alwaysEnforce() { | ||
return fipsModeEnabled; | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
.../java/org/elasticsearch/xpack/security/FIPS140PasswordHashingAlgorithmBootstrapCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.security; | ||
|
||
import org.elasticsearch.bootstrap.BootstrapCheck; | ||
import org.elasticsearch.bootstrap.BootstrapContext; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.xpack.core.XPackSettings; | ||
|
||
import java.util.Locale; | ||
|
||
public class FIPS140PasswordHashingAlgorithmBootstrapCheck implements BootstrapCheck { | ||
|
||
private final boolean fipsModeEnabled; | ||
|
||
FIPS140PasswordHashingAlgorithmBootstrapCheck(Settings settings) { | ||
this.fipsModeEnabled = Security.FIPS_MODE_ENABLED.get(settings); | ||
} | ||
|
||
/** | ||
* Test if the node fails the check. | ||
* | ||
* @param context the bootstrap context | ||
* @return the result of the bootstrap check | ||
*/ | ||
@Override | ||
public BootstrapCheckResult check(BootstrapContext context) { | ||
final String selectedAlgorithm = XPackSettings.PASSWORD_HASHING_ALGORITHM.get(context.settings); | ||
if (selectedAlgorithm.toLowerCase(Locale.ROOT).startsWith("pbkdf2") == false) { | ||
return BootstrapCheckResult.failure("Only PBKDF2 is allowed for password hashing in a FIPS-140 JVM. Please set the " + | ||
"appropriate value for [ " + XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey() + " ] setting."); | ||
} | ||
return BootstrapCheckResult.success(); | ||
} | ||
|
||
@Override | ||
public boolean alwaysEnforce() { | ||
return fipsModeEnabled; | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
...y/src/main/java/org/elasticsearch/xpack/security/FIPS140SecureSettingsBootstrapCheck.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.security; | ||
|
||
import org.elasticsearch.bootstrap.BootstrapCheck; | ||
import org.elasticsearch.bootstrap.BootstrapContext; | ||
import org.elasticsearch.common.settings.KeyStoreWrapper; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.env.Environment; | ||
|
||
import java.io.IOException; | ||
import java.io.UncheckedIOException; | ||
|
||
public class FIPS140SecureSettingsBootstrapCheck implements BootstrapCheck { | ||
|
||
private final boolean fipsModeEnabled; | ||
private final Environment environment; | ||
|
||
FIPS140SecureSettingsBootstrapCheck(Settings settings, Environment environment) { | ||
this.fipsModeEnabled = Security.FIPS_MODE_ENABLED.get(settings); | ||
this.environment = environment; | ||
} | ||
|
||
/** | ||
* Test if the node fails the check. | ||
* | ||
* @param context the bootstrap context | ||
* @return the result of the bootstrap check | ||
*/ | ||
@Override | ||
public BootstrapCheckResult check(BootstrapContext context) { | ||
if (fipsModeEnabled) { | ||
try (KeyStoreWrapper secureSettings = KeyStoreWrapper.load(environment.configFile())) { | ||
if (secureSettings != null && secureSettings.getFormatVersion() < 3) { | ||
return BootstrapCheckResult.failure("Secure settings store is not of the latest version. Please use " + | ||
"bin/elasticsearch-keystore create to generate a new secure settings store and migrate the secure settings there."); | ||
} | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
} | ||
return BootstrapCheckResult.success(); | ||
} | ||
|
||
@Override | ||
public boolean alwaysEnforce() { | ||
return fipsModeEnabled; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
...src/test/java/org/elasticsearch/xpack/security/FIPS140JKSKeystoreBootstrapCheckTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.security; | ||
|
||
import org.elasticsearch.bootstrap.BootstrapContext; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.test.ESTestCase; | ||
|
||
public class FIPS140JKSKeystoreBootstrapCheckTests extends ESTestCase { | ||
|
||
public void testNoKeystoreIsAllowed() { | ||
final Settings.Builder settings = Settings.builder() | ||
.put("xpack.security.fips_mode.enabled", "true"); | ||
assertFalse(new FIPS140JKSKeystoreBootstrapCheck(settings.build()).check(new BootstrapContext(settings.build(), null)).isFailure()); | ||
} | ||
|
||
public void testSSLKeystoreTypeIsNotAllowed() { | ||
final Settings.Builder settings = Settings.builder() | ||
.put("xpack.security.fips_mode.enabled", "true") | ||
.put("xpack.ssl.keystore.path", "/this/is/the/path") | ||
.put("xpack.ssl.keystore.type", "JKS"); | ||
assertTrue(new FIPS140JKSKeystoreBootstrapCheck(settings.build()).check(new BootstrapContext(settings.build(), null)).isFailure()); | ||
} | ||
|
||
public void testSSLImplicitKeystoreTypeIsNotAllowed() { | ||
final Settings.Builder settings = Settings.builder() | ||
.put("xpack.security.fips_mode.enabled", "true") | ||
.put("xpack.ssl.keystore.path", "/this/is/the/path") | ||
.put("xpack.ssl.keystore.type", "JKS"); | ||
assertTrue(new FIPS140JKSKeystoreBootstrapCheck(settings.build()).check(new BootstrapContext(settings.build(), null)).isFailure()); | ||
} | ||
|
||
public void testTransportSSLKeystoreTypeIsNotAllowed() { | ||
final Settings.Builder settings = Settings.builder() | ||
.put("xpack.security.fips_mode.enabled", "true") | ||
.put("xpack.security.transport.ssl.keystore.path", "/this/is/the/path") | ||
.put("xpack.security.transport.ssl.keystore.type", "JKS"); | ||
assertTrue(new FIPS140JKSKeystoreBootstrapCheck(settings.build()).check(new BootstrapContext(settings.build(), null)).isFailure()); | ||
} | ||
|
||
public void testHttpSSLKeystoreTypeIsNotAllowed() { | ||
final Settings.Builder settings = Settings.builder() | ||
.put("xpack.security.fips_mode.enabled", "true") | ||
.put("xpack.security.http.ssl.keystore.path", "/this/is/the/path") | ||
.put("xpack.security.http.ssl.keystore.type", "JKS"); | ||
assertTrue(new FIPS140JKSKeystoreBootstrapCheck(settings.build()).check(new BootstrapContext(settings.build(), null)).isFailure()); | ||
} | ||
|
||
public void testRealmKeystoreTypeIsNotAllowed() { | ||
final Settings.Builder settings = Settings.builder() | ||
.put("xpack.security.fips_mode.enabled", "true") | ||
.put("xpack.security.authc.realms.ldap.ssl.keystore.path", "/this/is/the/path") | ||
.put("xpack.security.authc.realms.ldap.ssl.keystore.type", "JKS"); | ||
assertTrue(new FIPS140JKSKeystoreBootstrapCheck(settings.build()).check(new BootstrapContext(settings.build(), null)).isFailure()); | ||
} | ||
|
||
public void testImplicitRealmKeystoreTypeIsNotAllowed() { | ||
final Settings.Builder settings = Settings.builder() | ||
.put("xpack.security.fips_mode.enabled", "true") | ||
.put("xpack.security.authc.realms.ldap.ssl.keystore.path", "/this/is/the/path"); | ||
assertTrue(new FIPS140JKSKeystoreBootstrapCheck(settings.build()).check(new BootstrapContext(settings.build(), null)).isFailure()); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
.../org/elasticsearch/xpack/security/FIPS140PasswordHashingAlgorithmBootstrapCheckTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
package org.elasticsearch.xpack.security; | ||
|
||
import org.elasticsearch.bootstrap.BootstrapContext; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.test.ESTestCase; | ||
import org.elasticsearch.xpack.core.XPackSettings; | ||
|
||
public class FIPS140PasswordHashingAlgorithmBootstrapCheckTests extends ESTestCase { | ||
|
||
public void testPBKDF2AlgorithmIsAllowed() { | ||
Settings settings = Settings.builder().put("xpack.security.fips_mode.enabled", "true").build(); | ||
|
||
settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "PBKDF2_10000").build(); | ||
assertFalse(new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings).check(new BootstrapContext(settings, null)).isFailure()); | ||
|
||
settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "PBKDF2").build(); | ||
assertFalse(new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings).check(new BootstrapContext(settings, null)).isFailure()); | ||
} | ||
|
||
public void testBCRYPTAlgorithmIsNotAllowed() { | ||
Settings settings = Settings.builder().put("xpack.security.fips_mode.enabled", "true").build(); | ||
assertTrue(new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings).check(new BootstrapContext(settings, null)).isFailure()); | ||
settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "BCRYPT").build(); | ||
assertTrue(new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings).check(new BootstrapContext(settings, null)).isFailure()); | ||
|
||
settings = Settings.builder().put(XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey(), "BCRYPT11").build(); | ||
assertTrue(new FIPS140PasswordHashingAlgorithmBootstrapCheck(settings).check(new BootstrapContext(settings, null)).isFailure()); | ||
} | ||
} |
Oops, something went wrong.