|
@@ -18,6 +18,7 @@
|
|
|
|
|
|
package org.apache.hadoop.hdfsproxy;
|
|
|
|
|
|
+import java.io.FileInputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.net.HttpURLConnection;
|
|
@@ -25,13 +26,20 @@ import java.net.InetSocketAddress;
|
|
|
import java.net.URI;
|
|
|
import java.net.URISyntaxException;
|
|
|
import java.net.URL;
|
|
|
+import java.security.KeyStore;
|
|
|
import java.security.cert.X509Certificate;
|
|
|
import java.util.Date;
|
|
|
import java.util.Set;
|
|
|
|
|
|
-import javax.net.ssl.HttpsURLConnection;
|
|
|
import javax.net.ssl.HostnameVerifier;
|
|
|
+import javax.net.ssl.HttpsURLConnection;
|
|
|
+import javax.net.ssl.KeyManager;
|
|
|
+import javax.net.ssl.KeyManagerFactory;
|
|
|
+import javax.net.ssl.SSLContext;
|
|
|
import javax.net.ssl.SSLSession;
|
|
|
+import javax.net.ssl.TrustManager;
|
|
|
+import javax.net.ssl.TrustManagerFactory;
|
|
|
+import javax.net.ssl.X509TrustManager;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
|
import org.apache.commons.logging.Log;
|
|
@@ -43,17 +51,19 @@ import org.apache.hadoop.io.IOUtils;
|
|
|
import org.apache.hadoop.net.NetUtils;
|
|
|
import org.apache.hadoop.util.HostsFileReader;
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* Proxy Utility .
|
|
|
*/
|
|
|
public class ProxyUtil {
|
|
|
public static final Log LOG = LogFactory.getLog(ProxyUtil.class);
|
|
|
private static final long MM_SECONDS_PER_DAY = 1000 * 60 * 60 * 24;
|
|
|
- private static final int CERT_EXPIRATION_WARNING_THRESHOLD = 30; // 30 days warning
|
|
|
-
|
|
|
+ private static final int CERT_EXPIRATION_WARNING_THRESHOLD = 30; // 30 days
|
|
|
+
|
|
|
+ // warning
|
|
|
+
|
|
|
private static enum UtilityOption {
|
|
|
- RELOAD("-reloadPermFiles"), CLEAR("-clearUgiCache"), GET("-get"), CHECKCERTS("-checkcerts");
|
|
|
+ RELOAD("-reloadPermFiles"), CLEAR("-clearUgiCache"), GET("-get"), CHECKCERTS(
|
|
|
+ "-checkcerts");
|
|
|
|
|
|
private String name = null;
|
|
|
|
|
@@ -65,7 +75,7 @@ public class ProxyUtil {
|
|
|
return name;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
* Dummy hostname verifier that is used to bypass hostname checking
|
|
|
*/
|
|
@@ -75,6 +85,21 @@ public class ProxyUtil {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Dummy trustmanager that is used to bypass server certificate checking
|
|
|
+ */
|
|
|
+ private static class DummyTrustManager implements X509TrustManager {
|
|
|
+ public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
|
|
+ }
|
|
|
+
|
|
|
+ public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
|
|
+ }
|
|
|
+
|
|
|
+ public X509Certificate[] getAcceptedIssuers() {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static HttpsURLConnection openConnection(String hostname, int port,
|
|
|
String path) throws IOException {
|
|
|
try {
|
|
@@ -90,21 +115,53 @@ public class ProxyUtil {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static void setupSslProps(Configuration conf) {
|
|
|
- System.setProperty("javax.net.ssl.trustStore", conf
|
|
|
- .get("ssl.client.truststore.location"));
|
|
|
- System.setProperty("javax.net.ssl.trustStorePassword", conf.get(
|
|
|
- "ssl.client.truststore.password", ""));
|
|
|
- System.setProperty("javax.net.ssl.trustStoreType", conf.get(
|
|
|
- "ssl.client.truststore.type", "jks"));
|
|
|
- System.setProperty("javax.net.ssl.keyStore", conf
|
|
|
- .get("ssl.client.keystore.location"));
|
|
|
- System.setProperty("javax.net.ssl.keyStorePassword", conf.get(
|
|
|
- "ssl.client.keystore.password", ""));
|
|
|
- System.setProperty("javax.net.ssl.keyPassword", conf.get(
|
|
|
- "ssl.client.keystore.keypassword", ""));
|
|
|
- System.setProperty("javax.net.ssl.keyStoreType", conf.get(
|
|
|
- "ssl.client.keystore.type", "jks"));
|
|
|
+ private static void setupSslProps(Configuration conf) throws IOException {
|
|
|
+ FileInputStream fis = null;
|
|
|
+ try {
|
|
|
+ SSLContext sc = SSLContext.getInstance("SSL");
|
|
|
+ KeyManager[] kms = null;
|
|
|
+ TrustManager[] tms = null;
|
|
|
+ if (conf.get("ssl.client.keystore.location") != null) {
|
|
|
+ // initialize default key manager with keystore file and pass
|
|
|
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
|
|
|
+ KeyStore ks = KeyStore.getInstance(conf.get("ssl.client.keystore.type",
|
|
|
+ "JKS"));
|
|
|
+ char[] ksPass = conf.get("ssl.client.keystore.password", "changeit")
|
|
|
+ .toCharArray();
|
|
|
+ fis = new FileInputStream(conf.get("ssl.client.keystore.location",
|
|
|
+ "keystore.jks"));
|
|
|
+ ks.load(fis, ksPass);
|
|
|
+ kmf.init(ks, conf.get("ssl.client.keystore.keypassword", "changeit")
|
|
|
+ .toCharArray());
|
|
|
+ kms = kmf.getKeyManagers();
|
|
|
+ fis.close();
|
|
|
+ fis = null;
|
|
|
+ }
|
|
|
+ // initialize default trust manager with keystore file and pass
|
|
|
+ if (conf.getBoolean("ssl.client.do.not.authenticate.server", false)) {
|
|
|
+ // by pass trustmanager validation
|
|
|
+ tms = new DummyTrustManager[] { new DummyTrustManager() };
|
|
|
+ } else {
|
|
|
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
|
|
|
+ KeyStore ts = KeyStore.getInstance(conf.get(
|
|
|
+ "ssl.client.truststore.type", "JKS"));
|
|
|
+ char[] tsPass = conf.get("ssl.client.truststore.password", "changeit")
|
|
|
+ .toCharArray();
|
|
|
+ fis = new FileInputStream(conf.get("ssl.client.truststore.location",
|
|
|
+ "truststore.jks"));
|
|
|
+ ts.load(fis, tsPass);
|
|
|
+ tmf.init(ts);
|
|
|
+ tms = tmf.getTrustManagers();
|
|
|
+ }
|
|
|
+ sc.init(kms, tms, new java.security.SecureRandom());
|
|
|
+ HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new IOException("Could not initialize SSLContext", e);
|
|
|
+ } finally {
|
|
|
+ if (fis != null) {
|
|
|
+ fis.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static InetSocketAddress getSslAddr(Configuration conf) throws IOException {
|
|
@@ -121,31 +178,33 @@ public class ProxyUtil {
|
|
|
int err = 0;
|
|
|
StringBuilder b = new StringBuilder();
|
|
|
|
|
|
- HostsFileReader hostsReader = new HostsFileReader(conf.get("hdfsproxy.hosts",
|
|
|
- "hdfsproxy-hosts"), "");
|
|
|
+ HostsFileReader hostsReader = new HostsFileReader(conf.get(
|
|
|
+ "hdfsproxy.hosts", "hdfsproxy-hosts"), "");
|
|
|
Set<String> hostsList = hostsReader.getHosts();
|
|
|
for (String hostname : hostsList) {
|
|
|
HttpsURLConnection connection = null;
|
|
|
try {
|
|
|
- connection = openConnection(hostname, sslPort, path);
|
|
|
- connection.connect();
|
|
|
+ connection = openConnection(hostname, sslPort, path);
|
|
|
+ connection.connect();
|
|
|
if (LOG.isDebugEnabled()) {
|
|
|
StringBuffer sb = new StringBuffer();
|
|
|
- X509Certificate[] clientCerts = (X509Certificate[]) connection.getLocalCertificates();
|
|
|
+ X509Certificate[] clientCerts = (X509Certificate[]) connection
|
|
|
+ .getLocalCertificates();
|
|
|
if (clientCerts != null) {
|
|
|
for (X509Certificate cert : clientCerts)
|
|
|
sb.append("\n Client certificate Subject Name is "
|
|
|
+ cert.getSubjectX500Principal().getName());
|
|
|
} else {
|
|
|
- sb.append("\n No client certificates were found");
|
|
|
+ sb.append("\n No client certificates were found");
|
|
|
}
|
|
|
- X509Certificate[] serverCerts = (X509Certificate[]) connection.getServerCertificates();
|
|
|
+ X509Certificate[] serverCerts = (X509Certificate[]) connection
|
|
|
+ .getServerCertificates();
|
|
|
if (serverCerts != null) {
|
|
|
for (X509Certificate cert : serverCerts)
|
|
|
sb.append("\n Server certificate Subject Name is "
|
|
|
+ cert.getSubjectX500Principal().getName());
|
|
|
} else {
|
|
|
- sb.append("\n No server certificates were found");
|
|
|
+ sb.append("\n No server certificates were found");
|
|
|
}
|
|
|
LOG.debug(sb.toString());
|
|
|
}
|
|
@@ -156,7 +215,8 @@ public class ProxyUtil {
|
|
|
}
|
|
|
} catch (IOException e) {
|
|
|
b.append("\n\t" + hostname + ": " + e.getLocalizedMessage());
|
|
|
- if (LOG.isDebugEnabled()) e.printStackTrace();
|
|
|
+ if (LOG.isDebugEnabled())
|
|
|
+ LOG.debug("Exception happend for host " + hostname, e);
|
|
|
err++;
|
|
|
} finally {
|
|
|
if (connection != null)
|
|
@@ -164,65 +224,73 @@ public class ProxyUtil {
|
|
|
}
|
|
|
}
|
|
|
if (err > 0) {
|
|
|
- System.err.print("Command failed on the following "
|
|
|
- + err + " host" + (err==1?":":"s:") + b.toString() + "\n");
|
|
|
+ System.err.print("Command failed on the following " + err + " host"
|
|
|
+ + (err == 1 ? ":" : "s:") + b.toString() + "\n");
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- static FSDataInputStream open(Configuration conf, String hostname, int port, String path) throws IOException {
|
|
|
+
|
|
|
+ static FSDataInputStream open(Configuration conf, String hostname, int port,
|
|
|
+ String path) throws IOException {
|
|
|
setupSslProps(conf);
|
|
|
HttpURLConnection connection = null;
|
|
|
connection = openConnection(hostname, port, path);
|
|
|
connection.connect();
|
|
|
final InputStream in = connection.getInputStream();
|
|
|
return new FSDataInputStream(new FSInputStream() {
|
|
|
- public int read() throws IOException {
|
|
|
- return in.read();
|
|
|
- }
|
|
|
- public int read(byte[] b, int off, int len) throws IOException {
|
|
|
- return in.read(b, off, len);
|
|
|
- }
|
|
|
+ public int read() throws IOException {
|
|
|
+ return in.read();
|
|
|
+ }
|
|
|
|
|
|
- public void close() throws IOException {
|
|
|
- in.close();
|
|
|
- }
|
|
|
+ public int read(byte[] b, int off, int len) throws IOException {
|
|
|
+ return in.read(b, off, len);
|
|
|
+ }
|
|
|
|
|
|
- public void seek(long pos) throws IOException {
|
|
|
- throw new IOException("Can't seek!");
|
|
|
- }
|
|
|
- public long getPos() throws IOException {
|
|
|
- throw new IOException("Position unknown!");
|
|
|
- }
|
|
|
- public boolean seekToNewSource(long targetPos) throws IOException {
|
|
|
- return false;
|
|
|
- }
|
|
|
- });
|
|
|
+ public void close() throws IOException {
|
|
|
+ in.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void seek(long pos) throws IOException {
|
|
|
+ throw new IOException("Can't seek!");
|
|
|
+ }
|
|
|
+
|
|
|
+ public long getPos() throws IOException {
|
|
|
+ throw new IOException("Position unknown!");
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean seekToNewSource(long targetPos) throws IOException {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
-
|
|
|
- static void checkServerCertsExpirationDays(Configuration conf, String hostname, int port) throws IOException {
|
|
|
+
|
|
|
+ static void checkServerCertsExpirationDays(Configuration conf,
|
|
|
+ String hostname, int port) throws IOException {
|
|
|
setupSslProps(conf);
|
|
|
HttpsURLConnection connection = null;
|
|
|
connection = openConnection(hostname, port, null);
|
|
|
connection.connect();
|
|
|
- X509Certificate[] serverCerts = (X509Certificate[]) connection.getServerCertificates();
|
|
|
+ X509Certificate[] serverCerts = (X509Certificate[]) connection
|
|
|
+ .getServerCertificates();
|
|
|
Date curDate = new Date();
|
|
|
long curTime = curDate.getTime();
|
|
|
if (serverCerts != null) {
|
|
|
for (X509Certificate cert : serverCerts) {
|
|
|
StringBuffer sb = new StringBuffer();
|
|
|
- sb.append("\n Server certificate Subject Name: " + cert.getSubjectX500Principal().getName());
|
|
|
+ sb.append("\n Server certificate Subject Name: "
|
|
|
+ + cert.getSubjectX500Principal().getName());
|
|
|
Date expDate = cert.getNotAfter();
|
|
|
long expTime = expDate.getTime();
|
|
|
- int dayOffSet = (int) ((expTime - curTime)/MM_SECONDS_PER_DAY);
|
|
|
+ int dayOffSet = (int) ((expTime - curTime) / MM_SECONDS_PER_DAY);
|
|
|
sb.append(" have " + dayOffSet + " days to expire");
|
|
|
- if (dayOffSet < CERT_EXPIRATION_WARNING_THRESHOLD) LOG.warn(sb.toString());
|
|
|
- else LOG.info(sb.toString());
|
|
|
+ if (dayOffSet < CERT_EXPIRATION_WARNING_THRESHOLD)
|
|
|
+ LOG.warn(sb.toString());
|
|
|
+ else
|
|
|
+ LOG.info(sb.toString());
|
|
|
}
|
|
|
} else {
|
|
|
- LOG.info("\n No Server certs was found");
|
|
|
+ LOG.info("\n No Server certs was found");
|
|
|
}
|
|
|
|
|
|
if (connection != null) {
|
|
@@ -231,24 +299,23 @@ public class ProxyUtil {
|
|
|
}
|
|
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
- if(args.length < 1 ||
|
|
|
- (!UtilityOption.RELOAD.getName().equalsIgnoreCase(args[0])
|
|
|
+ if (args.length < 1
|
|
|
+ || (!UtilityOption.RELOAD.getName().equalsIgnoreCase(args[0])
|
|
|
&& !UtilityOption.CLEAR.getName().equalsIgnoreCase(args[0])
|
|
|
- && !UtilityOption.GET.getName().equalsIgnoreCase(args[0])
|
|
|
- && !UtilityOption.CHECKCERTS.getName().equalsIgnoreCase(args[0])) ||
|
|
|
- (UtilityOption.GET.getName().equalsIgnoreCase(args[0]) && args.length != 4) ||
|
|
|
- (UtilityOption.CHECKCERTS.getName().equalsIgnoreCase(args[0]) && args.length != 3)) {
|
|
|
- System.err.println("Usage: ProxyUtil ["
|
|
|
- + UtilityOption.RELOAD.getName() + "] | ["
|
|
|
- + UtilityOption.CLEAR.getName() + "] | ["
|
|
|
+ && !UtilityOption.GET.getName().equalsIgnoreCase(args[0]) && !UtilityOption.CHECKCERTS
|
|
|
+ .getName().equalsIgnoreCase(args[0]))
|
|
|
+ || (UtilityOption.GET.getName().equalsIgnoreCase(args[0]) && args.length != 4)
|
|
|
+ || (UtilityOption.CHECKCERTS.getName().equalsIgnoreCase(args[0]) && args.length != 3)) {
|
|
|
+ System.err.println("Usage: ProxyUtil [" + UtilityOption.RELOAD.getName()
|
|
|
+ + "] | [" + UtilityOption.CLEAR.getName() + "] | ["
|
|
|
+ UtilityOption.GET.getName() + " <hostname> <#port> <path> ] | ["
|
|
|
+ UtilityOption.CHECKCERTS.getName() + " <hostname> <#port> ]");
|
|
|
- System.exit(0);
|
|
|
+ System.exit(0);
|
|
|
}
|
|
|
- Configuration conf = new Configuration(false);
|
|
|
+ Configuration conf = new Configuration(false);
|
|
|
conf.addResource("ssl-client.xml");
|
|
|
conf.addResource("hdfsproxy-default.xml");
|
|
|
-
|
|
|
+
|
|
|
if (UtilityOption.RELOAD.getName().equalsIgnoreCase(args[0])) {
|
|
|
// reload user-certs.xml and user-permissions.xml files
|
|
|
sendCommand(conf, "/reloadPermFiles");
|
|
@@ -266,5 +333,5 @@ public class ProxyUtil {
|
|
|
in.close();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
}
|