Skip to content

Loading modules via SSL

Rob Rudin edited this page Jan 24, 2024 · 21 revisions

ml-gradle and its underlying libraries - ml-javaclient-util and ml-app-deployer - provide support for creating an app server with a certificate template and then, in the case of a REST API server, loading modules via an SSL connection with that server.

Note that "SSL" is a misleading term these days, as the TLS protocol is widely used as a replacement for SSL. But "SSL" is still used throughout Java, particularly the SSLContext that is used to create a secure connection using either SSL or TLS.

As of ml-gradle 4.7.0, 2-way SSL - where the client must present a certificate and trust the server's certificate - is supported via properties and no longer requires writing Java code in your build.gradle file. Please see the section below on how to configure 2-way SSL.

The ssl-project example project shows an example of how this works - here are the moving parts:

  • A certificate template config file defines the template configuration.
  • The REST API server file includes a reference to the SSL certificate template.
  • The build.gradle file adds an instance of GenerateTemporaryCertificateCommand to the mlDeploy task. This temporary certificate is then used by the REST API server (the management API offers other options for generating real certificates). Without generating this certificate, the REST API server won't be able to accept HTTP or HTTPS connections.
  • gradle.properties includes mlSimpleSsl=true. This uses a "simple" or insecure approach where the server's certificate is not validated.

Note that if you've enabled SSL on the App-Services server (which defaults to port 8000), you'll also need to add mlAppServicesSimpleSsl=true for a "trust everything" approach.

Selecting the SSLContext protocol

Starting in 3.16.0, the default protocol is TLSv1.2. You can override this by setting the mlSimpleSsl and/or mlAppServicesSimpleSsl properties to any value besides "true" or "false".

Using your JVM's default keystore

Starting in 3.17.0, you can set mlRestUseDefaultKeystore=true and mlAppServicesUseDefaultKeystore=true so that your JVM's default keystore is used for trusting certificates (as opposed to the "trust everything" approach employed by mlSimpleSsl and mlAppServicesSimpleSsl). See the Property Reference for additional properties that you can configure when using this approach.

Note that when using this approach, you need to ensure that your JVM's default keystore - typically a file named cacerts - contains a certificate associated with the certificate template in use by the MarkLogic app server that ml-gradle will connect to. That certificate can be obtained via the following steps:

  1. Go to your MarkLogic server's Admin UI and select "Certificate Templates".
  2. Select the certificate template in use by your app server.
  3. Click on the "Status" tab for the certificate template.
  4. Scroll down to see the signed certificates for your certificate template. Depending on how you've configured your template, you may need to import all of these certificates into your JVM's default keystore.

Customizing the SSL objects

Instead of using mlSimpleSsl, you can always configure your own SSLContext and SSLHostnameVerifier. The AppConfig instance that is stored under the key "mlAppConfig" by ml-gradle has properties named "restSslContext" and "restSslHostnameVerifier" for these objects. You can set these to anything in your build.gradle file - here's a pseudocode example:

ext {
  def mySSLContext = write any Groovy code you want to create your own SSLContext
  def mySSLHostnameVerifier = write any Groovy code you want to create your own SSLHostnameVerifier
  def myTrustManager = write any Groovy code you want to create your own X509TrustManager

  mlAppConfig.restSslContext = mySSLContext
  mlAppConfig.restSslHostnameVerifier = mySSLHostnameVerifier
  mlAppConfig.restTrustManager = myTrustManager // Only supported starting in ml-gradle 3.8.3
}

Note that SSLHostnameVerifier is a MarkLogic Java Client class. It includes a few built-in implementations that may suffice for you.

As of version 3.0.0, you can also manually configure the SSL components for a connection to the App-Services server. This is necessary in case you've enabled SSL on the App-Services server, as that server is used for loading modules that are not REST extensions.

ext {
  mlAppConfig.appServicesSslContext = mySSLContext
  mlAppConfig.appServicesSslHostnameVerifier = mlSSLHostnameVerifier
  mlAppConfig.appServicesTrustManager = myTrustManager // Only supported starting in ml-gradle 3.8.3
}

Supporting 2-way SSL

Starting in ml-gradle 4.7.0, you can now configure 2-way SSL via properties. Since modules are typically loaded via both the App-Services port and the port of your REST API server, you will need to configure 2-way SSL for both connections (if one does not require 2-way SSL, then of course there is nothing further to configure for that connection).

The following properties allow you specify both a key store (which must contain your client certificate) and a trust store (which must contain the server's public certificate):

mlRestKeyStorePath=/path/to/keystore.jks
mlRestKeyStorePassword=optional password
mlRestKeyStoreType=JKS // Defaults to JKS
mlRestKeyStoreAlgorithm=SunX509 // Defaults to SunX509

mlRestTrustStorePath=/path/to/truststore.jks
mlRestTrustStorePassword=optional password
mlRestTrustStoreType=JKS // Defaults to JKS
mlRestTrustStoreAlgorithm=SunX509 // Defaults to SunX509

For the type and algorithm, if "JKS" and "SunX509" are the correct values, you do need to configure those.

If your App-Services app server requires 2-way SSL, you can use the following properties for that connection:

mlAppServicesKeyStorePath=/path/to/keystore.jks
mlAppServicesKeyStorePassword=optional password
mlAppServicesKeyStoreType=JKS // Defaults to JKS
mlAppServicesKeyStoreAlgorithm=SunX509 // Defaults to SunX509

mlAppServicesTrustStorePath=/path/to/truststore.jks
mlAppServicesTrustStorePassword=optional password
mlAppServicesTrustStoreType=JKS // Defaults to JKS
mlAppServicesTrustStoreAlgorithm=SunX509 // Defaults to SunX509

For ml-gradle prior to 4.7.0, the ssl-2way example project includes code in the project's build.gradle file to show how to construct an SSLContext based on a keystore containing a client certificate.

Clone this wiki locally