Data Encryption

Document created by resplin Employee on Jun 6, 2015
Version 1Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Core Repository ServicesEncryption


Introduction


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.


Alfresco Keystores


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.


Keystore Configuration


The main key store can be configured with the following properties (in repository.properties or overridden in alfresco-global.properties):


  • it's location is defined by the property 'encryption.keystore.location'.
  • the location of its metadata file is defined by the property 'encryption.keystore.keyMetaData.location'.

For the backup keystore, these properties are relevant:


  • it's location is defined by the property 'encryption.keystore.backup.location'.
  • the location of its metadata file is defined by the property 'encryption.keystore.backup.keyMetaData.location'.

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:


  • aliases=<active key aliases in the key store>
  • keystore.password=<key store password>
  • metadata.password=<metadata key password>

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.


Keystore Generation


Automatic Keystore Generation


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:


  • metadata.keyData : this is the key data used to generate the secret key
  • metadata.algorithm : this is the key algorithm used to generate the secret key

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

Manual Keystore Generation


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'.


Key Registration


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.


Encrypting Node Properties


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);

Changing Key Store Keys and Re-encryption


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:             


  • During bootstrap.
  • Using JMX (Enterprise only)

Bootstrap Re-encryption (Community and Enterprise)


Re-encryption occurs during repository bootstrap.


  • Stop the repository.
  • Set the property 'encryption.bootstrap.reencrypt' to 'true'
  • Backup the current keystore to backup-keystore i.e.

    mv keystore backup-keystore
    mv keystore-passwords.properties backup-keystore-passwords.properties

  • Copy your new keystore over the old keystore
  • Update keystore-passwords.properties with the passwords you used to create the keystore i.e. update the property 'keystore.password' with the keystore password and update 'metadata.password' with the metadata key password.
  • Re-start the repository.

JMX Re-encryption (Enterprise Only)


Re-encryption occurs while the repository is running.


  • Backup the current keystore to backup-keystore i.e.

    mv keystore backup-keystore
    mv keystore-passwords.properties backup-keystore-passwords.properties

  • Copy your new keystore over the old keystore.
  • In your JMX console, execute the operation Encryption -> Operations -> Encrypt

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.

Attachments

    Outcomes