Creating self-signed SSL certificates for Solr

Since the default SSL certificates that ship with Alfresco’s Solr integration expired the other week I’ve been having to fix up my local development installs that I’d previously configured with Solr.
The instructions on the wiki are pretty comprehensive, and together with the text file provided in the Solr integration package provide all the info you need to understand the process of creating your own keys and certificates for local testing.
After I stepped through the complete procedure documented there, with some slight modifications to avoid the interactive prompting, I found I had a set of commands which I could use in order to repeatedly re-generate a set of keys inside each installation directory on my system.
The first section in the following listing could be placed inside your .bash_profile file, and this is recommended to ensure that the password values you choose to use are not captured in your command history or in your terminal. The commands after that should be used repeatedly against each Alfresco installation you wish to generate keys and certificates for.

# The subject name of the key used to sign the certificates
REPO_SUBJECT_NAME="/C=GB/ST=UK/L=Maidenhead/O=Alfresco Software Ltd./OU=Unknown/CN=Alfresco Repository"
# The repository server certificate subject name, as specified in tomcat/conf/tomcat-users.xml with roles="repository"
REPO_CERT_DNAME="CN=Alfresco Repository, OU=Unknown, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB"
# The SOLR client certificate subject name, as specified in tomcat/conf/tomcat-users.xml with roles="repoclient"
SOLR_CLIENT_CERT_DNAME="CN=Alfresco Repository Client, OU=Unknown, O=Alfresco Software Ltd., L=Maidenhead, ST=UK, C=GB"
# The number of days before the certificate expires
CERTIFICATE_VALIDITY=36525
# Keystore password
KEYSTORE_PASSWORD=custompassword
BROWSER_KEYSTORE_PASSWORD=alfresco
openssl genrsa -des3 -passout pass:$KEYSTORE_PASSWORD -out ca.key 1024
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -passin pass:$KEYSTORE_PASSWORD -subj "$REPO_SUBJECT_NAME" -passout pass:$KEYSTORE_PASSWORD
# Generate Alfresco Repository SSL keystores
keytool -genkey -alias 'ssl.repo' -keyalg RSA -keystore ssl.keystore -storetype JCEKS -dname "$REPO_CERT_DNAME" -storepass "$KEYSTORE_PASSWORD" -keypass "$KEYSTORE_PASSWORD"
keytool -keystore ssl.keystore -alias 'ssl.repo' -certreq -file repo.csr -storetype JCEKS -storepass "$KEYSTORE_PASSWORD"
openssl x509 -CA ca.crt -CAkey ca.key -CAcreateserial -req -in repo.csr -out repo.crt -days "$CERTIFICATE_VALIDITY" -passin pass:$KEYSTORE_PASSWORD
keytool -import -alias 'alfresco.ca' -file ca.crt -keystore ssl.keystore -storetype JCEKS -storepass $KEYSTORE_PASSWORD -noprompt
keytool -import -alias 'ssl.repo' -file repo.crt -keystore ssl.keystore -storetype JCEKS -storepass $KEYSTORE_PASSWORD -noprompt
keytool -importkeystore -srckeystore ssl.keystore -srcstorepass $KEYSTORE_PASSWORD -srcstoretype JCEKS -srcalias 'ssl.repo' -srckeypass $KEYSTORE_PASSWORD -destkeystore browser.p12 -deststoretype pkcs12 -deststorepass $BROWSER_KEYSTORE_PASSWORD -destalias repo -destkeypass $BROWSER_KEYSTORE_PASSWORD
keytool -import -alias alfresco.ca -file ca.crt -keystore ssl.truststore -storetype JCEKS -storepass $KEYSTORE_PASSWORD -noprompt
# Generate Alfresco Solr SSL keystores
keytool -genkey -alias 'ssl.repo.client' -keyalg RSA -keystore ssl.repo.client.keystore -storetype JCEKS -storepass $KEYSTORE_PASSWORD -keypass "$KEYSTORE_PASSWORD" -dname "$SOLR_CLIENT_CERT_DNAME"
keytool -keystore ssl.repo.client.keystore -alias 'ssl.repo.client' -certreq -file ssl.repo.client.csr -storetype JCEKS -storepass $KEYSTORE_PASSWORD
openssl x509 -CA ca.crt -CAkey ca.key -CAcreateserial -req -in ssl.repo.client.csr -out ssl.repo.client.crt -days "$CERTIFICATE_VALIDITY" -passin pass:$KEYSTORE_PASSWORD
keytool -import -alias 'alfresco.ca' -file ca.crt -keystore ssl.repo.client.keystore -storetype JCEKS -storepass $KEYSTORE_PASSWORD -noprompt
keytool -import -alias 'ssl.repo.client' -file ssl.repo.client.crt -keystore ssl.repo.client.keystore -storetype JCEKS -storepass $KEYSTORE_PASSWORD -noprompt
keytool -import -alias 'alfresco.ca' -file ca.crt -keystore ssl.repo.client.truststore -storetype JCEKS -storepass $KEYSTORE_PASSWORD -noprompt
# Copy files
cp ssl.keystore ssl.truststore browser.p12 data/keystore/
cp ssl.repo.client.keystore ssl.repo.client.truststore solr/workspace-SpacesStore/conf
cp ssl.repo.client.keystore ssl.repo.client.truststore solr/archive-SpacesStore/conf
# Remove temporary files
rm repo.csr ca.key ca.crt repo.crt ssl.keystore browser.p12 ssl.truststore ssl.repo.client.csr ssl.repo.client.crt ssl.repo.client.keystore ssl.repo.client.truststore

Note that this will not update the Alfresco and Solr configuration with the password you choose for the keystores – you must do this separately in your alfresco-global.properties and in the properties file associated with each Solr core, as detailed in the Solr installation guide.
Lastly, this procedure should not be used in any public-facing or production instances, it is intended to be used in development environments only.

The sad reality of cycling in London

As a cyclist living in London I’ve watched the last few days of Olympic competition with great interest. Before the track events even started Team GB knocked up an impressive performance in both the road race and time trial events, culminating with Bradley Wiggins’s impressive win at Hampton Court yesterday.

But we were all brought back down to earth following the tragic news from last night of the young man who was killed last night on one of the roads around the Olympic park.

I first heard the news this morning, while driving into work. The reality was illustrated to me a mile or so further down the road.

Driving up the triple-lane westbound A4 from the Chiswick roundabout, I saw a cyclist on the road a hundred yards or so in front of me. I was in the nearside lane, he was moving out towards the offside lane to get out of the two other lanes (photo) which lead onto the M4 elevated section.

Shortly after he did so two cars overtook me, and passed him simultaneously, one overtaking him in the offside lane, the other undertaking in the middle lane. He was left sandwiched between them, cycling along the white line dividing the two lanes.

I felt for the guy. Unfortunately it seems indicative of the sort of behaviour one often sees on the road, with drivers treating cyclists as if they were invisible. Thankfully he was alright.

Now, you might think ‘why was he cycling in the road?’. The pavement alongside the westbound carriageway is a good few metres wide (unusually so for London), with a two-cycle path running down its length, which nicely bypasses the sliproad leading up onto the motorway by skirting around and underneath it.

The problem is the state of the thing. Bus stops, lamp posts and other street furniture sit right alongside it and even straddle it in some cases. Side roads cut across it with no apparent right of way for cyclists proceeding along it. Worse of all, the surface is full of so many bumps and potholes it’s worse than the surface of the moon.

Unless you have a good mountain bike you’re better in the road. That is the sad truth behind the cycle infrastructure that we do have, that even where it does exist you are often better off ignoring it and cycling down a tree-lane dual carriageway with traffic coming past you at 40mph.

I agree with Bradley Wiggins that both motorists and cyclists need to give more consideration of each other. But more importantly we need to rid ourselves of this 1950s vision of urban planning that the car is king and start putting cyclists on a more equal footing. Only then will we start to see fewer deaths and injuries on our roads.

Alfresco and ImageMagick on OSX

Since I migrated away from Windows on my development machine a couple of months back, I’ve not looked back. One of the main benefits I’ve found is being able to build software packages locally, and Homebrew makes that easy. Now I can easily grab the latest version of various dependencies such as MySQL and ImageMagick and install them in seconds, just as if I was using yum or apt-get.
However, one problem has plagued me since I started using the Homebrew-installed version of ImageMagick in conjunction with my local Alfresco installs, with errors such as this in the logs

 2012-08-02 10:20:10,547  DEBUG [transform.magick.AbstractImageMagickContentTransformerWorker] [main] org.alfresco.service.cmr.repository.ContentIOException: 07020000 Failed to perform ImageMagick transformation:
Execution result:
   os:         Mac OS X
   command:    [/usr/local/bin/convert, /Users/wabson/Development/projects/share-extras-2/software/tomcat/temp/Alfresco/ImageMagickContentTransformerWorker_init_source_4067880520213204197.gif[0], /Users/wabson/Development/projects/share-extras-2/software/tomcat/temp/Alfresco/ImageMagickContentTransformerWorker_init_target_7684811633126657147.png]
   succeeded:  true
   exit code:  133
   out:        
   err:        dyld: Symbol not found: __cg_jpeg_resync_to_restart
  Referenced from: /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ImageIO.framework/Versions/A/ImageIO
  Expected in: /usr/local/lib/libjpeg.8.dylib
 in /System/Libra

This frustrated me for a while. It happened every time Alfresco tried to call convert in order to effect an image transform – for instance generating doclib thumbnails – but running the exact same command at a bash prompt worked fine.
Various internet posts all pointed to the environment in which ImageMagick is run as being the cause for such problems. It seemed the environment variable DYLD_LIBRARY_PATH in particular was known to cause problems on OS X, but checking /etc/profile, /etc/bashrc and the custom alfresco.sh script I use to start up Alfresco (included in my Tomcat packages) did not yield any trace of such a variable.
Finally I found a comment in ALF-13452, which led me to check the Spring config within the thirdparty subsystem, responsible for starting up ImageMagick.

   <bean id="transformer.worker.ImageMagick">
      <property name="mimetypeService">
         <ref bean="mimetypeService" />
      </property>
      <property name="executer">
         <bean name="transformer.ImageMagick.Command">
            <property name="commandsAndArguments">
               <map>
                  <entry key=".*">
                     <list>
                        <value>${img.exe}</value>
                        <value>${source}</value>
                        <value>SPLIT:${options}</value>
                        <value>${target}</value>
                     </list>
                  </entry>
               </map>
            </property>
            <property name="processProperties">
               <map>
                  <entry key="MAGICK_HOME">
                     <value>${img.root}</value>
                  </entry>
                  <entry key="DYLD_LIBRARY_PATH">
                     <value>${img.dyn}</value>
                  </entry>
                  <entry key="LD_LIBRARY_PATH">
                     <value>${img.dyn}</value>
                  </entry>
               </map>
            </property>
            <property name="defaultProperties">
               <props>
                  <prop key="options"></prop>
               </props>
            </property>
         </bean>
      </property>
     ...

There it was. The subsystem itself was setting up a few environment variables before firing up the external process, and these were defined in processProperties. One was the DYLD_LIBRARY_PATH variable.
The solution was trivial. I copied the Spring config in tomcat/webapps/alfresco/WEB-INF/classes/alfresco/subsystems/thirdparty/default/imagemagick-transform-context.xml into tomcat/shared/classes/alfresco/extension/subsystems/thirdparty/default/default/imagemagick-transform-context.xml as per the subsystems docs on overriding beans, and commented out the offending <entry> element.

mkdir -p tomcat/shared/classes/alfresco/extension/subsystems/thirdparty/default/default/
cp tomcat/webapps/alfresco/WEB-INF/classes/alfresco/subsystems/thirdparty/default/imagemagick-transform-context.xml tomcat/shared/classes/alfresco/extension/subsystems/thirdparty/default/default/
vim tomcat/shared/classes/alfresco/extension/subsystems/thirdparty/default/default/imagemagick-transform-context.xml

The result – image conversions now work perfectly in my local dev environment using the Homebrew-installed version of ImageMagick.