Obsolete Pages{{Obsolete}}
The official documentation is at: http://docs.alfresco.com
Core Repository ServicesEncryption
This page is W.I.P: See ALF-9200: RINF 38: Encryption documentation and Quality tasks
Version 4.0 of Alfresco has added encryption capabilities (see ALF-8646) to support encryptable node properties. A new type 'd:encrypted' can be used to indicate that a node property is encryptable.
The data encryption system in Alfresco uses secret keys stored in a Java key store. Out of the box, a pre-configured main keystore is provided (WEB_INF/classes/alfresco/keystore/keystore) but you may either want to generate your own or let the repository create one during bootstrap (see below). The default keystore configuration protects the keys using two levels of password, a key store password and a password for each key. Currently the keystore contains only a 'metadata' secret key that is used for encrypting and decrypting node properties that are of type 'd:encrypted'.
A backup keystore can be configured. The main use case is if the keys need to be changed: the user backs up the main keystore to the backup keystore location and creates a new keystore in its place. If both main and backup keystores are configured, the repository encryption will work in 'fallback' mode. In this mode, decryption of node properties is tried firstly with the main keystore 'metadata' key; if that fails the backup keystore 'metadata' key is tried. In Enterprise, this allows keystores to be changed on disk and re-loaded without affecting the running of the repository. For Community, the repository needs to be stopped and restarted for keystore changes to be picked up.
Keystores are used also to protect repository/Solr communications using encryption and mutual authentication (see Alfresco And SOLR). In this case, the keystores store RSA keys and certificates.
The main key store can be configured with the following properties (in repository.properties or overridden in alfresco-global.properties):
For the backup keystore, these properties are relevant:
This means that keystores and metadata files can be locate wherever you desire (preferably, for security reasons, in different places). In addition, appropriate operating system permissions should be applied to limit their visibility to third parties.
Each keystore must have a corresponding keystore metadata file containing passwords and other metadata relevant to the keystore and its keys. The metadata file must contain three entries:
The repository will check at bootstrap if the 'metadata' key in the main keystore have been changed (unless running in fallback mode - see above - in which case the backup keystore is checked instead). This prevents accidental changes to the keystore. If it detects they have been changed an exception will occur and the bootstrap will stop.
The repository will detect a missing secret key keystore during bootstrap and create one on the fly. It will contain a single 'metadata' secret key. In order to do this, it assumes the existence of a keystore metadata file containing information about the 'metadata' key (the format of the metadata file is as defined in the metadata file format above). Specifically, it expects the following properties to be set:
The keyData can be generated by executing the class org.alfresco.encryption.GenerateSecretKey like this:
java -classpath 'projects/3rd-party/lib/commons/commons-codec-1.4.jar:projects/core/build/dist/alfresco-core-4.0.a.jar' org.alfresco.encryption.GenerateSecretKey
A new keystore can be generated using the Java keytool command as follows.
keytool -genseckey -alias metadata -keypass <metadata key password> -storepass <key store password> -keystore keystore -storetype JCEKS -keyalg DESede
Make sure the key store is placed in the location specified by the property 'encryption.keystore.location' and that the passwords you have used in the keytool commands are placed in the file specified by the property 'encryption.keystore.keyMetaData.location'.
The keystore keys are registered with the repository to ensure that they are not accidentally changed. During bootstrap and JMX keystore reload and re-encryption operations, the repository will check if the main keystore's keys have changed (in particular, the 'metadata' key) and, if they have, it will throw an exception.
Node properties can be encrypted in the repository by setting their type to 'd:encrypted' in the model. By default, the node service will not automatically encrypt and decrypt these properties as they pass into and out of the node service. The existing Alfresco clients such as Share and Alfresco Explorer will therefore not encrypt and decrypt these properties automatically - it is the responsibility of custom Java code to do this. This approach is intentional - clients should not automatically be able to decrypt and display encrypted property values.
The org.alfresco.repo.node.encryption.MetadataEncryptor class (defined as the Alfresco Spring bean with name 'metadataEncryptor') provides an interface to encrypt and decrypt encryptable properties. The repository's node integrity checking will ensure that encryptable properties are actually encrypted (by the MetaDataEncryptor) when they are passed to the node services. If they are not, an integrity violation exception is raised. For example, given the model:
<model name='test:encryptedPropModel' xmlns='http://www.alfresco.org/model/dictionary/1.0'>
<description>Alfresco Content Model</description>
<author>Alfresco</author>
<published>2005-05-30</published>
<version>1.0</version>
<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>
<namespace uri='http://www.alfresco.org/test/encryptedPropModel/1.0' prefix='test'/>
</namespaces>
<constraints>
</constraints>
<types>
<type name='test:encrypted'>
<title>Encrypted</title>
<description>The Base Type</description>
<parent>cm:content</parent>
<properties>
<property name='test:prop1'>
<type>d:encrypted</type>
<protected>true</protected>
<default></default>
<constraints>
</constraints>
</property>
</properties>
<associations>
</associations>
<mandatory-aspects>
</mandatory-aspects>
</type>
</types>
</model>
the following code creates a node of type 'test:encrypted' using the MetadataEncryptor to encrypt the property.
MetadataEncryptor metadataEncryptor = (MetadataEncryptor)ctx.getBean('metadataEncryptor');
Map<QName, Serializable> allProperties = new PropertyMap();
allProperties.put(ENCRYPTED_PROP_QNAME, 'ABC');
allProperties = metadataEncryptor.encrypt(allProperties);
try
{
// Create a node using the thread's locale
NodeRef nodeRef2 = nodeService.createNode(
nodeRef1,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, getName()),
ENCRYPTED_TYPE_QNAME, allProperties).getChildRef();
The property can be decrypted as follows:
Serializable encryptedPropertyValue = nodeService.getProperty(nodeRef2, ENCRYPTED_PROP_QNAME);
Serializable decryptedPropertyValue = metadataEncryptor.decrypt(ENCRYPTED_PROP_QNAME, encryptedPropertyValue);
assertEquals('ABC', decryptedPropertyValue);
Normally, the repository will check during bootstrap whether the keys in the main keystore have been changed (see above) in order to detect un-intentional keystore changes. However, if you intentionally want to change your keys you can do so and the repository will re-encrypt any existing encrypted node properties for you. New encrypted node properties will be encrypted using the new keys.
Changing your keys is a matter of backing up your keystore to a specific location and creating a new keystore in its place. This can be done in two ways:
Re-encryption occurs during repository bootstrap.
mv keystore backup-keystore
mv keystore-passwords.properties backup-keystore-passwords.properties
Re-encryption occurs while the repository is running.
mv keystore backup-keystore
mv keystore-passwords.properties backup-keystore-passwords.properties
This will re-read the main and backup keystores and re-encrypt encrypted properties. The repository can continue to run during this operation; any newly-created encrypted properties will be encrypted with the new key.