diff --git a/src/main/java/org/alfresco/encryption/AlfrescoKeyStoreImpl.java b/src/main/java/org/alfresco/encryption/AlfrescoKeyStoreImpl.java index 085bec231a..747d4e652a 100644 --- a/src/main/java/org/alfresco/encryption/AlfrescoKeyStoreImpl.java +++ b/src/main/java/org/alfresco/encryption/AlfrescoKeyStoreImpl.java @@ -322,7 +322,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore try { - keyInfoManager = getKeyInfoManager(getKeyMetaDataFileLocation()); + keyInfoManager = getKeyInfoManager(getKeyStoreParameters()); KeyStore ks = loadKeyStore(keyStoreParameters, keyInfoManager); logger.debug("Initializing key managers"); @@ -355,7 +355,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore try { - keyInfoManager = getKeyInfoManager(getKeyMetaDataFileLocation()); + keyInfoManager = getKeyInfoManager(getKeyStoreParameters()); KeyStore ks = loadKeyStore(getKeyStoreParameters(), keyInfoManager); logger.debug("Initializing trust managers"); @@ -376,12 +376,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore } } } - - protected String getKeyMetaDataFileLocation() - { - return keyStoreParameters.getKeyMetaDataFileLocation(); - } - + protected InputStream getKeyStoreStream(String location) throws FileNotFoundException { if(location == null) @@ -396,9 +391,17 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore return new FileOutputStream(getKeyStoreParameters().getLocation()); } - protected KeyInfoManager getKeyInfoManager(String metadataFileLocation) throws FileNotFoundException, IOException + protected KeyInfoManager getKeyInfoManager(KeyStoreParameters keyStoreParameters) throws IOException { - return new KeyInfoManager(metadataFileLocation, keyResourceLoader); + return new KeyInfoManager(keyStoreParameters, keyResourceLoader); + } + + @Deprecated + protected KeyInfoManager getKeyInfoManager(String metadataFileLocation) throws IOException + { + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setKeyMetaDataFileLocation(metadataFileLocation); + return new KeyInfoManager(keyStoreParameters, keyResourceLoader); } protected KeyMap cacheKeys(KeyStore ks, KeyInfoManager keyInfoManager) @@ -563,7 +566,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore try { - keyInfoManager = getKeyInfoManager(keyStoreParameters.getKeyMetaDataFileLocation()); + keyInfoManager = getKeyInfoManager(keyStoreParameters); ks = loadKeyStore(keyStoreParameters, keyInfoManager); // Loaded } @@ -635,7 +638,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore try { - keyInfoManager = getKeyInfoManager(getKeyMetaDataFileLocation()); + keyInfoManager = getKeyInfoManager(getKeyStoreParameters()); Key key = getSecretKey(keyInfoManager.getKeyInformation(keyAlias)); encryptionKeysRegistry.registerKey(keyAlias, key); keys.setKey(keyAlias, key); @@ -678,7 +681,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore { if(!keyStoreExists(keyStoreParameters.getLocation())) { - keyInfoManager = getKeyInfoManager(keyStoreParameters.getKeyMetaDataFileLocation()); + keyInfoManager = getKeyInfoManager(keyStoreParameters); KeyStore ks = initialiseKeyStore(keyStoreParameters.getType(), keyStoreParameters.getProvider()); String keyStorePassword = keyInfoManager.getKeyStorePassword(); @@ -686,7 +689,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore { throw new AlfrescoRuntimeException("Key store password is null for keystore at location " + getKeyStoreParameters().getLocation() - + ", key store meta data location" + getKeyMetaDataFileLocation()); + + ". Either specify it as a JVM property or in key store meta data location."); } for(String keyAlias : keys.getKeyAliases()) @@ -765,8 +768,13 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore } } - protected Key getSecretKey(KeyInformation keyInformation) throws NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException + protected Key getSecretKey(KeyInformation keyInformation) throws AlfrescoRuntimeException, NoSuchAlgorithmException, InvalidKeyException, InvalidKeySpecException { + if (keyInformation == null) + { + throw new AlfrescoRuntimeException("Unable to get secret key: no key information is provided"); + } + byte[] keyData = keyInformation.getKeyData(); if(keyData == null) @@ -796,7 +804,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore writeLock.lock(); try { - keyInfoManager = getKeyInfoManager(getKeyMetaDataFileLocation()); + keyInfoManager = getKeyInfoManager(getKeyStoreParameters()); KeyStore ks = loadKeyStore(getKeyStoreParameters(), keyInfoManager); // loading Key @@ -985,7 +993,7 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore public static class KeyInfoManager { private KeyResourceLoader keyResourceLoader; - private String metadataFileLocation; + private KeyStoreParameters keyStoreParameters; private Properties keyProps; private String keyStorePassword = null; private Map keyInfo; @@ -1005,10 +1013,10 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore } } - KeyInfoManager(String metadataFileLocation, KeyResourceLoader keyResourceLoader) throws IOException, FileNotFoundException + KeyInfoManager(KeyStoreParameters keyStoreParameters, KeyResourceLoader keyResourceLoader) throws IOException, FileNotFoundException { this.keyResourceLoader = keyResourceLoader; - this.metadataFileLocation = metadataFileLocation; + this.keyStoreParameters = keyStoreParameters; keyInfo = new HashMap(2); loadKeyMetaData(); } @@ -1025,31 +1033,73 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore * Where required, null values must be inserted into the map to indicate the presence * of a key that is not protected by a password. They entry for {@link #KEY_KEYSTORE_PASSWORD} * is required if the keystore is password protected. + * + * WARNING. Storing passwords (keyMetaDataFileLocation) on the file system is not following best security practices. + * + *

Loading of keys info from system (JVM) properties takes precedence over metadata file. + *

Set the unique ID of the keystore and remove the metadata file location property to use JVM properties lookup instead. The property lookup format is the following: + *

+ * */ protected void loadKeyMetaData() throws IOException, FileNotFoundException { - keyProps = keyResourceLoader.loadKeyMetaData(metadataFileLocation); - if(keyProps != null) + if (keyStoreParameters.getId() != null && + (keyStoreParameters.getKeyMetaDataFileLocation() == null || + keyStoreParameters.getKeyMetaDataFileLocation().isEmpty())) { - String aliases = keyProps.getProperty("aliases"); - if(aliases == null) + Properties jvmProperties = System.getProperties(); + keyStorePassword = jvmProperties.getProperty(keyStoreParameters.getId() + ".password"); + String aliases = jvmProperties.getProperty(keyStoreParameters.getId() + ".aliases"); + if (aliases == null || aliases.isEmpty()) { - throw new AlfrescoRuntimeException("Passwords file must contain an aliases key"); + logger.warn("No aliases were specified for " + keyStoreParameters.getId() + + " keystore"); } - - this.keyStorePassword = keyProps.getProperty(KEY_KEYSTORE_PASSWORD); - - StringTokenizer st = new StringTokenizer(aliases, ","); - while(st.hasMoreTokens()) + else { - String keyAlias = st.nextToken(); - keyInfo.put(keyAlias, loadKeyInformation(keyAlias)); + StringTokenizer st = new StringTokenizer(aliases, ","); + while(st.hasMoreTokens()) + { + String keyAlias = st.nextToken(); + keyInfo.put(keyAlias, loadKeyInformation(jvmProperties, keyAlias, keyStoreParameters.getId() + ".")); + } } } else { - // TODO - //throw new FileNotFoundException("Cannot find key metadata file " + getKeyMetaDataFileLocation()); + logger.warn("Storing passwords (" + keyStoreParameters.getKeyMetaDataFileLocation() + + ") on the file system is not following best security practices." + + " Please refer to documentation and use JVM properties instead"); + + keyProps = keyResourceLoader.loadKeyMetaData(keyStoreParameters.getKeyMetaDataFileLocation()); + if(keyProps != null) + { + String aliases = keyProps.getProperty("aliases"); + if(aliases == null) + { + throw new AlfrescoRuntimeException("Passwords file must contain an aliases key"); + } + + this.keyStorePassword = keyProps.getProperty(KEY_KEYSTORE_PASSWORD); + + StringTokenizer st = new StringTokenizer(aliases, ","); + while(st.hasMoreTokens()) + { + String keyAlias = st.nextToken(); + keyInfo.put(keyAlias, loadKeyInformation(keyProps, keyAlias, "")); + } + } + else + { + // TODO + //throw new FileNotFoundException("Cannot find key metadata file " + getKeyMetaDataFileLocation()); + } } } @@ -1067,11 +1117,11 @@ public class AlfrescoKeyStoreImpl implements AlfrescoKeyStore this.keyProps.remove(keyAlias); } - protected KeyInformation loadKeyInformation(String keyAlias) + protected KeyInformation loadKeyInformation(Properties keyProps, String keyAlias, String prefix) { - String keyPassword = keyProps.getProperty(keyAlias + ".password"); - String keyData = keyProps.getProperty(keyAlias + ".keyData"); - String keyAlgorithm = keyProps.getProperty(keyAlias + ".algorithm"); + String keyPassword = keyProps.getProperty(prefix + keyAlias + ".password"); + String keyData = keyProps.getProperty(prefix + keyAlias + ".keyData"); + String keyAlgorithm = keyProps.getProperty(prefix + keyAlias + ".algorithm"); byte[] keyDataBytes = null; if(keyData != null && !keyData.equals("")) diff --git a/src/main/java/org/alfresco/encryption/KeyStoreParameters.java b/src/main/java/org/alfresco/encryption/KeyStoreParameters.java index 5b8ebe4504..d70a26e59d 100644 --- a/src/main/java/org/alfresco/encryption/KeyStoreParameters.java +++ b/src/main/java/org/alfresco/encryption/KeyStoreParameters.java @@ -22,12 +22,15 @@ import org.alfresco.util.PropertyCheck; /** * Stores Java keystore initialisation parameters. - * + * + * WARNING. Storing passwords (keyMetaDataFileLocation) on the file system is not following best security practices. + * * @since 4.0 * */ public class KeyStoreParameters { + private String id; private String name; private String type; private String provider; @@ -38,8 +41,40 @@ public class KeyStoreParameters { } - public KeyStoreParameters(String name, String type, String keyStoreProvider, + /** + * WARNING. Storing passwords (keyMetaDataFileLocation) on the file system is not following best security practices. + * + *

Set the unique ID of the keystore and aliases to use Java system properties lookup instead. The property lookup format is: + *

+ * + * Loading of keys info from system (JVM) properties takes precedence over metadata file. + * + * @param id unique identifier of the keystore + * @param name human readable name of the keystore + * @param type type of the keystore + * @param keyStoreProvider keystore provider + * @param keyMetaDataFileLocation path to keystore metadata file on the file system + * @param location path to keystore on the file system + */ + public KeyStoreParameters(String id, String name, String type, String keyStoreProvider, String keyMetaDataFileLocation, String location) + { + this(name, type, keyStoreProvider, keyMetaDataFileLocation, location); + this.id = id; + } + + /** + * Use {@link #KeyStoreParameters(String, String, String, String, String, String)} instead + */ + @Deprecated() + public KeyStoreParameters(String name, String type, String keyStoreProvider, + String keyMetaDataFileLocation, String location) { super(); this.name = name; @@ -49,8 +84,13 @@ public class KeyStoreParameters this.location = location; } + public void init() { + if (!PropertyCheck.isValidPropertyString(getId())) + { + setId(null); + } if (!PropertyCheck.isValidPropertyString(getLocation())) { setLocation(null); @@ -69,6 +109,11 @@ public class KeyStoreParameters } } + public String getId() + { + return id; + } + public String getName() { return name; @@ -93,7 +138,12 @@ public class KeyStoreParameters { return location; } - + + public void setId(String id) + { + this.id = id; + } + public void setName(String name) { this.name = name; diff --git a/src/test/java/org/alfresco/encryption/AlfrescoKeyStoreTest.java b/src/test/java/org/alfresco/encryption/AlfrescoKeyStoreTest.java new file mode 100644 index 0000000000..e0bd3fd214 --- /dev/null +++ b/src/test/java/org/alfresco/encryption/AlfrescoKeyStoreTest.java @@ -0,0 +1,388 @@ +/* + * Copyright (C) 2005-2020 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.encryption; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.alfresco.error.AlfrescoRuntimeException; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class AlfrescoKeyStoreTest +{ + @Mock + private EncryptionKeysRegistry encryptionKeysRegistry; + + @Rule + public TestName testName = new TestName(); + + @Test + public void testSysPropConfig() + { + String keyStoreId = testName.getMethodName() + "-keystore"; + String alias1 = "mykey1"; + String alias2 = "mykey2"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-2.jks"); + + System.setProperty(keyStoreId + "." + "password", "ksPwd2"); + System.setProperty(keyStoreId + "." + "aliases", alias1 + "," + alias2); + System.setProperty(keyStoreId + "." + alias1 + "." + "password", "aliasPwd1"); + System.setProperty(keyStoreId + "." + alias2 + "." + "password", "aliasPwd2"); + + try + { + AlfrescoKeyStore alfrescoKeyStore = new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + Set expectedAliases = new HashSet<>(); + expectedAliases.add(alias1); + expectedAliases.add(alias2); + Assert.assertEquals("The aliases are not correct", expectedAliases, alfrescoKeyStore.getKeyAliases()); + + Assert.assertNotNull("Failed to retrieve a key from keystore.", alfrescoKeyStore.getKey(alias1)); + Assert.assertNotNull("Failed to retrieve a key from keystore.", alfrescoKeyStore.getKey(alias2)); + } + finally + { + System.clearProperty(keyStoreId + "." + "password"); + System.clearProperty(keyStoreId + "." + "aliases"); + System.clearProperty(keyStoreId + "." + alias1 + "." + "password"); + System.clearProperty(keyStoreId + "." + alias2 + "." + "password"); + } + + } + + @Test + public void testSysPropConfigWithoutAliases() + { + String keyStoreId = testName.getMethodName() + "-keystore"; + String alias1 = "mykey1"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + + System.setProperty(keyStoreId + "." + "password", "ksPwd1"); + System.setProperty(keyStoreId + "." + alias1 + "." + "password", "aliasPwd1"); + try + { + AlfrescoKeyStore keyStore = new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + Assert.assertNull(keyStore.getKey(alias1)); + } + finally + { + System.clearProperty(keyStoreId + "." + "password"); + System.clearProperty(keyStoreId + "." + alias1 + "." + "password"); + } + } + + @Test + public void testMetaDataFileConfig() + { + String alias1 = "mykey1"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + keyStoreParameters.setKeyMetaDataFileLocation("classpath:keystore-tests/ks1-metadata.properties"); + + AlfrescoKeyStore alfrescoKeyStore = new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + Set expectedAliases = new HashSet<>(); + expectedAliases.add(alias1); + Assert.assertEquals("The aliases are not correct", expectedAliases, alfrescoKeyStore.getKeyAliases()); + + Assert.assertNotNull("Failed to retrieve a key from keystore.", alfrescoKeyStore.getKey(alias1)); + } + + /** + * Config via System props should be default, but if the metadata file location is set, it will be used instead. + * This is done to maintain backwards compatibility and simplify testing use cases. + */ + @Test(expected = AlfrescoRuntimeException.class) + public void testConfigBothSystemAndFile() + { + String keyStoreId = testName.getMethodName() + "-keystore"; + String alias1 = "mykey1"; + String alias2 = "mykey2"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-2.jks"); + // use metadata file from keystore with one key + keyStoreParameters.setKeyMetaDataFileLocation("classpath:keystore-tests/ks1-metadata.properties"); + + System.setProperty(keyStoreId + "." + "password", "ksPwd2"); + System.setProperty(keyStoreId + "." + "aliases", alias1 + "," + alias2); + System.setProperty(keyStoreId + "." + alias1 + "." + "password", "aliasPwd1"); + System.setProperty(keyStoreId + "." + alias2 + "." + "password", "aliasPwd2"); + + try + { + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + finally + { + System.clearProperty(keyStoreId + "." + "password"); + System.clearProperty(keyStoreId + "." + "aliases"); + System.clearProperty(keyStoreId + "." + alias1 + "." + "password"); + System.clearProperty(keyStoreId + "." + alias2 + "." + "password"); + } + + } + + @Test(expected = AlfrescoRuntimeException.class) + public void testValidateKeysWrongAliasMetadataFile() throws Exception + { + String alias1 = "mykey1"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + keyStoreParameters.setKeyMetaDataFileLocation("classpath:keystore-tests/wrong-alias-metadata.properties"); + + AlfrescoKeyStoreImpl alfrescoKeyStore = new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + alfrescoKeyStore.setKeysToValidate(Collections.singleton(alias1)); + alfrescoKeyStore.setValidateKeyChanges(true); + alfrescoKeyStore.setEncryptionKeysRegistry(encryptionKeysRegistry); + alfrescoKeyStore.validateKeys(); + } + + @Test + public void testEmptyKeysMetadataFile() + { + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + keyStoreParameters.setKeyMetaDataFileLocation("classpath:keystore-tests/empty-alias-metadata.properties"); + + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + + @Test(expected = AlfrescoRuntimeException.class) + public void testWrongKeystorePasswordMetadataFile() + { + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + keyStoreParameters.setKeyMetaDataFileLocation("classpath:keystore-tests/wrong-keystore-password-metadata.properties"); + + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + + @Test(expected = AlfrescoRuntimeException.class) + public void testWrongKeyPasswordMetadataFile() + { + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + keyStoreParameters.setKeyMetaDataFileLocation("classpath:keystore-tests/wrong-key-password-metadata.properties"); + + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + + @Test(expected = AlfrescoRuntimeException.class) + public void testValidateKeysWrongAliasSysProps() throws Exception + { + String keyStoreId = testName.getMethodName() + "-keystore"; + String alias1 = "mykey1"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + + System.setProperty(keyStoreId + "." + "aliases", "wrong-alias,another-wrong-alias"); + System.setProperty(keyStoreId + "." + "password", "ksPwd1"); + System.setProperty(keyStoreId + "." + alias1 + "." + "password", "aliasPwd1"); + + try + { + AlfrescoKeyStoreImpl alfrescoKeyStore = new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + alfrescoKeyStore.setValidateKeyChanges(true); + alfrescoKeyStore.setKeysToValidate(Collections.singleton(alias1)); + alfrescoKeyStore.setEncryptionKeysRegistry(encryptionKeysRegistry); + alfrescoKeyStore.validateKeys(); + } + finally + { + System.clearProperty(keyStoreId + "." + "aliases"); + System.clearProperty(keyStoreId + "." + "password"); + System.clearProperty(keyStoreId + "." + alias1 + "." + "password"); + } + } + + @Test + public void testEmptyKeysSysProps() + { + String keyStoreId = testName.getMethodName() + "-keystore"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + + System.setProperty(keyStoreId + "." + "aliases", "empty-alias,another-empty-alias"); + System.setProperty(keyStoreId + "." + "password", "ksPwd1"); + + try + { + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + finally + { + System.clearProperty(keyStoreId + "." + "aliases"); + System.clearProperty(keyStoreId + "." + "password"); + } + } + + @Test(expected = AlfrescoRuntimeException.class) + public void testWrongKeystorePasswordSysProps() + { + String keyStoreId = testName.getMethodName() + "-keystore"; + String alias1 = "mykey1"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + + System.setProperty(keyStoreId + "." + "aliases", alias1); + System.setProperty(keyStoreId + "." + "password", "wrong-password"); + System.setProperty(keyStoreId + "." + alias1 + "." + "password", "aliasPwd1"); + + try + { + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + finally + { + System.clearProperty(keyStoreId + "." + "aliases"); + System.clearProperty(keyStoreId + "." + "password"); + System.clearProperty(keyStoreId + "." + alias1 + "." + "password"); + } + } + + @Test(expected = AlfrescoRuntimeException.class) + public void testWrongKeyPasswordSysProps() + { + String keyStoreId = testName.getMethodName() + "-keystore"; + String alias1 = "mykey1"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + + System.setProperty(keyStoreId + "." + "aliases", alias1); + System.setProperty(keyStoreId + "." + "password", "ksPwd1"); + System.setProperty(keyStoreId + "." + alias1 + "." + "password", "wrong-key-password"); + + try + { + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + finally + { + System.clearProperty(keyStoreId + "." + "aliases"); + System.clearProperty(keyStoreId + "." + "password"); + System.clearProperty(keyStoreId + "." + alias1 + "." + "password"); + } + } + + /** + * No exception is expected. An empty keystore can be created. + */ + @Test + public void testConfigEmptyKeystore() + { + String keyStoreId = testName.getMethodName() + "-keystore"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:non-existing-path/some-keystore.jks"); + + new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + } + + @Test(expected = AlfrescoRuntimeException.class) + public void testValidateKeysEmptyAliasSysProps() throws Exception + { + String keyStoreId = testName.getMethodName() + "-keystore"; + + KeyStoreParameters keyStoreParameters = new KeyStoreParameters(); + keyStoreParameters.setId(keyStoreId); + keyStoreParameters.setName(testName.getMethodName()); + keyStoreParameters.setType("JCEKS"); + keyStoreParameters.setProvider("SunJCE"); + keyStoreParameters.setLocation("classpath:keystore-tests/ks-test-1.jks"); + + System.setProperty(keyStoreId + "." + "password", "ksPwd1"); + + try + { + AlfrescoKeyStoreImpl alfrescoKeyStore = new AlfrescoKeyStoreImpl(keyStoreParameters, new SpringKeyResourceLoader()); + alfrescoKeyStore.setValidateKeyChanges(true); + alfrescoKeyStore.setKeysToValidate(Collections.singleton("non-existing-alias")); + alfrescoKeyStore.setEncryptionKeysRegistry(encryptionKeysRegistry); + alfrescoKeyStore.validateKeys(); + } + finally + { + System.clearProperty(keyStoreId + "." + "password"); + } + } +} diff --git a/src/test/resources/keystore-tests/empty-alias-metadata.properties b/src/test/resources/keystore-tests/empty-alias-metadata.properties new file mode 100644 index 0000000000..626fb1266b --- /dev/null +++ b/src/test/resources/keystore-tests/empty-alias-metadata.properties @@ -0,0 +1,2 @@ +aliases=empty-alias +keystore.password=ksPwd1 diff --git a/src/test/resources/keystore-tests/ks-test-1.jks b/src/test/resources/keystore-tests/ks-test-1.jks new file mode 100644 index 0000000000..01bd383454 Binary files /dev/null and b/src/test/resources/keystore-tests/ks-test-1.jks differ diff --git a/src/test/resources/keystore-tests/ks-test-2.jks b/src/test/resources/keystore-tests/ks-test-2.jks new file mode 100644 index 0000000000..3723222500 Binary files /dev/null and b/src/test/resources/keystore-tests/ks-test-2.jks differ diff --git a/src/test/resources/keystore-tests/ks1-metadata.properties b/src/test/resources/keystore-tests/ks1-metadata.properties new file mode 100644 index 0000000000..d21236fb6f --- /dev/null +++ b/src/test/resources/keystore-tests/ks1-metadata.properties @@ -0,0 +1,3 @@ +aliases=mykey1 +keystore.password=ksPwd1 +mykey1.password=aliasPwd1 \ No newline at end of file diff --git a/src/test/resources/keystore-tests/passwords.txt b/src/test/resources/keystore-tests/passwords.txt new file mode 100644 index 0000000000..f48d2729c1 --- /dev/null +++ b/src/test/resources/keystore-tests/passwords.txt @@ -0,0 +1,24 @@ +The keystores contained in this folder are used by tests. + +================== +== ks-test-1.ks == +================== + +Keystore password: ksPwd1 +Keystore type: JCEKS +Keystore provider: SunJCE + +Your keystore contains 1 entry +mykey1: aliasPwd1 + +================== +== ks-test-2.ks == +================== + +Keystore password: ksPwd2 +Keystore type: JCEKS +Keystore provider: SunJCE + +Your keystore contains 2 entries +mykey1: aliasPwd1 +mykey2: aliasPwd2 diff --git a/src/test/resources/keystore-tests/wrong-alias-metadata.properties b/src/test/resources/keystore-tests/wrong-alias-metadata.properties new file mode 100644 index 0000000000..e3616f1cb3 --- /dev/null +++ b/src/test/resources/keystore-tests/wrong-alias-metadata.properties @@ -0,0 +1,3 @@ +aliases=non-existing-alias +keystore.password=ksPwd1 +mykey1.password=aliasPwd1 \ No newline at end of file diff --git a/src/test/resources/keystore-tests/wrong-key-password-metadata.properties b/src/test/resources/keystore-tests/wrong-key-password-metadata.properties new file mode 100644 index 0000000000..ae8ff14924 --- /dev/null +++ b/src/test/resources/keystore-tests/wrong-key-password-metadata.properties @@ -0,0 +1,3 @@ +aliases=mykey1 +keystore.password=ksPwd1 +mykey1.password=wrong-key-password \ No newline at end of file diff --git a/src/test/resources/keystore-tests/wrong-keystore-password-metadata.properties b/src/test/resources/keystore-tests/wrong-keystore-password-metadata.properties new file mode 100644 index 0000000000..c2f92dffbe --- /dev/null +++ b/src/test/resources/keystore-tests/wrong-keystore-password-metadata.properties @@ -0,0 +1,3 @@ +aliases=mykey1 +keystore.password=wrong-password +mykey1.password=aliasPwd1 \ No newline at end of file