SLIDER-792 fix cert store file name collisions
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/14aa6edb Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/14aa6edb Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/14aa6edb Branch: refs/heads/feature/package_simplification_II Commit: 14aa6edbdf677cb5fd91d0195030238ebeb25e42 Parents: de41cb5 Author: Jon Maron <jma...@hortonworks.com> Authored: Tue Mar 3 11:06:14 2015 -0800 Committer: Jon Maron <jma...@hortonworks.com> Committed: Tue Mar 3 11:06:14 2015 -0800 ---------------------------------------------------------------------- .../providers/agent/AgentProviderService.java | 24 ++-- .../services/security/CertificateManager.java | 19 +-- .../services/security/KeystoreGenerator.java | 8 +- .../server/services/security/SecurityStore.java | 66 ++++++++++ .../security/SecurityStoreGenerator.java | 8 +- .../services/security/StoresGenerator.java | 21 ++-- .../services/security/TruststoreGenerator.java | 9 +- .../security/TestCertificateManager.java | 123 +++++++++++++------ 8 files changed, 200 insertions(+), 78 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java index 74eda97..1eeb8e5 100644 --- a/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java +++ b/slider-core/src/main/java/org/apache/slider/providers/agent/AgentProviderService.java @@ -95,6 +95,7 @@ import org.apache.slider.server.appmaster.web.rest.agent.RegistrationResponse; import org.apache.slider.server.appmaster.web.rest.agent.RegistrationStatus; import org.apache.slider.server.appmaster.web.rest.agent.StatusCommand; import org.apache.slider.server.services.security.CertificateManager; +import org.apache.slider.server.services.security.SecurityStore; import org.apache.slider.server.services.security.StoresGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -468,20 +469,21 @@ public class AgentProviderService extends AbstractProviderService implements MapOperations compOps = instanceDefinition.getAppConfOperations() .getComponent(role); // generate and localize security stores - File[] stores = generateSecurityStores(container, role, - instanceDefinition, compOps); - for (File store : stores) { + SecurityStore[] stores = generateSecurityStores(container, role, + instanceDefinition, compOps); + for (SecurityStore store : stores) { LocalResource keystoreResource = fileSystem.createAmResource( - uploadSecurityResource(store, fileSystem), LocalResourceType.FILE); - launcher.addLocalResource(String.format("secstores/%s.p12", role), + uploadSecurityResource(store.getFile(), fileSystem), LocalResourceType.FILE); + launcher.addLocalResource(String.format("secstores/%s-%s.p12", + store.getType(), role), keystoreResource); } } - private File[] generateSecurityStores(Container container, - String role, - AggregateConf instanceDefinition, - MapOperations compOps) + private SecurityStore[] generateSecurityStores(Container container, + String role, + AggregateConf instanceDefinition, + MapOperations compOps) throws SliderException, IOException { return StoresGenerator.generateSecurityStores(container.getNodeId().getHost(), container.getId().toString(), role, @@ -489,8 +491,8 @@ public class AgentProviderService extends AbstractProviderService implements } private boolean areStoresRequested(MapOperations compOps) { - return compOps != null ? Boolean.valueOf(compOps. - getOptionBool(SliderKeys.COMP_STORES_REQUIRED_KEY, false)) : false; + return compOps != null ? compOps. + getOptionBool(SliderKeys.COMP_STORES_REQUIRED_KEY, false) : false; } private void localizeContainerSSLResources(ContainerLauncher launcher, http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java b/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java index 14c8b73..8d8dfec 100644 --- a/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java +++ b/slider-core/src/main/java/org/apache/slider/server/services/security/CertificateManager.java @@ -221,10 +221,10 @@ public class CertificateManager { } } - public synchronized File generateContainerKeystore(String hostname, - String containerId, - String role, - String keystorePass) + public synchronized SecurityStore generateContainerKeystore(String hostname, + String containerId, + String role, + String keystorePass) throws SliderException { LOG.info("Generation of container keystore for container {} on {}", containerId, hostname); @@ -244,7 +244,8 @@ public class CertificateManager { String command = MessageFormat.format(EXPRT_KSTR, scriptArgs); runCommand(command); - return new File(srvrKstrDir, kstrName); + return new SecurityStore(new File(srvrKstrDir, kstrName), + SecurityStore.StoreType.keystore); } private static String getKeystoreFileName(String containerId, @@ -282,8 +283,9 @@ public class CertificateManager { runCommand(command); } - public File generateContainerTruststore(String containerId, String role, - String truststorePass) + public SecurityStore generateContainerTruststore(String containerId, + String role, + String truststorePass) throws SliderException { String srvrKstrDir = SecurityUtils.getSecurityDir(); @@ -299,7 +301,8 @@ public class CertificateManager { String command = MessageFormat.format(EXPRT_KSTR, scriptArgs); runCommand(command); - return new File(srvrKstrDir, kstrName); + return new SecurityStore(new File(srvrKstrDir, kstrName), + SecurityStore.StoreType.truststore); } private static String getTruststoreFileName(String role, String containerId) { http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/main/java/org/apache/slider/server/services/security/KeystoreGenerator.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/KeystoreGenerator.java b/slider-core/src/main/java/org/apache/slider/server/services/security/KeystoreGenerator.java index 8611024..e2339d5 100644 --- a/slider-core/src/main/java/org/apache/slider/server/services/security/KeystoreGenerator.java +++ b/slider-core/src/main/java/org/apache/slider/server/services/security/KeystoreGenerator.java @@ -35,11 +35,11 @@ public class KeystoreGenerator extends AbstractSecurityStoreGenerator { } @Override - public File generate(String hostname, String containerId, - AggregateConf instanceDefinition, - MapOperations compOps, String role) + public SecurityStore generate(String hostname, String containerId, + AggregateConf instanceDefinition, + MapOperations compOps, String role) throws SliderException, IOException { - File keystore = null; + SecurityStore keystore = null; String password = getStorePassword( instanceDefinition.getAppConf().credentials, compOps, role); if (password != null) { http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStore.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStore.java b/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStore.java new file mode 100644 index 0000000..fc54267 --- /dev/null +++ b/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStore.java @@ -0,0 +1,66 @@ +/* + * 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.slider.server.services.security; + +import java.io.File; + +/** + * + */ +public class SecurityStore { + private File file; + + public enum StoreType {truststore, keystore} + + private StoreType type; + + public String getType() { + return type.name(); + } + + public File getFile() { + return file; + } + + public SecurityStore(File file, + StoreType type) { + + this.file = file; + this.type = type; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SecurityStore that = (SecurityStore) o; + + if (file != null ? !file.equals(that.file) : that.file != null) + return false; + if (type != that.type) return false; + + return true; + } + + @Override + public int hashCode() { + int result = file != null ? file.hashCode() : 0; + result = 31 * result + (type != null ? type.hashCode() : 0); + return result; + } +} http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStoreGenerator.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStoreGenerator.java b/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStoreGenerator.java index 5549a92..a814988 100644 --- a/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStoreGenerator.java +++ b/slider-core/src/main/java/org/apache/slider/server/services/security/SecurityStoreGenerator.java @@ -29,9 +29,11 @@ import java.io.IOException; */ public interface SecurityStoreGenerator { - File generate(String hostname, String containerId, - AggregateConf instanceDefinition, MapOperations compOps, - String role) + SecurityStore generate(String hostname, + String containerId, + AggregateConf instanceDefinition, + MapOperations compOps, + String role) throws SliderException, IOException; boolean isStoreRequested(MapOperations compOps); http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/main/java/org/apache/slider/server/services/security/StoresGenerator.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/StoresGenerator.java b/slider-core/src/main/java/org/apache/slider/server/services/security/StoresGenerator.java index 98395b5..226250f 100644 --- a/slider-core/src/main/java/org/apache/slider/server/services/security/StoresGenerator.java +++ b/slider-core/src/main/java/org/apache/slider/server/services/security/StoresGenerator.java @@ -35,18 +35,21 @@ public class StoresGenerator { new KeystoreGenerator(certMgr), new TruststoreGenerator(certMgr) }; - public static File[] generateSecurityStores(String hostname, - String containerId, - String role, - AggregateConf instanceDefinition, - MapOperations compOps) + public static SecurityStore[] generateSecurityStores(String hostname, + String containerId, + String role, + AggregateConf instanceDefinition, + MapOperations compOps) throws SliderException, IOException { //discover which stores need generation based on the passwords configured - List<File> files = new ArrayList<File>(); + List<SecurityStore> files = new ArrayList<SecurityStore>(); for (SecurityStoreGenerator generator : GENERATORS) { if (generator.isStoreRequested(compOps)) { - File store = generator.generate(hostname, containerId, - instanceDefinition, compOps, role); + SecurityStore store = generator.generate(hostname, + containerId, + instanceDefinition, + compOps, + role); if (store != null) { files.add(store); } @@ -59,7 +62,7 @@ public class StoresGenerator { + "passwords are configured for the components " + "requiring the stores."); } - return files.toArray(new File[files.size()]); + return files.toArray(new SecurityStore[files.size()]); } } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/main/java/org/apache/slider/server/services/security/TruststoreGenerator.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/services/security/TruststoreGenerator.java b/slider-core/src/main/java/org/apache/slider/server/services/security/TruststoreGenerator.java index 4d0371b..d16dcbd 100644 --- a/slider-core/src/main/java/org/apache/slider/server/services/security/TruststoreGenerator.java +++ b/slider-core/src/main/java/org/apache/slider/server/services/security/TruststoreGenerator.java @@ -21,7 +21,6 @@ import org.apache.slider.core.conf.AggregateConf; import org.apache.slider.core.conf.MapOperations; import org.apache.slider.core.exceptions.SliderException; -import java.io.File; import java.io.IOException; /** @@ -35,11 +34,11 @@ public class TruststoreGenerator extends AbstractSecurityStoreGenerator { } @Override - public File generate(String hostname, String containerId, - AggregateConf instanceDefinition, - MapOperations compOps, String role) + public SecurityStore generate(String hostname, String containerId, + AggregateConf instanceDefinition, + MapOperations compOps, String role) throws SliderException, IOException { - File truststore = null; + SecurityStore truststore = null; String password = getStorePassword( instanceDefinition.getAppConf().credentials, compOps, role); if (password != null) { http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/14aa6edb/slider-core/src/test/java/org/apache/slider/server/services/security/TestCertificateManager.java ---------------------------------------------------------------------- diff --git a/slider-core/src/test/java/org/apache/slider/server/services/security/TestCertificateManager.java b/slider-core/src/test/java/org/apache/slider/server/services/security/TestCertificateManager.java index 6ca2898..7a4a586 100644 --- a/slider-core/src/test/java/org/apache/slider/server/services/security/TestCertificateManager.java +++ b/slider-core/src/test/java/org/apache/slider/server/services/security/TestCertificateManager.java @@ -130,11 +130,11 @@ public class TestCertificateManager { @Test public void testContainerKeystoreGeneration() throws Exception { - File keystoreFile = certMan.generateContainerKeystore("testhost", - "container1", - "component1", - "password"); - validateKeystore(keystoreFile, "testhost", "cahost"); + SecurityStore keystoreFile = certMan.generateContainerKeystore("testhost", + "container1", + "component1", + "password"); + validateKeystore(keystoreFile.getFile(), "testhost", "cahost"); } private void validateKeystore(File keystoreFile, String certHostname, @@ -189,11 +189,35 @@ public class TestCertificateManager { instanceDefinition.getAppConf().global.put( "app1.component1.password.property", "password"); instanceDefinition.resolve(); - File[] files = StoresGenerator.generateSecurityStores("testhost", "container1", - "component1", instanceDefinition, - compOps); + SecurityStore[] + files = StoresGenerator.generateSecurityStores("testhost", + "container1", + "component1", + instanceDefinition, + compOps); assertEquals("wrong number of stores", 1, files.length); - validateKeystore(files[0], "testhost", "cahost"); + validateKeystore(files[0].getFile(), "testhost", "cahost"); + } + + @Test + public void testContainerKeystoreGenerationViaStoresGeneratorUsingGlobalProps() throws Exception { + AggregateConf instanceDefinition = new AggregateConf(); + MapOperations compOps = new MapOperations(); + instanceDefinition.getAppConf().components.put("component1", compOps); + compOps.put(SliderKeys.COMP_KEYSTORE_PASSWORD_PROPERTY_KEY, + "app1.component1.password.property"); + instanceDefinition.getAppConf().global.put(SliderKeys.COMP_STORES_REQUIRED_KEY, "true"); + compOps.put( + "app1.component1.password.property", "password"); + instanceDefinition.resolve(); + SecurityStore[] + files = StoresGenerator.generateSecurityStores("testhost", + "container1", + "component1", + instanceDefinition, + compOps); + assertEquals("wrong number of stores", 1, files.length); + validateKeystore(files[0].getFile(), "testhost", "cahost"); } @Test @@ -207,30 +231,33 @@ public class TestCertificateManager { "app1.component1.password.property", "password"); instanceDefinition.getAppConf().global.put(SliderKeys.COMP_STORES_REQUIRED_KEY, "false"); instanceDefinition.resolve(); - File[] files = StoresGenerator.generateSecurityStores("testhost", "container1", - "component1", instanceDefinition, - compOps); + SecurityStore[] + files = StoresGenerator.generateSecurityStores("testhost", + "container1", + "component1", + instanceDefinition, + compOps); assertEquals("wrong number of stores", 1, files.length); - validateKeystore(files[0], "testhost", "cahost"); + validateKeystore(files[0].getFile(), "testhost", "cahost"); } @Test public void testContainerTrusttoreGeneration() throws Exception { - File keystoreFile = + SecurityStore keystoreFile = certMan.generateContainerKeystore("testhost", "container1", "component1", "keypass"); Assert.assertTrue("container keystore not generated", - keystoreFile.exists()); - File truststoreFile = + keystoreFile.getFile().exists()); + SecurityStore truststoreFile = certMan.generateContainerTruststore("container1", "component1", "trustpass" ); Assert.assertTrue("container truststore not generated", - truststoreFile.exists()); + truststoreFile.getFile().exists()); - validateTruststore(keystoreFile, truststoreFile); + validateTruststore(keystoreFile.getFile(), truststoreFile.getFile()); } @Test @@ -243,23 +270,29 @@ public class TestCertificateManager { setupCredentials(instanceDefinition, "test.keystore.password", null); - File[] files = StoresGenerator.generateSecurityStores("testhost", "container1", - "component1", instanceDefinition, - compOps); + SecurityStore[] + files = StoresGenerator.generateSecurityStores("testhost", + "container1", + "component1", + instanceDefinition, + compOps); assertEquals("wrong number of stores", 1, files.length); File keystoreFile = CertificateManager.getContainerKeystoreFilePath( "container1", "component1"); Assert.assertTrue("container keystore not generated", keystoreFile.exists()); + Assert.assertTrue("keystore not in returned list", - Arrays.asList(files).contains(keystoreFile)); + Arrays.asList(files).contains(new SecurityStore(keystoreFile, + SecurityStore.StoreType.keystore))); File truststoreFile = CertificateManager.getContainerTruststoreFilePath("component1", "container1"); Assert.assertFalse("container truststore generated", truststoreFile.exists()); Assert.assertFalse("truststore in returned list", - Arrays.asList(files).contains(truststoreFile)); + Arrays.asList(files).contains(new SecurityStore(truststoreFile, + SecurityStore.StoreType.truststore))); } @@ -271,9 +304,12 @@ public class TestCertificateManager { setupCredentials(instanceDefinition, null, SliderKeys.COMP_TRUSTSTORE_PASSWORD_ALIAS_DEFAULT); - File[] files = StoresGenerator.generateSecurityStores("testhost", "container1", - "component1", instanceDefinition, - compOps); + SecurityStore[] + files = StoresGenerator.generateSecurityStores("testhost", + "container1", + "component1", + instanceDefinition, + compOps); assertEquals("wrong number of stores", 1, files.length); File keystoreFile = CertificateManager.getContainerKeystoreFilePath( "container1", "component1"); @@ -287,7 +323,8 @@ public class TestCertificateManager { Assert.assertTrue("container truststore not generated", truststoreFile.exists()); Assert.assertTrue("truststore not in returned list", - Arrays.asList(files).contains(truststoreFile)); + Arrays.asList(files).contains(new SecurityStore(truststoreFile, + SecurityStore.StoreType.truststore))); } @@ -303,23 +340,28 @@ public class TestCertificateManager { setupCredentials(instanceDefinition, "test.keystore.password", "test.truststore.password"); - File[] files = StoresGenerator.generateSecurityStores("testhost", "container1", - "component1", instanceDefinition, - compOps); + SecurityStore[] + files = StoresGenerator.generateSecurityStores("testhost", + "container1", + "component1", + instanceDefinition, + compOps); assertEquals("wrong number of stores", 2, files.length); File keystoreFile = CertificateManager.getContainerKeystoreFilePath( "container1", "component1"); Assert.assertTrue("container keystore not generated", keystoreFile.exists()); Assert.assertTrue("keystore not in returned list", - Arrays.asList(files).contains(keystoreFile)); + Arrays.asList(files).contains(new SecurityStore(keystoreFile, + SecurityStore.StoreType.keystore))); File truststoreFile = CertificateManager.getContainerTruststoreFilePath("component1", "container1"); Assert.assertTrue("container truststore not generated", truststoreFile.exists()); Assert.assertTrue("truststore not in returned list", - Arrays.asList(files).contains(truststoreFile)); + Arrays.asList(files).contains(new SecurityStore(truststoreFile, + SecurityStore.StoreType.truststore))); validateTruststore(keystoreFile, truststoreFile); } @@ -404,23 +446,28 @@ public class TestCertificateManager { setupCredentials(instanceDefinition, SliderKeys.COMP_KEYSTORE_PASSWORD_ALIAS_DEFAULT, null); - File[] files = StoresGenerator.generateSecurityStores("testhost", "container1", - "component1", instanceDefinition, - compOps); + SecurityStore[] + files = StoresGenerator.generateSecurityStores("testhost", + "container1", + "component1", + instanceDefinition, + compOps); assertEquals("wrong number of stores", 1, files.length); File keystoreFile = CertificateManager.getContainerKeystoreFilePath( "container1", "component1"); Assert.assertTrue("container keystore not generated", keystoreFile.exists()); Assert.assertTrue("keystore not in returned list", - Arrays.asList(files).contains(keystoreFile)); + Arrays.asList(files).contains(new SecurityStore(keystoreFile, + SecurityStore.StoreType.keystore))); File truststoreFile = CertificateManager.getContainerTruststoreFilePath("component1", "container1"); Assert.assertFalse("container truststore generated", truststoreFile.exists()); Assert.assertFalse("truststore in returned list", - Arrays.asList(files).contains(truststoreFile)); + Arrays.asList(files).contains(new SecurityStore(truststoreFile, + SecurityStore.StoreType.truststore))); } @@ -433,7 +480,7 @@ public class TestCertificateManager { setupCredentials(instanceDefinition, "cant.be.found", null); try { - File[] files = StoresGenerator.generateSecurityStores("testhost", "container1", + StoresGenerator.generateSecurityStores("testhost", "container1", "component1", instanceDefinition, compOps); Assert.fail("SliderException should have been generated");