HADOOP-17337. S3A NetworkBinding has a runtime dependency on shaded httpclient. (#2599)
Contributed by Steve Loughran. Change-Id: I0471322fc88d8bc3896ac439aefb31e6a856936c
This commit is contained in:
parent
99337a4dd0
commit
70411cb1f1
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.apache.hadoop.fs.s3a.impl;
|
||||||
|
|
||||||
|
import javax.net.ssl.HostnameVerifier;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.amazonaws.ClientConfiguration;
|
||||||
|
import com.amazonaws.thirdparty.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
|
||||||
|
import org.apache.hadoop.security.ssl.DelegatingSSLSocketFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interacts with the Shaded httpclient library used in the full
|
||||||
|
* AWS SDK. If the S3A client is used with the unshaded SDK, this
|
||||||
|
* class will not link.
|
||||||
|
*/
|
||||||
|
public class ConfigureShadedAWSSocketFactory implements
|
||||||
|
NetworkBinding.ConfigureAWSSocketFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configureSocketFactory(final ClientConfiguration awsConf,
|
||||||
|
final DelegatingSSLSocketFactory.SSLChannelMode channelMode)
|
||||||
|
throws IOException {
|
||||||
|
DelegatingSSLSocketFactory.initializeDefaultFactory(channelMode);
|
||||||
|
awsConf.getApacheHttpClientConfig().setSslSocketFactory(
|
||||||
|
new SSLConnectionSocketFactory(
|
||||||
|
DelegatingSSLSocketFactory.getDefaultFactory(),
|
||||||
|
(HostnameVerifier) null));
|
||||||
|
}
|
||||||
|
}
|
@ -19,14 +19,10 @@
|
|||||||
package org.apache.hadoop.fs.s3a.impl;
|
package org.apache.hadoop.fs.s3a.impl;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
|
|
||||||
import com.amazonaws.ClientConfiguration;
|
import com.amazonaws.ClientConfiguration;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -43,20 +39,21 @@
|
|||||||
/**
|
/**
|
||||||
* Configures network settings when communicating with AWS services.
|
* Configures network settings when communicating with AWS services.
|
||||||
*/
|
*/
|
||||||
public class NetworkBinding {
|
public final class NetworkBinding {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
LoggerFactory.getLogger(NetworkBinding.class);
|
LoggerFactory.getLogger(NetworkBinding.class);
|
||||||
private static final String AWS_SOCKET_FACTORY_CLASSNAME = "com.amazonaws" +
|
private static final String BINDING_CLASSNAME = "org.apache.hadoop.fs.s3a.impl.ConfigureShadedAWSSocketFactory";
|
||||||
".thirdparty.apache.http.conn.ssl.SSLConnectionSocketFactory";
|
|
||||||
|
private NetworkBinding() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configures the {@code SSLConnectionSocketFactory} used by the AWS SDK.
|
* Configures the {@code SSLConnectionSocketFactory} used by the AWS SDK.
|
||||||
* A custom Socket Factory can be set using the method
|
* A custom Socket Factory can be set using the method
|
||||||
* {@code setSslSocketFactory()}.
|
* {@code setSslSocketFactory()}.
|
||||||
* If {@code SSLConnectionSocketFactory} cannot be found on the classpath, the value
|
* Uses reflection to do this via {@link ConfigureShadedAWSSocketFactory}
|
||||||
* of {@link org.apache.hadoop.fs.s3a.Constants#SSL_CHANNEL_MODE} is ignored.
|
* so as to avoid
|
||||||
*
|
|
||||||
* @param conf the {@link Configuration} used to get the client specified
|
* @param conf the {@link Configuration} used to get the client specified
|
||||||
* value of {@code SSL_CHANNEL_MODE}
|
* value of {@code SSL_CHANNEL_MODE}
|
||||||
* @param awsConf the {@code ClientConfiguration} to set the
|
* @param awsConf the {@code ClientConfiguration} to set the
|
||||||
@ -84,28 +81,33 @@ public static void bindSSLChannelMode(Configuration conf,
|
|||||||
|
|
||||||
DelegatingSSLSocketFactory.initializeDefaultFactory(channelMode);
|
DelegatingSSLSocketFactory.initializeDefaultFactory(channelMode);
|
||||||
try {
|
try {
|
||||||
// Look for AWS_SOCKET_FACTORY_CLASSNAME on the classpath and instantiate
|
// use reflection to load in our own binding class.
|
||||||
// an instance using the DelegatingSSLSocketFactory as the
|
// this is *probably* overkill, but it is how we can be fully confident
|
||||||
// SSLSocketFactory.
|
// that no attempt will be made to load/link to the AWS Shaded SDK except
|
||||||
Class<?> sslConnectionSocketFactory = Class.forName(
|
// within this try/catch block
|
||||||
AWS_SOCKET_FACTORY_CLASSNAME);
|
Class<? extends ConfigureAWSSocketFactory> clazz =
|
||||||
Constructor<?> factoryConstructor =
|
(Class<? extends ConfigureAWSSocketFactory>) Class.forName(BINDING_CLASSNAME);
|
||||||
sslConnectionSocketFactory.getDeclaredConstructor(
|
clazz.getConstructor()
|
||||||
SSLSocketFactory.class, HostnameVerifier.class);
|
.newInstance()
|
||||||
awsConf.getApacheHttpClientConfig().setSslSocketFactory(
|
.configureSocketFactory(awsConf, channelMode);
|
||||||
(com.amazonaws.thirdparty.apache.http.conn.ssl.
|
|
||||||
SSLConnectionSocketFactory) factoryConstructor
|
|
||||||
.newInstance(DelegatingSSLSocketFactory
|
|
||||||
.getDefaultFactory(),
|
|
||||||
(HostnameVerifier) null));
|
|
||||||
} catch (ClassNotFoundException | NoSuchMethodException |
|
} catch (ClassNotFoundException | NoSuchMethodException |
|
||||||
IllegalAccessException | InstantiationException |
|
IllegalAccessException | InstantiationException |
|
||||||
InvocationTargetException | LinkageError e) {
|
InvocationTargetException | LinkageError e) {
|
||||||
LOG.debug("Unable to create class {}, value of {} will be ignored",
|
LOG.debug("Unable to create class {}, value of {} will be ignored",
|
||||||
AWS_SOCKET_FACTORY_CLASSNAME, SSL_CHANNEL_MODE, e);
|
BINDING_CLASSNAME, SSL_CHANNEL_MODE, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface used to bind to the socket factory, allows the code which
|
||||||
|
* works with the shaded AWS libraries to exist in their own class.
|
||||||
|
*/
|
||||||
|
interface ConfigureAWSSocketFactory {
|
||||||
|
void configureSocketFactory(ClientConfiguration awsConf,
|
||||||
|
DelegatingSSLSocketFactory.SSLChannelMode channelMode)
|
||||||
|
throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an S3 bucket region as returned by a bucket location query,
|
* Given an S3 bucket region as returned by a bucket location query,
|
||||||
* fix it into a form which can be used by other AWS commands.
|
* fix it into a form which can be used by other AWS commands.
|
||||||
|
Loading…
Reference in New Issue
Block a user