You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2018/05/29 12:46:50 UTC
[ambari] branch trunk updated: [AMBARI-23920] Ambari 2way SSL does
not work if CA signed certs are used
This is an automated email from the ASF dual-hosted git repository.
rlevas pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new 36e41b9 [AMBARI-23920] Ambari 2way SSL does not work if CA signed certs are used
36e41b9 is described below
commit 36e41b962c08173227bdc6e140228cb9eef72981
Author: Robert Levas <rl...@hortonworks.com>
AuthorDate: Sat May 26 22:43:04 2018 -0400
[AMBARI-23920] Ambari 2way SSL does not work if CA signed certs are used
---
.../ambari/server/configuration/Configuration.java | 8 ++++
.../ambari/server/security/CertificateManager.java | 44 +++++++++++++++-------
.../unsecured/rest/CertificateDownload.java | 4 +-
.../server/security/CertificateManagerTest.java | 38 +++++++++++++++++++
4 files changed, 79 insertions(+), 15 deletions(-)
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 91eafe5..d9ffe24 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -544,6 +544,13 @@ public class Configuration {
"security.server.cert_name", "ca.crt");
/**
+ * The name of the file that contains the CA certificate chain for certificate validation during 2-way SSL communication.
+ */
+ @Markdown(description = "The name of the file located in the `security.server.keys_dir` directory containing the CA certificate chain used to verify certificates during 2-way SSL communications.")
+ public static final ConfigurationProperty<String> SRVR_CRT_CHAIN_NAME = new ConfigurationProperty<>(
+ "security.server.cert_chain_name", "ca_chain.pem");
+
+ /**
* The name of the certificate request file used when generating certificates.
*/
@Markdown(description = "The name of the certificate request file used when generating certificates.")
@@ -2726,6 +2733,7 @@ public class Configuration {
configsMap.put(SRVR_ONE_WAY_SSL_PORT.getKey(), getProperty(SRVR_ONE_WAY_SSL_PORT));
configsMap.put(SRVR_KSTR_DIR.getKey(), getProperty(SRVR_KSTR_DIR));
configsMap.put(SRVR_CRT_NAME.getKey(), getProperty(SRVR_CRT_NAME));
+ configsMap.put(SRVR_CRT_CHAIN_NAME.getKey(), getProperty(SRVR_CRT_CHAIN_NAME));
configsMap.put(SRVR_KEY_NAME.getKey(), getProperty(SRVR_KEY_NAME));
configsMap.put(SRVR_CSR_NAME.getKey(), getProperty(SRVR_CSR_NAME));
configsMap.put(KSTR_NAME.getKey(), getProperty(KSTR_NAME));
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/CertificateManager.java b/ambari-server/src/main/java/org/apache/ambari/server/security/CertificateManager.java
index 532c749..2ac54be 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/CertificateManager.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/CertificateManager.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
+import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.Map;
@@ -145,7 +146,7 @@ public class CertificateManager {
Map<String, String> configsMap = configs.getConfigsMap();
String srvrKstrDir = configsMap.get(Configuration.SRVR_KSTR_DIR.getKey());
String srvrCrtName = configsMap.get(Configuration.SRVR_CRT_NAME.getKey());
- String srvrCsrName = configsMap.get(Configuration.SRVR_CSR_NAME.getKey());;
+ String srvrCsrName = configsMap.get(Configuration.SRVR_CSR_NAME.getKey());
String srvrKeyName = configsMap.get(Configuration.SRVR_KEY_NAME.getKey());
String kstrName = configsMap.get(Configuration.KSTR_NAME.getKey());
String srvrCrtPass = configsMap.get(Configuration.SRVR_CRT_PASS.getKey());
@@ -174,20 +175,37 @@ public class CertificateManager {
}
/**
- * Returns server certificate content
- * @return string with server certificate content
+ * Returns server's PEM-encoded CA chain file content
+ * @return string server's PEM-encoded CA chain file content
*/
- public String getServerCert() {
- Map<String, String> configsMap = configs.getConfigsMap();
- File certFile = new File(configsMap.get(Configuration.SRVR_KSTR_DIR.getKey()) +
- File.separator + configsMap.get(Configuration.SRVR_CRT_NAME.getKey()));
- String srvrCrtContent = null;
- try {
- srvrCrtContent = FileUtils.readFileToString(certFile);
- } catch (IOException e) {
- LOG.error(e.getMessage());
+ public String getCACertificateChainContent() {
+ String serverCertDir = configs.getProperty(Configuration.SRVR_KSTR_DIR);
+
+ // Attempt to send the explicit CA certificate chain file.
+ String serverCertChainName = configs.getProperty(Configuration.SRVR_CRT_CHAIN_NAME);
+ File certChainFile = new File(serverCertDir, serverCertChainName);
+ if(certChainFile.exists()) {
+ try {
+ return new String(Files.readAllBytes(certChainFile.toPath()));
+ } catch (IOException e) {
+ LOG.error(e.getMessage());
+ }
}
- return srvrCrtContent;
+
+ // Fall back to the original way things were done and send the server's SSL certificate as the
+ // Certificate chain file.
+ String serverCertName = configs.getProperty(Configuration.SRVR_CRT_NAME);
+ File certFile = new File(serverCertDir, serverCertName);
+ if(certFile.canRead()) {
+ try {
+ return new String(Files.readAllBytes(certFile.toPath()));
+ } catch (IOException e) {
+ LOG.error(e.getMessage());
+ }
+ }
+
+ // If all else fails, send nothing...
+ return null;
}
/**
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/security/unsecured/rest/CertificateDownload.java b/ambari-server/src/main/java/org/apache/ambari/server/security/unsecured/rest/CertificateDownload.java
index 881e614..43a9106 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/security/unsecured/rest/CertificateDownload.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/security/unsecured/rest/CertificateDownload.java
@@ -41,8 +41,8 @@ public class CertificateDownload {
@GET @ApiIgnore // until documented
@Produces({MediaType.TEXT_PLAIN})
- public String downloadSrvrCrt() {
- return certMan.getServerCert();
+ public String downloadCACertificateChainFile() {
+ return certMan.getCACertificateChainContent();
}
}
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/security/CertificateManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/security/CertificateManagerTest.java
index dceeab2..47de7b5 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/security/CertificateManagerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/security/CertificateManagerTest.java
@@ -21,7 +21,9 @@ package org.apache.ambari.server.security;
import static org.easymock.EasyMock.expect;
import java.io.File;
+import java.io.IOException;
import java.lang.reflect.Method;
+import java.nio.file.Files;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -163,6 +165,42 @@ public class CertificateManagerTest extends EasyMockSupport {
Assert.assertEquals("Incorrect passphrase from the agent", response.getMessage());
}
+ @Test
+ public void testGetCACertificateChain() throws IOException {
+ Injector injector = getInjector();
+
+ File directory = folder.newFolder();
+ String caCertFileName = "myca.crt";
+ String caCertChainFileName = "myca_chain.pem";
+
+ Configuration configuration = injector.getInstance(Configuration.class);
+ expect(configuration.getProperty(Configuration.SRVR_KSTR_DIR)).andReturn(directory.getAbsolutePath()).anyTimes();
+ expect(configuration.getProperty(Configuration.SRVR_CRT_NAME)).andReturn(caCertFileName).anyTimes();
+ expect(configuration.getProperty(Configuration.SRVR_CRT_CHAIN_NAME)).andReturn(caCertChainFileName).anyTimes();
+
+ final File caCertFile = new File(directory, caCertFileName);
+ final File caCertChainFile = new File(directory, caCertChainFileName);
+
+ CertificateManager certificateManager = new CertificateManager();
+ injector.injectMembers(certificateManager);
+
+ replayAll();
+
+ String content;
+
+ // Only the CA certificate file is available, this is the fallback option
+ Files.write(caCertFile.toPath(), Collections.singleton(caCertFile.getAbsolutePath()));
+ content = certificateManager.getCACertificateChainContent();
+ Assert.assertEquals(caCertFile.getAbsolutePath(), content.trim());
+
+ // The CA certificate chain file is available, this is the preferred option
+ Files.write(caCertChainFile.toPath(), Collections.singleton(caCertChainFile.getAbsolutePath()));
+ content = certificateManager.getCACertificateChainContent();
+ Assert.assertEquals(caCertChainFile.getAbsolutePath(), content.trim());
+
+ verifyAll();
+ }
+
private Injector getInjector() {
return Guice.createInjector(new AbstractModule() {
--
To stop receiving notification emails like this one, please contact
rlevas@apache.org.