Skip to content

Loading modules via SSL

Rob Rudin edited this page Aug 15, 2023 · 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.

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 (see Referring to a resource by its ID for how this ID reference works).
  • 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 tells ml-gradle to use a very basic SSLContext and SSLHostnameVerifier (basic in that they do not validate the MarkLogic app server's certificate) when loading modules into a REST API server.

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

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. A future version of ml-gradle aims to automate this procedure via new properties so that you do not need to maintain this code yourself.

Clone this wiki locally