In the world of Java development, working with Maven repositories is essential, as these repositories host the dependencies that our applications rely on. While connecting to public repositories like Maven Central is straightforward, accessing private or secured Maven repositories requires additional configuration. Specifically, when connecting over HTTPS, a Java Keystore may need to be configured to trust the repository’s SSL certificate. Here’s how to set up a Java Keystore for secure HTTPS connections to a Maven repository, ensuring a seamless and secure build process.
Why configure a keystore?
Java applications, including Maven, use the Java Keystore (JKS) to manage certificates for secure communication over SSL/TLS. If your Maven repository uses HTTPS with a self-signed or non-standard certificate, Maven might reject the connection because it cannot verify the certificate’s authenticity. By adding the repository’s certificate to a trusted keystore, you’re explicitly telling Java and Maven to trust this certificate. This setup is particularly relevant for organizations using internal repositories or third-party vendors with their own certificate infrastructure.
Create a test certificate chain
At first we build a custom certificate for test purposes. Please see the following few lines of bash:
# Step 1: Generate Root CA key and self-signed certificate
openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem -subj "/C=US/ST=State/L=City/O=MyCompany/OU=Org/CN=RootCA"
# Step 2: Generate End-User key and CSR
openssl genrsa -out endUser.key 4096
openssl req -new -key endUser.key -out endUser.csr -subj "/C=US/ST=State/L=City/O=MyCompany/OU=Org/CN=EndUser"
# Step 3: Sign the End-User CSR with the Root CA to create the end-user certificate
openssl x509 -req -in endUser.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out endUser.crt -days 500 -sha256
Create a Java Keystore (JKS) from certificate and key
Next we build the JKS file from our new certificate and key:
openssl pkcs12 \
-export \
-in endUser.crt \
-inkey endUser.key \
-out temp.p12 \
-name personalcreds \
-password pass:sometemporarypw
keytool \
-importkeystore \
-deststorepass YOUR_DESIRED_JKS_PW \
-destkeystore somename.jks \
-srckeystore temp.p12 \
-srcstoretype PKCS12 \
-srcstorepass sometemporarypw \
-alias personalcreds
rm -f temp.p12
Set up and use Maven’s .mvnrc file
Configuring SSL for Maven using a .mavenrc
file may look familiar to you as it involves setting up environment variables for your Java KeyStore (JKS) settings:
export MAVEN_OPTS="-Djavax.net.ssl.keyStore=/path/to/your/keystore.jks \
-Djavax.net.ssl.keyStorePassword=yourKeystorePassword \
-Djavax.net.ssl.trustStore=/path/to/your/truststore.jks \
-Djavax.net.ssl.trustStorePassword=yourTruststorePassword"
Put the file somewhere where your shell is able to consume it or run
$ source /path/to/your/.mavenrc
yourself to have your SSL config up and running.
Configure .mvn/jvm.config file for Maven SSL Authentication
A .mvn/jvm.config
keeps your project well-structured with regards to separation of concern and allows for an easy Maven SSL configuration. Therefore this is the way I recommend. To use it properly create a .mvn directory in your Maven project’s root directory, put it on .gitignore (or an equivalent file depending on your VCS) and place a file jvm.config
in there. Here we place our Maven SSL config like this:
-Djavax.net.ssl.keyStore=/path/to/your/keystore.jks
-Djavax.net.ssl.keyStorePassword=yourKeystorePassword
-Djavax.net.ssl.trustStore=/path/to/your/truststore.jks
-Djavax.net.ssl.trustStorePassword=yourTruststorePassword
Use the Maven settings.xml for SSL config
If you prefer to have the whole authentication process at one place there’s always the settings.xml for you:
<servers>
<server>
<id>your-secured-repo</id>
<configuration>
<javax.net.ssl.keyStore>path/to/your/maven_truststore.jks</javax.net.ssl.keyStore>
<javax.net.ssl.keyStorePassword>changeit</javax.net.ssl.keyStorePassword>
<javax.net.ssl.trustStore>path/to/your/maven_truststore.jks</javax.net.ssl.trustStore>
<javax.net.ssl.trustStorePassword>changeit</javax.net.ssl.trustStorePassword>
</configuration>
</server>
</servers>
Benefits of a custom keystore configuration
Setting up a custom keystore for Maven offers flexibility and security. It enables secure connections to internal repositories or those requiring special certificates, without affecting the global Java truststore. Additionally, it simplifies management when dealing with multiple repositories or environments, as each project or CI/CD pipeline can use its own keystore as needed.
Final Thoughts
While configuring a Java Keystore may seem daunting, it’s a powerful way to manage secure connections to Maven repositories. By following these steps, you can ensure that your Java applications are securely retrieving dependencies, protecting your codebase and development environment from potential threats. So next time you encounter an SSL error connecting to a repository, remember—it might just be a keystore configuration away from a quick fix! The full CA and JKS script can be found in this gist, and if you are not fed up with Java, here’s an interesting post covering Browser Test Automation in Java. If you’d rather see something else, don’t worry, here’s the Python version. One more I’d like to share with you: Fresh from the oven comes a post, where I explain the SQLException „before start of resultset“. Give it a click and and see you next time!