We have recently had to change a maven project to use a repository hosted on an SSL secured server. I expected it to be easy expecting lots of documentation and help from maven, java and other forums available online. As it turned out I had a nightmare journey. The documentation is sparse to say the least and does not proivde issue tracking, alternatives or even a simple Q&A to easily troubleshoot common problems. To be honest there were times when I wanted to throw my machine and the floor and walk olut of the office in a hissy fit... fortunately, I didn't and thus I still have a job, and so that nobody else has to go through the same pain I have, you dont have to worry. I will now provide you with a simple guide for setting up your SSL connectivity in Maven in a step by step (with troubleshooting) guide. I won't bore you with the intricacies of the SSL jave implementations nor will I go into depth the reasons why certain things are required, however, I will try to give you hints when things go wrong and I will point out the problems I had:
1. Before you start, ensure you check with the repository manager as to what versions of Java and Maven are required (if any) to support your project using the secure repository. If you are having problems later down the line revisit this step as it may be an issue.
2. Maven provides a page for setting up the certificates but it didn't go far enough:http://maven.apache.org/guides/mini/guide-repository-ssl.html although in there defence it is only a "mini-guide" :-)
Some things to point out about the guide. It doesn't easily explain how to configure your .mavenrc file (this is only relevant to unix/linux machnies in any case) nor does it give any troubleshooting, which I would have liked to see.
The keytool comes with your java implementation, and if this step has tripped you up it is probably because you are running a runtime environment rather than a JDK, the keytool requires a JDK instation so you MUST set your JAVA_HOME to a JDK rather than a JRE!
Now you should have been given a certificate that you have installed on Firefox or Internet Explorer or one of many other browsers. I wont go into detail about "backup" of your certificate but this is what you will need to do to get a "keystore" file based version of your personal cetificate (with password protection). This link will help you with this on Firefox: https://support.comodo.com/index.php?_m=knowledgebase&_a=viewarticle&kbarticleid=1221
You can also check the existence of your certificate in the in the newly created keystore using (note that the storetype for the personal certificates from firefox will be in PKCS12 format or maybe a later version depending on when you read this blog):
keytool -keystore <my_certificates>.p12 -storetype pkcs12 -storepass <password> -list
Note that this is a store of certificates and can contain many cetificates if required. Java does not talk directly to certificates but requires stores to hold them. At this point you will either have another keystore of certificates from the host system you are trying to connect to (*.jks or *.p12) or the certificates themselves (*.pem). If you only have the certificates you will need to add them to a keyStore manually using the keytool:
keytool -import -trustcacerts -alias <alias_name> -file <host_cert.pem> -keystore <your_keystore_name.pks> -storepass <password> -noprompt -v
If the keystore doesn't exist it will create it for you. Note we are creating a default keystore type of PKS but you can create a PKCS12 store too by defining the -storetype PKCS12 switch. As many certificates as you need can be added in this way to the same store. To view what is in this store use the following:
keytool -keystore <your_keystore_name.pks> -storepass <password> -list
So by now you have 2 keystores, one for your personal certifcates and one for the "trust" certifcates from the host.
We then have 2 options for maven. You can either add the required parameters to the mvn command call directly (or via a calling script), or you can create a mavenrc file. This file comes in different flavours depending on which platform you are running:
in Linux: /etc/mavenrc or $HOME/.mavenrc file (for me it was in $HOME)
in Windows: %HOMEDRIVE%%HOMEPATH%\mavenrc_pre.bat file which is usually C:\Documents
and Settings\<username>\mavenrc_pre.bat (ensure you check the exact path by running echo %HOMEDRIVE%%HOMEPATH% . The resultant echo will show you where to locate your file.
My first attempt at implementation was by creating a wrapper mvn script which resided in the same directory as my pom.xml, my_certs.p12 and the host_certs.jks files making it possible to providerelative paths for all of SSL files:
set MAVEN_OPTS=%DEBUG% %TRUST_STORE% %KEY_STORE% %TRUST_STORE_PASSWORD% %KEY_STORE_PASSWORD% %TRUST_STORE_TYPE% %KEY_STORE_TYPE%
call mvn %MAVEN_OPTS% %MAVEN_COMMANDS%
Note we call maven at the end adding the MAVEN_OPTS to the command line rather than using them as "environment variables" as this does not work. This all allows you to run the SSL certs from the command line without having to use a mavenrc file. Also note the debug command I have added, it allows you to see the debug from the JSSE engine attempting to handshake with the SSL server. Here you can check your settings to ensure everything is being picked up correctly. If you dont see any debug appearing then your commands are not being picked up correctly so try running the maven command by hand that the script is running to ensure all of the -D parameters are being added correctly.
To use the mavenrc file route (for example if you need eclipse or another IDE to integrate with maven) here is my final version of the mavenrc_pre.bat file:
set MAVEN_OPTS=%TRUST_STORE% %KEY_STORE% %TRUST_STORE_PASSWORD% %KEY_STORE_PASSWORD% %TRUST_STORE_TYPE% %KEY_STORE_TYPE% %DEBUG%
echo Done: MAVEN_OPTS=%MAVEN_OPTS%
On Linux this file converts to:
MAVEN_OPTS="$TRUST_STORE $KEY_STORE $TRUST_STORE_PASSWORD $KEY_STORE_PASSWORD $TRUST_STORE_TYPE $KEY_STORE_TYPE $DEBUG"
echo Done: MAVEN_OPTS=$MAVEN_OPTS
Note that here we have created something similar as using the command line options but note the differences - now we must use absolute paths. At the end I have added some debug for running mvn to ensure that these MAVEN_OPTS are actually set. Remember also on any unix system that the content needs to be tailored to the specific shell you are using.
If this has all gone well then you should see that the handshakes work and all of your dependencies are downloaded correctly. Finding the right location for the MAVEN_OPTS file and then the setting of the MAVEN_OPTS value was my biggest issue - note sometimes quotes are required around the options for some systems while not for others.