Skip to content

HADOOP-16346: Stabilize S3A OpenSSL support #1764

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions hadoop-common-project/hadoop-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,11 @@
<dependency>
<groupId>org.wildfly.openssl</groupId>
<artifactId>wildfly-openssl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wildfly.openssl</groupId>
<artifactId>wildfly-openssl-java</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
* SSL with no modification to the list of enabled ciphers.</li>
* </ul>
* </p>
*
* In order to load OpenSSL, applications must ensure the wildfly-openssl
* artifact is on the classpath. Currently, only ABFS and S3A provide
* wildfly-openssl as a runtime dependency.
*/
public final class DelegatingSSLSocketFactory extends SSLSocketFactory {

Expand Down Expand Up @@ -170,8 +174,14 @@ private void initializeSSLContext(SSLChannelMode preferredChannelMode)
OpenSSLProvider.register();
openSSLProviderRegistered = true;
}
java.util.logging.Logger logger = java.util.logging.Logger.getLogger(
SSL.class.getName());
logger.setLevel(Level.WARNING);
ctx = SSLContext.getInstance("openssl.TLS");
ctx.init(null, null, null);
// Strong reference needs to be kept to logger until initialization of
// SSLContext finished (see HADOOP-16174):
logger.setLevel(Level.INFO);
channelMode = SSLChannelMode.OpenSSL;
break;
case Default_JSSE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1978,11 +1978,16 @@
<description>
If secure connections to S3 are enabled, configures the SSL
implementation used to encrypt connections to S3. Supported values are:
"default_jsse" and "default_jsse_with_gcm". "default_jsse" uses the Java
Secure Socket Extension package (JSSE). However, when running on Java 8,
the GCM cipher is removed from the list of enabled ciphers. This is due
to performance issues with GCM in Java 8. "default_jsse_with_gcm" uses
the JSSE with the default list of cipher suites.
"default_jsse", "default_jsse_with_gcm", "default", and "openssl".
"default_jsse" uses the Java Secure Socket Extension package (JSSE).
However, when running on Java 8, the GCM cipher is removed from the list
of enabled ciphers. This is due to performance issues with GCM in Java 8.
"default_jsse_with_gcm" uses the JSSE with the default list of cipher
suites. "default_jsse_with_gcm" is equivalent to the behavior prior to
this feature being introduced. "default" attempts to use OpenSSL rather
than the JSSE for SSL encryption, if OpenSSL libraries cannot be loaded,
it falls back to the "default_jsse" behavior. "openssl" attempts to use
OpenSSL as well, but fails if OpenSSL libraries cannot be loaded.
</description>
</property>

Expand Down
8 changes: 7 additions & 1 deletion hadoop-project/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
<jline.version>3.9.0</jline.version>
<powermock.version>1.5.6</powermock.version>
<solr.version>7.7.0</solr.version>
<openssl-wildfly.version>1.0.7.Final</openssl-wildfly.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -1358,7 +1359,12 @@
<dependency>
<groupId>org.wildfly.openssl</groupId>
<artifactId>wildfly-openssl</artifactId>
<version>1.0.7.Final</version>
<version>${openssl-wildfly.version}</version>
</dependency>
<dependency>
<groupId>org.wildfly.openssl</groupId>
<artifactId>wildfly-openssl-java</artifactId>
<version>${openssl-wildfly.version}</version>
</dependency>

<dependency>
Expand Down
5 changes: 5 additions & 0 deletions hadoop-tools/hadoop-aws/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,11 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wildfly.openssl</groupId>
<artifactId>wildfly-openssl</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,6 @@ public static void bindSSLChannelMode(Configuration conf,
throw new IllegalArgumentException(channelModeString +
" is not a valid value for " + SSL_CHANNEL_MODE);
}
if (channelMode == DelegatingSSLSocketFactory.SSLChannelMode.OpenSSL ||
channelMode == DelegatingSSLSocketFactory.SSLChannelMode.Default) {
throw new UnsupportedOperationException("S3A does not support " +
"setting " + SSL_CHANNEL_MODE + " " +
DelegatingSSLSocketFactory.SSLChannelMode.OpenSSL + " or " +
DelegatingSSLSocketFactory.SSLChannelMode.Default);
}

// Look for AWS_SOCKET_FACTORY_CLASSNAME on the classpath and instantiate
// an instance using the DelegatingSSLSocketFactory as the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -535,10 +535,41 @@ GCM cipher is only disabled on Java 8. GCM performance has been improved
in Java 9, so if `default_jsse` is specified and applications run on Java
9, they should see no difference compared to running with the vanilla JSSE.

Other options for `fs.s3a.ssl.channel.mode` include `default_jsse_with_gcm`.
This option includes GCM in the list of cipher suites on Java 8, so it is
equivalent to running with the vanilla JSSE. The naming convention is setup
in order to preserve backwards compatibility with HADOOP-15669.
`fs.s3a.ssl.channel.mode` can be set to `default_jsse_with_gcm`. This option
includes GCM in the list of cipher suites on Java 8, so it is equivalent to
running with the vanilla JSSE.

### OpenSSL Acceleration

**Experimental Feature**

As of HADOOP-16050 and HADOOP-16346, `fs.s3a.ssl.channel.mode` can be set to
either `default` or `openssl` to enable native OpenSSL acceleration of HTTPS
requests. OpenSSL implements the SSL and TLS protocols using native code. For
users reading a large amount of data over HTTPS, OpenSSL can provide a
significant performance benefit over the JSSE.

S3A uses the
[WildFly OpenSSL](https://github.com/wildfly-security/wildfly-openssl) library
to bind OpenSSL to the Java JSSE APIs. This library allows S3A to
transparently read data using OpenSSL. The wildfly-openssl library is a
runtime dependency of S3A and contains native libraries for binding the Java
JSSE to OpenSSL.

WildFly OpenSSL must load OpenSSL itself. This can be done using the system
property `org.wildfly.openssl.path`. For example,
`HADOOP_OPTS="-Dorg.wildfly.openssl.path=<path to OpenSSL libraries>
${HADOOP_OPTS}"`. See WildFly OpenSSL documentation for more details.

When `fs.s3a.ssl.channel.mode` is set to `default`, S3A will attempt to load
the OpenSSL libraries using the WildFly library. If it is unsuccessful, it
will fall back to the `default_jsse` behavior.

When `fs.s3a.ssl.channel.mode` is set to `openssl`, S3A will attempt to load
the OpenSSL libraries using WildFly. If it is unsuccessful, it will throw an
exception and S3A initialization will fail.

### `fs.s3a.ssl.channel.mode` Configuration

`fs.s3a.ssl.channel.mode` can be configured as follows:

Expand All @@ -549,11 +580,16 @@ in order to preserve backwards compatibility with HADOOP-15669.
<description>
If secure connections to S3 are enabled, configures the SSL
implementation used to encrypt connections to S3. Supported values are:
"default_jsse" and "default_jsse_with_gcm". "default_jsse" uses the Java
Secure Socket Extension package (JSSE). However, when running on Java 8,
the GCM cipher is removed from the list of enabled ciphers. This is due
to performance issues with GCM in Java 8. "default_jsse_with_gcm" uses
the JSSE with the default list of cipher suites.
"default_jsse", "default_jsse_with_gcm", "default", and "openssl".
"default_jsse" uses the Java Secure Socket Extension package (JSSE).
However, when running on Java 8, the GCM cipher is removed from the list
of enabled ciphers. This is due to performance issues with GCM in Java 8.
"default_jsse_with_gcm" uses the JSSE with the default list of cipher
suites. "default_jsse_with_gcm" is equivalent to the behavior prior to
this feature being introduced. "default" attempts to use OpenSSL rather
than the JSSE for SSL encryption, if OpenSSL libraries cannot be loaded,
it falls back to the "default_jsse" behavior. "openssl" attempts to use
OpenSSL as well, but fails if OpenSSL libraries cannot be loaded.
</description>
</property>
```
Expand All @@ -564,6 +600,11 @@ Supported values for `fs.s3a.ssl.channel.mode`:
|-------------------------------|-------------|
| default_jsse | Uses Java JSSE without GCM on Java 8 |
| default_jsse_with_gcm | Uses Java JSSE |
| default | Uses OpenSSL, falls back to default_jsse if OpenSSL cannot be loaded |
| openssl | Uses OpenSSL, fails if OpenSSL cannot be loaded |

The naming convention is setup in order to preserve backwards compatibility
with HADOOP-15669.

Other options may be added to `fs.s3a.ssl.channel.mode` in the future as
further SSL optimizations are made.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.Arrays;
import java.util.Collection;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
Expand All @@ -41,6 +42,7 @@
import org.apache.hadoop.fs.s3a.S3AInputPolicy;
import org.apache.hadoop.fs.s3a.S3ATestUtils;
import org.apache.hadoop.security.ssl.DelegatingSSLSocketFactory;
import org.apache.hadoop.util.NativeCodeLoader;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.apache.hadoop.fs.s3a.Constants.INPUT_FADVISE;
Expand All @@ -55,6 +57,9 @@
SSLChannelMode.Default_JSSE;
import static org.apache.hadoop.security.ssl.DelegatingSSLSocketFactory.
SSLChannelMode.Default_JSSE_with_GCM;
import static org.apache.hadoop.security.ssl.DelegatingSSLSocketFactory.
SSLChannelMode.OpenSSL;
import static org.junit.Assume.assumeTrue;


/**
Expand Down Expand Up @@ -84,7 +89,7 @@ public class ITestS3AContractSeek extends AbstractContractSeekTest {
public static Collection<Object[]> params() {
return Arrays.asList(new Object[][]{
{INPUT_FADV_SEQUENTIAL, Default_JSSE},
{INPUT_FADV_RANDOM, Default_JSSE_with_GCM},
{INPUT_FADV_RANDOM, OpenSSL},
{INPUT_FADV_NORMAL, Default_JSSE_with_GCM},
});
}
Expand Down Expand Up @@ -200,6 +205,14 @@ public S3AFileSystem getFileSystem() {
return (S3AFileSystem) super.getFileSystem();
}

@Before
public void validateSSLChannelMode() {
if (this.sslChannelMode == OpenSSL) {
assumeTrue(NativeCodeLoader.isNativeCodeLoaded() &&
NativeCodeLoader.buildSupportsOpenssl());
}
}

@Test
public void testReadPolicyInFS() throws Throwable {
describe("Verify the read policy is being consistently set");
Expand Down
2 changes: 1 addition & 1 deletion hadoop-tools/hadoop-azure/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@
<dependency>
<groupId>org.wildfly.openssl</groupId>
<artifactId>wildfly-openssl</artifactId>
<scope>compile</scope>
<scope>runtime</scope>
</dependency>

<!--com.fasterxml.jackson is used by WASB, not ABFS-->
Expand Down