Monday, June 20, 2016

Running SonarQube behind a proxy

I am a longtime user of the SonarQube quality management platform and was very pleased when SonarQube 5.6 LTS was released. I expected that the upgrade from the 4.5.7 LTS version would be as trouble-free as updates in the past. Unfortunately I noticed that the native https support was dropped. Thus the https support now has to be provided by a proxy as described in the "Securing the Server Behind a Proxy" documentation part.

It might be super easy to do this if you know what to do, but I had to struggel a while to get it working. I would like to share the steps I have taken.

(1) SonarQube configuration

My SonarQube 4.5.7 LTS native https configuration looked like that:
   # TCP port for incoming HTTPS connections. Disabled when value is -1 (default).

   # HTTPS - the password used to access the server certificate from the
   # specified keystore file. The default value is "changeit".

   # HTTPS - the pathname of the keystore file where is stored the server certificate.
   # By default, the pathname is the file ".keystore" in the user home.
   # If keystoreType doesn't need a file use empty value.

   # HTTPS - the type of keystore file to be used for the server certificate.
   # The default value is JKS (Java KeyStore).
As you see my server certificate was located in a PKCS12 keystore file and password protected.
The new SonarQube 5.6 LTS configuration does not include these parameters anymore. Thus I decided to run SonarQube on its default port 9000 for http on the machine.
Global access via port 80 (http) and port 443 (https) should be provided by an Apache HTTP server that acts as a proxy from now.

(2) Using Apache HTTP server as a proxy

My SonarQube server is a windows machine. Thus I needed a binary Apache HTTP Server distribution for Windows and decided to use the "Apache Lounge Distribution". Installation and service set up worked as described and smooth.

Apache HTTP should work as a http and https proxy for my SonarQube service. Therefore I added two virtual hosts to the configuration. Both ports redirect to the SonarQube service that is running on the same machine on port 9000.

(below only the activated or added parts of the Apache httpd.conf file are shown)
   LoadModule headers_module modules/
   LoadModule proxy_module modules/
   LoadModule proxy_http_module modules/
   LoadModule ssl_module modules/

   ProxyRequests off
   SSLPassPhraseDialog "exec:C:\MyKeystorePath\passphrase.bat"

   <VirtualHost *:80>
       ServerName MySonarQubeServerName
       ProxyPass / http://localhost:9000/
       ProxyPassReverse / http://localhost:9000/

   Listen 443
   <VirtualHost *:443>
        ServerName MySonarQubeServerName
        RequestHeader set X-Forwarded-Proto "https"
        ProxyPass / http://localhost:9000/
        ProxyPassReverse / http://localhost:9000/
        SSLEngine on
        SSLCertificateFile "C:\MyKeystorePath\MyKeystoreFile.crt"
        SSLCertificateKeyFile "C:\MyKeystorePath\MyKeystoreFile.key"

I had to uncomment the shown "LoadModule" lines to activate the modules that are needed for the proxy and SSL support. You can find detailed information about the configuration elements in the Apache Documentation (VirtualHosts, mod_headers, mod_proxy, mod_ssl).

The VirtualHost configuration is not difficult to understand. I just want to explain the (for me) special parts:

    RequestHeader set X-Forwarded-Proto "https"

This additional header ensures that a redirect will not fall back to http. The need for this configuration is mentioned in the SonarQube documentation.

SSLCertificateFile "C:\MyKeystorePath\MyKeystoreFile.crt"
SSLCertificateKeyFile "C:\MyKeystorePath\MyKeystoreFile.key"

To activate SSL a keystore and key file has to be provided. I was able to convert my PKCS12 file that I used for the former native SonarQube https support into these files with the openssl tool. The openssl tool luckily was provided in the bash of my Git installation.
$ openssl pkcs12 -in MyKeystoreFile.pfx -nocerts -passin pass:MyKeystorePassword -passout pass:MyKeystorePassword -out MyKeystoreFile.key
$ openssl pkcs12 -in MyKeystoreFile.pfx -clcerts -nokeys -passin pass:MyKeystorePassword -passout pass:MyKeystorePassword -out MyKeystoreFile.crt

You can find more information of the pkcs12 command in the OpenSSL docs. I must admit that I picked up the solution from various StackOverflow/ServerFault post like this and just added the password options that were required in my case.

The files are password protected. Therefore I need a program to serve the password to the Apache server on startup. This is what
SSLPassPhraseDialog "exec:C:\MyKeystorePath\passphrase.bat"

is for. "passphrase.bat" is very simple and just contains the line
@echo MyKeystorePassword
That's it. It was the hardest part of the update for me. The actual SonarQube software and database update went smoothly as always. Thanks to SonarSource for their great product and OSS conrtibution.

I would be happy if this information is useful for someone else.