Merge -r 1370044:1370045 from trunk to branch. FIXES: HADOOP-8644
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1370050 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7f92566e21
commit
80f8a6f8a3
|
@ -171,6 +171,7 @@ public class AuthenticatedURL {
|
|||
}
|
||||
|
||||
private Authenticator authenticator;
|
||||
private ConnectionConfigurator connConfigurator;
|
||||
|
||||
/**
|
||||
* Creates an {@link AuthenticatedURL}.
|
||||
|
@ -186,11 +187,25 @@ public class AuthenticatedURL {
|
|||
* KerberosAuthenticator} is used.
|
||||
*/
|
||||
public AuthenticatedURL(Authenticator authenticator) {
|
||||
this(authenticator, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an <code>AuthenticatedURL</code>.
|
||||
*
|
||||
* @param authenticator the {@link Authenticator} instance to use, if <code>null</code> a {@link
|
||||
* KerberosAuthenticator} is used.
|
||||
* @param connConfigurator a connection configurator.
|
||||
*/
|
||||
public AuthenticatedURL(Authenticator authenticator,
|
||||
ConnectionConfigurator connConfigurator) {
|
||||
try {
|
||||
this.authenticator = (authenticator != null) ? authenticator : DEFAULT_AUTHENTICATOR.newInstance();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
this.connConfigurator = connConfigurator;
|
||||
this.authenticator.setConnectionConfigurator(connConfigurator);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,6 +231,9 @@ public class AuthenticatedURL {
|
|||
}
|
||||
authenticator.authenticate(url, token);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
if (connConfigurator != null) {
|
||||
conn = connConfigurator.configure(conn);
|
||||
}
|
||||
injectToken(conn, token);
|
||||
return conn;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,14 @@ import java.net.URL;
|
|||
*/
|
||||
public interface Authenticator {
|
||||
|
||||
/**
|
||||
* Sets a {@link ConnectionConfigurator} instance to use for
|
||||
* configuring connections.
|
||||
*
|
||||
* @param configurator the {@link ConnectionConfigurator} instance.
|
||||
*/
|
||||
public void setConnectionConfigurator(ConnectionConfigurator configurator);
|
||||
|
||||
/**
|
||||
* Authenticates against a URL and returns a {@link AuthenticatedURL.Token} to be
|
||||
* used by subsequent requests.
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Licensed 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. See accompanying LICENSE file.
|
||||
*/
|
||||
package org.apache.hadoop.security.authentication.client;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
/**
|
||||
* Interface to configure {@link HttpURLConnection} created by
|
||||
* {@link AuthenticatedURL} instances.
|
||||
*/
|
||||
public interface ConnectionConfigurator {
|
||||
|
||||
/**
|
||||
* Configures the given {@link HttpURLConnection} instance.
|
||||
*
|
||||
* @param conn the {@link HttpURLConnection} instance to configure.
|
||||
* @return the configured {@link HttpURLConnection} instance.
|
||||
*
|
||||
* @throws IOException if an IO error occurred.
|
||||
*/
|
||||
public HttpURLConnection configure(HttpURLConnection conn) throws IOException;
|
||||
|
||||
}
|
|
@ -113,6 +113,18 @@ public class KerberosAuthenticator implements Authenticator {
|
|||
private URL url;
|
||||
private HttpURLConnection conn;
|
||||
private Base64 base64;
|
||||
private ConnectionConfigurator connConfigurator;
|
||||
|
||||
/**
|
||||
* Sets a {@link ConnectionConfigurator} instance to use for
|
||||
* configuring connections.
|
||||
*
|
||||
* @param configurator the {@link ConnectionConfigurator} instance.
|
||||
*/
|
||||
@Override
|
||||
public void setConnectionConfigurator(ConnectionConfigurator configurator) {
|
||||
connConfigurator = configurator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs SPNEGO authentication against the specified URL.
|
||||
|
@ -135,6 +147,9 @@ public class KerberosAuthenticator implements Authenticator {
|
|||
this.url = url;
|
||||
base64 = new Base64(0);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
if (connConfigurator != null) {
|
||||
conn = connConfigurator.configure(conn);
|
||||
}
|
||||
conn.setRequestMethod(AUTH_HTTP_METHOD);
|
||||
conn.connect();
|
||||
if (isNegotiate()) {
|
||||
|
@ -244,6 +259,9 @@ public class KerberosAuthenticator implements Authenticator {
|
|||
private void sendToken(byte[] outToken) throws IOException, AuthenticationException {
|
||||
String token = base64.encodeToString(outToken);
|
||||
conn = (HttpURLConnection) url.openConnection();
|
||||
if (connConfigurator != null) {
|
||||
conn = connConfigurator.configure(conn);
|
||||
}
|
||||
conn.setRequestMethod(AUTH_HTTP_METHOD);
|
||||
conn.setRequestProperty(AUTHORIZATION, NEGOTIATE + " " + token);
|
||||
conn.connect();
|
||||
|
|
|
@ -32,6 +32,19 @@ public class PseudoAuthenticator implements Authenticator {
|
|||
|
||||
private static final String USER_NAME_EQ = USER_NAME + "=";
|
||||
|
||||
private ConnectionConfigurator connConfigurator;
|
||||
|
||||
/**
|
||||
* Sets a {@link ConnectionConfigurator} instance to use for
|
||||
* configuring connections.
|
||||
*
|
||||
* @param configurator the {@link ConnectionConfigurator} instance.
|
||||
*/
|
||||
@Override
|
||||
public void setConnectionConfigurator(ConnectionConfigurator configurator) {
|
||||
connConfigurator = configurator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs simple authentication against the specified URL.
|
||||
* <p/>
|
||||
|
@ -56,6 +69,9 @@ public class PseudoAuthenticator implements Authenticator {
|
|||
strUrl += paramSeparator + USER_NAME_EQ + getUserName();
|
||||
url = new URL(strUrl);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
if (connConfigurator != null) {
|
||||
conn = connConfigurator.configure(conn);
|
||||
}
|
||||
conn.setRequestMethod("OPTIONS");
|
||||
conn.connect();
|
||||
AuthenticatedURL.extractToken(conn, token);
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.apache.hadoop.security.authentication.client;
|
|||
|
||||
import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
|
||||
import junit.framework.TestCase;
|
||||
import org.mockito.Mockito;
|
||||
import org.mortbay.jetty.Server;
|
||||
import org.mortbay.jetty.servlet.Context;
|
||||
import org.mortbay.jetty.servlet.FilterHolder;
|
||||
|
@ -120,8 +121,11 @@ public abstract class AuthenticatorTestCase extends TestCase {
|
|||
try {
|
||||
URL url = new URL(getBaseURL());
|
||||
AuthenticatedURL.Token token = new AuthenticatedURL.Token();
|
||||
AuthenticatedURL aUrl = new AuthenticatedURL(authenticator);
|
||||
ConnectionConfigurator connConf =
|
||||
Mockito.mock(ConnectionConfigurator.class);
|
||||
AuthenticatedURL aUrl = new AuthenticatedURL(authenticator, connConf);
|
||||
HttpURLConnection conn = aUrl.openConnection(url, token);
|
||||
Mockito.verify(connConf).configure(Mockito.<HttpURLConnection>any());
|
||||
String tokenStr = token.toString();
|
||||
if (doPost) {
|
||||
conn.setRequestMethod("POST");
|
||||
|
|
|
@ -18,6 +18,7 @@ import junit.framework.TestCase;
|
|||
import org.mockito.Mockito;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -114,4 +115,21 @@ public class TestAuthenticatedURL extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testConnectionConfigurator() throws Exception {
|
||||
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
|
||||
Mockito.when(conn.getResponseCode()).
|
||||
thenReturn(HttpURLConnection.HTTP_UNAUTHORIZED);
|
||||
|
||||
ConnectionConfigurator connConf =
|
||||
Mockito.mock(ConnectionConfigurator.class);
|
||||
Mockito.when(connConf.configure(Mockito.<HttpURLConnection>any())).
|
||||
thenReturn(conn);
|
||||
|
||||
Authenticator authenticator = Mockito.mock(Authenticator.class);
|
||||
|
||||
AuthenticatedURL aURL = new AuthenticatedURL(authenticator, connConf);
|
||||
aURL.openConnection(new URL("http://foo"), new AuthenticatedURL.Token());
|
||||
Mockito.verify(connConf).configure(Mockito.<HttpURLConnection>any());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ Release 2.0.1-alpha - UNRELEASED
|
|||
|
||||
HADOOP-8465. hadoop-auth should support ephemeral authentication (tucu)
|
||||
|
||||
HADOOP-8644. AuthenticatedURL should be able to use SSLFactory. (tucu)
|
||||
|
||||
IMPROVEMENTS
|
||||
|
||||
HADOOP-8340. SNAPSHOT build versions should compare as less than their eventual
|
||||
|
|
|
@ -20,14 +20,17 @@ package org.apache.hadoop.security.ssl;
|
|||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.security.authentication.client.ConnectionConfigurator;
|
||||
import org.apache.hadoop.util.ReflectionUtils;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
|
@ -42,7 +45,7 @@ import java.security.GeneralSecurityException;
|
|||
*/
|
||||
@InterfaceAudience.Private
|
||||
@InterfaceStability.Evolving
|
||||
public class SSLFactory {
|
||||
public class SSLFactory implements ConnectionConfigurator {
|
||||
|
||||
@InterfaceAudience.Private
|
||||
public static enum Mode { CLIENT, SERVER }
|
||||
|
@ -234,4 +237,29 @@ public class SSLFactory {
|
|||
return requireClientCert;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the given {@link HttpURLConnection} is an {@link HttpsURLConnection}
|
||||
* configures the connection with the {@link SSLSocketFactory} and
|
||||
* {@link HostnameVerifier} of this SSLFactory, otherwise does nothing.
|
||||
*
|
||||
* @param conn the {@link HttpURLConnection} instance to configure.
|
||||
* @return the configured {@link HttpURLConnection} instance.
|
||||
*
|
||||
* @throws IOException if an IO error occurred.
|
||||
*/
|
||||
@Override
|
||||
public HttpURLConnection configure(HttpURLConnection conn)
|
||||
throws IOException {
|
||||
if (conn instanceof HttpsURLConnection) {
|
||||
HttpsURLConnection sslConn = (HttpsURLConnection) conn;
|
||||
try {
|
||||
sslConn.setSSLSocketFactory(createSSLSocketFactory());
|
||||
} catch (GeneralSecurityException ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
sslConn.setHostnameVerifier(getHostnameVerifier());
|
||||
conn = sslConn;
|
||||
}
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.junit.Before;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
@ -161,4 +162,23 @@ public class TestSSLFactory {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionConfigurator() throws Exception {
|
||||
Configuration conf = createConfiguration(false);
|
||||
conf.set(SSLFactory.SSL_HOSTNAME_VERIFIER_KEY, "STRICT_IE6");
|
||||
SSLFactory sslFactory = new SSLFactory(SSLFactory.Mode.CLIENT, conf);
|
||||
try {
|
||||
sslFactory.init();
|
||||
HttpsURLConnection sslConn =
|
||||
(HttpsURLConnection) new URL("https://foo").openConnection();
|
||||
Assert.assertNotSame("STRICT_IE6",
|
||||
sslConn.getHostnameVerifier().toString());
|
||||
sslFactory.configure(sslConn);
|
||||
Assert.assertEquals("STRICT_IE6",
|
||||
sslConn.getHostnameVerifier().toString());
|
||||
} finally {
|
||||
sslFactory.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue