Truststore Configuration on RTF
This solution enables you to configure a truststore at the Runtime Fabric (RTF) infrastructure level, shared across all deployed Mule applications. The truststore is stored as a Kubernetes Secret and automatically mounted into pods.
Step 1: Create the Kubernetes Secret
Via kubectl
# 1. Connect to your RTF cluster
kubectl config use-context <your-rtf-context>
# 2. Verify the namespace (typically rtf or a dedicated namespace)
kubectl get namespaces
# 3. Create the secret containing the truststore
kubectl create secret generic mule-truststore \
--from-file=truststore.jks=/local/path/to/truststore.jks \
--from-literal=truststore.password='YourPassword123!' \
--namespace=rtf
# 4. Verify the secret creation
kubectl get secret mule-truststore -n rtf
kubectl describe secret mule-truststore -n rtf
Step 2: Configure Volume Mount
Via Custom Resource RTF
Create rtf-truststore-config.yaml:
apiVersion: runtime-fabric.mulesoft.com/v1beta1
kind: Application
metadata:
name: global-truststore-config
namespace: rtf
spec:
volumeMounts:
- name: truststore-volume
mountPath: /opt/mule/conf/truststore
readOnly: true
volumes:
- name: truststore-volume
secret:
secretName: mule-truststore
items:
- key: truststore.jks
path: truststore.jks
Apply the configuration:
Step 3: Configure Runtime Manager
A. Application Properties
In Runtime Manager > Applications > Settings > Properties, add:
# Path to mounted truststore
truststore.path=/opt/mule/conf/truststore/truststore.jks
truststore.type=JKS
# Password will be injected via environment variable
truststore.password=${TRUSTSTORE_PASSWORD}
B. JVM Properties (Advanced Settings)
In Settings > Advanced > JVM Arguments:
-Djavax.net.ssl.trustStore=/opt/mule/conf/truststore/truststore.jks
-Djavax.net.ssl.trustStorePassword=${TRUSTSTORE_PASSWORD}
-Djavax.net.ssl.trustStoreType=JKS
Step 4: Mule Application Configuration
Mule Configuration (src/main/resources/mule-config.xml)
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:tls="http://www.mulesoft.org/schema/mule/tls"
xmlns:http="http://www.mulesoft.org/schema/mule/http">
<!-- Global TLS Configuration -->
<tls:context name="Global_TLS_Context">
<tls:trust-store
path="${truststore.path}"
password="${truststore.password}"
type="${truststore.type}"
algorithm="SunX509"
insecure="false"/>
</tls:context>
<!-- HTTP Request Configuration -->
<http:request-config name="HTTPS_Config">
<http:request-connection
protocol="HTTPS"
host="api.example.com"
port="443">
<tls:context ref="Global_TLS_Context"/>
</http:request-connection>
</http:request-config>
<flow name="secure-api-call">
<http:request
config-ref="HTTPS_Config"
path="/api/endpoint"
method="GET"/>
</flow>
</mule>
Properties File (mule-app.properties)
truststore.path=/opt/mule/conf/truststore/truststore.jks
truststore.password=${secure::truststore.password}
truststore.type=JKS
Step 5: Deployment and Verification
1. Deploy Your Application
Deploy via Runtime Manager or using Anypoint CLI:
anypoint-cli runtime-mgr cloudhub-application deploy \
--runtime-version 4.9.6 \
--target rtf-cluster \
my-app app.jar
2. Verify Mount in Pod
List the pods for your application:
Access the pod:
Verify the truststore:
# Check file exists
ls -la /opt/mule/conf/truststore/
-r--r--r-- 1 mule mule 2048 Dec 16 10:00 truststore.jks
# List certificates
keytool -list -v -keystore /opt/mule/conf/truststore/truststore.jks \
-storepass $TRUSTSTORE_PASSWORD
# Check environment variables
env | grep TRUSTSTORE
3. Test SSL Connectivity
From within the pod:
# Using curl
curl -v https://api.example.com
# Using OpenSSL
openssl s_client -connect api.example.com:443 \
-CAfile /opt/mule/conf/truststore/truststore.jks
4. Check Application Logs
In Runtime Manager > Applications > Logs, look for:
INFO TlsConfiguration - Loading truststore from: /opt/mule/conf/truststore/truststore.jks
INFO TlsConfiguration - Truststore loaded successfully
Step 6: Multi-Environment Management
Structure by Namespace
# DEV
kubectl create secret generic mule-truststore \
--from-file=truststore.jks=truststore-dev.jks \
--from-literal=truststore.password='DevPassword123!' \
--namespace=rtf-dev
# VAL
kubectl create secret generic mule-truststore \
--from-file=truststore.jks=truststore-val.jks \
--from-literal=truststore.password='TestPassword456!' \
--namespace=rtf-val
# PROD
kubectl create secret generic mule-truststore \
--from-file=truststore.jks=truststore-prod.jks \
--from-literal=truststore.password='ProdPassword789!' \
--namespace=rtf-prod
Step 7: Certificate Rotation
Automated Rotation Script
Create rotate-truststore.sh:
#!/bin/bash
set -e
NAMESPACE="rtf"
SECRET_NAME="mule-truststore"
NEW_TRUSTSTORE="/path/to/new/truststore.jks"
NEW_PASSWORD="NewPassword123!"
echo "Starting truststore rotation..."
# 1. Backup existing secret
echo "Backing up existing secret..."
kubectl get secret $SECRET_NAME -n $NAMESPACE -o yaml > \
backup-truststore-$(date +%Y%m%d-%H%M%S).yaml
# 2. Delete old secret
echo "Deleting old secret..."
kubectl delete secret $SECRET_NAME -n $NAMESPACE
# 3. Create new secret
echo "Creating new secret..."
kubectl create secret generic $SECRET_NAME \
--from-file=truststore.jks=$NEW_TRUSTSTORE \
--from-literal=truststore.password="$NEW_PASSWORD" \
--namespace=$NAMESPACE
# 4. Rolling restart of applications
echo "Restarting applications..."
for deployment in $(kubectl get deployments -n $NAMESPACE -o name); do
echo " - Restarting $deployment"
kubectl rollout restart $deployment -n $NAMESPACE
kubectl rollout status $deployment -n $NAMESPACE --timeout=5m
done
echo "Rotation completed successfully!"
Post-Rotation Verification
# Verify all apps are running
kubectl get pods -n rtf
# Check logs for SSL/TLS errors
kubectl logs -l app=my-app -n rtf --tail=100 | grep -i "ssl\|tls\|certificate"
Step 8: Monitoring and Alerts
Certificate Expiration Monitoring ConfigMap
Create truststore-monitoring.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: truststore-monitoring
namespace: rtf
data:
check-expiration.sh: |
#!/bin/bash
TRUSTSTORE="/opt/mule/conf/truststore/truststore.jks"
PASSWORD="$TRUSTSTORE_PASSWORD"
WARN_DAYS=30
keytool -list -v -keystore $TRUSTSTORE -storepass $PASSWORD | \
grep "Valid" | while read line; do
expiry_date=$(echo $line | sed 's/.*until: //')
expiry_epoch=$(date -d "$expiry_date" +%s)
current_epoch=$(date +%s)
days_left=$(( ($expiry_epoch - $current_epoch) / 86400 ))
if [ $days_left -lt $WARN_DAYS ]; then
echo "Certificate expires in $days_left days!"
fi
done
Automated Monitoring CronJob
Create cert-monitoring-cronjob.yaml:
apiVersion: batch/v1
kind: CronJob
metadata:
name: truststore-expiry-check
namespace: rtf
spec:
schedule: "0 6 * * *" # Daily at 6 AM
jobTemplate:
spec:
template:
spec:
containers:
- name: cert-checker
image: openjdk:11-jre-slim
command: ["/bin/bash", "/scripts/check-expiration.sh"]
volumeMounts:
- name: truststore-volume
mountPath: /opt/mule/conf/truststore
- name: scripts
mountPath: /scripts
volumes:
- name: truststore-volume
secret:
secretName: mule-truststore
- name: scripts
configMap:
name: truststore-monitoring
restartPolicy: OnFailure
Benefits
- Centralization: Single truststore for all applications
- Security: Encrypted storage via Kubernetes Secrets
- Maintenance: Easy rotation without redeploying applications
- Consistency: Uniform SSL/TLS configuration across all environments
- Audit: Traceability through Kubernetes RBAC
Key Considerations
- RBAC Access: Limit who can read/modify secrets
- Backup: Regularly backup your secrets
- Rotation: Plan rotation before certificate expiration
- Testing: Validate in dev/val environments before production