Skip to content

Enable tests in FIPS 140 in JDK 11 #48378

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

Merged
merged 20 commits into from
Nov 15, 2019
Merged

Conversation

jkakavas
Copy link
Member

This change enables us to run our test suites in JVMs configured in
FIPS 140 approved mode. It does so by:

  • Using BouncyCastle FIPS Cryptographic provider and BSJSSE in
    FIPS mode. These are used as testRuntime dependencies for unit
    tests and internal clusters, and copied (relevant jars)
    explicitly to the lib directory for testclusters used in REST tests

  • Configuring any given runtime Java in FIPS mode using the system
    properties java.security.properties and java.security.policy
    with the == operator that overrides the default JVM properties
    and policy.

Running the tests in FIPS 140 approved mode doesn't require an
additional configuration either in CI workers or locally and is
controlled by specifying -Dtests.fips.enabled=true

Closes: #37250
Supersedes: #41024

This change enables us to run our test suites in JVMs configured in
FIPS 140 approved mode. It does so by:

- Using BouncyCastle FIPS Cryptographic provider and BSJSSE in
FIPS mode. These are used as testRuntime dependencies for unit
tests and internal clusters, and copied (relevant jars)
explicitly to the lib directory for testclusters used in REST tests

- Configuring any given runtime Java in FIPS mode using the system
properties `java.security.properties` and `java.security.policy`
with the `==` operator that overrides the default JVM properties
and policy.

Running the tests in FIPS 140 approved mode doesn't require an
additional configuration either in CI workers or locally and is
controlled by specifying `-Dtests.fips.enabled=true`
@jkakavas jkakavas added >test Issues or PRs that are addressing/adding tests :Delivery/Build Build or test infrastructure :Security/Security Security issues without another label v8.0.0 labels Oct 23, 2019
@jkakavas jkakavas requested review from tvernum and alpar-t October 23, 2019 10:06
@elasticmachine
Copy link
Collaborator

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

@elasticmachine
Copy link
Collaborator

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

@jkakavas jkakavas changed the title Reenable fips tests Enable tests in FIPS 140 in JDK 11 Oct 23, 2019
X509ExtendedTrustManager loadedTrustManager = Optional.ofNullable(trustConfig.createTrustManager(env)).
orElse(getEmptyTrustManager());
X509ExtendedKeyManager loadedKeyManager = keyConfig.createKeyManager(env);
X509ExtendedTrustManager loadedTrustManager = trustConfig.createTrustManager(env);
Copy link
Member Author

Choose a reason for hiding this comment

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

We'd never call getEmptyTrustManager as none of the implementations of createTrustManager returns null. As for an emtpyKeyManager, this could only happen for KeyConfig NONE - so I moved this there

@@ -153,15 +153,16 @@ public void testReloadingKeyStore() throws Exception {
* Tests the reloading of SSLContext when a PEM key and certificate are used.
*/
public void testPEMKeyConfigReloading() throws Exception {
assumeFalse("This fails with BCJSSE with 'certificate does not verify with supplied key'", inFipsJvm());
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 follow these up with appropriate issues once the troubleshooting is concluded

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we link them to an issue or something. I don't love having temporary assumeFalse in tests without a way to trace it back to an action.

@@ -38,6 +38,7 @@
private final AtomicInteger openPages = new AtomicInteger(0);

public void testPingPongAndClose() throws Exception {
assumeFalse("Fails in normalClose as receiveDriver.getOutboundBuffer().hasEncryptedBytesToFlush() is false", inFipsJvm());
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 follow these up with appropriate issues once the troubleshooting is concluded

@jkakavas
Copy link
Member Author

Fun fact: BCJSSE doesn't disallow the use of JKS keystores as SunJSSE did. SunJSSE also does not explicitly disallow JKS, it just mandates that the keystore instances used for calling init() on a KeyManagerFactory should come from the Provider. Since the BCFIPS provider does not offer a JKS keystore implementation, JKS keystores could not be used.
This "limitation" is now lifted because BCJSSE doesn't control this but the implementation of JKS (https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/999dbd4192d0f819cb5224f26e9e7fa75ca6f289/src/java.base/share/classes/sun/security/provider/KeyProtector.java#L46) is not FIPS 140 approved so we should continue to not support JKS keystores in FIPS mode and thus shouldn't attempt to run tests that depend on using a JKS keystore in FIPS.

}
}

private void configureNodeForFips() {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should do this externally, you can use testclusters.all {} to configure all clusters in a project, so combining that with allprojects {} would allow you to configure it across the board

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 can't figure out how I can reference the file locations from within the BuildPlugin if I do this in testclusters.all {}. Any ideas ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Locations of what files exactly?

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 fips_java.security, fips_java.policy and cacerts.bcfks that I copy as extra config files

Copy link
Contributor

Choose a reason for hiding this comment

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

That's problematic indeed. getConfigDir is public, but we don't have a way to iterate over the nodes, or configure nodes individually.

Does this needs to be an absolute path ? Would a path relative to cwd work ? e.x. conf/fips_java.policy i think that's how this problem is solved elsewhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

These paths are passed as values to system properties, not used in ES configuration so we either need an absolute path. Maybe we have a global reference to the ES_CONF_DIR that can be resolved in a system property? I'll look into it

Copy link
Member Author

Choose a reason for hiding this comment

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

Solution required adding ES_PATH_CONF to the substitutions we do when parsing jvm.properties . Can't think of a side-effect but I wanted to raise it for visibility when this is reviewed

* Copies extra jars to the `/lib` directory.
* //TODO: Remove this when system modules are available
*/
private void copyExtraJars() {
Copy link
Contributor

Choose a reason for hiding this comment

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

We prefer not to couple testclusters with random project configuration like an extraJars configuration.
Would be better to have extra jars work exactly as extra config files so these jars could be passed in externally.

A more generic way would be to add the possibility to add hooks right before the task starts.

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 moved this outside as suggested, similar to how extraConfigurationFiles work

@jkakavas
Copy link
Member Author

@atorok I have addressed your comments, please take another look

@jkakavas
Copy link
Member Author

ci/1 failed due to #48440

@elasticmachine run elasticsearch-ci/1

Copy link
Contributor

@alpar-t alpar-t left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks !

@jkakavas
Copy link
Member Author

@elasticmachine run elasticsearch-ci/packaging-sample-matrix

logToProcessStdout("Setting up " + extraJarFiles.size() + " additional jar dependencies");
}
extraJarFiles.forEach(from -> {
Path destination = getDistroDir().resolve("lib").resolve(from.getName());
Copy link
Member

Choose a reason for hiding this comment

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

I think this will leave trash behind. @atorok don't we setup a link for the lib dir? This would copy into the lib dir and be left behind after the test is run?

Copy link
Contributor

@alpar-t alpar-t Oct 30, 2019

Choose a reason for hiding this comment

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

We don't set up links for directories, so this will be fine.
We create a matching directory structure, and create hard links for the files.

That does bring up a slightly different problem, if we were to replace one of the jars with this mechanism, that will be reflected for all invocations across all projects because the initial file could have changed. That would be really hard to spot and debug. We originally had code to set the links to read only so this would error out, maybe we should get that back ? It would work across the board, as opposed to just checking that the libs don't replace other libs.

Copy link
Member Author

Choose a reason for hiding this comment

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

is this something that should be taken into consideration in the context of this PR @atorok or are we ok to merge this and address it in a follow up ?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's ok as a follow-up

@jkakavas
Copy link
Member Author

@elasticmachine run elasticsearch-ci/1

@jkakavas
Copy link
Member Author

ping @tvernum for a look at this one. Specifically the changes around SSLService and the empty{Trust,Key}Manager

@@ -153,15 +153,16 @@ public void testReloadingKeyStore() throws Exception {
* Tests the reloading of SSLContext when a PEM key and certificate are used.
*/
public void testPEMKeyConfigReloading() throws Exception {
assumeFalse("This fails with BCJSSE with 'certificate does not verify with supplied key'", inFipsJvm());
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we link them to an issue or something. I don't love having temporary assumeFalse in tests without a way to trace it back to an action.

@@ -239,6 +239,8 @@ public void testGroupLookupBase() throws Exception {
* (one failure, one success) depending on which file content is in place.
*/
public void testSslTrustIsReloaded() throws Exception {
assumeFalse("NPE thrown in BCFIPS JSSE - addressed in https://github" +
".com/bcgit/bc-java/commit/5aed687e17a3cd63f34373cafe92699b90076fb6#diff-8e5d8089bc0d504d93194a1e484d3950R179", inFipsJvm());
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we re-wrap this string so the URL is on a single line?

@jkakavas jkakavas merged commit c7689ce into elastic:master Nov 15, 2019
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Nov 22, 2019
This change enables us to run our test suites in JVMs configured in
FIPS 140 approved mode. It does so by:

- Using BouncyCastle FIPS Cryptographic provider and BSJSSE in
FIPS mode. These are used as testRuntime dependencies for unit
tests and internal clusters, and copied (relevant jars)
explicitly to the lib directory for testclusters used in REST tests

- Configuring any given runtime Java in FIPS mode with the bundled
policy and security properties files, setting the system
properties java.security.properties and java.security.policy
with the == operator that overrides the default JVM properties
and policy.

Running the tests in FIPS 140 approved mode doesn't require an
additional configuration either in CI workers or locally and is
controlled by specifying -Dtests.fips.enabled=true

Closes: elastic#37250
Supersedes: elastic#41024
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Feb 5, 2020
The relevant handling part has been removed in infra, FIPS 140
testing needs to be enabled in the same manner as it happened for
master and 7.x in elastic#48378 and elastic#49485

resolves: elastic#51924
jkakavas added a commit that referenced this pull request Feb 5, 2020
The relevant handling part has been removed in infra, FIPS 140
testing needs to be enabled in the same manner as it happened for
master and 7.x in #48378 and #49485

resolves: #51924
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Feb 6, 2020
The relevant handling part has been removed in infra, FIPS 140
testing needs to be enabled in the same manner as it happened for
master and 7.x in elastic#48378 and elastic#49485

resolves: elastic#51980
jkakavas added a commit that referenced this pull request Feb 6, 2020
The relevant handling part has been removed in infra, FIPS 140
testing needs to be enabled in the same manner as it happened for
master and 7.x in #48378 and #49485

resolves: #51980
@mark-vieira mark-vieira added the Team:Delivery Meta label for Delivery team label 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 >test Issues or PRs that are addressing/adding tests v8.0.0-alpha1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a FIPS 140-2 enabled JDK 11 JVM in CI
7 participants