You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2013/09/21 18:11:54 UTC
git commit: KNOX-137 - added the ability to get the public cert of
the gateway to AliasService and utilized it to log certificate CN/hostname
and validity period on startup to the JettySSLService
Updated Branches:
refs/heads/master a4fa09b74 -> 3d2afec68
KNOX-137 - added the ability to get the public cert of the gateway to AliasService and utilized it to log certificate CN/hostname and validity period on startup to the JettySSLService
Project: http://git-wip-us.apache.org/repos/asf/incubator-knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-knox/commit/3d2afec6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-knox/tree/3d2afec6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-knox/diff/3d2afec6
Branch: refs/heads/master
Commit: 3d2afec68f44d7eb866e46f56dab368cce4e5511
Parents: a4fa09b
Author: Larry McCay <lm...@hortonworks.com>
Authored: Sat Sep 21 12:11:45 2013 -0400
Committer: Larry McCay <lm...@hortonworks.com>
Committed: Sat Sep 21 12:11:45 2013 -0400
----------------------------------------------------------------------
.../apache/hadoop/gateway/GatewayMessages.java | 7 +
.../security/impl/DefaultAliasService.java | 19 +-
.../services/security/impl/JettySSLService.java | 19 ++
.../services/security/CryptoServiceTest.java | 7 +
.../gateway/services/security/AliasService.java | 4 +-
.../gateway/util/X500PrincipalParser.java | 189 +++++++++++++++++++
6 files changed, 241 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/3d2afec6/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
index 6efef71..fc17fd4 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
@@ -25,6 +25,7 @@ import org.apache.hadoop.gateway.i18n.messages.StackTrace;
import java.io.File;
import java.net.URI;
+import java.util.Date;
import java.util.Map;
/**
@@ -266,4 +267,10 @@ public interface GatewayMessages {
@Message( level = MessageLevel.DEBUG, text = "Gateway services have not been initialized." )
void gatewayServicesNotInitialized();
+
+ @Message( level = MessageLevel.INFO, text = "The Gateway SSL certificate is issued to hostname: {0}." )
+ void certificateHostNameForGateway(String cn);
+
+ @Message( level = MessageLevel.INFO, text = "The Gateway SSL certificate is valid between: {0} and {1}." )
+ void certificateValidityPeriod(Date notBefore, Date notAfter);
}
http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/3d2afec6/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
index 5fd2883..4d38400 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
@@ -17,8 +17,8 @@
*/
package org.apache.hadoop.gateway.services.security.impl;
-import java.security.Key;
-import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
import java.util.Map;
import java.util.Random;
@@ -26,7 +26,6 @@ import org.apache.hadoop.gateway.config.GatewayConfig;
import org.apache.hadoop.gateway.services.ServiceLifecycleException;
import org.apache.hadoop.gateway.services.security.AliasService;
import org.apache.hadoop.gateway.services.security.KeystoreService;
-import org.apache.hadoop.gateway.services.security.KeystoreServiceException;
public class DefaultAliasService implements AliasService {
@@ -111,4 +110,18 @@ public class DefaultAliasService implements AliasService {
generateAliasForCluster("__gateway", alias);
}
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.services.security.AliasService#getCertificateForGateway(java.lang.String)
+ */
+ @Override
+ public Certificate getCertificateForGateway(String alias) {
+ Certificate cert = null;
+ try {
+ cert = this.keystoreService.getKeystoreForGateway().getCertificate(alias);
+ } catch (KeyStoreException e) {
+ // TODO: log appropriately
+ // should we throw an exception?
+ }
+ return cert;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/3d2afec6/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/JettySSLService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/JettySSLService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/JettySSLService.java
index 4a9e1c7..0e40e99 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/JettySSLService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/JettySSLService.java
@@ -18,8 +18,13 @@
package org.apache.hadoop.gateway.services.security.impl;
import java.io.File;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Date;
import java.util.Map;
+import javax.security.auth.x500.X500Principal;
+
import org.apache.hadoop.gateway.GatewayMessages;
import org.apache.hadoop.gateway.config.GatewayConfig;
import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
@@ -29,6 +34,7 @@ import org.apache.hadoop.gateway.services.security.KeystoreService;
import org.apache.hadoop.gateway.services.security.KeystoreServiceException;
import org.apache.hadoop.gateway.services.security.MasterService;
import org.apache.hadoop.gateway.services.security.SSLService;
+import org.apache.hadoop.gateway.util.X500PrincipalParser;
import org.eclipse.jetty.server.ssl.SslConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@@ -81,6 +87,19 @@ public class JettySSLService implements SSLService {
else {
log.keyStoreForGatewayFoundNotCreating();
}
+ // let's log the hostname (CN) and cert expiry from the gateway's public cert to aid in SSL debugging
+ Certificate cert = as.getCertificateForGateway("gateway-identity");
+ if (cert instanceof X509Certificate) {
+ X500Principal x500Principal = ((X509Certificate)cert).getSubjectX500Principal();
+ X500PrincipalParser parser = new X500PrincipalParser(x500Principal);
+ log.certificateHostNameForGateway(parser.getCN());
+ Date notBefore = ((X509Certificate) cert).getNotBefore();
+ Date notAfter = ((X509Certificate) cert).getNotAfter();
+ log.certificateValidityPeriod(notBefore, notAfter);
+ }
+ else {
+ throw new ServiceLifecycleException("Public certificate for the gateway is not of the expected type of X509Certificate. Something is wrong with the gateway keystore.");
+ }
} catch (KeystoreServiceException e) {
throw new ServiceLifecycleException("Keystore was not loaded properly - the provided (or persisted) master secret may not match the password for the keystore.", e);
}
http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/3d2afec6/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java b/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
index d014242..af6ba43 100644
--- a/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
+++ b/gateway-server/src/test/java/org/apache/hadoop/gateway/services/security/CryptoServiceTest.java
@@ -27,6 +27,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import java.security.cert.Certificate;
import java.util.Map;
import static org.junit.Assert.assertEquals;
@@ -85,6 +86,12 @@ public class CryptoServiceTest {
// TODO Auto-generated method stub
}
+
+ @Override
+ public Certificate getCertificateForGateway(String alias) {
+ // TODO Auto-generated method stub
+ return null;
+ }
};
cs = new DefaultCryptoService().setAliasService(as);
}
http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/3d2afec6/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/AliasService.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/AliasService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/AliasService.java
index b32bbb1..a34cf29 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/AliasService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/AliasService.java
@@ -17,7 +17,7 @@
*/
package org.apache.hadoop.gateway.services.security;
-import java.security.Key;
+import java.security.cert.Certificate;
import org.apache.hadoop.gateway.services.Service;
@@ -34,4 +34,6 @@ public interface AliasService extends Service {
public abstract char[] getPasswordFromAliasForGateway(String alias);
void generateAliasForGateway(String alias);
+
+ Certificate getCertificateForGateway(String alias);
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/3d2afec6/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/X500PrincipalParser.java
----------------------------------------------------------------------
diff --git a/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/X500PrincipalParser.java b/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/X500PrincipalParser.java
new file mode 100644
index 0000000..c7d65d9
--- /dev/null
+++ b/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/X500PrincipalParser.java
@@ -0,0 +1,189 @@
+/**
+ * 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.gateway.util;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.security.auth.x500.X500Principal;
+
+public class X500PrincipalParser
+{
+ public static int LEASTSIGNIFICANT = 0;
+ public static int MOSTSIGNIFICANT = 1;
+
+ public final static String attrCN = "CN";
+ public final static String attrOU = "OU";
+ public final static String attrO = "O";
+ public final static String attrC = "C";
+ public final static String attrL = "L";
+ public final static String attrST = "ST";
+ public final static String attrSTREET = "STREET";
+ public final static String attrEMAIL = "EMAILADDRESS";
+ public final static String attrUID = "UID";
+
+ ArrayList rdnNameArray = new ArrayList();
+
+ private final static String attrTerminator = "=";
+
+ public X500PrincipalParser(X500Principal principal)
+ {
+ parseDN(principal.getName(X500Principal.RFC2253));
+ }
+
+ public ArrayList getAllValues(String attributeID)
+ {
+ ArrayList retList = new ArrayList();
+ String searchPart = attributeID + attrTerminator;
+
+ for(Iterator iter = rdnNameArray.iterator(); iter.hasNext();)
+ {
+ ArrayList nameList = (ArrayList)iter.next();
+ String namePart = (String)nameList.get(0);
+
+ if(namePart.startsWith(searchPart))
+ {
+ // Return the string starting after the ID string and the = sign that follows it.
+ retList.add(namePart.toString().substring(searchPart.length()));
+ }
+ }
+
+ return retList;
+
+ }
+
+ public String getC()
+ {
+ return findPart(attrC);
+ }
+
+ public String getCN()
+ {
+ return findPart(attrCN);
+ }
+
+ public String getEMAILDDRESS()
+ {
+ return findPart(attrEMAIL);
+ }
+
+ public String getL()
+ {
+ return findPart(attrL);
+ }
+
+ public String getO()
+ {
+ return findPart(attrO);
+
+ }
+
+ public String getOU()
+ {
+ return findPart(attrOU);
+
+ }
+
+ public String getST()
+ {
+ return findPart(attrST);
+ }
+
+ public String getSTREET()
+ {
+ return findPart(attrSTREET);
+ }
+
+ public String getUID()
+ {
+ return findPart(attrUID);
+ }
+
+ private String findPart(String attributeID)
+ {
+ return findSignificantPart(attributeID, MOSTSIGNIFICANT);
+ }
+
+ private String findSignificantPart(String attributeID, int significance)
+ {
+ String retNamePart = null;
+ String searchPart = attributeID + attrTerminator;
+
+ for(Iterator iter = rdnNameArray.iterator(); iter.hasNext();)
+ {
+ ArrayList nameList = (ArrayList)iter.next();
+ String namePart = (String)nameList.get(0);
+
+ if(namePart.startsWith(searchPart))
+ {
+ // Return the string starting after the ID string and the = sign that follows it.
+ retNamePart = namePart.toString().substring(searchPart.length());
+ // By definition the first one is most significant
+ if(significance == MOSTSIGNIFICANT)
+ break;
+ }
+ }
+
+ return retNamePart;
+ }
+
+ private void parseDN(String dn) throws IllegalArgumentException
+ {
+ int startIndex = 0;
+ char c = '\0';
+ ArrayList nameValues = new ArrayList();
+
+ rdnNameArray.clear();
+
+ while(startIndex < dn.length())
+ {
+ int endIndex;
+ for(endIndex = startIndex; endIndex < dn.length(); endIndex++)
+ {
+ c = dn.charAt(endIndex);
+ if(c == ',' || c == '+')
+ break;
+ if(c == '\\')
+ {
+ endIndex++; // skip the escaped char
+ }
+ }
+
+ if(endIndex > dn.length())
+ throw new IllegalArgumentException("unterminated escape " + dn);
+
+ nameValues.add(dn.substring(startIndex, endIndex));
+
+ if(c != '+')
+ {
+ rdnNameArray.add(nameValues);
+ if(endIndex != dn.length())
+ nameValues = new ArrayList();
+ else
+ nameValues = null;
+ }
+ startIndex = endIndex + 1;
+ }
+ if(nameValues != null)
+ {
+ throw new IllegalArgumentException("improperly terminated DN " + dn);
+ }
+ }
+
+}
\ No newline at end of file