alxgomz

Collaborative Edition on Alfresco using LibreOffice Online

Blog Post created by alxgomz Employee on Mar 19, 2019

Being able to edit a file concurrently by multiple users is a need we’re coming across more and more when dicussing with customers on the field.
At the time of writing, the out-of-the-box solution to deliver this kind of feature within Alfresco is to use the GoogleDocs module.
This module allows for content stored in Alfresco to be collaboratively edited using Google’s online application suite (text editor, spreasheet editor, presentations) and saved back in the repository.
However some customer may not want to use Google services for different reasons (e.g, cost or data sensitivity), in which case there are far less options.
If you’re concerned about your data being sent to a public cloud and prefer having them securely stored on-premise in Alfresco instead, there may be a solution to help you.

LibreOffice OnLine (LOOL)

Alfresco uses LibreOffice (and formerly OpenOffice) for a very long time. This is one of the component providing our out-of-the-box transformation service (either through OODirect or jodconverter).
After delivering an opensource productivity Suite on the desktop, the Libreoffice team has started working on a similar feature set with a more SaaS approach: LibreOffice OnLine (LOOL).
Don’t get me wrong here: LOOL is not a SaaS solution you have to subscribe to, and that’s the intersting thing with it. LOOL is a service you can install on-premise in order to provide edition tools for office documents. And of course, as that’s what’s our main interest here, it provide collaborative edition capabilities. LOOL itself already provides a solution to having collaborative edition, while keeping your data in compliance with your SSI company policy!
Here I’ll detail how to integrate LOOL with your prefered on-premise content management system, thus bringing the collaborative edition feature inside Alfresco!

Alfresco integration

LibreOffice OnLine is actually a WOPI client and needs to talk to a WOPI server.

If you want to know more about the WOPi protocol you can check its definition here

The WOPI server role will be endorsed by Alfresco itself using 2 modules (one for the repo and one for Share). Those AMPs have been created by Magenta. All credits goes to them, here, I’m just giving guidance on how to install and configure it for Alfresco Content Services:

In terms of network flows, the following diagram shows what conenction are used

network flows Alfresco Libreofice Online

In this document we’ll use Alfresco Content Service 5.2.4.

Installation

LOOL installation

Fortunately it is now very simple to install LOOL (using the CODE distribution). The simple commands bellow should work for a Debian based Linux distribution.
Alongside this document we’ll use Debian 9.

$ echo 'deb https://www.collaboraoffice.com/repos/CollaboraOnline/CODE-debian9 ./' | sudo tee /etc/apt/sources.list.d/code.list
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0C54D189F4BA284D
$ sudo apt update
$ sudo apt install loolwsd code-brand

If you’re just testing you’ll probably be interested in using the docker image available at docker hub

LOOL configuration

By default the office online suite is configured to use SSL but the certificates are not provided. We then have to create those (or disable SSL if not targeting production).

$ sudo mkdir /etc/loolwsd/ssl

Copy to this newly created folder:

  • the certificate private key: /etc/loolwsd/ssl/loolwsd.key (make sure it’s only readable to the user runnning LOOL: lool)
  • the certificate itself: /etc/loolwsd/ssl/loolwsd.crt
  • the public CA certificate: /etc/loolwsd/ssl/cacert.pem

If you want ot use selfsigned certificates, this is a bit more tricky but do-able. Start with the commands bellow to generate the self-signed certificate:

$ sudo openssl genrsa -out /etc/loolwsd/ssl/loolwsd.key
$ sudo chown lool /etc/loolwsd/ssl/loolwsd.key
$ sudo chmod 400 /etc/loolwsd/ssl/loolwsd.key
$ cp /etc/ssl/openssl.cnf /tmp/loolwsd_ssl.cnf
$ cat >> /tmp/loolwsd_ssl.cnf <<EOT
[ san ]
subjectAltName = @alt_names
[alt_names]
IP.1 = 192.168.0.185
EOT
$ sudo openssl req -new -x509 -sha256 -nodes -key /etc/loolwsd/ssl/loolwsd.key -days 9999 -out /etc/loolwsd/ssl/loolwsd.crt -config /tmp/loolwsd_ssl.cnf -extensions san

IP.1 must match the IP address where the libreoffice online service is available. Change it to match your needs

Additionnally, if you’re using self signed certificate, it is required the Alfresco JVM trusts this certificate .

$ keytool -importcert -alias lool -file /etc/loolwsd/ssl/loolwsd.crt -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit -storetype JKS

Of course, keystore path, type and passwords must match your environment

The client browser must also trust this certificate!

If LOOL traffic is wrapped in SSL, you’ll also need to have Alfresco protected by SSL. This is because most browser today will prevent pages with mixed content (http & https) from being displayed.
It means you have to configure Alfresco for SSL. Please refer to the official documentation in order to do that: https://docs.alfresco.com/5.2/concepts/configure-ssl-intro.html.
Again if you use a selfsigned certificate (or a certificate from a private pki ) for Alfresco, it is required to let LOOL trust that certificate. The way to do it depends on the distribution the service is running on. On Debian-like systems you can do:

$ keytool -exportcert -alias ssl.alfresco.ca -keystore alf_data/keystore/ssl.keystore -storetype JCEKS -storepass kT9X6oe68t | openssl x509 -inform DER -outform PEM -in - | sudo tee /usr/local/ca-certificates/alfresco.crt
$ sudo update-ca-certificates

The example command above uses the default Alfresco Keystore, path and password which you should have changed. Make sure to use the correct ones for your environment.

Now open the service configuration file /etc/loolwsd/loolwsd.xml and edit the ssl section as shown bellow:

...
<ssl desc="SSL settings">
 <enable type="bool" desc="Controls whether SSL encryption is enable (do not disable for production deployment). If default is false, must first be compiled with SSL support to enable." default="true">true</enable>
 <termination desc="Connection via proxy where loolwsd acts as working via https, but actually uses http." type="bool" default="true">false</termination>
 <cert_file_path desc="Path to the cert file" relative="false">/etc/loolwsd/ssl/loolwsd.crt</cert_file_path>
 <key_file_path desc="Path to the key file" relative="false">/etc/loolwsd/ssl/loolwsd.key</key_file_path>
 <ca_file_path desc="Path to the ca file" relative="false">/etc/loolwsd/ca-chain.cert.pem</ca_file_path>
 <cipher_list desc="List of OpenSSL ciphers to accept" default="ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"></cipher_list>
 <hpkp desc="Enable HTTP Public key pinning" enable="false" report_only="false">
  <max_age desc="HPKP's max-age directive - time in seconds browser should remember the pins" enable="true">1000</max_age>
<report_uri desc="HPKP's report-uri directive - pin validation failure are reported at this URL" enable="false"></report_uri>
 <pins desc="Base64 encoded SPKI fingerprints of keys to be pinned">
 <pin></pin>
 </pins>
 </hpkp>
</ssl>
...

Also edit the net section to match your needs:

...
<net desc="Network settings">
 <proto type="string" default="all" desc="Protocol to use IPv4, IPv6 or all for both">all</proto>
 <listen type="string" default="any" desc="Listen address that loolwsd binds to. Can be 'any' or 'loopback'.">any</listen>
 <service_root type="path" default="" desc="Prefix all the pages, websockets, etc. with this path."></service_root>
 <post_allow desc="Allow/deny client IP address for POST(REST)." allow="true">
 <host desc="The IPv4 private 192.168 block as plain IPv4 dotted decimal addresses.">192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host>
 <host desc="Ditto, but as IPv4-mapped IPv6 addresses">::ffff:192\.168\.[0-9]{1,3}\.[0-9]{1,3}</host>
 <host desc="The IPv4 loopback (localhost) address.">127\.0\.0\.1</host>
 <host desc="Ditto, but as IPv4-mapped IPv6 address">::ffff:127\.0\.0\.1</host>
 <host desc="The IPv6 loopback (localhost) address.">::1</host>
 </post_allow>
 <frame_ancestors desc="Specify who is allowed to embed the LO Online iframe (loolwsd and WOPI host are always allowed). Separate multiple hosts by space.">alfresco.myecm.org:1800</frame_ancestors>
</net>
...

Pay attention to the post_allow element, its value has to match the IP of your clients (all the browser which may request to edit files). The default configuration is to allow local access and access from a 192.168.0.0/16 network.

The frame_ancestors element should be left alone as the wopi host (alfresco) is normally part of it by default. However there may be cases where it is required (e.g if running on a non-default network port)

Now make sure to have you alfresco host declared as an authorized wopi host in the storage section:

<storage desc="Backend storage">
    <filesystem allow="false" />
    <wopi desc="Allow/deny wopi storage. Mutually exclusive with webdav." allow="true">
       <host desc="Allow from Alfresco" allow="true">alfresco.myecm.org</host>
        <max_file_size desc="Maximum document size in bytes to load. 0 for unlimited." type="uint">0</max_file_size>                                                                      
    </wopi>
    <webdav desc="Allow/deny webdav storage. Mutually exclusive with wopi." allow="false">
        <host desc="Hostname to allow" allow="false">localhost</host>
    </webdav>
</storage>

the wopi host specified must match you alfresco hostname as used by web browsers

On the Alfresco side add the following properties to the alfresco-global.properties file:

...
lool.wopi.url=https://loolhost:9980
lool.wopi.url.discovery=https://loolhost:9980/hosting/discovery
lool.wopi.alfresco.host=https://alfrescohost:8443/alfresco/s
...

Where loolhost is the server name where you installed LOOL, and alfrescohost the local server where alfresco is running
It is possible to install both on the same server of course.

Only use FQDN names (matching the certificates CN if using SSL), do not use localhost.

Use appropriate ports

Applying AMPs

There are 2 AMPs available. In order to turn Alfresco into a WOPI host you’ll need the repo AMP, and to add the necessary Share pages and buttons to allow UI integration the share AMP is needed.
We’ll first need to get the sources and build them:

$ git clone https://github.com/magenta-aps/alfresco-repo-libreoffice-online-module.git_
$ cd alfresco-repo-libreoffice-online-module
$ vim pom.xml
$ mvn package

When editing the pom.xml make sure to:

  • set alfresco.platform.version & alfresco.share.version to your version in the repo pom.xml
  • set alfresco.surf.version to the surf version matching you alfresco version in the share pom.xml
  • set maven.alfresco.edition to enterprise

Copy the resulting .amp files located in target/ to the amps and amps_share folders of your alfresco installation and run:

$ ./bin/apply_amps.sh

You can now restart the services:

$ sudo systemctl restart loolwsd
$ ./alfresco.sh restart tomcat

You can now test editing Office documents simultaneously with differents users and see how convenient LibreOffice OnLine makes it.

Below examples of spreadsheet and presentations concurrent edition by "Administrator" and "Alex" users:

 

Each user can see what the others are doing and who's editing.

 

calc collab

impress collabAs you can see in the screenshot above, the share module needs some tweaking if you're not using english locale. But that should really just be a matter of adding the right message bundle. to the share AMP

Outcomes