Skip to content

Commit

Permalink
Refactor FIPS BootstrapChecks to simple checks (elastic#47499)
Browse files Browse the repository at this point in the history
FIPS 140 bootstrap checks should not be bootstrap checks as they
are always enforced. This commit moves the validation logic within
the security plugin.
The FIPS140SecureSettingsBootstrapCheck was not applicable as the
keystore was being loaded on init, before the Bootstrap checks
were checked, so an elasticsearch keystore of version < 3 would
cause the node to fail in a FIPS 140 JVM before the bootstrap check
kicked in, and as such hasn't been migrated.

Resolves: elastic#34772
  • Loading branch information
jkakavas committed Oct 22, 2019
1 parent 0656207 commit d44e13a
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 445 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
import org.elasticsearch.xpack.core.monitoring.MonitoringField;

import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.BiFunction;

Expand All @@ -28,6 +30,9 @@
*/
public class XPackLicenseState {

public static final Set<OperationMode> FIPS_ALLOWED_LICENSE_OPERATION_MODES =
EnumSet.of(License.OperationMode.PLATINUM, License.OperationMode.TRIAL);

/** Messages for each feature which are printed when the license expires. */
static final Map<String, String[]> EXPIRATION_MESSAGES;
static {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public static String getKeyStoreType(Setting<Optional<String>> setting, Settings
return setting.get(settings).orElseGet(() -> inferKeyStoreType(path));
}

private static String inferKeyStoreType(String path) {
public static String inferKeyStoreType(String path) {
String name = path == null ? "" : path.toLowerCase(Locale.ROOT);
if (name.endsWith(".p12") || name.endsWith(".pfx") || name.endsWith(".pkcs12")) {
return PKCS12_KEYSTORE_TYPE;
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.elasticsearch.cluster.metadata.IndexMetaData.INDEX_FORMAT_SETTING;
import static org.elasticsearch.license.XPackLicenseState.FIPS_ALLOWED_LICENSE_OPERATION_MODES;
import static org.elasticsearch.xpack.core.XPackSettings.API_KEY_SERVICE_ENABLED_SETTING;
import static org.elasticsearch.xpack.core.XPackSettings.HTTP_SSL_ENABLED;
import static org.elasticsearch.xpack.core.security.index.RestrictedIndicesNames.SECURITY_MAIN_ALIAS;
Expand Down Expand Up @@ -313,11 +314,7 @@ public Security(Settings settings, final Path configPath) {
new ApiKeySSLBootstrapCheck(),
new TokenSSLBootstrapCheck(),
new PkiRealmBootstrapCheck(getSslService()),
new TLSLicenseBootstrapCheck(),
new FIPS140SecureSettingsBootstrapCheck(settings, env),
new FIPS140JKSKeystoreBootstrapCheck(),
new FIPS140PasswordHashingAlgorithmBootstrapCheck(),
new FIPS140LicenseBootstrapCheck()));
new TLSLicenseBootstrapCheck()));
checks.addAll(InternalRealms.getBootstrapChecks(settings, env));
this.bootstrapChecks = Collections.unmodifiableList(checks);
Automatons.updateConfiguration(settings);
Expand All @@ -330,6 +327,9 @@ public Security(Settings settings, final Path configPath) {

private static void runStartupChecks(Settings settings) {
validateRealmSettings(settings);
if (XPackSettings.FIPS_MODE_ENABLED.get(settings)) {
validateForFips(settings);
}
}

@Override
Expand Down Expand Up @@ -882,6 +882,37 @@ static void validateRealmSettings(Settings settings) {
}
}

static void validateForFips(Settings settings) {
final List<String> validationErrors = new ArrayList<>();
Settings keystoreTypeSettings = settings.filter(k -> k.endsWith("keystore.type"))
.filter(k -> settings.get(k).equalsIgnoreCase("jks"));
if (keystoreTypeSettings.isEmpty() == false) {
validationErrors.add("JKS Keystores cannot be used in a FIPS 140 compliant JVM. Please " +
"revisit [" + keystoreTypeSettings.toDelimitedString(',') + "] settings");
}
Settings keystorePathSettings = settings.filter(k -> k.endsWith("keystore.path"))
.filter(k -> settings.hasValue(k.replace(".path", ".type")) == false);
if (keystorePathSettings.isEmpty() == false && SSLConfigurationSettings.inferKeyStoreType(null).equals("jks")) {
validationErrors.add("JKS Keystores cannot be used in a FIPS 140 compliant JVM. Please " +
"revisit [" + keystorePathSettings.toDelimitedString(',') + "] settings");
}
final String selectedAlgorithm = XPackSettings.PASSWORD_HASHING_ALGORITHM.get(settings);
if (selectedAlgorithm.toLowerCase(Locale.ROOT).startsWith("pbkdf2") == false) {
validationErrors.add("Only PBKDF2 is allowed for password hashing in a FIPS 140 JVM. Please set the " +
"appropriate value for [ " + XPackSettings.PASSWORD_HASHING_ALGORITHM.getKey() + " ] setting.");
}

if (validationErrors.isEmpty() == false) {
final StringBuilder sb = new StringBuilder();
sb.append("Validation for FIPS 140 mode failed: \n");
int index = 0;
for (String error : validationErrors) {
sb.append(++index).append(": ").append(error).append(";\n");
}
throw new IllegalArgumentException(sb.toString());
}
}

@Override
public List<TransportInterceptor> getTransportInterceptors(NamedWriteableRegistry namedWriteableRegistry, ThreadContext threadContext) {
if (transportClientMode || enabled == false) { // don't register anything if we are not enabled
Expand Down Expand Up @@ -1044,7 +1075,7 @@ public void accept(DiscoveryNode node, ClusterState state) {
if (inFipsMode) {
License license = LicenseService.getLicense(state.metaData());
if (license != null &&
FIPS140LicenseBootstrapCheck.ALLOWED_LICENSE_OPERATION_MODES.contains(license.operationMode()) == false) {
FIPS_ALLOWED_LICENSE_OPERATION_MODES.contains(license.operationMode()) == false) {
throw new IllegalStateException("FIPS mode cannot be used with a [" + license.operationMode() +
"] license. It is only allowed with a Platinum or Trial license.");

Expand Down

This file was deleted.

This file was deleted.

Loading

0 comments on commit d44e13a

Please sign in to comment.