Skip to main content
ImportantLucidworks recommends not virus scanning the fusion/data folder. Virus scanning can cause slow performance, and it can cause downtime if it quarantines an index file identified as a possible virus.
Fusion uses a number of security measures:
  • Authenticating UI users – Fusion authenticates users when they log in. Logging in creates a new Fusion session. Fusion also authenticates users when the Sessions REST API creates a session.
  • Authorizing UI users – Fusion authorizes users to use specific parts of the Fusion UI.
    UI users must also be authorized to make API requests, because the UI makes API requests.
  • Authenticating and authorizing users who make API requests
  • Password Encryption- Fusion uses 128-bit AES keys to encrypt passwords and “AES/CBC/PKCS7Padding” for the cipher. The ciphertext is also signed.
  • Using session cookies
  • Using an external authentication provider (optional) - A security realm can specify use of an external authentication provider, such as LDAP, JWT, or SAML.
  • Using SSL/TLS to ensure that data in flight between your application and Fusion is not observable (optional) - See SSL Security (Unix) or SSL Security (Windows).
  • Constraining the documents that are indexed (optional)
  • Trimming the documents that are returned by queries based on authorization (optional)
Fusion’s UI (which is accessed through the Fusion Proxy service) can run over SSL for secure communication with any HTTP client, using the Java Secure Socket Extension (JSSE) framework. You configure Fusion for SSL by configuring Fusion’s Proxy and UI services.

Required software

Configuring Fusion for SSL requires the following software:
  • Java Development Kit. To store certificates, you can use the Java keytool Key and Certificate Management utility which is a part of the JDK.
  • OpenSSL. You might need the openssl command line tool:
    • If you have the certificate chain and private key as separate files, then you can use the openssl command line tool to create a PKCS #12 file.
    • If you have an intermediate CA certificate, then you can use it and openssl to generate the certificate chain and private key files.

Load an SSL certificate into a Fusion keystore

The SSL protocol is based on public-key cryptography where encryption keys come in public key/private key pairs. An SSL certificate is used to verify the authenticity of a particular server. It contains the web site name, contact email address, company information and the public key used to encrypt the communication which is shared with the entities that communicate with the owner of the public/private key pair.The server has a locally-protected private key that is accessible via a JSEE keystore.The keystore maintains both the server certificate and the private key, so that when a server authenticates itself to the client, it uses the private key from its keystore for the initial SSL handshake.Load the certificate into a Fusion keystore. Perform the tasks in the appropriate section:
  • Self-signed certificate. If Fusion is behind a firewall, you can use a self-signed certificate for SSL communication with other hosts in your internal network. Create a keystore for the Fusion Proxy service and load the keystore with the self-signed PKCS #12 certificate.
  • Certificate signed by a certificate authority. In a production environment, SSL certificates typically originate with certificate signing requests (CSRs) and are signed by a trusted third-party Certificate Authority (CA). Create a keystore for the Fusion Proxy service and load the keystore with the PKCS #12 certificate from a CA.

Alternative 1: Self-signed certificate

If you are using a CSR-originated certificate from a trusted certificate authority, proceed to Alternative 2: CA-signed certificate.
If Fusion is behind a firewall, you can use a self-signed certificate for SSL communication with other hosts in your internal network. Create a keystore for the Fusion Proxy service and load the keystore with the self-signed PKCS #12 certificate.To store certificates, you can use the Java keytool Key and Certificate Management utility which is a part of the JDK.How to create a keystore and load a self-signed certificate
  1. Set environment variables:
    export JAVA_HOME=JavaHomeDirectory
    export FUSION_HOME=FusionHomeDirectory
    
  2. Create the Fusion Proxy service keystore, generate the key pair and self-signed certificate, and load them into the keystore:
    "$JAVA_HOME/bin/keytool" -genkeypair -keystore "$FUSION_HOME/apps/jetty/proxy/etc/keystore" -dname "CN=CommonName, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown" -keypass KeyPassword -storepass KeystorePassword -keyalg RSA -alias selfsigned -deststoretype pkcs12 -ext SAN=dns:ServerFqdn,ip:ServerIpAddress
    
    You must include the qualified domain name and/or the IP address of the Fusion server in the -ext SAN part of the command. Failure to do so results in SSL validation errors.
    Example command:
    "$JAVA_HOME/bin/keytool" -genkeypair -keystore "$FUSION_HOME/apps/jetty/proxy/etc/keystore" -dname "CN=search.mycorp, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown" -keypass 59Winter.Is.Long45 -storepass 46I.Prefer.Vanilla24 -keyalg RSA -alias selfsigned -deststoretype pkcs12 -ext SAN=dns:search.mycorp,ip:192.168.1.40,dns:localhost
    
The resulting certificate enables validated SSL transport to these hosts:
https://search.mycorp:ProxyPort
https://192.168.1.40:ProxyPort
https://localhost:ProxyPort
Where ProxyPort is the Fusion Proxy port.

Alternative 2: CA-signed certificate

If Fusion is behind a firewall and you are using a self-signed certificate, skip this section. Perform the tasks in Alternative 1: Self-signed certificate.
In a production environment, SSL certificates typically originate with certificate signing requests (CSRs) and are signed by a trusted third-party Certificate Authority (CA).The steps here assume that you are the person who will be obtaining the SSL certificate chain and private key files. If you are not that person, contact your system administrator.

Preliminary steps

  1. Obtain a domain from a domain registrar.
  2. Change the A record of your domain to the public IP address of your web server instance.

Generate SSL certificate files

Use an SSL certificate provider to generate the certificate chain and private key files, or a PKCS #12 certificate, from a trusted CA:
  • Certificate chain and private key files. In this case, you will need to convert these files into a single certificate file in PKCS #12 format.
  • A PKCS #12 certificate. This must contain both the certificate chain and private key. In this case, no conversion is necessary.
How to obtain certificate files
  1. In most cases, you will need to temporarily open ports 80 and 443 in your firewall configuration. The SSL certificate provider must be able to make successful HTTP and HTTPS requests to your server through the Domain Name System (DNS).
  2. Use an SSL certificate provider to generate the certificate chain (fullchain.pem) and private key (privkey.pem) files, or the PKCS #12 certificate, from a trusted CA. Steps will vary based on the certificate provider. Contact your certificate provider for details.
  3. Close ports 80 and 443 in your firewall configuration.
  4. Change the A record of your domain to the public domain-name address of your web server instance.
Proceed to the next sections as follows:

Convert the certificate chain and private key files to a PKCS #12 certificate

If you have a PKCS #12 certificate, skip this section and proceed to the section Import the PKCS #12 certificate into the Fusion Proxy service keystore.
With the certificate chain and private key as separate files, use the openssl command line tool in OpenSSL to create a PKCS #12 certificate.
openssl pkcs12 -export -out /path/to/keystore.p12 -in /path/to/fullchain.pem -inkey /path/to/privkey.pem
Do not enter a blank password.

Create the Fusion Proxy service keystore and import the PKCS #12 certificate

Use the Java keytool Key and Certificate Management utility to create a keystore for the Fusion Proxy service ($FUSION_HOME/apps/jetty/proxy/etc/keystore) and import the PKCS #12 certificate file. Fusion uses this certificate to perform SSL.
  1. To create the keystore and import the PKCS #12 certificate:
  2. Use the keytool import command to create a JSSE keystore.
    keytool -importkeystore -srckeystore /path/to/keystore.p12 -srcstoretype PKCS12 -destkeystore "$FUSION_HOME/apps/jetty/proxy/etc/keystore" -deststoretype PKCS12
    
  3. (Optional) If desired, delete the PKCS #12 certificate file that resides outside of the Fusion Proxy service keystore (the one you created from the certificate chain and private key files, or obtained from a trusted CA.
    rm /path/to/keystore.p12
    

Enable HTTPS in the Fusion Proxy service

Before beginning these steps, load an SSL certificate into a Fusion keystore.How to enable HTTPS in the Fusion Proxy service:
  1. (Only for Fusion Server 4.0.x and 4.1.0) Prevent the start.jar program from downloading a default keystore file, which is not needed. Edit $FUSION_HOME/apps/jetty/home/modules/ssl.mod. Comment out the indicated line using #. Change:
    [files]
    https://raw.githubusercontent.com/eclipse/jetty.project/master/jetty-server/src/test/config/etc/keystore?id=${jetty.tag.version}|etc/keystore
    
    To:
    [files]
    # https://raw.githubusercontent.com/eclipse/jetty.project/master/jetty-server/src/test/config/etc/keystore?id=${jetty.tag.version}|etc/keystore
    
  2. Set environment variables:
    export JAVA_HOME=JavaHomeDirectory
    export FUSION_HOME=FusionHomeDirectory
    
  3. Add HTTPS protocol support to the Jetty TLS (SSL) connector:
    cd "$FUSION_HOME/apps/jetty/proxy/"
    java -jar "$FUSION_HOME/apps/jetty/home/start.jar" --add-to-start=https
    
    Example output:
    INFO: ssl             initialized (transitively) in ${jetty.base}/start.ini
    INFO: https           initialized in ${jetty.base}/start.ini
    INFO: Base directory was modified
    
  4. Get the obfuscated version of your keystore password:
    java -cp "$FUSION_HOME/apps/jetty/home/lib/*" org.eclipse.jetty.util.security.Password PASSWORD
    
    Replace PASSWORD with the password you used for the keystore. If the password contains special characters, URL encode them. Example output:
    2018-05-15 12:32:48.988:INFO::main: Logging initialized @133ms
    password345XYZ
    OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0
    MD5:b91cd1a54781790beaa2baf741fa6789
    
  5. Edit the file $FUSION_HOME/apps/jetty/proxy/start.ini:
    1. Include obfuscated passwords by adding these properties to the end of the file:
      * `jetty.sslContext.keyStorePassword`
      * `jetty.sslContext.keyManagerPassword`
      * `jetty.sslContext.trustStorePassword`
      
    2. Use the OBF-encrypted password from step 4 (including the OBF: string) as the value for all three of the properties.
      For example:
      ## Keystore password
      jetty.sslContext.keyStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
      ...
      
      ## KeyManager password
      jetty.sslContext.keyManagerPassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
      ## Truststore password
      jetty.sslContext.trustStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
    3. Set the local SSL port by adding the jetty.ssl.port property to the end of the file, and providing the port number. For example:
      ## Connector port to listen on
      jetty.ssl.port=8443
      
    4. Save the file $FUSION_HOME/apps/jetty/proxy/start.ini.

Restart Fusion and test access through HTTPS

  1. Restart all Fusion services:
    ./bin/fusion restart
    
    HTTPS should now be enabled in the Fusion Proxy service.
  2. Sign in to the Fusion UI. Specify the HTTPS URL scheme and SSL port, for example, https://search.mycorp:8443.

Disable HTTP access to the Fusion Proxy service

Disable HTTP access. You have a choice. Perform the tasks in the appropriate section:

Alternative 1: Disable HTTP access on the firewall or load balancer

Disable HTTP access to the Fusion Proxy service on the firewall or load balancer:
  1. Disallow all requests for port 8764 from the outside world. Only localhost should be able to communicate with Fusion on the non-SSL port 8764. Block all other requestors.
  2. If you are using a firewall or load balancer in front of Fusion, use it to redirect all HTTP requests to use HTTPS instead. For example, Apache would redirect all incoming HTTP traffic to HTTPS.

Alternative 2: Disable listening for HTTP requests in the Fusion Proxy service

Ideally, you should disable HTTP access using the firewall or load balancer. Follow the steps in this section only if disabling HTTP access on the firewall or load balancer is not feasible.
You can only use this alternative if your SSL certificate covers a hostname that can be accessed from the local host. For example, if your certificate only covers https://fusion.com, then your local machine must be able to access Fusion from that exact host. If necessary, change the hosts file so that this can work.How to disable HTTP
  1. Edit /opt/lucidworks/fusion/latest.x/apps/jetty/proxy/start.d/http.ini.
    1. Change this line:
      --module=http
      
      To:
      #--module=http
      
    2. Save the file.
  2. Edit the Fusion configuration file, /opt/lucidworks/fusion/latest.x/conf/fusion.cors.
    1. Ensure that the Agent JVM uses the Fusion Proxy service’s keystore by adding this to the end of the file:
      agent.jvmOptions=-Djavax.net.ssl.trustStore="${FUSION_HOME}/apps/jetty/proxy/etc/keystore" -Djavax.net.ssl.trustStorePassword=PASSWORD -Djavax.net.ssl.keyStore="${FUSION_HOME}/apps/jetty/proxy/etc/keystore" -Djavax.net.ssl.keyStorePassword=PASSWORD
      
      Replace PASSWORD with your Fusion keystore password.
    2. Uncomment the default.address and change it to the hostname of the server that is validated by your SSL certificate.
      If the hostname saved in default.address is not validated by your SSL certificate, then the Fusion Proxy service will not start, because the agent’s liveness detector will not be able to access the HTTPS port to determine whether Fusion is running.
      If you self-signed the certificate, then the default.address must match the hostname you specified while signing the certificate. Failure to do this will result in the Fusion Proxy service not starting after you have disabled HTTP.
      For example, if your SSL certificate’s validated hostname is search.mycorp, then change:
      #default.address = 127.0.0.1
      
      To:
      default.address = search.mycorp
      
    3. Change the proxy.port to the SSL port you chose.
    4. Uncomment proxy.ssl and change its value to true. Change:
      # proxy.ssl=false
      
      To:
      proxy.ssl=true
      
Stopping and starting Fusion is needed for these changes to take effect. But there is a bit more to do concerning the Fusion Agent before restarting Fusion.

References and tutorials

Fusion’s UI (which is accessed through the Fusion Proxy service) can run over SSL for secure communication with any HTTP client, using the Java Secure Socket Extension (JSSE) framework. You configure Fusion for SSL by configuring Fusion’s Proxy and UI services.

Required software

Configuring Fusion for SSL requires the following software:
  • Java Development Kit. To store certificates, you can use the Java keytool Key and Certificate Management utility which is a part of the JDK.
  • OpenSSL. You might need the openssl command line tool:
    • If you have the certificate chain and private key as separate files, then you can use the openssl command line tool to create a PKCS #12 file.
    • If you have an intermediate CA certificate, then you can use it and openssl to generate the certificate chain and private key files.

Overview of procedure

How to configure Fusion for SSL:
  1. Load an SSL certificate into a Fusion keystore.
  2. Enable SSL in the Fusion Proxy service.
  3. Restart Fusion and test access through HTTPS.
  4. Disable HTTP access to the Fusion Proxy service.

Load an SSL certificate into a Fusion keystore

The SSL protocol is based on public-key cryptography where encryption keys come in public key/private key pairs. An SSL certificate is used to verify the authenticity of a particular server. It contains the web site name, contact email address, company information and the public key used to encrypt the communication which is shared with the entities that communicate with the owner of the public/private key pair.The server has a locally-protected private key that is accessible via a JSEE keystore.The keystore maintains both the server certificate and the private key, so that when a server authenticates itself to the client, it uses the private key from its keystore for the initial SSL handshake.Load the certificate into a Fusion keystore. Perform the tasks in the appropriate section:
  • Self-signed certificate. If Fusion is behind a firewall, you can use a self-signed certificate for SSL communication with other hosts in your internal network. Create a keystore for the Fusion Proxy service and load the keystore with the self-signed PKCS #12 certificate.
  • Certificate signed by a certificate authority. In a production environment, SSL certificates typically originate with certificate signing requests (CSRs) and are signed by a trusted third-party Certificate Authority (CA). Create a keystore for the Fusion Proxy service and load the keystore with the PKCS #12 certificate from a CA.

Alternative 1: Self-signed certificate

If you are using a CSR-originated certificate from a trusted certificate authority, proceed to Alternative 2: CA-signed certificate.
If Fusion is behind a firewall, you can use a self-signed certificate for SSL communication with other hosts in your internal network. Create a keystore for the Fusion Proxy service and load the keystore with the self-signed PKCS #12 certificate.To store certificates, you can use the Java keytool Key and Certificate Management utility which is a part of the JDK.How to create a keystore and load a self-signed certificate
  1. Set environment variables:
    set JAVA_HOME=JavaHomeDirectory
    set FUSION_HOME=FusionHomeDirectory
    
  2. Create the Fusion Proxy service keystore, generate the key pair and self-signed certificate, and load them into the keystore:
    "%JAVA_HOME%\bin\keytool.exe" -genkeypair -keystore "%FUSION_HOME%\apps\jetty\proxy\etc\keystore" -dname "CN=CommonName, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown" -keypass KeyPassword -storepass KeystorePassword -keyalg RSA -alias selfsigned -deststoretype pkcs12 -ext SAN=dns:ServerFqdn,ip:ServerIpAddress
    
    You must include the qualified domain name and/or the IP address of the Fusion server in the -ext SAN part of the command. Failure to do so results in SSL validation errors.
    Example command:
    "%JAVA_HOME%\bin\keytool.exe" -genkeypair -keystore "%FUSION_HOME%\apps\jetty\proxy\etc\keystore" -dname "CN=CommonName, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown" -keypass 59Winter.Is.Long45 -storepass 46I.Prefer.Vanilla24 -keyalg RSA -alias selfsigned -deststoretype pkcs12 -ext SAN=dns:search.mycorp,ip:192.168.1.40,dns:localhost
    
    The resulting certificate enables validated SSL transport to these hosts:
https://search.mycorp:ProxyPort
https://192.168.1.40:ProxyPort
https://localhost:ProxyPort
Where ProxyPort is the Fusion Proxy port.

Alternative 2: CA-signed certificate

If Fusion is behind a firewall and you are using a self-signed certificate, skip this section. Perform the tasks in Alternative 1: Self-signed certificate.
In a production environment, SSL certificates typically originate with certificate signing requests (CSRs) and are signed by a trusted third-party Certificate Authority (CA).The steps here assume that you are the person who will be obtaining the SSL certificate chain and private key files. If you are not that person, contact your system administrator.

Preliminary steps

  1. Obtain a domain from a domain registrar.
  2. Change the A record of your domain to the public IP address of your web server instance.

Generate SSL certificate files

Use an SSL certificate provider to generate the certificate chain and private key files, or a PKCS #12 certificate, from a trusted CA:
  • Certificate chain and private key files. In this case, you will need to convert these files into a single certificate file in PKCS #12 format.
  • A PKCS #12 certificate that contains both the certificate chain and private key. In this case, no conversion is necessary.
How to obtain certificate files
  1. In most cases, you will need to temporarily open ports 80 and 443 in your firewall configuration. The SSL certificate provider must be able to make successful HTTP and HTTPS requests to your server through the Domain Name System (DNS).
  2. Use an SSL certificate provider to generate the certificate chain (fullchain.pem) and private key (privkey.pem) files, or the PKCS #12 certificate, from a trusted CA. Steps will vary based on the certificate provider. Contact your certificate provider for details.
  3. Close ports 80 and 443 in your firewall configuration.
  4. Change the A record of your domain to the public domain-name address of your web server instance.
Proceed to the next sections as follows:

Convert the certificate chain and private key files to a PKCS #12 certificate

If you have a PKCS #12 certificate, skip this section and proceed to the section Import the PKCS #12 certificate into the Fusion Proxy service keystore.
How to create a PKCS #12 certificateWith the certificate chain and private key as separate files, use the openssl command line tool in OpenSSL to create a PKCS #12 certificate.
openssl pkcs12 -export -out \path\to\keystore.p12 -in \path\to\fullchain.pem -inkey \path\to\privkey.pem
Do not enter a blank password.

Create the Fusion Proxy service keystore and import the PKCS #12 certificate

Use the Java keytool Key and Certificate Management utility to create a keystore for the Fusion Proxy service (%FUSION_HOME%\apps\jetty\proxy\etc\keystore) and import the PKCS #12 certificate file. Fusion uses this certificate to perform SSL.
If you are starting with a certificate file in PFX format (file extension .pfx), that format is now identical to PKCS #12 format.
  1. To create the keystore and import the PKCS #12 certificate:
    "%JAVA_HOME%\bin\keytool.exe" -genkeypair -alias mykeystore -keyalg RSA -keysize 2048 -keystore keystore.jks
    
    "%JAVA_HOME%\bin\keytool.exe" -importkeystore -srckeystore mycertificate.p12 -srcstoretype PKCS12 -destkeystore keystore.jks
    
  2. Use the keytool import command to create a JSSE keystore.
    keytool -importkeystore -srckeystore \path\to\keystore.p12 -srcstoretype PKCS12 -destkeystore "%FUSION_HOME%\apps\jetty\proxy\etc\keystore" -deststoretype PKCS12
    
  3. (Optional) If desired, delete the PKCS #12 certificate file that resides outside of the Fusion Proxy service keystore (the one you created from the certificate chain and private key files, or obtained from a trusted CA.
    del \path\to\keystore.p12
    

Enable HTTPS in the Fusion Proxy service

Before beginning these steps, load an SSL certificate into a Fusion keystore.How to enable HTTPS in the Fusion Proxy service:
  1. Set environment variables:
    set JAVA_HOME=JavaHomeDirectory
    set FUSION_HOME=FusionHomeDirectory
    
  2. Add HTTPS protocol support to the Jetty TLS (SSL) connector:
    cd "%FUSION_HOME%\apps\jetty\proxy\"
    java -jar "%FUSION_HOME%\apps\jetty\home\start.jar" --add-to-start=https
    
    Example output:
    INFO: ssl             initialized (transitively) in ${jetty.base}/start.ini
    INFO: https           initialized in ${jetty.base}/start.ini
    INFO: Base directory was modified
    
  3. Get the obfuscated version of your keystore password:
    java -cp "$FUSION_HOME/apps/jetty/home/lib/*" org.eclipse.jetty.util.security.Password PASSWORD
    
    Replace PASSWORD with the password you used for the keystore. If the password contains special characters, URL encode them. Example output:
    2018-05-15 12:32:48.988:INFO::main: Logging initialized @133ms
    password345XYZ
    OBF:1vn21ugu1saj1v9i1v941sar1ugw1vo0
    MD5:b91cd1a54781790beaa2baf741fa6789
    
  4. Edit the file %FUSION_HOME%\apps\jetty\proxy\start.ini:
    1. Include obfuscated passwords by adding these properties to the end of the file:
      • jetty.sslContext.keyStorePassword
      • jetty.sslContext.keyManagerPassword
      • jetty.sslContext.trustStorePassword
    2. Use the OBF-encrypted password from step 4 (including the OBF: string) as the value for all three of the properties.
      For example:
      ## Keystore password
      jetty.sslContext.keyStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
      ...
      
      ## KeyManager password
      jetty.sslContext.keyManagerPassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
      ## Truststore password
      jetty.sslContext.trustStorePassword=OBF:2uha1vgt1jg01a4b1a4j1jda1vg11ugg
      
    3. Set the local SSL port by adding the jetty.ssl.port property to the end of the file, and providing the port number. For example:
      ## Connector port to listen on
      jetty.ssl.port=8443
      
    4. Save the file %FUSION_HOME%\apps\jetty\proxy\start.ini.

Restart Fusion and test access through HTTPS

  1. Restart all Fusion services:
    bin\fusion.cmd restart
    
    HTTPS should now be enabled in the Fusion Proxy service.
  2. Sign in to the Fusion UI. Specify the HTTPS URL scheme and SSL port, for example, https://search.mycorp:8443.

Disable HTTP access to the Fusion Proxy service

Disable HTTP access. You have a choice. Perform the tasks in the appropriate section:

Alternative 1: Disable HTTP access on the firewall or load balancer

Disable HTTP access to the Fusion Proxy service on the firewall or load balancer:
  1. Disallow all requests for port 8764 from the outside world. Only localhost should be able to communicate with Fusion on the non-SSL port 8764. Block all other requestors.
  2. If you are using a firewall or load balancer in front of Fusion, use it to redirect all HTTP requests to use HTTPS instead. For example, Apache would redirect all incoming HTTP traffic to HTTPS.

Alternative 2: Disable listening for HTTP requests in the Fusion Proxy service

Ideally, you should disable HTTP access using the firewall or load balancer. Follow the steps in this section only if disabling HTTP access on the firewall or load balancer is not feasible.
You can only use this alternative if your SSL certificate covers a hostname that can be accessed from the local host. For example, if your certificate only covers https://fusion.com, then your local machine must be able to access Fusion from that exact host. If necessary, change the hosts file so that this can work.How to disable HTTP
  1. Edit \lucidworks\fusion\latest.x\apps\jetty\proxy\start.d\http.ini.
    1. Change this line:
      --module=http
      
      To:
      #--module=http
      
    2. Save the file.
  2. Edit the Fusion configuration file, \lucidworks\fusion\latest.x\conf\fusion.cors.
    1. Ensure that the Agent JVM uses the Fusion Proxy service’s keystore by adding this to the end of the file:
      agent.jvmOptions=-Djavax.net.ssl.trustStore="%{FUSION_HOME}%\\apps\\jetty\\proxy\\etc\\keystore" -Djavax.net.ssl.trustStorePassword=PASSWORD -Djavax.net.ssl.keyStore="%{FUSION_HOME}%\\apps\\jetty\\proxy\\etc\\keystore" -Djavax.net.ssl.keyStorePassword=PASSWORD
      
      Replace PASSWORD with your Fusion keystore password.
    2. Uncomment the default.address and change it to the hostname of the server that is validated by your SSL certificate.
      If the hostname saved in default.address is not validated by your SSL certificate, then the Fusion Proxy service will not start, because the agent’s liveness detector will not be able to access the HTTPS port to determine whether Fusion is running.
      If you self-signed the certificate, then the default.address must match the hostname you specified while signing the certificate. Failure to do this will result in the Fusion Proxy service not starting after you have disabled HTTP.
      For example, if your SSL certificate’s validated hostname is search.mycorp, then change:
      #default.address = 127.0.0.1
      
      To:
      default.address = search.mycorp
      
    3. Change the proxy.port to the SSL port you chose. For example, change:
      proxy.port = 8764
      
      To:
      proxy.port = 8443
      
    4. Uncomment proxy.ssl and change its value to true. Change:
      # proxy.ssl=false
      
      To:
      proxy.ssl=true
      
Stop and start Fusion for these changes to take effect.

References and tutorials

Fusion user login

When logging into the Fusion UI, a user provides a username and password, as well as their assigned security realm. An administrator must specify these in Fusion (using the native security realm) or configure Fusion to use an external authentication provider (for example, LDAP or SAML). See Access control. Fusion uses roles defined by permissions to authorize Fusion UI access and perform tasks in Fusion, including searching. The recommended method to delegate permissions is as follows:
  • Assign each user to a role and create custom roles as needed.
  • Assign permissions on a per-app basis.

Manage users with security realms

Fusion uses security realms to authenticate users of the Fusion UI. Each user has an assigned security realm, which the user must select when logging in. If the user selects a different realm, authentication fails. A security realm also provides a list of roles as follows:
  • The list always includes the role(s) that are specified in the security realm.
  • (Optional) If an external directory service (such as LDAP) is used for authentication, the list can also contain roles that are mapped from the names of the directory-service groups. That is, you can configure a security realm to return group information for users from that same directory service.
  • (Optional) The security realm can reference one or more Fusion roles or, when using an external directory service provider, use group membership information from the provider to determine roles for users. Fusion maps the group names to role names and adds these roles to the user’s list of roles.
Fusion does not use permissions from LDAP to authorize UI access or API requests. It only obtains group names (optionally), which are used as role names or are mapped to role names. If an Active Directory Security Query Trimming Stage is used, then directory-service permissions are used for trimming. If a connector supports security trimming, then connector permissions are used for trimming.

Per-request authentication

Requests to the Fusion REST API must specify a security realm for per-request authentication, unless a session cookie is used (which contains information about the security realm). Fusion authorizes requested operations based on API permissions specified for the user and for the user’s role(s). Fusion considers the role(s) specified in the user definition and in the security realm. Fusion creates a list of roles when a session is created, that is, when a user logs in or when the Sessions REST API creates a session. Authorization based on permissions and its layering is at request time. You can define multiple security realms for a Fusion instance. A Fusion instance can manage multiple security realms, which allows users from different domains to have (different levels of) access to specific Fusion collections.

Read-only root file system

Fusion 5.9.9 and later supports a read-only root file system to safeguard against unauthorized modifications, protecting your deployment against malicious software and other attacks. Most services operate efficiently in this mode, and for components that need write access, a separate writable mount is available using specific helm configurations. Read-only mode should only be enabled for services that do not require CRUD access. See Enable Read-Only Root File System for examples of how to configure this feature.
This topic describes how to configure a read-only root file system for a Fusion deployment. Read-only mode safeguards your file system against unauthorized changes, such as by malicious software or other attacks. Enabling this feature entails configuring the readOnlyRootFilesystem attribute in the Fusion Helm chart.
This feature is available starting in Fusion 5.9.9 and in all subsequent Fusion 5.9 releases.
Beginning with Fusion 5.9.10, all of Fusion’s services are designed to work with a read-only root file system, but some external services may require write access to the file system. In that case, you can configure a read-only root file system and mount a separate writable file system for these services.The examples below show how to configure a read-only root file system for various Fusion services.

Solr

fusion:
  solr:
    containerSecurityContext:
      readOnlyRootFilesystem: true
With optional services:
fusion:
  solr:
    exporter:
      enabled: true
      securityContext:
        readOnlyRootFilesystem: true
    containerSecurityContext:
      readOnlyRootFilesystem: true

Zookeeper

fusion:
  zookeeper:
    containerSecurityContext:
      readOnlyRootFilesystem: true
With optional services:
fusion:
  zookeeper:
    containerSecurityContext:
      readOnlyRootFilesystem: true
    exporters:
      jmx:
        enabled: true
      zookeeper:
        enabled: true
    jobs:
      chroots:
        enabled: true
        config:
          create:
            - /root-read-only

Kafka

fusion:
  kafka:
    containerSecurityContext:
      readOnlyRootFilesystem: true
With optional services:
fusion:
  kafka:
    containerSecurityContext:
      readOnlyRootFilesystem: true
    volumePermissions:
      enabled: true
      containerSecurityContext:
        readOnlyRootFilesystem: true
    metrics:
      kafka:
        containerSecurityContext:
          readOnlyRootFilesystem: true
          enabled: true
      jmx:
        enabled: true
        containerSecurityContext:
          enabled: true
          readOnlyRootFilesystem: true
    externalAccess:
      enabled: true
      autoDiscovery:
        enabled: true
        containerSecurityContext:
          enabled: true
          readOnlyRootFilesystem: true
    provisioning:
      enabled: true
      topics:
      - name: test
        partitions: 1
        replicationFactor: 1
        ## https://kafka.apache.org/documentation/#topicconfigs
        config:
          max.message.bytes: 64000
          flush.messages: 1
      containerSecurityContext:
        readOnlyRootFilesystem: true
        enabled: true

ML Model Service

fusion:
  ml-model-service:
    ambassador:
      containerSecurityContext:
        readOnlyRootFilesystem: true
    milvus:
      mysql:
        containerSecurityContext:
          readOnlyRootFilesystem: true
      securityContext:
        readOnlyRootFilesystem: true
With optional services:
fusion:
  ml-model-service:
    ambassador:
      containerSecurityContext:
        readOnlyRootFilesystem: true
      prometheusExporter:
        enabled: true
        securityContext:
          readOnlyRootFilesystem: true
    milvus:
      mysql:
        metrics:
          enabled: true
          securityContext:
            readOnlyRootFilesystem: true
        containerSecurityContext:
          readOnlyRootFilesystem: true
      cluster:
        enabled: false
      mishards:
        securityContext:
          readOnlyRootFilesystem: true
      admin:
        enabled: true
        securityContext:
          readOnlyRootFilesystem: true
      securityContext:
        readOnlyRootFilesystem: true

Argo

fusion:
  argo:
    minio:
      containerSecurityContext:
        readOnlyRootFilesystem: true
      extraVolumes:
        - name: config-dir
          emptyDir: {}
        - name: certs-dir
          emptyDir: {}
      extraVolumeMounts:
        - name: config-dir
          mountPath: /.minio
        - name: certs-dir
          mountPath: /etc/minio/certs
    server:
      securityContext:
        readOnlyRootFilesystem: true
    controller:
      securityContext:
        readOnlyRootFilesystem: true
    mainContainer:
      securityContext:
        readOnlyRootFilesystem: true
    executor:
      securityContext:
        readOnlyRootFilesystem: true

Seldon Core Operator

fusion:
  seldon-core-operator:
    containersSecurityContext:
      readOnlyRootFilesystem: true

Argo Common Workflows

fusion:
  argo-common-workflows:
    containerSecurityContext:
      readOnlyRootFilesystem: true

Question Answering

fusion:
  question-answering:
    containersSecurityContext:
      readOnlyRootFilesystem: true

Classification

fusion:
  classification:
    containersSecurityContext:
      readOnlyRootFilesystem: true

All-in-one values.yaml example

fusion:
  solr:
    containerSecurityContext:
      readOnlyRootFilesystem: true
  solr-managed:
    containerSecurityContext:
      readOnlyRootFilesystem: true
  zookeeper:
    containerSecurityContext:
      readOnlyRootFilesystem: true
  kafka:
    containerSecurityContext:
      readOnlyRootFilesystem: true
  ml-model-service:
    ambassador:
      containerSecurityContext:
        readOnlyRootFilesystem: true
    milvus:
      mysql:
        containerSecurityContext:
          readOnlyRootFilesystem: true
      securityContext:
        readOnlyRootFilesystem: true
  argo:
    minio:
      containerSecurityContext:
        readOnlyRootFilesystem: true
      extraVolumes:
        - name: config-dir
          emptyDir: {}
        - name: certs-dir
          emptyDir: {}
      extraVolumeMounts:
        - name: config-dir
          mountPath: /.minio
        - name: certs-dir
          mountPath: /etc/minio/certs
    server:
      securityContext:
        readOnlyRootFilesystem: true
    controller:
      securityContext:
        readOnlyRootFilesystem: true
    mainContainer:
      securityContext:
        readOnlyRootFilesystem: true
    executor:
      securityContext:
        readOnlyRootFilesystem: true
  seldon-core-operator:
    containersSecurityContext:
      readOnlyRootFilesystem: true
  argo-common-workflows:
    containerSecurityContext:
      readOnlyRootFilesystem: true
  question-answering:
    containersSecurityContext:
      readOnlyRootFilesystem: true
  classification:
    containersSecurityContext:
      readOnlyRootFilesystem: true

All-in-one values.yaml with optional services example

fusion:
  argo:
    minio:
      persistence:
        enabled: false
      containerSecurityContext:
        readOnlyRootFilesystem: true
      extraVolumes:
        - name: config-dir
          emptyDir: {}
        - name: certs-dir
          emptyDir: {}
      extraVolumeMounts:
        - name: config-dir
          mountPath: /.minio
        - name: certs-dir
          mountPath: /etc/minio/certs
    server:
      securityContext:
        readOnlyRootFilesystem: true
    controller:
      securityContext:
        readOnlyRootFilesystem: true
    mainContainer:
      securityContext:
        readOnlyRootFilesystem: true
    executor:
      securityContext:
        readOnlyRootFilesystem: true
  solr:
    exporter:
      enabled: true
      securityContext:
        readOnlyRootFilesystem: true
    containerSecurityContext:
      readOnlyRootFilesystem: true
    # tls:
    #   enabled: true
  solr-managed:
    exporter:
      enabled: true
      securityContext:
        readOnlyRootFilesystem: true
    enableExternalFiles: true
    enabledStorage:
    - gcs
    processRaw:
      image:
        repository: fusion-dev-docker.ci-artifactory.lucidworks.com
      cloudRoot: gs://lw-managed-fusion-data/tmp
      gcs:
        secret: gcs-key
        secretFieldName: key.json
      securityContext:
        readOnlyRootFilesystem: true
    containerSecurityContext:
      readOnlyRootFilesystem: true
    # tls:
    #   enabled: true
  zookeeper:
    containerSecurityContext:
      readOnlyRootFilesystem: true
    exporters:
      jmx:
        enabled: true
      zookeeper:
        enabled: true
    jobs:
      chroots:
        # enabled: true
        config:
          create:
            - /root-read-only
  kafka:
    containerSecurityContext:
      readOnlyRootFilesystem: true
    volumePermissions:
      enabled: true
      image:
        repository: "fusion-dev-docker.ci-artifactory.lucidworks.com/os-shell"
      containerSecurityContext:
        readOnlyRootFilesystem: true
    metrics:
      kafka:
        containerSecurityContext:
          readOnlyRootFilesystem: true
          enabled: true
      jmx:
        enabled: true
        containerSecurityContext:
          enabled: true
          readOnlyRootFilesystem: true
    externalAccess:
      enabled: true
      autoDiscovery:
        enabled: true
        containerSecurityContext:
          enabled: true
          readOnlyRootFilesystem: true
    provisioning:
      enabled: true
      topics:
      - name: test
        partitions: 1
        replicationFactor: 1
        ## https://kafka.apache.org/documentation/#topicconfigs
        config:
          max.message.bytes: 64000
          flush.messages: 1
      containerSecurityContext:
        readOnlyRootFilesystem: true
        enabled: true
  ml-model-service:
    enabled: true
    ambassador:
      containerSecurityContext:
        readOnlyRootFilesystem: true
      prometheusExporter:
        enabled: true
        securityContext:
          readOnlyRootFilesystem: true
    milvus:
      mysql:
        metrics:
          enabled: true
          securityContext:
            readOnlyRootFilesystem: true
        containerSecurityContext:
          readOnlyRootFilesystem: true
      cluster:
        enabled: false
      mishards:
        securityContext:
          readOnlyRootFilesystem: true
      admin:
        enabled: true
        securityContext:
          readOnlyRootFilesystem: true
      securityContext:
        readOnlyRootFilesystem: true
  seldon-core-operator:
    containersSecurityContext:
      readOnlyRootFilesystem: true
  argo-common-workflows:
    containerSecurityContext:
      readOnlyRootFilesystem: true
  question-answering:
    containersSecurityContext:
      readOnlyRootFilesystem: true
  classification:
    containersSecurityContext:
      readOnlyRootFilesystem: true

Supported services

The table below lists the services that support a read-only root file system, the ones that have it enabled by default, and the Fusion release in which support was added:
Chart NamePod NameContainer NameSupportedDefault enabledSupported version
admin-uiadmin-uiadmin-ui5.9.9+
api-gatewayapi-gatewayinit/api-gateway5.9.9+
api-gatewayapi-gatewayapi-gateway5.9.9+
api-gatewayapi-gatewaygenerate-jks5.9.9+
apps-managerapps-managerapps-manager5.9.9+
argoargo-serverargo-server5.9.10+
argoargo-executorexecutor5.9.10+
argoargo-mainContainermainContainer5.9.10+
argoargo-controllercontroller5.9.10+
argo/miniominiominio5.9.10+
argo/miniominiominio5.9.10+
argo/miniomake-bucket-jobminio-mc5.9.10+
argo-common-workflowsdelete-modelinit/main/wait5.9.10+
argo-common-workflowsdeploy-modelinit/main/wait5.9.10+
argo-common-workflowsmilvus-maintenanceinit/main/wait5.9.10+
argo-common-workflowsupload-model-to-cloudinit/main/wait5.9.10+
async-parsingasync-parsingtika-server5.9.9+
async-parsingasync-parsingasync-parsing5.9.9+
auth-uiauth-uiauth-ui5.9.9+
classic-rest-serviceclassic-rest-serviceinit/import-certs5.9.10+
classic-rest-serviceclassic-rest-serviceclassic-rest-service5.9.9+
classificationargo/classificationinit/wait/main5.9.10+
connector-pluginconnector-plugininit/import-certs5.9.10+
connector-pluginconnector-pluginconnector-plugin5.9.9+
connectorsconnectorsconnectors5.9.9+
connectors-backendCRD5.9.9+
connectors-backendconnectors-backendconnectors-backend5.9.9+
fusion-adminfusion-adminadmin5.9.9+
fusion-commonscheck-admin5.9.9+
fusion-commonscheck-api-gateway5.9.9+
fusion-commonscheck-indexing5.9.9+
fusion-commonscheck-kafka5.9.9+
fusion-commonscheck-logstash5.9.9+
fusion-commonscheck-pulsar5.9.9+
fusion-commonssetup-keystore-and-properties5.9.9+
fusion-commonscheck-zk5.9.9+
fusion-config-syncfusion-config-syncfusion-config-sync5.9.9+
fusion-data-augmentationargo/data-augmentation/volume-fixinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/init-workspaceinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/write-job-configsinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/write-io-configsinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/add-zkhostinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/pull-data-training-and-metadatainit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/pull-data-training-and-metadata-cloudinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/volume-fix2init/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/synonym-listinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/download-synonym-dictionaryinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/keystroke-listinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/download-keystroke-blobinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/augmentinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/push-augmented-datainit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/push-augmented-data-cloudinit/main/wait5.9.10+
fusion-indexingfusion-indexingfusion-indexing5.9.9+
fusion-resourcesfusion-resources-secret-hooksetup-keystore-and-properties5.9.10+
insightsinsightsinsights5.9.9+
job-launcherjob-launcherjob-launcher5.9.9+
job-launcherjob-launcherkubectl-runner5.9.9+
job-launcherjob-launcher-spark-cleanupkubectl-runner5.9.9+
job-launcherspark-kubernetes-driverspark-kubernetes-driver5.9.10+
job-launcherspark-kubernetes-executorspark-kubernetes-executor5.9.10+
job-rest-serverjob-rest-serverjob-rest-server5.9.9+
kafkakafka-metricskafka-exporter-archived5.9.10+
kafkakafka-provisioninginit/wait-for-available-kafka5.9.10+
kafkakafka-provisioningkafka-provisioning5.9.10+
kafkakafkakafka5.9.10+
kafkakafkajmx-exporter5.9.10+
kafkakafkainit/check-zk5.9.9+
kafkakafkainit/auto-discovery5.9.10+
kafkakafkainit/volume-permissions5.9.10+
lwai-gatewaylwai-gatewaylwai-gateway5.9.9+
ml-model-serviceml-model-servicejava-service5.9.9+
ml-model-serviceml-model-service-namespace-hookkubectl-runner5.9.9+
ml-model-service/ambassadorambassadorambassador5.9.10+
ml-model-service/ambassadorambassadorprometheus-exporter5.9.10+
ml-model-service/milvusmilvus-writablemilvus5.9.10+
ml-model-service/milvusmilvus-writableinit/wait-for-mysql5.9.10+
ml-model-service/milvusmilvus-writableinit/create-for-share-storage5.9.10+
ml-model-service/milvusmilvus-adminadmin5.9.10+
ml-model-service/milvusmilvus-admininit/wait-for-milvus5.9.10+
ml-model-service/milvusmilvus-mishardsinit/wait-for-mysql5.9.10+
ml-model-service/milvusmilvus-mishardsinit/wait-for-mysql5.9.10+
ml-model-service/milvusmilvus-mishardsmishards5.9.10+
ml-model-service/milvus/mysqlmysqlinit/remove-lost-found5.9.10+
ml-model-service/milvus/mysqlmysqlmysql5.9.10+
pm-uipm-uipm-ui5.9.9+
query-pipelinequery-pipelinequery-pipeline5.9.9+
question-answeringargo/qna-coldstart/init-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/write-job-configsinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/add-zkHostinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/pull-datainit/wait/main5.9.10+
question-answeringargo/qna-coldstart/pull-data-cloudinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/traininit/wait/main5.9.10+
question-answeringargo/qna-coldstart/list-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/post-modelinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/apply-seldon-deploymentinit/wait/main5.9.10+
question-answeringargo/qna-supervised/init-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-supervised/write-job-configsinit/wait/main5.9.10+
question-answeringargo/qna-supervised/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-supervised/add-zkhostinit/wait/main5.9.10+
question-answeringargo/qna-supervised/pull-qa-data-cloudinit/wait/main5.9.10+
question-answeringargo/qna-supervised/pull-qa-datainit/wait/main5.9.10+
question-answeringargo/qna-supervised/traininit/wait/main5.9.10+
question-answeringargo/qna-supervised/train-with-textsinit/wait/main5.9.10+
question-answeringargo/qna-supervised/list-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-supervised/post-modelinit/wait/main5.9.10+
question-answeringargo/qna-supervised/apply-seldon-deploymentinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/init-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/write-job-configsinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/add-zkhostinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/list-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/pull-eval-datainit/wait/main5.9.10+
question-answeringargo/qna-evaluation/pull-eval-data-cloudinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/evaluateinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/push-eval-results-cloudinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/push-eval-resultsinit/wait/main5.9.10+
recommenderargo/item-recommender-userinit/wait/main5.9.10+
recommenderargo/item-recommender-user/init-workspaceinit/wait/main5.9.10+
recommenderargo/item-recommender-user/write-job-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-user/write-io-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-user/add-zkhostinit/wait/main5.9.10+
recommenderargo/item-recommender-user/pull-data-training-and-metadatainit/wait/main5.9.10+
recommenderargo/item-recommender-user/pull-data-training-and-metadata-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-user/train-with-metadatainit/wait/main5.9.10+
recommenderargo/item-recommender-user/train-without-metadatainit/wait/main5.9.10+
recommenderargo/item-recommender-user/push-recommendationsinit/wait/main5.9.10+
recommenderargo/item-recommender-user/push-recommendations-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-user/add-default-exclude-queryinit/wait/main5.9.10+
recommenderargo/item-recommender-user/init-workspaceinit/wait/main5.9.10+
recommenderargo/item-recommender-content/copy-modelinit/wait/main5.9.10+
recommenderargo/item-recommender-content/write-job-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-content/write-io-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-content/add-zkhostinit/wait/main5.9.10+
recommenderargo/item-recommender-content/pull-datainit/wait/main5.9.10+
recommenderargo/item-recommender-content/pull-data-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-content/traininit/wait/main5.9.10+
recommenderargo/item-recommender-content/push-contentinit/wait/main5.9.10+
recommenderargo/item-recommender-content/push-content-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-content/add-default-exclude-queryinit/wait/main5.9.10+
recommenderargo/item-recommender-content/delete-old-content-recommendationsinit/wait/main5.9.10+
reverse-searchreverse-searchinit/set-reverse-search-zone5.9.10+
reverse-searchreverse-searchinit/check-zk5.9.9+
reverse-searchreverse-searchinit/enable-tls-in-reverse-search5.9.10+
reverse-searchreverse-searchreverse-search5.9.10+
rules-uirules-uirules-ui5.9.9+
seldon-core-operatorseldon-controller-managermanager5.9.10+
seldon-core-operatorseldon-spartakus-volunteerseldon-spartakus-volunteer5.9.9+
seldon-core-operatorcrd/SeldonDeployment✅/❌5.9.9+
solrsolrinit/set-solr-zone5.9.10+
solrsolrinit/enable-tls-in-solr5.9.10+
solrconfigset-bootstrapconfigset-bootstrap5.9.10+
solrsolrsolr5.9.10+
solrsolr-exporterexporter5.9.10+
solrsolr-exporterinit/solr-init5.9.10+
solr-managedconfigset-bootstrapconfigset-bootstrap5.9.10+
solr-managedexporterexporter5.9.10+
solr-managedexporterinit/solr-init5.9.10+
solr-managedsolrinit/set-solr-zone5.9.10+
solr-managedsolrinit/enable-tls-in-solr5.9.10+
solr-managedsolrsolr5.9.10+
solr-managedsolrprocess-raw5.9.10+
solr-backup-runnersolr-backup-runner-backupsolr-backups5.9.10+
solr-backup-runnersolr-backup-runner-prunesolr-prune5.9.10+
templatingtemplatingtemplating5.9.9+
webappswebappswebapps5.9.9+
zookeeperzookeeperzookeeper5.9.10+
zookeeperzookeeperjmx-exporter5.9.10+
zookeeperzookeeperzookeeper-exporter5.9.10+
zookeeperzookeeper-chrootsmain5.9.10+
The table below lists the services that support a read-only root file system, the ones that have it enabled by default, and the Fusion release in which support was added.
Chart NamePod NameContainer NameSupportedDefault enabledSupported version
admin-uiadmin-uiadmin-ui5.9.9+
api-gatewayapi-gatewayinit/api-gateway5.9.9+
api-gatewayapi-gatewayapi-gateway5.9.9+
api-gatewayapi-gatewaygenerate-jks5.9.9+
apps-managerapps-managerapps-manager5.9.9+
argoargo-serverargo-server5.9.10+
argoargo-executorexecutor5.9.10+
argoargo-mainContainermainContainer5.9.10+
argoargo-controllercontroller5.9.10+
argo/miniominiominio5.9.10+
argo/miniominiominio5.9.10+
argo/miniomake-bucket-jobminio-mc5.9.10+
argo-common-workflowsdelete-modelinit/main/wait5.9.10+
argo-common-workflowsdeploy-modelinit/main/wait5.9.10+
argo-common-workflowsmilvus-maintenanceinit/main/wait5.9.10+
argo-common-workflowsupload-model-to-cloudinit/main/wait5.9.10+
async-parsingasync-parsingtika-server5.9.9+
async-parsingasync-parsingasync-parsing5.9.9+
auth-uiauth-uiauth-ui5.9.9+
classic-rest-serviceclassic-rest-serviceinit/import-certs5.9.10+
classic-rest-serviceclassic-rest-serviceclassic-rest-service5.9.9+
classificationargo/classificationinit/wait/main5.9.10+
connector-pluginconnector-plugininit/import-certs5.9.10+
connector-pluginconnector-pluginconnector-plugin5.9.9+
connectorsconnectorsconnectors5.9.9+
connectors-backendCRD5.9.9+
connectors-backendconnectors-backendconnectors-backend5.9.9+
fusion-adminfusion-adminadmin5.9.9+
fusion-commonscheck-admin5.9.9+
fusion-commonscheck-api-gateway5.9.9+
fusion-commonscheck-indexing5.9.9+
fusion-commonscheck-kafka5.9.9+
fusion-commonscheck-logstash5.9.9+
fusion-commonscheck-pulsar5.9.9+
fusion-commonssetup-keystore-and-properties5.9.9+
fusion-commonscheck-zk5.9.9+
fusion-config-syncfusion-config-syncfusion-config-sync5.9.9+
fusion-data-augmentationargo/data-augmentation/volume-fixinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/init-workspaceinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/write-job-configsinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/write-io-configsinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/add-zkhostinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/pull-data-training-and-metadatainit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/pull-data-training-and-metadata-cloudinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/volume-fix2init/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/synonym-listinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/download-synonym-dictionaryinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/keystroke-listinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/download-keystroke-blobinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/augmentinit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/push-augmented-datainit/main/wait5.9.10+
fusion-data-augmentationargo/data-augmentation/push-augmented-data-cloudinit/main/wait5.9.10+
fusion-indexingfusion-indexingfusion-indexing5.9.9+
fusion-resourcesfusion-resources-secret-hooksetup-keystore-and-properties5.9.10+
insightsinsightsinsights5.9.9+
job-launcherjob-launcherjob-launcher5.9.9+
job-launcherjob-launcherkubectl-runner5.9.9+
job-launcherjob-launcher-spark-cleanupkubectl-runner5.9.9+
job-launcherspark-kubernetes-driverspark-kubernetes-driver5.9.10+
job-launcherspark-kubernetes-executorspark-kubernetes-executor5.9.10+
job-rest-serverjob-rest-serverjob-rest-server5.9.9+
kafkakafka-metricskafka-exporter-archived5.9.10+
kafkakafka-provisioninginit/wait-for-available-kafka5.9.10+
kafkakafka-provisioningkafka-provisioning5.9.10+
kafkakafkakafka5.9.10+
kafkakafkajmx-exporter5.9.10+
kafkakafkainit/check-zk5.9.9+
kafkakafkainit/auto-discovery5.9.10+
kafkakafkainit/volume-permissions5.9.10+
lwai-gatewaylwai-gatewaylwai-gateway5.9.9+
ml-model-serviceml-model-servicejava-service5.9.9+
ml-model-serviceml-model-service-namespace-hookkubectl-runner5.9.9+
ml-model-service/ambassadorambassadorambassador5.9.10+
ml-model-service/ambassadorambassadorprometheus-exporter5.9.10+
ml-model-service/milvusmilvus-writablemilvus5.9.10+
ml-model-service/milvusmilvus-writableinit/wait-for-mysql5.9.10+
ml-model-service/milvusmilvus-writableinit/create-for-share-storage5.9.10+
ml-model-service/milvusmilvus-adminadmin5.9.10+
ml-model-service/milvusmilvus-admininit/wait-for-milvus5.9.10+
ml-model-service/milvusmilvus-mishardsinit/wait-for-mysql5.9.10+
ml-model-service/milvusmilvus-mishardsinit/wait-for-mysql5.9.10+
ml-model-service/milvusmilvus-mishardsmishards5.9.10+
ml-model-service/milvus/mysqlmysqlinit/remove-lost-found5.9.10+
ml-model-service/milvus/mysqlmysqlmysql5.9.10+
pm-uipm-uipm-ui5.9.9+
query-pipelinequery-pipelinequery-pipeline5.9.9+
question-answeringargo/qna-coldstart/init-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/write-job-configsinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/add-zkHostinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/pull-datainit/wait/main5.9.10+
question-answeringargo/qna-coldstart/pull-data-cloudinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/traininit/wait/main5.9.10+
question-answeringargo/qna-coldstart/list-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/post-modelinit/wait/main5.9.10+
question-answeringargo/qna-coldstart/apply-seldon-deploymentinit/wait/main5.9.10+
question-answeringargo/qna-supervised/init-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-supervised/write-job-configsinit/wait/main5.9.10+
question-answeringargo/qna-supervised/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-supervised/add-zkhostinit/wait/main5.9.10+
question-answeringargo/qna-supervised/pull-qa-data-cloudinit/wait/main5.9.10+
question-answeringargo/qna-supervised/pull-qa-datainit/wait/main5.9.10+
question-answeringargo/qna-supervised/traininit/wait/main5.9.10+
question-answeringargo/qna-supervised/train-with-textsinit/wait/main5.9.10+
question-answeringargo/qna-supervised/list-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-supervised/post-modelinit/wait/main5.9.10+
question-answeringargo/qna-supervised/apply-seldon-deploymentinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/init-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/write-job-configsinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/write-io-configsinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/add-zkhostinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/list-workspaceinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/pull-eval-datainit/wait/main5.9.10+
question-answeringargo/qna-evaluation/pull-eval-data-cloudinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/evaluateinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/push-eval-results-cloudinit/wait/main5.9.10+
question-answeringargo/qna-evaluation/push-eval-resultsinit/wait/main5.9.10+
recommenderargo/item-recommender-userinit/wait/main5.9.10+
recommenderargo/item-recommender-user/init-workspaceinit/wait/main5.9.10+
recommenderargo/item-recommender-user/write-job-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-user/write-io-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-user/add-zkhostinit/wait/main5.9.10+
recommenderargo/item-recommender-user/pull-data-training-and-metadatainit/wait/main5.9.10+
recommenderargo/item-recommender-user/pull-data-training-and-metadata-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-user/train-with-metadatainit/wait/main5.9.10+
recommenderargo/item-recommender-user/train-without-metadatainit/wait/main5.9.10+
recommenderargo/item-recommender-user/push-recommendationsinit/wait/main5.9.10+
recommenderargo/item-recommender-user/push-recommendations-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-user/add-default-exclude-queryinit/wait/main5.9.10+
recommenderargo/item-recommender-user/init-workspaceinit/wait/main5.9.10+
recommenderargo/item-recommender-content/copy-modelinit/wait/main5.9.10+
recommenderargo/item-recommender-content/write-job-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-content/write-io-configsinit/wait/main5.9.10+
recommenderargo/item-recommender-content/add-zkhostinit/wait/main5.9.10+
recommenderargo/item-recommender-content/pull-datainit/wait/main5.9.10+
recommenderargo/item-recommender-content/pull-data-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-content/traininit/wait/main5.9.10+
recommenderargo/item-recommender-content/push-contentinit/wait/main5.9.10+
recommenderargo/item-recommender-content/push-content-cloudinit/wait/main5.9.10+
recommenderargo/item-recommender-content/add-default-exclude-queryinit/wait/main5.9.10+
recommenderargo/item-recommender-content/delete-old-content-recommendationsinit/wait/main5.9.10+
reverse-searchreverse-searchinit/set-reverse-search-zone5.9.10+
reverse-searchreverse-searchinit/check-zk5.9.9+
reverse-searchreverse-searchinit/enable-tls-in-reverse-search5.9.10+
reverse-searchreverse-searchreverse-search5.9.10+
rules-uirules-uirules-ui5.9.9+
seldon-core-operatorseldon-controller-managermanager5.9.10+
seldon-core-operatorseldon-spartakus-volunteerseldon-spartakus-volunteer5.9.9+
seldon-core-operatorcrd/SeldonDeployment✅/❌5.9.9+
solrsolrinit/set-solr-zone5.9.10+
solrsolrinit/enable-tls-in-solr5.9.10+
solrconfigset-bootstrapconfigset-bootstrap5.9.10+
solrsolrsolr5.9.10+
solrsolr-exporterexporter5.9.10+
solrsolr-exporterinit/solr-init5.9.10+
solr-managedconfigset-bootstrapconfigset-bootstrap5.9.10+
solr-managedexporterexporter5.9.10+
solr-managedexporterinit/solr-init5.9.10+
solr-managedsolrinit/set-solr-zone5.9.10+
solr-managedsolrinit/enable-tls-in-solr5.9.10+
solr-managedsolrsolr5.9.10+
solr-managedsolrprocess-raw5.9.10+
solr-backup-runnersolr-backup-runner-backupsolr-backups5.9.10+
solr-backup-runnersolr-backup-runner-prunesolr-prune5.9.10+
templatingtemplatingtemplating5.9.9+
webappswebappswebapps5.9.9+
zookeeperzookeeperzookeeper5.9.10+
zookeeperzookeeperjmx-exporter5.9.10+
zookeeperzookeeperzookeeper-exporter5.9.10+
zookeeperzookeeper-chrootsmain5.9.10+

Learn more

You can configure Active Directory Federation Services (AD FS) for SAML single sign-on (SSO) authentication in Fusion. This guide explains how to set up Spring Boot OAuth2 with AD FS.
OAuth-based authentication against AD FS requires AD FS 3.0 or later which is available from Windows Server 2012 R2 onwards.

Configure a Security Realm in Fusion

In Fusion, create a Security Realm for AD FS.
  1. In the Fusion workspace, navigate to System > Access Control.
  2. Click Security Realms.
  3. Click Add Security Realm.
  4. Enter the following information for the new realm:
    • Enter a Name. The name must be unique and should be descriptive yet short.
    • Select saml from the Type pulldown menu.
    When you select a type, Fusion displays additional configuration options.
    • The default value for Enabled is true. This setting controls whether or not Fusion allows user logins for this security realm.
    • The default value for Ephemeral Users is false. When disabled, this setting prevents ephemeral users from being created in ZooKeeper during login. If enabled, this property negates Auto Create Users.
    • The default value for Auto Create Users is true. If enabled, a user account is created automatically upon initial authentication. If disabled, then a Fusion user with admin permissions must create Fusion users.
Under SAML Realm, configure the following information:
  • Enter the Identity Provider URL. This URL is used by the SAML authority for single sign-on. For example: https://www.example.com/APP-PATH/adfs/ls
  • Enter the URL of the IdP Issuer. For example: http://www.example.com/adfs/services/trust.
    • IdP Issuer must match <saml:Issuer> in the SAML payload.
  • Optional: Provide the App Issuer. This field is required if there is an audienceRestriction in the SAML assertion and must match <saml:Audience> in the SAML payload.
  • In the Certificate Fingerprint, paste the contents of the SAML authority certificate, without the certificate header and footer.
  • Optional: Enter the User ID Attribute. By default, the Fusion username is the same as the login name known to the Identity Provider. When another field or attribute in the user record stored by the IdP should be used as the Fusion username, that attribute name is the value of the User ID Attribute.
  • Optional: Provide a Post Login Redirect URL. If not set, the Fusion URL is used.
  • Optional: Provide a Logout URL.
    1. Optional: Under Groups Mapping, specify the Group Name Attribute and add group mappings.
    2. Click Save.

Set up the application (relying party trust) in AD FS

Create a relying party trust in the AD FS Management console. For more details, refer to the Microsoft AD FS documentation.
The following screenshots may differ from your setup depending on the version of AD FS you’re using.
  1. Launch the Add Relying Party Trust Wizard, then select Claims aware. adfs-relying-party-2
  2. Choose the option to enter the data manually. adfs-relying-party-1
  3. Set a Display name. adfs-relying-party-3
  4. Configure URL. Enable the option for SAML 2.0 WebSSO protocol. adfs-relying-party-5
  5. Set the Relying party trust identifier to the URL of the Fusion application. adfs-relying-party-identifier
  6. Edit the Claim Rules to pass through the User Principal Name as the NameID claim. adfs-principal-roles-claim-rule
  7. In a terminal, create the OAuth AD FS client for the Fusion application:
    Add-ADFSClient -Name "Fusion OAuth" -ClientId "1234567890-ABCDEF" -RedirectUri="http://localhost:8080/oauthLogin"
    
The ClientId should be a GUID and the RedirectUri must point to the Fusion application URL, with /oauthLogin appended. Here, localhost is used for testing a Fusion application running on the local development machine.

Configure the OAuth module for the application setup in AD FS

Create a new configuration file in conf/security/oauth.conf.
client-id: 168f3ee4-63fc-4723-a61a-6473f6cb515d
adfs-url: https://your-adfs-server/adfs
resource: http://localhost:8080
high-trust: false
Replace the client-id, adfs-url and resource parameters for your environment.
  • The client-id is the ID that was set up against AD FS using the Add-ADFSClient PowerShell command.
  • The adfs-url is the URL of the AD FS server with the /adfs context appended.
  • The resource is the relying party trust identifier set up in AD FS management.
  • The high-trust parameter is only required when integrating the AD FS and SharePoint modules. This article is only concerned with authentication against AD FS.

Test the authentication

When a user goes to the Fusion login page, they will be redirected to the AD FS OAuth login page. After the user logs in, the user will be returned to Fusion as an authenticated user. The Fusion user’s details will also be populated with any basic information available from the decoded OAuth token such as roles and the user principal name.
Enterprise customers may want to use a signed certificate from an Enterprise Certificate Authority (CA), such as GoDaddy or Let’s Encrypt for their Fusion 5 deployment.The Fusion 5 default setup will create a self-signed Java Keystore (JKS) file that is used as the JSON Web Token (JWT) signer.The following instructions detail how to create the api-gateway.jks file using a CA signed certificate.

Prerequisites

New installations

1. Create a JKS

Run the following command, replacing the dname(Distinguished Name) field with the name that matches your customer environment, and the keypass and storepass fields with a secure password.This will create the api-gateway.jks:keytool -genkeypair -keyalg rsa -keysize 2048 -validity 3650 -dname "CN=sample, OU=sample, O=sample, L=sample, S=sample, C=sample" -storetype jks -keystore api-gateway.jks -keypass password -storepass password -alias jwt-signer
If you change the alias or keystore/truststore passwords, you will need to update the api-gateway deployment YAML with the new values.

2. Create a Certificate Signing Request (CSR)

Run the following command to create a new fusion.csr, which will be sent to the CA:keytool -keystore api-gateway.jks -certreq -alias jwt-signer -file fusion.csr

3. Send the CSR to your CA to get a signed certificate

The CA will return one of two possible responses:
  • A PKCS12 certificate file, such as CAreply.pkcs. This is a full keystore containing all the keys you need, including the root certificate and the signed chain certificate.
  • Several PEM files, such as 0000_cert.pem, 0000_chain.pem, and 0001_chain.pem. These files contain the root certificate, the chain certificate(s), and the signed chain certificate.

4. Import the signed certificate into the api-gateway.jks

  • If you received a PKCS file, import it using the following keytool command:
keytool -importcert -alias jwt-signer -file <CAreply.pkcs> -keystore api-gateway.jks -trustcacerts
  • If you receive PEM files, run the following commands to import the keys:
    • keytool -importcert -alias root -file 0000_cert.pem -keystore api-gateway.jks -trustcacerts
    • keytool -importcert -alias intermediate -file 0000_chain.pem -keystore api-gateway.jks -trustcacerts
    • keytool -importcert -alias jwt-signer -file 0001_chain.pem -keystore api-gateway.jks -trustcacerts

5. Upload the api-gateway.jks as a Kubernetes generic secret

The api-gateway service will pull down the api-gateway.jks file during initialization as a Kubernetes secret:
  1. Delete the <namespace>-api-gateway.jks secret if it already exists.
  2. Upload the new secret with the following command:
k create secret generic <namespace>-api-gateway-jks --from-file api-gateway.jks

6. Install Fusion 5 using Helm

See Deploy Fusion 5 on Other Kubernetes Platforms for more information.

Existing installation

1. Create a JKS with your CA certificate or the java keytool

If you are using the Java keytool, you can run the same command used in the Create a JKS section:keytool -genkeypair -keyalg rsa -keysize 2048 -validity 3650 -dname "CN=sample, OU=sample, O=sample, L=sample, S=sample, C=sample" -storetype jks -keystore api-gateway.jks -keypass myPassword -storepass myPassword -alias jwt-signer

2. Scale down Fusion deployment to 0

This step will allow Fusion services to find the latest JKS once it is scaled up at the final step.See Deploy Fusion at Scale for more information on the process.

3. Delete the existing Kubernetes JKS secret for Fusion

As in the Upload the api-gateway.jks as a Kubernetes generic secret section, delete the existing <namespace>-api-gateway.jks secret.

4. Create a Kubernetes secret with the JKS using the name of the deployment

Upload a new secret using the api-gateway.jks file with the following command:k create secret generic <deployment>-api-gateway-jks --from-file api-gateway.jks

5. Scale up Fusion deployment

Fusion should accept the JKS once this step is complete.
Sometimes when you call out to HTTPS resources in connectors, index pipelines, query pipelines, or spark jobs, the HTTPS web resource is signed using an Enterprise or Self-Signed CA. This results in Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.You can ignore all SSL validation, but that’s not secure.Whether it’s Spark, Connectors, Indexing, Query, or something else, adding trusted SSL certificates lets you can access these HTTPS web resources.

Obtain each public certificate in .pem format.

The first thing you need is the public certificates in X.509 PEM format. Refer to How to save a remote server SSL certificate locally as a file for information on how to do this.One example is to run:
openssl s_client -connect self-signed.badssl.com:443 2>/dev/null </dev/null |  sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /home/ndipiazza/Downloads/spark-ssl-test/badssl-com-chain.pem
This creates /home/ndipiazza/Downloads/spark-ssl-test/badssl-com-chain.pem, which is a public certificate from a public self-signed HTTPS site.

Trust store certificate option

  1. Embed at runtime each enterprise/self-signed certificate to a local trust store used by the Apache HttpClient.

Add each public certificate to the trust store

This option is only available in Fusion releases 5.9.2 and later.
Only use this option if you have installed Fusion using the $tlsEnabled=true, which follows this guide: Enable Transport Layer Security (TLS) for Fusion Microservices.The steps are to:
  1. Download the truststore from the fusion-truststore Kubernetes secret to a local folder.
  2. Add any additional certificates to the truststore that you need using Java’s keytool.
  3. Upload the updated truststore back to the secrets store.
At this point, you will no longer have the SSL verification errors when communicating with your HTTPS resource.Here is a bash script for this first option:
# add a cert to the truststore

cert_to_add=/home/ndipiazza/Downloads/spark-ssl-test/badssl-com-chain.pem

kubectl get secret fusion-truststore \
    --namespace=$NAMESPACE \
    -o jsonpath="{['data']['truststore\\.jks']}" | \
base64 -d > truststore.jks

keytool -import -alias self-signed.badssl.com -keystore truststore.jks -file "${cert_to_add}" -storepass changeit

echo "\"$(cat truststore.jks | base64 -w 0)\"" > truststore.jks.base64

kubectl get secret fusion-truststore \
    --namespace=$NAMESPACE \
    -o json | \
jq --slurpfile enc truststore.jks.base64 '.data["truststore.jks"]=$enc[0]' | \
kubectl apply -f -

Verifying it works

Test access to this HTTPS resource with a Scala example. Below is an example Scala script that uses an Apache HttpClient that fetches a URL, but that URL is self-signed. If you you do not have this public certificate in your trust store, SSL validation will fail.In this example, we attempt to talk to self-signed.badssl.com, which is a public site with a self-signed SSL certificate. Prior to adding the SSL certificate into the trust store, it fails. When you add the cert, it works. Save this script as Collections → Job → Add → Script, then save this job and run it.
import org.apache.commons.io.IOUtils
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.HttpClients

import java.io.{IOException, InputStream}
import java.security.cert.{CertificateFactory, X509Certificate}
import java.security.{GeneralSecurityException, KeyStore}

def url = "https://self-signed.badssl.com"

def createEmptyKeyStore(): KeyStore = {
  val keyStore = KeyStore.getInstance("JKS")
  keyStore.load(null, null);
  keyStore;
}

@throws[IOException]
@throws[GeneralSecurityException]
def loadCertificate(publicCertIn: InputStream): X509Certificate = {
  val factory = CertificateFactory.getInstance("X.509")
  val cert = factory.generateCertificate(publicCertIn).asInstanceOf[X509Certificate]
  cert
}

/**
 * Returns the text content from a REST URL. Returns a blank String if there
 * is a problem.
 */
def getRestContent(url:String): String = {
  val httpClient = HttpClients.custom()
    .build();
  val httpResponse = httpClient.execute(new HttpGet(url))
  val entity = httpResponse.getEntity
  var content = ""
  if (entity != null) {
    val inputStream = entity.getContent
    content = IOUtils.toString(inputStream)
    inputStream.close()
  }
  httpClient.close()
  content
}

val content = getRestContent(url)
println(content);

Embed each enterprise/self-signed certificate to a local trust store used by the Apache HttpClient at runtime

This option embeds the public certificates for the trusted domains in the code, then inserts them into a local keystore used by Apache HttpClient.Use this approach:
  • If you do not have Kubernetes admin access to edit the keystore secret.
  • If the HTTPS URL is isolated to a single job or pipeline stage, as it is simpler to do it this way versus adding it to the keystore.

How to use it

  1. Use the X.509 certificate file created earlier and copy it as text. In your program, create a map of {alias, pem file string} called trustedPublicCertificates that contains your public certificates.
  2. Replace trustedPublicCertificates with an alias name as the key of the map, then set the PEM file string contents as the value.
  3. Use the Apache HttpClient to access the resource.

Examples

Here are examples for Apache HttpClient using a custom set of public keys in the SSL trust store to communicate with HTTPS sites with enterprise/self-signed certificates .Examples:
Scala Example:
import org.apache.commons.io.IOUtils
import org.apache.http.client.methods.HttpGet
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
import org.apache.http.impl.client.HttpClients
import org.apache.http.ssl.SSLContexts

import java.io.{ByteArrayInputStream, IOException, InputStream}
import java.security.{GeneralSecurityException, KeyStore}
import java.security.cert.{CertificateFactory, X509Certificate}
import javax.net.ssl.HostnameVerifier

def url = "https://self-signed.badssl.com"

def trustedPublicCertificates = Map("sharepoint-local" -> "-----BEGIN CERTIFICATE-----\nMIIDeTCCAmGgAwIBAgIJAMnA8BB8xT6wMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNp\nc2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTAeFw0y\nMTEwMTEyMDAzNTRaFw0yMzEwMTEyMDAzNTRaMGIxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQK\nDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2\nPmzAS2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMW\nhyefdOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3A\nxPxTuW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqve\nww9HdFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SY\nQCeFxxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaMyMDAwCQYDVR0T\nBAIwADAjBgNVHREEHDAaggwqLmJhZHNzbC5jb22CCmJhZHNzbC5jb20wDQYJKoZI\nhvcNAQELBQADggEBAC4DensZ5tCTeCNJbHABYPwwqLUFOMITKOOgF3t8EqOan0CH\nST1NNi4jPslWrVhQ4Y3UbAhRBdqXl5N/NFfMzDosPpOjFgtifh8Z2s3w8vdlEZzf\nA4mYTC8APgdpWyNgMsp8cdXQF7QOfdnqOfdnY+pfc8a8joObR7HEaeVxhJs+XL4E\nCLByw5FR+svkYgCbQGWIgrM1cRpmXemt6Gf/XgFNP2PdubxqDEcnWlTMk8FCBVb1\nnVDSiPjYShwnWsOOshshCRCAiIBPCKPX0QwKDComQlRrgMIvddaSzFFTKPoNZjC+\nCUspSNnL7V9IIHvqKlRSmu+zIpm2VJCp1xLulk8=\n-----END CERTIFICATE-----")

def createEmptyKeyStore(): KeyStore = {
  val keyStore = KeyStore.getInstance("JKS")
  keyStore.load(null, null);
  keyStore;
}

@throws[IOException]
@throws[GeneralSecurityException]
def loadCertificate(publicCertIn: InputStream): X509Certificate = {
  val factory = CertificateFactory.getInstance("X.509")
  val cert = factory.generateCertificate(publicCertIn).asInstanceOf[X509Certificate]
  cert
}

/**
 * Returns the text content from a REST URL. Returns a blank String if there
 * is a problem.
 */
def getRestContent(url:String): String = {
  val sslBuilder = SSLContexts.custom()
  val keyStore = createEmptyKeyStore()  
    for ((alias,certificate) <- trustedPublicCertificates) {
    keyStore.setCertificateEntry(alias, loadCertificate(new ByteArrayInputStream(certificate.getBytes)))
  }

  val sslContextBuilder = sslBuilder.loadTrustMaterial(keyStore, null)
  val sslContext = sslContextBuilder.build()
  val hostnameVerifier = null : HostnameVerifier
  val sslConSocFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier)  
    val httpClient = HttpClients.custom()
    .setSSLSocketFactory(sslConSocFactory)
    .build();
  val httpResponse = httpClient.execute(new HttpGet(url))
  val entity = httpResponse.getEntity
  var content = ""
  if (entity != null) {
    val inputStream = entity.getContent
    content = IOUtils.toString(inputStream)
    inputStream.close()
  }
  httpClient.close()
  content
}

val content = getRestContent(url)
println(content);
Nashorn JavaScript Example
var IOUtils = org.apache.commons.io.IOUtils;
var CloseableHttpResponse = org.apache.http.client.methods.CloseableHttpResponse;
var HttpGet = org.apache.http.client.methods.HttpGet;
var SSLConnectionSocketFactory = org.apache.http.conn.ssl.SSLConnectionSocketFactory;
var CloseableHttpClient = org.apache.http.impl.client.CloseableHttpClient;
var HttpClients = org.apache.http.impl.client.HttpClients;
var SSLContextBuilder = org.apache.http.ssl.SSLContextBuilder;
var SSLContexts = org.apache.http.ssl.SSLContexts;
var HostnameVerifier = javax.net.ssl.HostnameVerifier;
var SSLContext = javax.net.ssl.SSLContext;
var ByteArrayInputStream = java.io.ByteArrayInputStream;
var IOException = java.io.IOException;
var InputStream = java.io.InputStream;
var StandardCharsets = java.nio.charset.StandardCharsets;
var KeyStore = java.security.KeyStore;
var KeyStoreException = java.security.KeyStoreException;
var NoSuchAlgorithmException = java.security.NoSuchAlgorithmException;
var CertificateException = java.security.cert.CertificateException;
var CertificateFactory = java.security.cert.CertificateFactory;
var X509Certificate = java.security.cert.X509Certificate;
var HashMap = java.util.HashMap;
var Map = java.util.Map;

var TRUSTED_PUBLIC_CERTS = new HashMap();
TRUSTED_PUBLIC_CERTS.put("your-alias-here", "-----BEGIN CERTIFICATE-----\nMIIDPTCCAiW...GOwbrrZXosMs=\n-----END CERTIFICATE-----");

var url = "https://your-self-signed-site-or-whatever.local";

var sslBuilder = SSLContexts.custom();
var keyStore = createEmptyKeyStore();

for each (var e in TRUSTED_PUBLIC_CERTS.entrySet()) {
  try {
    keyStore.setCertificateEntry(e.getKey(), loadCertificate(new ByteArrayInputStream(e.getValue().getBytes())));
  } catch (e) {
    throw new RuntimeException(e);
  }
}

var sslContextBuilder = sslBuilder.loadTrustMaterial(keyStore, null);
var sslContext = sslContextBuilder.build();
var sslConSocFactory = new SSLConnectionSocketFactory(sslContext, null);

var httpClient = HttpClients.custom()
    .setSSLSocketFactory(sslConSocFactory)
    .build();
var response = httpClient.execute(new HttpGet(url));
try {
  if (response.getStatusLine().getStatusCode() != 200) {
     throw new Exception("Bad status code " + response.getStatusLine());
  }
  print(IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8));
} finally {
  response.close();
  httpClient.close();
}

function createEmptyKeyStore() {
  var keyStore = KeyStore.getInstance("JKS");
  keyStore.load(null, null);
  return keyStore;
}

function loadCertificate(publicCertIn) {
  var factory = CertificateFactory.getInstance("X.509");
  return factory.generateCertificate(publicCertIn);
}

Java Example
import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

public class HttpClientWithTruststoreLoadedAtRuntime {
  static final String url = "https://self-signed.badssl.com";
  static final Map<String, String> TRUSTED_PUBLIC_CERTS = new HashMap<>();
  static {
    // Put your certificate here 
    TRUSTED_PUBLIC_CERTS.put("your-alias-here" -> "-----BEGIN CERTIFICATE-----\nMIIDeTCCAmGgAwIBAgIJAMnA8BB8xT6wMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV\nBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNp\nc2NvMQ8wDQYDVQQKDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTAeFw0y\nMTEwMTEyMDAzNTRaFw0yMzEwMTEyMDAzNTRaMGIxCzAJBgNVBAYTAlVTMRMwEQYD\nVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQK\nDAZCYWRTU0wxFTATBgNVBAMMDCouYmFkc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEB\nBQADggEPADCCAQoCggEBAMIE7PiM7gTCs9hQ1XBYzJMY61yoaEmwIrX5lZ6xKyx2\nPmzAS2BMTOqytMAPgLaw+XLJhgL5XEFdEyt/ccRLvOmULlA3pmccYYz2QULFRtMW\nhyefdOsKnRFSJiFzbIRMeVXk0WvoBj1IFVKtsyjbqv9u/2CVSndrOfEk0TG23U3A\nxPxTuW1CrbV8/q71FdIzSOciccfCFHpsKOo3St/qbLVytH5aohbcabFXRNsKEqve\nww9HdFxBIuGa+RuT5q0iBikusbpJHAwnnqP7i/dAcgCskgjZjFeEU4EFy+b+a1SY\nQCeFxxC7c3DvaRhBB0VVfPlkPz0sw6l865MaTIbRyoUCAwEAAaMyMDAwCQYDVR0T\nBAIwADAjBgNVHREEHDAaggwqLmJhZHNzbC5jb22CCmJhZHNzbC5jb20wDQYJKoZI\nhvcNAQELBQADggEBAC4DensZ5tCTeCNJbHABYPwwqLUFOMITKOOgF3t8EqOan0CH\nST1NNi4jPslWrVhQ4Y3UbAhRBdqXl5N/NFfMzDosPpOjFgtifh8Z2s3w8vdlEZzf\nA4mYTC8APgdpWyNgMsp8cdXQF7QOfdnqOfdnY+pfc8a8joObR7HEaeVxhJs+XL4E\nCLByw5FR+svkYgCbQGWIgrM1cRpmXemt6Gf/XgFNP2PdubxqDEcnWlTMk8FCBVb1\nnVDSiPjYShwnWsOOshshCRCAiIBPCKPX0QwKDComQlRrgMIvddaSzFFTKPoNZjC+\nCUspSNnL7V9IIHvqKlRSmu+zIpm2VJCp1xLulk8=\n-----END CERTIFICATE-----")
  }

  public static void main(String[] args) throws Exception {
    SSLContextBuilder sslBuilder = SSLContexts.custom();
    KeyStore keyStore = createEmptyKeyStore();
    TRUSTED_PUBLIC_CERTS.forEach((alias, certificate) -> {
        try {
        keyStore.setCertificateEntry(alias, loadCertificate(new ByteArrayInputStream(certificate.getBytes())));
        } catch (KeyStoreException | CertificateException e) {
        throw new RuntimeException(e);
        }
    });
    SSLContextBuilder sslContextBuilder = sslBuilder.loadTrustMaterial(keyStore, null);
    SSLContext sslContext = sslContextBuilder.build();
    SSLConnectionSocketFactory sslConSocFactory = new SSLConnectionSocketFactory(sslContext, (HostnameVerifier) null);
    try (CloseableHttpClient httpClient = HttpClients.custom()
        .setSSLSocketFactory(sslConSocFactory)
        .build()) {
        try (CloseableHttpResponse response = httpClient.execute(new HttpGet(url))) {
        if (response.getStatusLine().getStatusCode() != 200) {
           throw new Exception("Bad status code " + response.getStatusLine());
        }
        System.out.println(IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8));
        }
    }
  }
  private static KeyStore createEmptyKeyStore()
        throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException {
    KeyStore keyStore = KeyStore.getInstance("JKS");
    keyStore.load(null, null);
    return keyStore;
  }

  private static X509Certificate loadCertificate(InputStream publicCertIn) throws CertificateException {
    CertificateFactory factory = CertificateFactory.getInstance("X.509");
    return (X509Certificate) factory.generateCertificate(publicCertIn);
  }
}
I