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

Test adjustments for FIPS 140 in Java 8 #52211

Closed
wants to merge 6 commits into from

Conversation

jkakavas
Copy link
Member

This commit touches many of our tests but the changes are actually
few. Setting xpack.security.ssl.diagnose.trust to true
wraps SunJSSE TrustManager with our own DiagnosticTrustManager and
this is not allowed when SunJSSE is in FIPS mode. So when we
use SunJSSE in FIPS mode ( currently only when running our tests
with FIPS mode on for Java 8 runtime ), we need to make sure that
the Diagnostic TrustManager is not enabled. This change
ensures that whenever a new SSLService is to be created, we
explicitly pass xpack.security.ssl.diagnose.trust=false in the
settings used for the SSLService, when we run in FIPS mode in
Java 8.

This commit touches many of our tests but the changes are actually
few. Setting xpack.security.ssl.diagnose.trust to true
wraps SunJSSE TrustManager with our own DiagnosticTrustManager and
this is not allowed when SunJSSE is in FIPS mode. So when we
use SunJSSE in FIPS mode ( currently only when running our tests
with FIPS mode on for Java 8 runtime ), we need to make sure that
the Diagnostic TrustManager is not enabled. This change
ensures that whenever a new SSLService is to be created, we
explicitly pass xpack.security.ssl.diagnose.trust=false in the
settings used for the SSLService, when we run in FIPS mode in
Java 8.
@jkakavas jkakavas added :Delivery/Build Build or test infrastructure >test-failure Triaged test failures from CI :Security/Security Security issues without another label v7.7.0 labels Feb 11, 2020
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra (:Core/Infra/Build)

@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-security (:Security/Security)

@@ -153,12 +154,17 @@ protected void setLicenseState(XPackLicenseState licenseState) {
NamedXContentRegistry xContentRegistry, Environment environment,
NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry) {
List<Object> components = new ArrayList<>();
// This is a hack, but the settings we add in #additionalSettings() are not added to the environment instance
// (in org.elasticsearch.node.Node) which is passed in `createComponents` of each of the plugins. So the environment
// we get here wouldn't have the additional setting. This is a known issue, and once it is resolved, the code here
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure how we track this and if we have an issue for it ( couldn't find one but I might have failed ) . There was some relevant discussion around this in #49667. Discussed it briefly with @rjernst on slack, and I didn't want to open an issue for this specific case here as it is only part of the problem.

Copy link
Contributor

Choose a reason for hiding this comment

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

That doesn't sound right to me. Doesn't environment contain the extra settings here? I think it's supposed to.

Copy link
Member

Choose a reason for hiding this comment

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

Yes environment should have the extra settings. My comment in slack was about the Settings passed into Plugin constructors.

@jkakavas
Copy link
Member Author

09:34:37 Step 1/26 : FROM centos:7 AS builder
09:34:37 Get https://registry-1.docker.io/v2/: net/http: TLS handshake timeout
09:34:37 
09:34:38 
09:34:38 > Task :extractElasticsearchLinux7.7.0-SNAPSHOT
09:34:39 
09:34:39 > Task :modules:reindex:javadoc
09:34:39 Could not load entry 982b9b97231514a30536541e6a2aae42 from remote build cache
09:34:39 org.gradle.caching.BuildCacheException: Read timed out

@jkakavas
Copy link
Member Author

@elasticmachine run elasticsearch-ci/default-distro

@jkakavas
Copy link
Member Author

jkakavas commented Feb 12, 2020

importing inFipsSunJsseJvm() and using it in classes that extend LuceneTestCase directly causes failures like https://gradle-enterprise.elastic.co/s/yphikcuckyz5e where the transport client doesn't connect to the node. Ι spent time on understanding why but need to move on for now so I replicated the check for (Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP)) && JavaVersion.current().getVersion().get(0) == 8) in EnrichTransportClientIT and MigrateToolIT


TransportClient client = new PreBuiltXPackTransportClient(clientSettings).addTransportAddresses(transportAddresses);
.put(SecurityField.USER_SETTING.getKey(), "transport_user:x-pack-test-password");
if (Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP)) && JavaVersion.current().getVersion().get(0) == 8) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't you just do this? I tried the import against your branch and it was OK.

Suggested change
if (Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP)) && JavaVersion.current().getVersion().get(0) == 8) {
if (inFipsSunJsseJvm()) {

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -67,6 +70,9 @@ private static Client startClient(Path tempDir, TransportAddress... transportAdd
.put("client.transport.ignore_cluster_name", true)
.put("xpack.security.enabled", false)
.put(Environment.PATH_HOME_SETTING.getKey(), tempDir);
if (Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP)) && JavaVersion.current().getVersion().get(0) == 8) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here?

Suggested change
if (Boolean.parseBoolean(System.getProperty(FIPS_SYSPROP)) && JavaVersion.current().getVersion().get(0) == 8) {
if (inFipsSunJsseJvm()) {

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

This needs a comment in code (and preferably a tracking issue) or someone may inadvertently try to make the same obvious change.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, that makes total sense - I'll make do

Copy link
Contributor

@tvernum tvernum left a comment

Choose a reason for hiding this comment

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

LGTM, but I'd like to understand what's going on in createComponents.

@@ -153,12 +154,17 @@ protected void setLicenseState(XPackLicenseState licenseState) {
NamedXContentRegistry xContentRegistry, Environment environment,
NodeEnvironment nodeEnvironment, NamedWriteableRegistry namedWriteableRegistry) {
List<Object> components = new ArrayList<>();
// This is a hack, but the settings we add in #additionalSettings() are not added to the environment instance
// (in org.elasticsearch.node.Node) which is passed in `createComponents` of each of the plugins. So the environment
// we get here wouldn't have the additional setting. This is a known issue, and once it is resolved, the code here
Copy link
Contributor

Choose a reason for hiding this comment

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

That doesn't sound right to me. Doesn't environment contain the extra settings here? I think it's supposed to.

@jkakavas
Copy link
Member Author

jkakavas commented Feb 18, 2020

That doesn't sound right to me. Doesn't environment contain the extra settings here? I think it's supposed to.

Happy to explain @tvernum , this tripped me also while troubleshooting the errors.

See

protected Node(
final Environment environment, Collection<Class<? extends Plugin>> classpathPlugins, boolean forbidPrivateIndexSettings) {
logger = LogManager.getLogger(Node.class);

We get the environment in the constructor of the Node

Then in

this.pluginsService = new PluginsService(tmpSettings, environment.configFile(), environment.modulesFile(),
environment.pluginsFile(), classpathPlugins);
final Settings settings = pluginsService.updatedSettings();
final Set<DiscoveryNodeRole> possibleRoles = Stream.concat(
DiscoveryNodeRole.BUILT_IN_ROLES.stream(),
pluginsService.filterPlugins(Plugin.class)
.stream()
.map(Plugin::getRoles)
.flatMap(Set::stream))
.collect(Collectors.toSet());
DiscoveryNode.setPossibleRoles(possibleRoles);
localNodeFactory = new LocalNodeFactory(settings, nodeEnvironment.nodeId());
// create the environment based on the finalized (processed) view of the settings
// this is just to makes sure that people get the same settings, no matter where they ask them from
this.environment = new Environment(settings, environment.configFile());

we call updatedSettings() on the plugins, get their new settings and create a new Environment that we store in the class variable environment. We now have the local scope environment which is what is passed in the constructor and the this.environment which is the Environment with the potentially added settings from the plugins.

I would think that we then use this.environment for the rest of the method, and we do for the most part, except when we don't.

final MetaDataCreateIndexService metaDataCreateIndexService = new MetaDataCreateIndexService(
settings,
clusterService,
indicesService,
clusterModule.getAllocationService(),
aliasValidator,
environment,
settingsModule.getIndexScopedSettings(),
threadPool,
xContentRegistry,
systemIndexDescriptors,
forbidPrivateIndexSettings);
Collection<Object> pluginComponents = pluginsService.filterPlugins(Plugin.class).stream()
.flatMap(p -> p.createComponents(client, clusterService, threadPool, resourceWatcherService,
scriptModule.getScriptService(), xContentRegistry, environment, nodeEnvironment,
namedWriteableRegistry).stream())
.collect(Collectors.toList());

We create the MetaDataCreateIndexService and we call createComponents() on each of the plugins using the local scope environment which doesn't have the additional settings. And this is why this

NamedXContentRegistry xContentRegistry, Environment environment,

doesn't have the additional settings

Now, it could be that this is a simple mistake because the method parameter shadows the class field, but @elastic/es-core-infra is aware of this and it made sense to attack this at in a different PR, this my comment in #52211 (comment).

HTH

@jkakavas
Copy link
Member Author

@rjernst I think I addressed your comment, but pinging for an explicit LGTM just in case

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

Sorry for causing confusion. This does seem like a case where we should use additionalSettings().

if (inFipsSunJsseJvm()) {
Settings additionalSettings = Settings.builder()
.put(existingEnvironment.settings())
.put(XPackSettings.DIAGNOSE_TRUST_EXCEPTIONS_SETTING.getKey(), false)
Copy link
Member

Choose a reason for hiding this comment

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

Can't this be returnned from additionalSettings()?

Copy link
Member Author

@jkakavas jkakavas Feb 20, 2020

Choose a reason for hiding this comment

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

Apologies if I misunderstood @rjernst but did you read through #52211 (comment) ? I'll go and double check this again but this was supposed to show why additionalSettings doesn't solve this here

Copy link
Member

Choose a reason for hiding this comment

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

Sorry I missed that explanation. It looks to me like a bug. We should be passing the final environment everywhere once it is created.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll raise a PR to fix that then and change to use additionalSettings here

Copy link
Member

Choose a reason for hiding this comment

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

I've opened #52602 to cleanup the name to avoid this situation.

@bpintea bpintea added the v7.8.0 label Mar 25, 2020
@bpintea bpintea removed the v7.7.0 label Mar 25, 2020
@rjernst rjernst added Team:Core/Infra Meta label for core/infra team Team:Security Meta label for security team labels May 4, 2020
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request May 11, 2020
This change aims to fix our setup in CI so that we can run 7.x in
FIPS 140 mode. The major issue that we have in 7.x and did not
have in master is that we can't use the diagnostic trust manager
in FIPS mode in Java 8 with SunJSSE in FIPS approved mode as it
explicitly disallows the wrapping of X509TrustManager.

Previous attempts like elastic#56427 and elastic#52211 focused on disabling the
setting in all of our tests when creating a Settings object or
on setting fips_mode.enabled accordingly (which implicitly disables
the diagnostic trust manager). The attempts weren't future proof
though as nothing would forbid someone to add new tests without
setting the necessary setting and forcing this would be very
inconvenient for any other case ( see
elastic#56427 (comment)
for the full argumentation).

This change introduces a system property that effectively bypasses
the configuration value of xpack.security.ssl.diagnose.trust and
disables the diagnostic trust manager. We will then set this
system property in our periodic CI jobs for Java 8.
@jkakavas jkakavas closed this May 11, 2020
jkakavas added a commit that referenced this pull request May 15, 2020
This change aims to fix our setup in CI so that we can run 7.x in
FIPS 140 mode. The major issue that we have in 7.x and did not
have in master is that we can't use the diagnostic trust manager
in FIPS mode in Java 8 with SunJSSE in FIPS approved mode as it
explicitly disallows the wrapping of X509TrustManager.

Previous attempts like #56427 and #52211 focused on disabling the
setting in all of our tests when creating a Settings object or
on setting fips_mode.enabled accordingly (which implicitly disables
the diagnostic trust manager). The attempts weren't future proof
though as nothing would forbid someone to add new tests without
setting the necessary setting and forcing this would be very
inconvenient for any other case ( see
#56427 (comment) for the full argumentation).

This change introduces a runtime check in SSLService that overrides
the configuration value of xpack.security.ssl.diagnose.trust and
disables the diagnostic trust manager when we are running in Java 8
and the SunJSSE provider is set in FIPS mode.
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Jun 5, 2020
This change aims to fix our setup in CI so that we can run 7.x in
FIPS 140 mode. The major issue that we have in 7.x and did not
have in master is that we can't use the diagnostic trust manager
in FIPS mode in Java 8 with SunJSSE in FIPS approved mode as it
explicitly disallows the wrapping of X509TrustManager.

Previous attempts like elastic#56427 and elastic#52211 focused on disabling the
setting in all of our tests when creating a Settings object or
on setting fips_mode.enabled accordingly (which implicitly disables
the diagnostic trust manager). The attempts weren't future proof
though as nothing would forbid someone to add new tests without
setting the necessary setting and forcing this would be very
inconvenient for any other case ( see
elastic#56427 (comment) for the full argumentation).

This change introduces a runtime check in SSLService that overrides
the configuration value of xpack.security.ssl.diagnose.trust and
disables the diagnostic trust manager when we are running in Java 8
and the SunJSSE provider is set in FIPS mode.
jkakavas added a commit that referenced this pull request Jun 8, 2020
This change aims to fix our setup in CI so that we can run 7.x in
FIPS 140 mode. The major issue that we have in 7.x and did not
have in master is that we can't use the diagnostic trust manager
in FIPS mode in Java 8 with SunJSSE in FIPS approved mode as it
explicitly disallows the wrapping of X509TrustManager.

Previous attempts like #56427 and #52211 focused on disabling the
setting in all of our tests when creating a Settings object or
on setting fips_mode.enabled accordingly (which implicitly disables
the diagnostic trust manager). The attempts weren't future proof
though as nothing would forbid someone to add new tests without
setting the necessary setting and forcing this would be very
inconvenient for any other case ( see
#56427 (comment) for the full argumentation).

This change introduces a runtime check in SSLService that overrides
the configuration value of xpack.security.ssl.diagnose.trust and
disables the diagnostic trust manager when we are running in Java 8
and the SunJSSE provider is set in FIPS mode.
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Jun 9, 2020
This change aims to fix our setup in CI so that we can run 7.x in
FIPS 140 mode. The major issue that we have in 7.x and did not
have in master is that we can't use the diagnostic trust manager
in FIPS mode in Java 8 with SunJSSE in FIPS approved mode as it
explicitly disallows the wrapping of X509TrustManager.

Previous attempts like elastic#56427 and elastic#52211 focused on disabling the
setting in all of our tests when creating a Settings object or
on setting fips_mode.enabled accordingly (which implicitly disables
the diagnostic trust manager). The attempts weren't future proof
though as nothing would forbid someone to add new tests without
setting the necessary setting and forcing this would be very
inconvenient for any other case ( see

This change introduces a runtime check in SSLService that overrides
the configuration value of xpack.security.ssl.diagnose.trust and
disables the diagnostic trust manager when we are running in Java 8
and the SunJSSE provider is set in FIPS mode.
jkakavas added a commit that referenced this pull request Jun 16, 2020
This change aims to fix our setup in CI so that we can run 7.7 in
FIPS 140 mode. The major issue that we have in 7.x and did not
have in master is that we can't use the diagnostic trust manager
in FIPS mode in Java 8 with SunJSSE in FIPS approved mode as it
explicitly disallows the wrapping of X509TrustManager.

Previous attempts like #56427 and #52211 focused on disabling the
setting in all of our tests when creating a Settings object or
on setting fips_mode.enabled accordingly (which implicitly disables
the diagnostic trust manager). The attempts weren't future proof
though as nothing would forbid someone to add new tests without
setting the necessary setting and forcing this would be very
inconvenient for any other case ( see

This change introduces a runtime check in SSLService that overrides
the configuration value of xpack.security.ssl.diagnose.trust and
disables the diagnostic trust manager when we are running in Java 8
and the SunJSSE provider is set in FIPS mode.
@mark-vieira mark-vieira added Team:Delivery Meta label for Delivery team and removed Team:Core/Infra Meta label for core/infra team labels Nov 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Delivery/Build Build or test infrastructure :Security/Security Security issues without another label Team:Delivery Meta label for Delivery team Team:Security Meta label for security team >test-failure Triaged test failures from CI v7.9.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants