From de6fbae0bd1d7ab1e22cbe644dca5e7a5929deb8 Mon Sep 17 00:00:00 2001 From: Steven Glover Date: Tue, 19 Jul 2011 11:28:57 +0000 Subject: [PATCH] Initial checkin for ALF-8702: "RSOLR 026: Alfresco to SOLR communication and configuration" Initial checkin for ALF-8791: "RSOLR 036: Update IndexChecker to support SOLR" git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29179 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/.keystore | Bin 645 -> 1254 bytes config/alfresco/encryption-context.xml | 24 +- config/alfresco/repository.properties | 10 + .../node/encryption/MetadataEncryptor.java | 4 +- .../encryption/AbstractEncryptor.java | 232 ----------------- .../encryption/AbstractKeyProvider.java | 17 -- .../security/encryption/DefaultEncryptor.java | 75 ------ .../repo/security/encryption/Encryptor.java | 93 ------- .../security/encryption/EncryptorTest.java | 71 ----- .../repo/security/encryption/KeyProvider.java | 29 --- .../encryption/KeyStoreKeyProviderTest.java | 164 ------------ .../encryption/KeystoreKeyProvider.java | 246 ------------------ 12 files changed, 32 insertions(+), 933 deletions(-) delete mode 100644 source/java/org/alfresco/repo/security/encryption/AbstractEncryptor.java delete mode 100644 source/java/org/alfresco/repo/security/encryption/AbstractKeyProvider.java delete mode 100644 source/java/org/alfresco/repo/security/encryption/DefaultEncryptor.java delete mode 100644 source/java/org/alfresco/repo/security/encryption/Encryptor.java delete mode 100644 source/java/org/alfresco/repo/security/encryption/EncryptorTest.java delete mode 100644 source/java/org/alfresco/repo/security/encryption/KeyProvider.java delete mode 100644 source/java/org/alfresco/repo/security/encryption/KeyStoreKeyProviderTest.java delete mode 100644 source/java/org/alfresco/repo/security/encryption/KeystoreKeyProvider.java diff --git a/config/alfresco/.keystore b/config/alfresco/.keystore index 22d2b69a4125591ab9a9a64175644d3e129e81d7..7e966eebae5433614e59d7d350981be1add2c621 100644 GIT binary patch delta 380 zcmV-?0fYX91?CA1&d$!x0000200002u?%Gb5&!@I0{{ebZ)|b^00A)xpgvQPBItiU z`gz-`!ar~V0Tgv{0Db@k0003XM;|C_?r2@*fdH%{|GSD{%jSSUD}~ukkT>y9EwQ~L zIQ^G$tz+@bJo1nV_*qq;&yhey|M1 zX&PXoj4SG#gDV8qBj4wqwM_9A&m|q=Mz!d%K&3rn9sakqT$6(WP@HL}whA|(mJj=9QT>oTxwuBQR6T?DzX9lwlBbdiA_VHg2T8d(RTQVYs?3u= a0x}e_lt#oHhZsNCVyf39Ep}9?C1Nos%CP(Z delta 42 vcmaFH*~-du4hR?+7?^;VaU)MElgRGiytqd04I9_@cS*41?tL=(qXQ=ZGU^Y1 diff --git a/config/alfresco/encryption-context.xml b/config/alfresco/encryption-context.xml index 3c2e93cd09..1821136c03 100644 --- a/config/alfresco/encryption-context.xml +++ b/config/alfresco/encryption-context.xml @@ -9,9 +9,13 @@ http://code.google.com/p/spring-crypto-utils/schema/crypt http://code.google.com/p/spring-crypto-utils/schema/crypt.xsd"> + + + - + + @@ -22,10 +26,22 @@ - - + + - + + + + + + + + + + + + + diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index 11c6b85298..a4c848e585 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -658,6 +658,7 @@ deployment.filesystem.default.metadatadir=${deployment.filesystem.metadatadir}/d # encryption.encryption.cipherAlgorithm=DESede/CBC/PKCS5Padding encryption.keystore.location=classpath:alfresco/.keystore +encryption.keystore.passwordsFile.location= encryption.keystore.provider= encryption.keystore.type=JCEKS # The password protecting the keystore entries @@ -666,6 +667,15 @@ encryption.keystore.password=mp6yc0UD9e encryption.keystore.password.metadata=oKIWzVdEdA # The password protecting the alias: solr encryption.keystore.password.solr=TxHTtOnrwQ +encryption.messageTimeout=30000 +encryption.macAlgorithm=HmacSHA1 + +# SOLR connection details +solr.solrHost=localhost +solr.solrUrl=http://${solr.solrHost}:8080/solr +solr.solrUser=solr +solr.solrPassword=solr +solr.secureComms.enabled=true # # Web Publishing Properties diff --git a/source/java/org/alfresco/repo/node/encryption/MetadataEncryptor.java b/source/java/org/alfresco/repo/node/encryption/MetadataEncryptor.java index f40623968e..911e045ace 100644 --- a/source/java/org/alfresco/repo/node/encryption/MetadataEncryptor.java +++ b/source/java/org/alfresco/repo/node/encryption/MetadataEncryptor.java @@ -8,10 +8,10 @@ import java.util.Set; import javax.crypto.SealedObject; +import org.alfresco.encryption.Encryptor; +import org.alfresco.encryption.KeyProvider; import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.encryption.Encryptor; -import org.alfresco.repo.security.encryption.KeyProvider; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.dictionary.PropertyDefinition; diff --git a/source/java/org/alfresco/repo/security/encryption/AbstractEncryptor.java b/source/java/org/alfresco/repo/security/encryption/AbstractEncryptor.java deleted file mode 100644 index afe45ab5a5..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/AbstractEncryptor.java +++ /dev/null @@ -1,232 +0,0 @@ -package org.alfresco.repo.security.encryption; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.security.AlgorithmParameters; -import java.security.Key; - -import javax.crypto.Cipher; -import javax.crypto.SealedObject; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.util.Pair; -import org.alfresco.util.PropertyCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Basic support for encryption engines. - * - * @since 4.0 - */ -public abstract class AbstractEncryptor implements Encryptor -{ - private static final Log logger = LogFactory.getLog(AbstractEncryptor.class); - - private KeyProvider keyProvider; - - /** - * Constructs with defaults - */ - protected AbstractEncryptor() - { - } - - /** - * @param keyProvider provides encryption keys based on aliases - */ - public void setKeyProvider(KeyProvider keyProvider) - { - this.keyProvider = keyProvider; - } - - public void init() - { - PropertyCheck.mandatory(this, "keyProvider", keyProvider); - } - - @Override - public Cipher getCipher(String keyAlias, AlgorithmParameters params, int mode) - { - // Get the encryption key - Key key = keyProvider.getKey(keyAlias); - if (key == null) - { - // No encryption possible - return null; - } - try - { - Cipher cipher = getCipher(key, params, mode); - // Done - if (logger.isDebugEnabled()) - { - logger.debug("Cipher constructed: alias=" + keyAlias + "; mode=" + mode + ": " + cipher); - } - return cipher; - } - catch (Exception e) - { - throw new AlfrescoRuntimeException( - "Failed to construct cipher: alias=" + keyAlias + "; mode=" + mode, - e); - } - } - - /** - * Factory method to be written by implementations to construct and initialize - * physical ciphering objects. - * - * @param keyAlias the key alias - * @param params algorithm-specific parameters - * @param mode the cipher mode - * @return - */ - protected abstract Cipher getCipher(Key key, AlgorithmParameters params, int mode) throws Exception; - - /** - * {@inheritDoc} - */ - @Override - public Pair encrypt(String keyAlias, AlgorithmParameters params, byte[] input) - { - Cipher cipher = getCipher(keyAlias, params, Cipher.ENCRYPT_MODE); - if (cipher == null) - { - return new Pair(input, null); - } - try - { - byte[] output = cipher.doFinal(input); - params = cipher.getParameters(); - return new Pair(output, params); - } - catch (Throwable e) - { - throw new AlfrescoRuntimeException("Decryption failed for key alias: " + keyAlias, e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public byte[] decrypt(String keyAlias, AlgorithmParameters params, byte[] input) - { - Cipher cipher = getCipher(keyAlias, params, Cipher.DECRYPT_MODE); - if (cipher == null) - { - return input; - } - try - { - return cipher.doFinal(input); - } - catch (Throwable e) - { - throw new AlfrescoRuntimeException("Decryption failed for key alias: " + keyAlias, e); - } - } - - /** - * {@inheritDoc} - *

- * Serializes and {@link #encrypt(byte[]) encrypts} the input data. - */ - @Override - public Pair encryptObject(String keyAlias, AlgorithmParameters params, Object input) - { - try - { - ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(input); - byte[] unencrypted = bos.toByteArray(); - return encrypt(keyAlias, params, unencrypted); - } - catch (Exception e) - { - throw new AlfrescoRuntimeException("Failed to serialize or encrypt object", e); - } - } - - /** - * {@inheritDoc} - *

- * {@link #decrypt(byte[]) Decrypts} and deserializes the input data - */ - @Override - public Object decryptObject(String keyAlias, AlgorithmParameters params, byte[] input) - { - try - { - byte[] unencrypted = decrypt(keyAlias, params, input); - ByteArrayInputStream bis = new ByteArrayInputStream(unencrypted); - ObjectInputStream ois = new ObjectInputStream(bis); - Object obj = ois.readObject(); - return obj; - } - catch (Exception e) - { - throw new AlfrescoRuntimeException("Failed to deserialize or decrypt object", e); - } - } - - @Override - public Serializable sealObject(String keyAlias, AlgorithmParameters params, Serializable input) - { - if (input == null) - { - return null; - } - Cipher cipher = getCipher(keyAlias, params, Cipher.ENCRYPT_MODE); - if (cipher == null) - { - return input; - } - try - { - return new SealedObject(input, cipher); - } - catch (Exception e) - { - throw new AlfrescoRuntimeException("Failed to seal object", e); - } - } - - @Override - public Serializable unsealObject(String keyAlias, Serializable input) - { - if (input == null) - { - return input; - } - // Don't unseal it if it is not sealed - if (!(input instanceof SealedObject)) - { - return input; - } - // Get the Key, rather than a Cipher - Key key = keyProvider.getKey(keyAlias); - if (key == null) - { - // The client will be expecting to unseal the object - throw new IllegalStateException("No key matching " + keyAlias + ". Cannot unseal object."); - } - // Unseal it using the key - SealedObject sealedInput = (SealedObject) input; - try - { - Serializable output = (Serializable) sealedInput.getObject(key); - // Done - return output; - } - catch (Exception e) - { - throw new AlfrescoRuntimeException("Failed to unseal object", e); - } - } -} diff --git a/source/java/org/alfresco/repo/security/encryption/AbstractKeyProvider.java b/source/java/org/alfresco/repo/security/encryption/AbstractKeyProvider.java deleted file mode 100644 index 51ea70d58f..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/AbstractKeyProvider.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.alfresco.repo.security.encryption; - -/** - * Basic support for key providers - *

- * TODO: This class will provide the alias name mapping so that use-cases can be mapped - * to different alias names in the keystore. - * - * @author Derek Hulley - * @since 4.0 - */ -public abstract class AbstractKeyProvider implements KeyProvider -{ - /* - * Not a useless class. - */ -} diff --git a/source/java/org/alfresco/repo/security/encryption/DefaultEncryptor.java b/source/java/org/alfresco/repo/security/encryption/DefaultEncryptor.java deleted file mode 100644 index a59414844a..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/DefaultEncryptor.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.alfresco.repo.security.encryption; - -import java.security.AlgorithmParameters; -import java.security.Key; - -import javax.crypto.Cipher; - -import org.alfresco.util.PropertyCheck; - -/** - * @author Derek Hulley - * @since 4.0 - */ -public class DefaultEncryptor extends AbstractEncryptor -{ - private String cipherAlgorithm; - private String cipherProvider; - - private final ThreadLocal threadCipher; - - /** - * Default constructor for IOC - */ - public DefaultEncryptor() - { - threadCipher = new ThreadLocal(); - } - - /** - * Convenience constructor for tests - */ - /* package */ DefaultEncryptor(KeyProvider keyProvider, String cipherAlgorithm, String cipherProvider) - { - this(); - setKeyProvider(keyProvider); - setCipherAlgorithm(cipherAlgorithm); - setCipherProvider(cipherProvider); - } - - public void setCipherAlgorithm(String cipherAlgorithm) - { - this.cipherAlgorithm = cipherAlgorithm; - } - - public void setCipherProvider(String cipherProvider) - { - this.cipherProvider = cipherProvider; - } - - public void init() - { - super.init(); - PropertyCheck.mandatory(this, "cipherAlgorithm", cipherAlgorithm); - } - - @Override - protected Cipher getCipher(Key key, AlgorithmParameters params, int mode) throws Exception - { - Cipher cipher = threadCipher.get(); - if (cipher == null) - { - if (cipherProvider == null) - { - cipher = Cipher.getInstance(cipherAlgorithm); - } - else - { - cipher = Cipher.getInstance(cipherAlgorithm, cipherProvider); - } - threadCipher.set(cipher); - } - cipher.init(mode, key, params); - return cipher; - } -} diff --git a/source/java/org/alfresco/repo/security/encryption/Encryptor.java b/source/java/org/alfresco/repo/security/encryption/Encryptor.java deleted file mode 100644 index 89e8ed1c20..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/Encryptor.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.alfresco.repo.security.encryption; - -import java.io.Serializable; -import java.security.AlgorithmParameters; - -import javax.crypto.Cipher; - -import org.alfresco.util.Pair; - - -/** - * Interface providing methods to encrypt and decrypt data. - * - * @since 4.0 - */ -public interface Encryptor -{ - /** - * Get the basic cipher that must be used for the given use-case - * - * @param keyAlias the encryption key alias - * @param params the parameters for the encryption or decryption - * @param mode the encryption mode - * @return the cipher to use or null if there is no - * key associated with the key alias - */ - Cipher getCipher(String keyAlias, AlgorithmParameters params, int mode); - - /** - * Encrypt some bytes - * - * @param keyAlias the encryption key alias - * @param input the data to encrypt - * @return the encrypted data and parameters used - */ - Pair encrypt(String keyAlias, AlgorithmParameters params, byte[] input); - - /** - * Decrypt some bytes - * - * @param keyAlias the encryption key alias - * @param input the data to decrypt - * @return the unencrypted data - */ - byte[] decrypt(String keyAlias, AlgorithmParameters params, byte[] input); - - /** - * Encrypt an object - * - * @param keyAlias the encryption key alias - * @param input the object to write to bytes - * @return the encrypted data and parameters used - */ - Pair encryptObject(String keyAlias, AlgorithmParameters params, Object input); - - /** - * Decrypt data as an object - * - * @param keyAlias the encryption key alias - * @param input the data to decrypt - * @return the unencrypted data deserialized - */ - Object decryptObject(String keyAlias, AlgorithmParameters params, byte[] input); - - /** - * Convenience method to seal on object up cryptographically. - *

- * Note that the original object may be returned directly if there is no key associated with - * the alias. - * - * @param keyAlias the encryption key alias - * @param input the object to encrypt and seal - * @return the sealed object that can be decrypted with the original key - */ - Serializable sealObject(String keyAlias, AlgorithmParameters params, Serializable input); - - /** - * Convenience method to unseal on object sealed up cryptographically. - *

- * Note that the algorithm parameters not provided on the assumption that a symmetric key - * algorithm is in use - only the key is required for unsealing. - *

- * Note that the original object may be returned directly if there is no key associated with - * the alias or if the input object is not a SealedObject. - * - * @param keyAlias the encryption key alias - * @param input the object to decrypt and unseal - * @return the original unsealed object that was encrypted with the original key - * @throws IllegalStateException if the key alias is not valid and the input is a - * SealedObject - */ - Serializable unsealObject(String keyAlias, Serializable input); -} diff --git a/source/java/org/alfresco/repo/security/encryption/EncryptorTest.java b/source/java/org/alfresco/repo/security/encryption/EncryptorTest.java deleted file mode 100644 index 9b254064eb..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/EncryptorTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.alfresco.repo.security.encryption; - -import java.io.Serializable; -import java.security.AlgorithmParameters; - -import junit.framework.TestCase; - -import org.alfresco.util.Pair; -import org.bouncycastle.util.Arrays; - -/** - * @since 4.0 - */ -public class EncryptorTest extends TestCase -{ - private DefaultEncryptor encryptor; - - public void setUp() throws Exception - { - encryptor = new DefaultEncryptor( - KeyStoreKeyProviderTest.getTestKeyStoreProvider(), - "DESede/CBC/PKCS5Padding", - null); - encryptor.init(); // Not currently necessary - } - - public void testBasicBytes_NoKey() - { - byte[] bytes = new byte[] {11, 12, 13}; - - Pair encryptedPair = encryptor.encrypt("fluff", null, bytes); - byte[] decrypted = encryptor.decrypt( - "fluff", - encryptedPair.getSecond(), - encryptedPair.getFirst()); - assertTrue("Encryption round trip failed. ", Arrays.areEqual(bytes, decrypted)); - } - - public void testBasicBytes_WithKey() - { - byte[] bytes = new byte[] {11, 12, 13}; - - Pair encryptedPair = encryptor.encrypt("mykey1", null, bytes); - byte[] decrypted = encryptor.decrypt( - "mykey1", - encryptedPair.getSecond(), - encryptedPair.getFirst()); - assertTrue("Encryption round trip failed. ", Arrays.areEqual(bytes, decrypted)); - } - - public void testBasicObject() - { - Object testObject = " This is a string, but will be serialized "; - - Pair encryptedPair = encryptor.encryptObject("mykey2", null, testObject); - Object output = encryptor.decryptObject( - "mykey2", - encryptedPair.getSecond(), - encryptedPair.getFirst()); - assertEquals("Encryption round trip failed. ", testObject, output); - } - - public void testSealedObject() - { - Serializable testObject = " This is a string, but will be serialized "; - - Serializable sealedObject = encryptor.sealObject("mykey2", null, testObject); - Object output = encryptor.unsealObject("mykey2", sealedObject); - assertEquals("Encryption round trip failed. ", testObject, output); - } -} diff --git a/source/java/org/alfresco/repo/security/encryption/KeyProvider.java b/source/java/org/alfresco/repo/security/encryption/KeyProvider.java deleted file mode 100644 index 282836a3b1..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/KeyProvider.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.alfresco.repo.security.encryption; - -import java.security.Key; - -/** - * A key provider returns the secret keys for different use cases. - * - * @since 4.0 - */ -public interface KeyProvider -{ - // TODO: Allow the aliases to be configured i.e. include an alias mapper - /** - * Constant representing the keystore alias for keys to encrypt/decrype node metadata - */ - public static final String ALIAS_METADATA = "metadata"; - /** - * Constant representing the keystore alias for keys to encrypt/decrype SOLR transfer data - */ - public static final String ALIAS_SOLR = "solr"; - - /** - * Get an encryption key if available. - * - * @param keyAlias the key alias - * @return the encryption key or null if there is no associated key - */ - public Key getKey(String keyAlias); -} diff --git a/source/java/org/alfresco/repo/security/encryption/KeyStoreKeyProviderTest.java b/source/java/org/alfresco/repo/security/encryption/KeyStoreKeyProviderTest.java deleted file mode 100644 index d72d3119df..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/KeyStoreKeyProviderTest.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.alfresco.repo.security.encryption; - -import java.security.Key; -import java.security.KeyStore; -import java.security.UnrecoverableKeyException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.util.ApplicationContextHelper; -import org.springframework.context.ApplicationContext; - -import junit.framework.TestCase; - -/** - * Tests {@link KeystoreKeyProvider} - * - * @author Derek Hulley - * @since 4.0 - */ -public class KeyStoreKeyProviderTest extends TestCase -{ - private static final String FILE_ONE = "classpath:alfresco/keystore-tests/ks-test-1.jks"; - private static final String FILE_TWO = "classpath:alfresco/keystore-tests/ks-test-2.jks"; - private static final String FILE_THREE = "classpath:alfresco/keystore-tests/ks-test-3.jks"; - private static final String ALIAS_ONE = "mykey1"; - private static final String ALIAS_TWO = "mykey2"; - private static final String ALIAS_THREE = "mykey3"; - - /** - * Helper utility to create a two-alias keystore. - *

- * TODO: Allow the required aliases and key types to be specified and generate - * a keystore on the fly - */ - /* package */ static KeystoreKeyProvider getTestKeyStoreProvider() - { - Map passwords = new HashMap(5); - passwords.put(KeystoreKeyProvider.KEY_KEYSTORE_PASSWORD, "ksPwd2"); - passwords.put(ALIAS_ONE, "aliasPwd1"); - passwords.put(ALIAS_TWO, "aliasPwd2"); - KeystoreKeyProvider ks = new KeystoreKeyProvider( - FILE_TWO, - "SunJCE", - "JCEKS", - passwords); - return ks; - } - - public void setUp() throws Exception - { - } - - public void testNoKeyStorePasswords() throws Exception - { - KeystoreKeyProvider keyProvider = new KeystoreKeyProvider( - FILE_ONE, - "SunJCE", - "JCEKS", - Collections.emptyMap()); - // This has succeeded because we have not attempted to access it - assertNull("Should be no keys available", keyProvider.getKey(ALIAS_ONE)); - } - - public void testKeyStoreWithOnlyAliasPasswords() throws Exception - { - KeystoreKeyProvider keyProvider = new KeystoreKeyProvider( - FILE_TWO, - "SunJCE", - "JCEKS", - Collections.singletonMap(ALIAS_ONE, "aliasPwd1")); - // This has succeeded because we have not attempted to access it - assertNotNull("Should be able to key alias with same password", keyProvider.getKey(ALIAS_ONE)); - } - - public void testAliasWithIncorrectPassword_One() throws Exception - { - try - { - new KeystoreKeyProvider( - FILE_ONE, - "SunJCE", - "JCEKS", - Collections.singletonMap(ALIAS_ONE, "password_fail")); - fail("Expect to fail because password is incorrect"); - } - catch (AlfrescoRuntimeException e) - { - // Expected - assertTrue(e.getCause() instanceof UnrecoverableKeyException); - } - } - - public void testAliasWithIncorrectPassword_Two() throws Exception - { - try - { - new KeystoreKeyProvider( - FILE_TWO, - "SunJCE", - "JCEKS", - Collections.singletonMap(ALIAS_TWO, "password_fail")); - fail("Expect to fail because password is incorrect"); - } - catch (AlfrescoRuntimeException e) - { - // Expected - assertTrue(e.getCause() instanceof UnrecoverableKeyException); - } - } - - public void testAliasWithCorrectPassword_One() throws Exception - { - KeystoreKeyProvider ks = new KeystoreKeyProvider( - FILE_ONE, - "SunJCE", - "JCEKS", - Collections.singletonMap(ALIAS_ONE, "aliasPwd1")); - Key keyOne = ks.getKey(ALIAS_ONE); - assertNotNull(keyOne); - } - - public void testAliasWithCorrectPassword_Two() throws Exception - { - Map passwords = new HashMap(5); - passwords.put(ALIAS_ONE, "aliasPwd1"); - passwords.put(ALIAS_TWO, "aliasPwd2"); - KeystoreKeyProvider ks = new KeystoreKeyProvider( - FILE_TWO, - "SunJCE", - "JCEKS", - passwords); - assertNotNull(ks.getKey(ALIAS_ONE)); - assertNotNull(ks.getKey(ALIAS_TWO)); - } - - public void testAliasWithCorrectPassword_Three() throws Exception - { - Map passwords = new HashMap(5); - passwords.put(ALIAS_ONE, "aliasPwd1"); - passwords.put(ALIAS_TWO, "aliasPwd2"); - passwords.put(ALIAS_THREE, "aliasPwd3"); - KeystoreKeyProvider ks = new KeystoreKeyProvider( - FILE_THREE, - "SunJCE", - "JCEKS", - passwords); - assertNotNull(ks.getKey(ALIAS_ONE)); - assertNotNull(ks.getKey(ALIAS_TWO)); - assertNull(ks.getKey(ALIAS_THREE)); - } - - /** - * TODO: Do we need spring-crypto when it is V1.0? - */ - public void DISABLED_testSpringCrypto() throws Throwable - { - ApplicationContext ctx = ApplicationContextHelper.getApplicationContext( - new String[] {"alfresco/keystore-tests/encryption-test-context.xml"}); - @SuppressWarnings("unused") - KeyStore ks1 = (KeyStore) ctx.getBean("ks-test-1"); - } -} diff --git a/source/java/org/alfresco/repo/security/encryption/KeystoreKeyProvider.java b/source/java/org/alfresco/repo/security/encryption/KeystoreKeyProvider.java deleted file mode 100644 index 00848060f8..0000000000 --- a/source/java/org/alfresco/repo/security/encryption/KeystoreKeyProvider.java +++ /dev/null @@ -1,246 +0,0 @@ -package org.alfresco.repo.security.encryption; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.Key; -import java.security.KeyStore; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; -import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.util.PropertyCheck; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.util.ResourceUtils; - -/** - * - * Provides the system-wide secret key for symmetric database encryption from a key store - * in the filesystem. - * - * @author Derek Hulley - * @since 4.0 - */ -public class KeystoreKeyProvider extends AbstractKeyProvider -{ - public static final String KEY_KEYSTORE_PASSWORD = "keystore"; - - private static final Log logger = LogFactory.getLog(KeyProvider.class); - - // Will be cleared after initialization - private Map passwords; - private String location; - private String provider; - private String type; - private Map keys; - - private final ReadLock readLock; - private final WriteLock writeLock; - - /** - * Constructs the provider with required defaults - */ - public KeystoreKeyProvider() - { - ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - readLock = lock.readLock(); - writeLock = lock.writeLock(); - keys = new HashMap(7); - } - - /** - * Convenience constructor for tests. Note that {@link #init()} is also called. - */ - /* package */ KeystoreKeyProvider(String location, String provider, String type, Map passwords) - { - this(); - setLocation(location); - setProvider(provider); - setType(type); - setPasswords(passwords); - init(); - } - - public void setLocation(String location) - { - this.location = location; - } - - public void setProvider(String provider) - { - this.provider = provider; - } - - public void setType(String type) - { - this.type = type; - } - - /** - * Set the map of passwords to access the keystore. - *

- * 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. - * - * @param passwords a map of passwords including null values - */ - public void setPasswords(Map passwords) - { - this.passwords = new HashMap(passwords); - } - - public void init() - { - writeLock.lock(); - try - { - safeInit(); - } - finally - { - writeLock.unlock(); - } - } - - /** - * Initializes class; must be done in a write lock. - */ - private void safeInit() - { - if (!PropertyCheck.isValidPropertyString(location)) - { - location = null; - } - if (!PropertyCheck.isValidPropertyString(provider)) - { - provider = null; - } - if (!PropertyCheck.isValidPropertyString(type)) - { - type = null; - } - - PropertyCheck.mandatory(this, "location", location); - // Extract the keystore password - String pwdKeyStore = passwords.get(KEY_KEYSTORE_PASSWORD); - - // Make sure we choose the default type, if required - if (type == null) - { - type = KeyStore.getDefaultType(); - } - - KeyStore ks = null; - InputStream is = null; - try - { - if (provider == null) - { - ks = KeyStore.getInstance(type); - } - else - { - ks = KeyStore.getInstance(type, provider); - } - // Load it up - File ksFile = ResourceUtils.getFile(location); - if (!ksFile.exists()) - { - throw new IOException("Unable to find keystore file: " + ksFile); - } - is = new FileInputStream(ksFile); - ks.load(is, pwdKeyStore == null ? null : pwdKeyStore.toCharArray()); - // Loaded - if (logger.isDebugEnabled()) - { - logger.debug( - "Initialize keystore provider: \n" + - " Location: " + location + "\n" + - " Provider: " + provider + "\n" + - " Type: " + type); - } - } - catch (Throwable e) - { - throw new AlfrescoRuntimeException( - "Failed to initialize keystore provider: \n" + - " Location: " + location + "\n" + - " Provider: " + provider + "\n" + - " Type: " + type, - e); - } - finally - { - pwdKeyStore = null; - passwords.remove(KEY_KEYSTORE_PASSWORD); - if (is != null) - { - try { is.close(); } catch (Throwable e) {} - } - } - - // Now get the other keys - for (Map.Entry element : passwords.entrySet()) - { - String keyAlias = element.getKey(); - String passwordStr = element.getValue(); - if (!PropertyCheck.isValidPropertyString(passwordStr)) - { - // Force a failure because the property was not properly initialized - PropertyCheck.mandatory(this, "passwords." + keyAlias, null); - } - // Null is an acceptable value (means no key) - Key key = null; - // Attempt to key the key - try - { - key = ks.getKey(keyAlias, passwordStr == null ? null : passwordStr.toCharArray()); - keys.put(keyAlias, key); - // Key loaded - if (logger.isDebugEnabled()) - { - logger.debug( - "Retrieved key from keystore: \n" + - " Location: " + location + "\n" + - " Provider: " + provider + "\n" + - " Type: " + type + "\n" + - " Alias: " + keyAlias + "\n" + - " Password?: " + (passwordStr != null)); - } - } - catch (Throwable e) - { - throw new AlfrescoRuntimeException( - "Failed to retrieve key from keystore: \n" + - " Location: " + location + "\n" + - " Provider: " + provider + "\n" + - " Type: " + type + "\n" + - " Alias: " + keyAlias + "\n" + - " Password?: " + (passwordStr != null), - e); - } - } - // Clear passwords - passwords.clear(); - } - - @Override - public Key getKey(String keyAlias) - { - readLock.lock(); - try - { - return keys.get(keyAlias); - } - finally - { - readLock.unlock(); - } - } -}