From cfabcb18e3420dd71c6a11878e4f7dfb3982b388 Mon Sep 17 00:00:00 2001 From: Steven Glover Date: Fri, 26 Aug 2011 16:15:48 +0000 Subject: [PATCH] ALF-9510: wip. Further code changes. Plus, some code tidy up, comments. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30111 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/encryption-context.xml | 35 ++- config/alfresco/node-services-context.xml | 5 +- config/alfresco/repository.properties | 19 +- .../encryption/BootstrapReEncryptor.java | 6 +- .../alfresco/encryption/EncryptionTests.java | 8 +- .../org/alfresco/encryption/ReEncryptor.java | 204 ++++++++++++------ .../search/impl/solr/SolrQueryHTTPClient.java | 1 + 7 files changed, 187 insertions(+), 91 deletions(-) diff --git a/config/alfresco/encryption-context.xml b/config/alfresco/encryption-context.xml index 57d675a510..b05dccd1bb 100644 --- a/config/alfresco/encryption-context.xml +++ b/config/alfresco/encryption-context.xml @@ -45,7 +45,16 @@ - + + + + + + + + + + @@ -53,20 +62,36 @@ - - + + + + + + + + + + + + + + + + - + + + + - diff --git a/config/alfresco/node-services-context.xml b/config/alfresco/node-services-context.xml index dd23433008..33361054f9 100644 --- a/config/alfresco/node-services-context.xml +++ b/config/alfresco/node-services-context.xml @@ -243,10 +243,11 @@ - + - + + diff --git a/config/alfresco/repository.properties b/config/alfresco/repository.properties index 5827192643..fa65081396 100644 --- a/config/alfresco/repository.properties +++ b/config/alfresco/repository.properties @@ -680,10 +680,10 @@ deployment.filesystem.default.metadatadir=${deployment.filesystem.metadatadir}/d # # Encryption properties # -#dir.keystore=${dir.root}/keystore # default keystores location dir.keystore=classpath:alfresco/keystore +# general encryption parameters encryption.keySpec.class=org.alfresco.encryption.DESEDEKeyGenerator encryption.keyAlgorithm=DESede encryption.cipherAlgorithm=DESede/CBC/PKCS5Padding @@ -694,11 +694,11 @@ encryption.keystore.keyMetaData.location=${dir.keystore}/keystore-passwords.prop encryption.keystore.provider= encryption.keystore.type=JCEKS -# backup keystore (if configured) -encryption.keystore.backup.location= -encryption.keystore.backup.keyMetaData.location= +# backup secret key keystore configuration +encryption.keystore.backup.location=${dir.keystore}/backup-keystore +encryption.keystore.backup.keyMetaData.location=${dir.keystore}/backup-keystore-passwords.properties encryption.keystore.backup.provider= -encryption.keystore.backup.type= +encryption.keystore.backup.type=JCEKS # Should encryptable properties be re-encrypted with new encryption keys on botstrap? encryption.bootstrap.reencrypt=false @@ -707,7 +707,7 @@ encryption.bootstrap.reencrypt=false encryption.mac.messageTimeout=30000 encryption.mac.algorithm=HmacSHA1 -# ssl +# ssl encryption encryption.ssl.keystore.location=${dir.keystore}/ssl.keystore encryption.ssl.keystore.provider= encryption.ssl.keystore.type=JCEKS @@ -717,6 +717,8 @@ encryption.ssl.truststore.provider= encryption.ssl.truststore.type=JCEKS encryption.ssl.truststore.keyMetaData.location=${dir.keystore}/ssl-truststore-passwords.properties +encryption.reencryptor.chunkSize=50 + # SOLR connection details (e.g. for JMX) solr.host=localhost solr.port=8080 @@ -726,8 +728,11 @@ solr.solrPassword=solr # none, https solr.secureComms=https -# ms +# Solr connection timeouts +# solr connect timeout in ms solr.solrConnectTimeout=5000 + +# cron expression defining how often the Solr Admin client (used by JMX) pings Solr if it goes away solr.solrPingCronExpression=0 0/5 * * * ? * # diff --git a/source/java/org/alfresco/encryption/BootstrapReEncryptor.java b/source/java/org/alfresco/encryption/BootstrapReEncryptor.java index a2e4f3a9e8..94efad30e7 100644 --- a/source/java/org/alfresco/encryption/BootstrapReEncryptor.java +++ b/source/java/org/alfresco/encryption/BootstrapReEncryptor.java @@ -50,11 +50,7 @@ public class BootstrapReEncryptor extends AbstractLifecycleBean { try { - return reEncryptor.reEncrypt(); - } - catch(MissingKeyException e) - { - throw new AlfrescoRuntimeException("Bootstrap re-encryption failed", e); + return reEncryptor.bootstrapReEncrypt(); } catch(MissingKeyStoreException e) { diff --git a/source/java/org/alfresco/encryption/EncryptionTests.java b/source/java/org/alfresco/encryption/EncryptionTests.java index 146b82cf22..e5874bd0ca 100644 --- a/source/java/org/alfresco/encryption/EncryptionTests.java +++ b/source/java/org/alfresco/encryption/EncryptionTests.java @@ -266,16 +266,12 @@ public class EncryptionTests extends TestCase { try { - reEncryptor.reEncrypt(); + reEncryptor.bootstrapReEncrypt(); fail("Should have caught missing backup key store"); } - catch(MissingKeyException e) - { - fail(""); - } catch(MissingKeyStoreException e) { - + System.out.println("Successfully caught missing key store exception"); } } diff --git a/source/java/org/alfresco/encryption/ReEncryptor.java b/source/java/org/alfresco/encryption/ReEncryptor.java index f3ca6f3d51..a1299e4a29 100644 --- a/source/java/org/alfresco/encryption/ReEncryptor.java +++ b/source/java/org/alfresco/encryption/ReEncryptor.java @@ -19,17 +19,14 @@ package org.alfresco.encryption; import java.io.Serializable; -import java.security.Key; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Map; import javax.crypto.SealedObject; -import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.batch.BatchProcessWorkProvider; import org.alfresco.repo.batch.BatchProcessor; import org.alfresco.repo.dictionary.DictionaryDAO; @@ -52,7 +49,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.extensions.surf.util.I18NUtil; -// TODO use Batch code to run in parallel // TODO lock so that only one encryptor can run at a time /** * Re-encrypts encryptable repository properties using a new set of encryption keys. @@ -60,7 +56,12 @@ import org.springframework.extensions.surf.util.I18NUtil; * a backup decryptor (using the old encryption keys) if necessary, and then re-encrypts * the properties. * - * The system can stay running during this operation. + * Can run in one of two ways: + * + *
    + *
  • during bootstrap (used by the community edition of the software) + *
  • by using JMX. In this case, the system can stay running while the re-encryption takes place. + *
* * @since 4.0 */ @@ -73,17 +74,21 @@ public class ReEncryptor implements ApplicationContextAware private DictionaryService dictionaryService; private TransactionService transactionService; private QNameDAO qnameDAO; - - private KeyStoreParameters backupKeyStoreParameters; + + private MetadataEncryptor metadataEncryptor; +// private KeyStoreParameters keyStoreParameters; +// private KeyStoreParameters backupKeyStoreParameters; + private AlfrescoKeyStore backupKeyStore; + private AlfrescoKeyStore keyStore; + private KeyProvider backupKeyProvider; private KeyProvider keyProvider; - private KeyResourceLoader keyResourceLoader; - +// private KeyResourceLoader keyResourceLoader; + private ApplicationContext applicationContext; private RetryingTransactionHelper transactionHelper; private String cipherAlgorithm; - // TODO propertize - private int chunkSize = 50; + private int chunkSize; private boolean splitTxns = true; /** @@ -96,6 +101,16 @@ public class ReEncryptor implements ApplicationContextAware this.transactionHelper.setForceWritable(true); } + public void setMetadataEncryptor(MetadataEncryptor metadataEncryptor) + { + this.metadataEncryptor = metadataEncryptor; + } + + public void setChunkSize(int chunkSize) + { + this.chunkSize = chunkSize; + } + public void setSplitTxns(boolean splitTxns) { this.splitTxns = splitTxns; @@ -126,15 +141,35 @@ public class ReEncryptor implements ApplicationContextAware this.cipherAlgorithm = cipherAlgorithm; } - public void setBackupKeyStoreParameters(KeyStoreParameters backupKeyStoreParameters) - { - this.backupKeyStoreParameters = backupKeyStoreParameters; - } +// public void setKeyStoreParameters(KeyStoreParameters keyStoreParameters) +// { +// this.keyStoreParameters = keyStoreParameters; +// } +// +// public void setBackupKeyStoreParameters(KeyStoreParameters backupKeyStoreParameters) +// { +// this.backupKeyStoreParameters = backupKeyStoreParameters; +// } - protected KeyProvider getKeyProvider(KeyStoreParameters keyStoreParameters) +// protected KeyProvider getKeyProvider(AlfrescoKeyStore keyStore) +// { +// KeyProvider keyProvider = new KeystoreKeyProvider(keyStore); +// return keyProvider; +// } + + public void setBackupKeyStore(AlfrescoKeyStore backupKeyStore) { - KeyProvider keyProvider = new KeystoreKeyProvider(keyStoreParameters, keyResourceLoader); - return keyProvider; + this.backupKeyStore = backupKeyStore; + } + + public void setKeyStore(AlfrescoKeyStore keyStore) + { + this.keyStore = keyStore; + } + + public void setBackupKeyProvider(KeyProvider backupKeyProvider) + { + this.backupKeyProvider = backupKeyProvider; } public void setKeyProvider(KeyProvider keyProvider) @@ -142,44 +177,84 @@ public class ReEncryptor implements ApplicationContextAware this.keyProvider = keyProvider; } - public void setKeyResourceLoader(KeyResourceLoader keyResourceLoader) - { - this.keyResourceLoader = keyResourceLoader; - } +// public void setKeyResourceLoader(KeyResourceLoader keyResourceLoader) +// { +// this.keyResourceLoader = keyResourceLoader; +// } + +// public MetadataEncryptor getMetadataEncryptor() +// { +// DefaultEncryptor backupEncryptor = new DefaultEncryptor(); +// backupEncryptor.setCipherProvider(null); // TODO parameterize +// backupEncryptor.setCipherAlgorithm(cipherAlgorithm); +// backupEncryptor.setKeyProvider(backupKeyProvider); +// +// DefaultEncryptor encryptor = new DefaultEncryptor(); +// encryptor.setCipherProvider(null); // TODO parameterize +// encryptor.setCipherAlgorithm(cipherAlgorithm); +// encryptor.setKeyProvider(keyProvider); +// +// DefaultFallbackEncryptor fallbackEncryptor = new DefaultFallbackEncryptor(encryptor, backupEncryptor); +// MetadataEncryptor metadataEncryptor = new MetadataEncryptor(); +// metadataEncryptor.setEncryptor(fallbackEncryptor); +// metadataEncryptor.setDictionaryService(dictionaryService); +// return metadataEncryptor; +// } +// +// public MetadataEncryptor getMetadataEncryptor(KeyProvider backupKeyProvider, KeyProvider newKeyProvider) +// { +// DefaultEncryptor backupEncryptor = new DefaultEncryptor(); +// backupEncryptor.setCipherProvider(null); // TODO parameterize +// backupEncryptor.setCipherAlgorithm(cipherAlgorithm); +// backupEncryptor.setKeyProvider(backupKeyProvider); +// +// DefaultEncryptor encryptor = new DefaultEncryptor(); +// encryptor.setCipherProvider(null); // TODO parameterize +// encryptor.setCipherAlgorithm(cipherAlgorithm); +// encryptor.setKeyProvider(newKeyProvider); +// +// DefaultFallbackEncryptor fallbackEncryptor = new DefaultFallbackEncryptor(encryptor, backupEncryptor); +// MetadataEncryptor metadataEncryptor = new MetadataEncryptor(); +// metadataEncryptor.setEncryptor(fallbackEncryptor); +// metadataEncryptor.setDictionaryService(dictionaryService); +// return metadataEncryptor; +// } - public MetadataEncryptor getMetadataEncryptor(KeyProvider backupKeyProvider, KeyProvider newKeyProvider) - { - DefaultEncryptor backupEncryptor = new DefaultEncryptor(); - backupEncryptor.setCipherProvider(null); // TODO parameterize - backupEncryptor.setCipherAlgorithm(cipherAlgorithm); - backupEncryptor.setKeyProvider(backupKeyProvider); +// protected KeyProvider getKeyProvider(final Map keys) +// { +// KeyProvider keyProvider = new KeyProvider() +// { +// @Override +// public Key getKey(String keyAlias) +// { +// return keys.get(keyAlias); +// } +// }; +// return keyProvider; +// } + protected Encryptor getEncryptor(KeyProvider keyProvider) + { DefaultEncryptor encryptor = new DefaultEncryptor(); encryptor.setCipherProvider(null); // TODO parameterize encryptor.setCipherAlgorithm(cipherAlgorithm); - encryptor.setKeyProvider(newKeyProvider); + encryptor.setKeyProvider(keyProvider); - DefaultFallbackEncryptor fallbackEncryptor = new DefaultFallbackEncryptor(encryptor, backupEncryptor); - MetadataEncryptor metadataEncryptor = new MetadataEncryptor(); - metadataEncryptor.setEncryptor(fallbackEncryptor); - metadataEncryptor.setDictionaryService(dictionaryService); - return metadataEncryptor; + return encryptor; } - protected KeyProvider getKeyProvider(final Map keys) + /** + * For testing use. + * + * @param keyProvider + */ + void reEncrypt(KeyProvider keyProvider) { - KeyProvider keyProvider = new KeyProvider() - { - @Override - public Key getKey(String keyAlias) - { - return keys.get(keyAlias); - } - }; - return keyProvider; + metadataEncryptor.setEncryptor(getEncryptor(keyProvider)); + reEncryptImpl(); } - protected void reencrypt(final MetadataEncryptor metadataEncryptor, final List properties) + protected void reEncrypt(final MetadataEncryptor metadataEncryptor, final List properties) { final Iterator it = properties.iterator(); BatchProcessor.BatchProcessWorker worker = new BatchProcessor.BatchProcessWorker() @@ -265,19 +340,13 @@ public class ReEncryptor implements ApplicationContextAware /** * Re-encrypt using the configured backup keystore to decrypt and the main keystore to encrypt */ - public int reEncrypt() throws MissingKeyException, MissingKeyStoreException + public int bootstrapReEncrypt() throws MissingKeyStoreException { - if(!backupKeyStoreParameters.isDefined()) + if(backupKeyStore.getKey(KeyProvider.ALIAS_METADATA) == null) { - throw new MissingKeyStoreException("Backup key store is not defined"); + throw new MissingKeyStoreException("Backup key store is either not present or does not contain a metadata encryption key"); } - KeyProvider backupKeyProvider = getKeyProvider(backupKeyStoreParameters); - if(backupKeyProvider.getKey(KeyProvider.ALIAS_METADATA) == null) - { - throw new MissingKeyException("Unable to find the metadata key in backup key store. Does the backup key store exist?"); - } - MetadataEncryptor metadataEncryptor = getMetadataEncryptor(backupKeyProvider, keyProvider); - return reEncrypt(metadataEncryptor); + return reEncrypt(); } /** @@ -288,19 +357,22 @@ public class ReEncryptor implements ApplicationContextAware * placed in the repository keystore directory. This can be done while the repository is running and it will be picked * up automatically the next time the repository restarts. */ - public int reEncrypt(KeyStoreParameters parameters) + public int reEncrypt() throws MissingKeyStoreException { - KeyProvider newKeyProvider = getKeyProvider(parameters); - return reEncrypt(newKeyProvider); - } - - public int reEncrypt(KeyProvider newKeyProvider) - { - MetadataEncryptor metadataEncryptor = getMetadataEncryptor(keyProvider, newKeyProvider); - return reEncrypt(metadataEncryptor); + backupKeyStore.reload(); + keyStore.reload(); + if(keyStore.getKey(KeyProvider.ALIAS_METADATA) == null) + { + throw new MissingKeyStoreException("Main key store is either not present or does not contain a metadata encryption key"); + } + if(backupKeyStore.getKey(KeyProvider.ALIAS_METADATA) == null) + { + throw new MissingKeyStoreException("Backup key store is either not present or does not contain a metadata encryption key"); + } + return reEncryptImpl(); } - protected int reEncrypt(MetadataEncryptor metadataEncryptor) + protected int reEncryptImpl() { // get properties that are encrypted Collection propertyDefs = dictionaryDAO.getPropertiesOfDataType(DataTypeDefinition.ENCRYPTED); @@ -313,7 +385,7 @@ public class ReEncryptor implements ApplicationContextAware } // reencrypt these properties - reencrypt(metadataEncryptor, properties); + reEncrypt(metadataEncryptor, properties); if(logger.isDebugEnabled()) { diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java b/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java index 6498fe57da..173ca8bbde 100644 --- a/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java +++ b/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java @@ -303,6 +303,7 @@ public class SolrQueryHTTPClient body.put("textAttributes", textAttributes); PostMethod post = new PostMethod(url.toString()); + // TOOD deal with redirects for SSL post.setRequestEntity(new ByteArrayRequestEntity(body.toString().getBytes("UTF-8"), "application/json")); try