mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Remaining commits for ALF-9510:
o re-encryptor o secret key keystore creation Removed secret key keystores from Solr Added pcks12 secret key keystore for use in browsers git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@30208 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Binary file not shown.
@@ -1013,7 +1013,7 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="solrHttpClientFactory" class="org.alfresco.httpclient.HttpClientFactory">
|
||||
<bean id="solrHttpClientFactory" class="org.alfresco.httpclient.HttpClientFactory" init-method="init">
|
||||
<property name="secureCommsType" value="${solr.secureComms}"/>
|
||||
<property name="sSLEncryptionParameters" ref="sslEncryptionParameters"/>
|
||||
<property name="keyResourceLoader" ref="springKeyResourceLoader"/>
|
||||
|
@@ -11,7 +11,9 @@
|
||||
|
||||
<!-- Beans to initilize encryption -->
|
||||
|
||||
<!-- TODO i18n for key store names -->
|
||||
<bean id="sslKeyStoreParameters" class="org.alfresco.encryption.KeyStoreParameters">
|
||||
<property name="name" value="SSL Key Store"/>
|
||||
<property name="location" value="${encryption.ssl.keystore.location}"/>
|
||||
<property name="type" value="${encryption.ssl.keystore.type}"/>
|
||||
<property name="provider" value="${encryption.ssl.keystore.provider}"/>
|
||||
@@ -19,6 +21,7 @@
|
||||
</bean>
|
||||
|
||||
<bean id="sslTrustStoreParameters" class="org.alfresco.encryption.KeyStoreParameters">
|
||||
<property name="name" value="SSL Trust Store"/>
|
||||
<property name="location" value="${encryption.ssl.truststore.location}"/>
|
||||
<property name="type" value="${encryption.ssl.truststore.type}"/>
|
||||
<property name="provider" value="${encryption.ssl.truststore.provider}"/>
|
||||
@@ -30,6 +33,21 @@
|
||||
<property name="trustStoreParameters" ref="sslTrustStoreParameters"/>
|
||||
</bean>
|
||||
|
||||
<bean id="ssl.keyStore" class="org.alfresco.encryption.AlfrescoKeyStoreImpl" init-method="init">
|
||||
<property name="keyStoreParameters" ref="sslKeyStoreParameters"/>
|
||||
<property name="keyResourceLoader" ref="springKeyResourceLoader"/>
|
||||
</bean>
|
||||
|
||||
<bean id="ssl.trustStore" class="org.alfresco.encryption.AlfrescoKeyStoreImpl" init-method="init">
|
||||
<property name="keyStoreParameters" ref="sslTrustStoreParameters"/>
|
||||
<property name="keyResourceLoader" ref="springKeyResourceLoader"/>
|
||||
</bean>
|
||||
<!--
|
||||
<bean id="authSSLProtocolSocketFactory" class="org.alfresco.encryption.ssl.AuthSSLProtocolSocketFactory">
|
||||
<property name="keyStore" ref="ssl.keyStore"/>
|
||||
<property name="trustStore" ref="ssl.trustStore"/>
|
||||
</bean>
|
||||
-->
|
||||
<bean id="md5EncryptionParameters" class="org.alfresco.httpclient.MD5EncryptionParameters">
|
||||
<property name="cipherAlgorithm" value="${encryption.cipherAlgorithm}"/>
|
||||
<property name="messageTimeout" value="${encryption.mac.messageTimeout}"/>
|
||||
@@ -40,6 +58,7 @@
|
||||
</bean>
|
||||
|
||||
<bean id="keyStoreParameters" class="org.alfresco.encryption.KeyStoreParameters">
|
||||
<property name="name" value="Key Store"/>
|
||||
<property name="location" value="${encryption.keystore.location}"/>
|
||||
<property name="provider" value="${encryption.keystore.provider}"/>
|
||||
<property name="type" value="${encryption.keystore.type}"/>
|
||||
@@ -56,6 +75,7 @@
|
||||
</bean>
|
||||
|
||||
<bean id="backupKeyStoreParameters" class="org.alfresco.encryption.KeyStoreParameters">
|
||||
<property name="name" value="Backup Key Store"/>
|
||||
<property name="location" value="${encryption.keystore.backup.location}"/>
|
||||
<property name="provider" value="${encryption.keystore.backup.provider}"/>
|
||||
<property name="type" value="${encryption.keystore.backup.type}"/>
|
||||
@@ -86,20 +106,6 @@
|
||||
<property name="fallback" ref="backupEncryptor" />
|
||||
</bean>
|
||||
|
||||
<bean id="reEncryptor" class="org.alfresco.encryption.ReEncryptor">
|
||||
<property name="chunkSize" value="${encryption.reencryptor.chunkSize}"/>
|
||||
<property name="backupKeyStore" ref="backupKeyStore"/>
|
||||
<property name="keyStore" ref="keyStore"/>
|
||||
<property name="backupKeyProvider" ref="backupKeyProvider"/>
|
||||
<property name="keyProvider" ref="keyProvider"/>
|
||||
<property name="transactionService" ref="transactionService"/>
|
||||
<property name="dictionaryService" ref="dictionaryService"/>
|
||||
<property name="nodeDAO" ref="nodeDAO"/>
|
||||
<property name="dictionaryDAO" ref="dictionaryDAO"/>
|
||||
<property name="qnameDAO" ref="qnameDAO"/>
|
||||
<property name="cipherAlgorithm" value="${encryption.cipherAlgorithm}"/>
|
||||
</bean>
|
||||
|
||||
<bean id="encryptionKeysRegistry" class="org.alfresco.encryption.EncryptionKeysRegistryImpl">
|
||||
<property name="transactionService" ref="transactionService"/>
|
||||
<property name="attributeService" ref="attributeService"/>
|
||||
|
BIN
config/alfresco/keystore/browser.p12
Normal file
BIN
config/alfresco/keystore/browser.p12
Normal file
Binary file not shown.
Binary file not shown.
@@ -4,8 +4,4 @@ keystore.password=mp6yc0UD9e
|
||||
# The password protecting the alias: metadata
|
||||
metadata.keyData=
|
||||
metadata.algorithm=DESede
|
||||
metadata.password=oKIWzVdEdA
|
||||
# The password protecting the alias: solr
|
||||
#solr.keyData=
|
||||
#solr.algorithm=DESede
|
||||
#solr.password=TxHTtOnrwQ
|
||||
metadata.password=oKIWzVdEdA
|
@@ -37,6 +37,9 @@ system.mt.warn.upgrade_mt_admin_context=Please update your alfresco/extension/mt
|
||||
system.usage.err.no_txn=RepoUsageComponent must be called in a transaction.
|
||||
system.usage.err.no_txn_readwrite=RepoUsageComponent must be called in a read-write transaction.
|
||||
|
||||
# Re-encryptor
|
||||
reencryptor.batchprocessor.name=Reencryptor
|
||||
|
||||
# START TRANSLATION
|
||||
system.usage.warn.limit_users_approached=The allowable user limit of {0} is being approached. There are {1} users in the system.
|
||||
system.usage.warn.limit_users_reached=The allowable user limit of {0} has been reached. There are {1} users in the system.
|
||||
|
@@ -249,5 +249,16 @@
|
||||
<property name="dictionaryService" ref="dictionaryService" />
|
||||
<property name="encryptor" ref="fallbackEncryptor" />
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="reEncryptor" class="org.alfresco.encryption.ReEncryptor">
|
||||
<property name="chunkSize" value="${encryption.reencryptor.chunkSize}"/>
|
||||
<property name="backupKeyProvider" ref="backupKeyProvider"/>
|
||||
<property name="keyProvider" ref="keyProvider"/>
|
||||
<property name="transactionService" ref="transactionService"/>
|
||||
<property name="nodeDAO" ref="nodeDAO"/>
|
||||
<property name="dictionaryDAO" ref="dictionaryDAO"/>
|
||||
<property name="qnameDAO" ref="qnameDAO"/>
|
||||
<property name="metadataEncryptor" ref="metadataEncryptor"/>
|
||||
<property name="jobLockService" ref="jobLockService"/>
|
||||
</bean>
|
||||
</beans>
|
||||
|
@@ -56,7 +56,6 @@ import org.springframework.context.ApplicationContext;
|
||||
public class EncryptionTests extends TestCase
|
||||
{
|
||||
private static final String TEST_MODEL = "org/alfresco/encryption/reencryption_model.xml";
|
||||
// private static final String TEST_BUNDLE = "org/alfresco/encryption/encryptiontest_model";
|
||||
|
||||
private static int NUM_PROPERTIES = 500;
|
||||
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
@@ -72,11 +71,13 @@ public class EncryptionTests extends TestCase
|
||||
private MetadataEncryptor metadataEncryptor;
|
||||
private ReEncryptor reEncryptor;
|
||||
private String cipherAlgorithm = "DESede/CBC/PKCS5Padding";
|
||||
private KeyStoreParameters keyStoreParameters;
|
||||
private KeyStoreParameters backupKeyStoreParameters;
|
||||
private AlfrescoKeyStoreImpl backupKeyStore;
|
||||
private KeyResourceLoader keyResourceLoader;
|
||||
private EncryptionKeysRegistryImpl encryptionKeysRegistry;
|
||||
private KeyStoreChecker keyStoreChecker;
|
||||
private DefaultEncryptor mainEncryptor;
|
||||
private DefaultEncryptor backupEncryptor;
|
||||
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private DictionaryDAO dictionaryDAO;
|
||||
@@ -102,8 +103,10 @@ public class EncryptionTests extends TestCase
|
||||
reEncryptor = (ReEncryptor)ctx.getBean("reEncryptor");
|
||||
backupKeyStoreParameters = (KeyStoreParameters)ctx.getBean("backupKeyStoreParameters");
|
||||
keyStoreChecker = (KeyStoreChecker)ctx.getBean("keyStoreChecker");
|
||||
keyStoreParameters = (KeyStoreParameters)ctx.getBean("keyStoreParameters");
|
||||
encryptionKeysRegistry = (EncryptionKeysRegistryImpl)ctx.getBean("encryptionKeysRegistry");
|
||||
backupKeyStore = (AlfrescoKeyStoreImpl)ctx.getBean("backupKeyStore");
|
||||
mainEncryptor = (DefaultEncryptor)ctx.getBean("encryptor");
|
||||
backupEncryptor = (DefaultEncryptor)ctx.getBean("backupEncryptor");
|
||||
|
||||
// reencrypt in one txn (since we don't commit the model, the qnames won't be available across transactions)
|
||||
reEncryptor.setSplitTxns(false);
|
||||
@@ -162,18 +165,26 @@ public class EncryptionTests extends TestCase
|
||||
{
|
||||
return keys.get(keyAlias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh()
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
};
|
||||
return keyProvider;
|
||||
}
|
||||
|
||||
protected Encryptor getEncryptor(KeyProvider keyProvider)
|
||||
protected Encryptor getFallbackEncryptor(KeyProvider keyProvider)
|
||||
{
|
||||
DefaultEncryptor encryptor = new DefaultEncryptor();
|
||||
encryptor.setCipherAlgorithm(cipherAlgorithm);
|
||||
encryptor.setCipherProvider(null);
|
||||
encryptor.setKeyProvider(keyProvider);
|
||||
|
||||
DefaultFallbackEncryptor fallbackEncryptor = new DefaultFallbackEncryptor(encryptor, mainEncryptor);
|
||||
|
||||
return encryptor;
|
||||
return fallbackEncryptor;
|
||||
}
|
||||
|
||||
protected MetadataEncryptor getMetadataEncryptor(Encryptor encryptor)
|
||||
@@ -185,7 +196,7 @@ public class EncryptionTests extends TestCase
|
||||
return metadataEncryptor;
|
||||
}
|
||||
|
||||
protected void createEncryptedProperties(List<NodeRef> nodes, MetadataEncryptor metadataEncryptor)
|
||||
protected void createEncryptedProperties(List<NodeRef> nodes)
|
||||
{
|
||||
for(int i = 0; i < NUM_PROPERTIES; i++)
|
||||
{
|
||||
@@ -218,20 +229,26 @@ public class EncryptionTests extends TestCase
|
||||
|
||||
public void testReEncrypt()
|
||||
{
|
||||
KeyProvider backupKeyProvider = backupEncryptor.getKeyProvider();
|
||||
KeyProvider mainKeyProvider = mainEncryptor.getKeyProvider();
|
||||
try
|
||||
{
|
||||
// Create encrypted properties using the configured encryptor and key provider
|
||||
createEncryptedProperties(before, metadataEncryptor);
|
||||
createEncryptedProperties(before);
|
||||
|
||||
// Create encrypted properties using the new encryptor and key provider
|
||||
KeyProvider newKeyProvider = getKeyProvider(newKeys);
|
||||
Encryptor newEncryptor = getEncryptor(newKeyProvider);
|
||||
MetadataEncryptor newMetadataEncryptor = getMetadataEncryptor(newEncryptor);
|
||||
createEncryptedProperties(after, newMetadataEncryptor);
|
||||
|
||||
|
||||
// set backup encryptor key provider to main encryptor key provider and drop in
|
||||
// new key provider for main encryptor
|
||||
backupEncryptor.setKeyProvider(mainEncryptor.getKeyProvider());
|
||||
mainEncryptor.setKeyProvider(newKeyProvider);
|
||||
|
||||
createEncryptedProperties(after);
|
||||
|
||||
// re-encrypt
|
||||
long start = System.currentTimeMillis();
|
||||
reEncryptor.reEncrypt(newKeyProvider);
|
||||
System.out.println(reEncryptor.reEncrypt() + " properties re-encrypted");
|
||||
System.out.println("Re-encrypted " + NUM_PROPERTIES*2 + " properties in " + (System.currentTimeMillis() - start) + "ms");
|
||||
|
||||
// check that the nodes have been re-encrypted properly i.e. check that the properties
|
||||
@@ -239,7 +256,7 @@ public class EncryptionTests extends TestCase
|
||||
for(NodeRef nodeRef : before)
|
||||
{
|
||||
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
|
||||
props = newMetadataEncryptor.decrypt(props);
|
||||
props = metadataEncryptor.decrypt(props);
|
||||
assertNotNull("", props.get(PROP));
|
||||
assertEquals("", nodeRef.toString(), props.get(PROP));
|
||||
}
|
||||
@@ -247,11 +264,15 @@ public class EncryptionTests extends TestCase
|
||||
for(NodeRef nodeRef : after)
|
||||
{
|
||||
Map<QName, Serializable> props = nodeService.getProperties(nodeRef);
|
||||
props = newMetadataEncryptor.decrypt(props);
|
||||
props = metadataEncryptor.decrypt(props);
|
||||
assertNotNull("", props.get(PROP));
|
||||
assertEquals("", nodeRef.toString(), props.get(PROP));
|
||||
}
|
||||
}
|
||||
catch(MissingKeyStoreException e)
|
||||
{
|
||||
fail(e.getMessage());
|
||||
}
|
||||
catch(AlfrescoRuntimeException e)
|
||||
{
|
||||
if(e.getCause() instanceof InvalidKeyException)
|
||||
@@ -260,12 +281,21 @@ public class EncryptionTests extends TestCase
|
||||
fail();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
backupEncryptor.setKeyProvider(backupKeyProvider);
|
||||
mainEncryptor.setKeyProvider(mainKeyProvider);
|
||||
}
|
||||
}
|
||||
|
||||
public void testBootstrapReEncrypt()
|
||||
{
|
||||
try
|
||||
{
|
||||
// ensure that the backup key store is not available
|
||||
backupKeyStoreParameters.setLocation("");
|
||||
backupKeyStore.reload();
|
||||
|
||||
reEncryptor.bootstrapReEncrypt();
|
||||
fail("Should have caught missing backup key store");
|
||||
}
|
||||
|
@@ -61,7 +61,7 @@ public class KeyStoreKeyProviderTest extends TestCase
|
||||
passwords.put(AlfrescoKeyStore.KEY_KEYSTORE_PASSWORD, "ksPwd2");
|
||||
passwords.put(ALIAS_ONE, "aliasPwd1");
|
||||
passwords.put(ALIAS_TWO, "aliasPwd2");
|
||||
KeyStoreParameters encryptionParameters = new KeyStoreParameters("JCEKS", "SunJCE", null, FILE_TWO);
|
||||
KeyStoreParameters encryptionParameters = new KeyStoreParameters("test", "JCEKS", "SunJCE", null, FILE_TWO);
|
||||
KeystoreKeyProvider keyProvider = new KeystoreKeyProvider(encryptionParameters, getKeyStoreLoader(passwords));
|
||||
// FILE_TWO,
|
||||
// getKeyStoreLoader(),
|
||||
@@ -77,7 +77,7 @@ public class KeyStoreKeyProviderTest extends TestCase
|
||||
// passwords.put(KeyStoreManager.KEY_KEYSTORE_PASSWORD, "ksPwd2");
|
||||
// passwords.put(ALIAS_ONE, "aliasPwd1");
|
||||
// passwords.put(ALIAS_TWO, "aliasPwd2");
|
||||
KeyStoreParameters encryptionParameters = new KeyStoreParameters("JCEKS", "SunJCE", null, keyStoreLocation);
|
||||
KeyStoreParameters encryptionParameters = new KeyStoreParameters("test", "JCEKS", "SunJCE", null, keyStoreLocation);
|
||||
KeystoreKeyProvider keyProvider = new KeystoreKeyProvider(encryptionParameters, getKeyStoreLoader(passwords));
|
||||
// FILE_TWO,
|
||||
// getKeyStoreLoader(),
|
||||
|
@@ -35,11 +35,14 @@ import org.alfresco.repo.domain.node.NodePropertyEntity;
|
||||
import org.alfresco.repo.domain.node.NodePropertyKey;
|
||||
import org.alfresco.repo.domain.node.NodePropertyValue;
|
||||
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||
import org.alfresco.repo.lock.JobLockService;
|
||||
import org.alfresco.repo.lock.LockAcquisitionException;
|
||||
import org.alfresco.repo.node.encryption.MetadataEncryptor;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -49,7 +52,6 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
|
||||
// TODO lock so that only one encryptor can run at a time
|
||||
/**
|
||||
* Re-encrypts encryptable repository properties using a new set of encryption keys.
|
||||
* Decrypts the repository properties using the default encryptor, falling back to
|
||||
@@ -59,8 +61,8 @@ import org.springframework.extensions.surf.util.I18NUtil;
|
||||
* Can run in one of two ways:
|
||||
*
|
||||
* <ul>
|
||||
* <li> during bootstrap (used by the community edition of the software)
|
||||
* <li> by using JMX. In this case, the system can stay running while the re-encryption takes place.
|
||||
* <li> during bootstrap.
|
||||
* <li> by using JMX (available only to Enterprise). In this case, the system can stay running while the re-encryption takes place.
|
||||
* </ul>
|
||||
*
|
||||
* @since 4.0
|
||||
@@ -71,32 +73,28 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
|
||||
private NodeDAO nodeDAO;
|
||||
private DictionaryDAO dictionaryDAO;
|
||||
private DictionaryService dictionaryService;
|
||||
private TransactionService transactionService;
|
||||
private QNameDAO qnameDAO;
|
||||
|
||||
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 ApplicationContext applicationContext;
|
||||
private TransactionService transactionService;
|
||||
private RetryingTransactionHelper transactionHelper;
|
||||
private String cipherAlgorithm;
|
||||
|
||||
private int chunkSize;
|
||||
private boolean splitTxns = true;
|
||||
|
||||
private static final QName LOCK = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "OrphanReaper");
|
||||
private JobLockService jobLockService;
|
||||
|
||||
/**
|
||||
* Set the transaction provider so that each execution can be performed within a transaction
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
this.transactionService = transactionService;
|
||||
this.transactionHelper = transactionService.getRetryingTransactionHelper();
|
||||
this.transactionHelper.setForceWritable(true);
|
||||
}
|
||||
@@ -106,6 +104,16 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
this.metadataEncryptor = metadataEncryptor;
|
||||
}
|
||||
|
||||
public MetadataEncryptor getMetadataEncryptor()
|
||||
{
|
||||
return metadataEncryptor;
|
||||
}
|
||||
|
||||
public void setJobLockService(JobLockService jobLockService)
|
||||
{
|
||||
this.jobLockService = jobLockService;
|
||||
}
|
||||
|
||||
public void setChunkSize(int chunkSize)
|
||||
{
|
||||
this.chunkSize = chunkSize;
|
||||
@@ -126,47 +134,11 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
this.dictionaryDAO = dictionaryDAO;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setQnameDAO(QNameDAO qnameDAO)
|
||||
{
|
||||
this.qnameDAO = qnameDAO;
|
||||
}
|
||||
|
||||
public void setCipherAlgorithm(String cipherAlgorithm)
|
||||
{
|
||||
this.cipherAlgorithm = cipherAlgorithm;
|
||||
}
|
||||
|
||||
// public void setKeyStoreParameters(KeyStoreParameters keyStoreParameters)
|
||||
// {
|
||||
// this.keyStoreParameters = keyStoreParameters;
|
||||
// }
|
||||
//
|
||||
// public void setBackupKeyStoreParameters(KeyStoreParameters backupKeyStoreParameters)
|
||||
// {
|
||||
// this.backupKeyStoreParameters = backupKeyStoreParameters;
|
||||
// }
|
||||
|
||||
// protected KeyProvider getKeyProvider(AlfrescoKeyStore keyStore)
|
||||
// {
|
||||
// KeyProvider keyProvider = new KeystoreKeyProvider(keyStore);
|
||||
// return keyProvider;
|
||||
// }
|
||||
|
||||
public void setBackupKeyStore(AlfrescoKeyStore backupKeyStore)
|
||||
{
|
||||
this.backupKeyStore = backupKeyStore;
|
||||
}
|
||||
|
||||
public void setKeyStore(AlfrescoKeyStore keyStore)
|
||||
{
|
||||
this.keyStore = keyStore;
|
||||
}
|
||||
|
||||
public void setBackupKeyProvider(KeyProvider backupKeyProvider)
|
||||
{
|
||||
this.backupKeyProvider = backupKeyProvider;
|
||||
@@ -176,87 +148,44 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
{
|
||||
this.keyProvider = keyProvider;
|
||||
}
|
||||
|
||||
// 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;
|
||||
// }
|
||||
|
||||
// protected KeyProvider getKeyProvider(final Map<String, Key> keys)
|
||||
// {
|
||||
// KeyProvider keyProvider = new KeyProvider()
|
||||
// {
|
||||
// @Override
|
||||
// public Key getKey(String keyAlias)
|
||||
// {
|
||||
// return keys.get(keyAlias);
|
||||
// }
|
||||
// };
|
||||
// return keyProvider;
|
||||
// }
|
||||
/**
|
||||
* Attempts to get the lock. If the lock couldn't be taken, then <tt>null</tt> is returned.
|
||||
*
|
||||
* @return Returns the lock token or <tt>null</tt>
|
||||
*/
|
||||
private String getLock(long time)
|
||||
{
|
||||
try
|
||||
{
|
||||
return jobLockService.getLock(LOCK, time);
|
||||
}
|
||||
catch (LockAcquisitionException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Encryptor getEncryptor(KeyProvider keyProvider)
|
||||
{
|
||||
DefaultEncryptor encryptor = new DefaultEncryptor();
|
||||
encryptor.setCipherProvider(null); // TODO parameterize
|
||||
encryptor.setCipherAlgorithm(cipherAlgorithm);
|
||||
encryptor.setKeyProvider(keyProvider);
|
||||
/**
|
||||
* Attempts to get the lock. If it fails, the current transaction is marked for rollback.
|
||||
*
|
||||
* @return Returns the lock token
|
||||
*/
|
||||
private void refreshLock(String lockToken, long time)
|
||||
{
|
||||
if (lockToken == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Must provide existing lockToken");
|
||||
}
|
||||
jobLockService.refreshLock(lockToken, LOCK, time);
|
||||
}
|
||||
|
||||
return encryptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing use.
|
||||
*
|
||||
* @param keyProvider
|
||||
*/
|
||||
void reEncrypt(KeyProvider keyProvider)
|
||||
{
|
||||
metadataEncryptor.setEncryptor(getEncryptor(keyProvider));
|
||||
reEncryptImpl();
|
||||
}
|
||||
|
||||
protected void reEncrypt(final MetadataEncryptor metadataEncryptor, final List<NodePropertyEntity> properties)
|
||||
protected void reEncryptProperties(final List<NodePropertyEntity> properties, final String lockToken)
|
||||
{
|
||||
final Iterator<NodePropertyEntity> it = properties.iterator();
|
||||
|
||||
// TODO use BatchProcessWorkerAdaptor?
|
||||
|
||||
BatchProcessor.BatchProcessWorker<NodePropertyEntity> worker = new BatchProcessor.BatchProcessWorker<NodePropertyEntity>()
|
||||
{
|
||||
public String getIdentifier(NodePropertyEntity entity)
|
||||
@@ -266,6 +195,7 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
|
||||
public void beforeProcess() throws Throwable
|
||||
{
|
||||
refreshLock(lockToken, chunkSize * 100L);
|
||||
}
|
||||
|
||||
public void afterProcess() throws Throwable
|
||||
@@ -287,9 +217,9 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
// decrypt...
|
||||
Serializable decrypted = metadataEncryptor.decrypt(propertyQName, sealed);
|
||||
|
||||
// ...and then re-encrypt. The new keys will be used.
|
||||
// ...and then re-encrypt. The new key will be used.
|
||||
Serializable resealed = metadataEncryptor.encrypt(propertyQName, decrypted);
|
||||
|
||||
|
||||
// TODO update resealed using batch update?
|
||||
// does the node DAO do batch updating?
|
||||
nodeDAO.setNodeProperties(entity.getNodeId(), Collections.singletonMap(propertyQName, resealed));
|
||||
@@ -315,12 +245,16 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
@Override
|
||||
public Collection<NodePropertyEntity> getNextWork()
|
||||
{
|
||||
int count = 0;
|
||||
List<NodePropertyEntity> sublist = new ArrayList<NodePropertyEntity>(chunkSize);
|
||||
while(it.hasNext() && count < chunkSize)
|
||||
|
||||
synchronized(it)
|
||||
{
|
||||
sublist.add(it.next());
|
||||
count++;
|
||||
int count = 0;
|
||||
while(it.hasNext() && count < chunkSize)
|
||||
{
|
||||
sublist.add(it.next());
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return sublist;
|
||||
@@ -329,12 +263,12 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
|
||||
// TODO, "propertize" these numbers
|
||||
new BatchProcessor<NodePropertyEntity>(
|
||||
I18NUtil.getMessage(""),
|
||||
I18NUtil.getMessage("reencryptor.batchprocessor.name"), // TODO i18n name
|
||||
transactionHelper,
|
||||
provider,
|
||||
2, 20,
|
||||
2, 100,
|
||||
applicationContext,
|
||||
logger, 20).process(worker, splitTxns);
|
||||
logger, 100).process(worker, splitTxns);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -342,7 +276,7 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
*/
|
||||
public int bootstrapReEncrypt() throws MissingKeyStoreException
|
||||
{
|
||||
if(backupKeyStore.getKey(KeyProvider.ALIAS_METADATA) == null)
|
||||
if(backupKeyProvider.getKey(KeyProvider.ALIAS_METADATA) == null)
|
||||
{
|
||||
throw new MissingKeyStoreException("Backup key store is either not present or does not contain a metadata encryption key");
|
||||
}
|
||||
@@ -353,39 +287,59 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
* Re-encrypt by decrypting using the configured keystore and encrypting using a keystore configured using the provided new key store parameters.
|
||||
* Called from e.g. JMX.
|
||||
*
|
||||
* Note: it is the responsibility of the end user to ensure that the keystore configured by newKeyStoreParameters is
|
||||
* 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.
|
||||
* Note: it is the responsibility of the end user to ensure that the underlying keystores have been set up appropriately
|
||||
* i.e. the old key store is backed up to the location defined by the property '${dir.keystore}/backup-keystore' and the new
|
||||
* key store replaces it. This can be done while the repository is running.
|
||||
*/
|
||||
public int reEncrypt() throws MissingKeyStoreException
|
||||
{
|
||||
backupKeyStore.reload();
|
||||
keyStore.reload();
|
||||
if(keyStore.getKey(KeyProvider.ALIAS_METADATA) == null)
|
||||
// refresh the key providers to pick up changes made
|
||||
backupKeyProvider.refresh();
|
||||
keyProvider.refresh();
|
||||
|
||||
if(keyProvider.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)
|
||||
if(backupKeyProvider.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();
|
||||
|
||||
int numProps = reEncryptImpl();
|
||||
return numProps;
|
||||
}
|
||||
|
||||
protected int reEncryptImpl()
|
||||
{
|
||||
// get properties that are encrypted
|
||||
RetryingTransactionCallback<String> txnWork = new RetryingTransactionCallback<String>()
|
||||
{
|
||||
public String execute() throws Exception
|
||||
{
|
||||
String lockToken = getLock(20000L);
|
||||
return lockToken;
|
||||
}
|
||||
};
|
||||
|
||||
String lockToken = transactionService.getRetryingTransactionHelper().doInTransaction(txnWork, false, true);
|
||||
if(lockToken == null)
|
||||
{
|
||||
logger.warn("Can't get lock. Assume multiple re-encryptors ...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get encrypted properties
|
||||
Collection<PropertyDefinition> propertyDefs = dictionaryDAO.getPropertiesOfDataType(DataTypeDefinition.ENCRYPTED);
|
||||
// TODO use callback mechanism
|
||||
// TODO use callback mechanism, or select based on set of nodes?
|
||||
List<NodePropertyEntity> properties = nodeDAO.selectProperties(propertyDefs);
|
||||
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Found " + properties.size() + " properties to re-encrypt...");
|
||||
}
|
||||
|
||||
// reencrypt these properties
|
||||
reEncrypt(metadataEncryptor, properties);
|
||||
// reencrypt these properties TODO don't call if num props == 0
|
||||
reEncryptProperties(properties, lockToken);
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
@@ -396,8 +350,7 @@ public class ReEncryptor implements ApplicationContextAware
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
<imports>
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
|
||||
</imports>
|
||||
|
||||
<namespaces>
|
||||
@@ -23,7 +24,7 @@
|
||||
<type name="test:base">
|
||||
<title>Base</title>
|
||||
<description>The Base Type</description>
|
||||
<parent></parent>
|
||||
<parent>cm:content</parent>
|
||||
|
||||
<properties>
|
||||
<property name="test:prop1">
|
||||
|
@@ -42,8 +42,11 @@ import org.alfresco.service.cmr.search.SearchParameters.FieldFacetSort;
|
||||
import org.alfresco.service.cmr.search.SearchParameters.SortDefinition;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.apache.commons.codec.net.URLCodec;
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.HttpStatus;
|
||||
import org.apache.commons.httpclient.URI;
|
||||
import org.apache.commons.httpclient.UsernamePasswordCredentials;
|
||||
import org.apache.commons.httpclient.auth.AuthScope;
|
||||
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
|
||||
@@ -303,13 +306,23 @@ 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
|
||||
{
|
||||
httpClient.executeMethod(post);
|
||||
|
||||
if(post.getStatusCode() == HttpStatus.SC_MOVED_PERMANENTLY || post.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY)
|
||||
{
|
||||
Header locationHeader = post.getResponseHeader("location");
|
||||
if (locationHeader != null)
|
||||
{
|
||||
String redirectLocation = locationHeader.getValue();
|
||||
post.setURI(new URI(redirectLocation, true));
|
||||
httpClient.executeMethod(post);
|
||||
}
|
||||
}
|
||||
|
||||
if (post.getStatusCode() != HttpServletResponse.SC_OK)
|
||||
{
|
||||
throw new LuceneQueryParserException("Request failed " + post.getStatusCode() + " " + url.toString());
|
||||
|
Reference in New Issue
Block a user