+

Configure TLS and Last-mile Security for Runtime Fabric Deployments on Self-Managed Kubernetes

30 min read
Was this tutorial helpful?
Thank you for your feedback!

This tutorial was updated in January 2022 and is based on Runtime Fabric v1.10 release.

In this tutorial, we’ll walk you through configuring TLS and last-mile security for a hello world application deployed using Runtime Fabric v1.10 on Self-Managed Kubernetes. You’ll learn how to:

  • Configure TLS for an NGINX Ingress
  • Update an existing Hello World Mule app to use a TLS context
  • Update an NGINX Ingress to use last-mile security
  • Deploy and test a simple, secured, Hello World Mule app

To get started as simply and quickly as possible, this tutorial includes steps to configure TLS for an NGINX ingress. TLS features supported by various Ingress controllers may differ. Please refer to your platform specific documentation to understand how TLS works in your environment.

Prerequisites

  • Getting Started with Runtime Fabric - This tutorial builds on the installation and configuration of Runtime Fabric on Self-Managed Kubernetes. You must have completed one of the getting started with Runtime Fabric series - either EKS, AKS or GKE.
  • Anypoint Platform - A unified, single solution for iPaaS and full lifecycle API management. Sign up for a 30 day trial.
  • Anypoint Studio - An interactive development environment for MuleSoft developers. See installing Anypoint Studio.
  • kubectl - A command line tool for working with Kubernetes clusters. This tutorial requires that you use version 1.21 or later. For more information, see installing kubectl.
  • curl - A command line tool for transferring data using various network protocols. See installing curl.
  • OpenSSL - A software library for applications that secure communications over computer networks. See OpenSSL for more information.

Configure TLS for Ingress

Generate certificate and private key

1 - Use openssl to create a self-signed certificate and corresponding private key with the following command.

1
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -subj '/C=AU/ST=NSW/L=Sydney/O=MuleSoft/OU=SE/CN=rtf.example.com' -nodes

Output

1
2
3
4
Generating a 4096 bit RSA private key
....++
writing new private key to 'key.pem'
-----

This step is for the tutorial only. For production environments you must obtain a valid CA-signed certificate. When generating the self-signed certificate make sure the Common Name (CN) matches the URL you are using in the Runtime Fabric Ingress. In our tutorials we’re using rtf.example.com

Create Kubernetes Secret

This step will use the certificate and private key created in the last step to create a kubernetes secret that will allow the private key and certificate to be used within the ingress configuration. For additional details refer to the documentation.

1 - Use the following command to create a kubernetes secret.

1
kubectl create secret tls example-tls --namespace rtf --key key.pem --cert cert.pem

Output

1
secret/example-tls created

Add TLS to Ingress

This step will update the Ingress template within Runtime Fabric to use TLS by adding the tls section. The template is used to create individual Ingress instances for each API deployed in your Runtime Fabric cluster. For additional details refer to the documentation.

1 - Update the custom Ingress configuration created in the previous tutorial to add TLS and save the file as ingress-tls.yaml.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite ^/app-name(/|$)(.*) /$2 break;
  name: rtf-ingress-template
  namespace: rtf
spec:
  tls:
  - hosts:
    - rtf.example.com
    secretName: example-tls
  ingressClassName: rtf-nginx
  rules:
  - host: rtf.example.com
    http:
      paths:
      - path: /app-name
        pathType: Prefix
        backend:
          service:
            name: service-name
            port:
              name: service-port

2 - Apply the configuration using the following command. Update the path and name where appropriate.

1
kubectl apply -f path\ingress-tls.yaml

Output

1
ingress.networking.k8s.io/rtf-ingress-template configured

3 - Update the Ingress reference for the hello-world-2921 application that was deployed in the previous tutorial. In Anypoint Platform Runtime Manager click Applications then hello-world-2921 then select Ingress. Update the Host field to use https://rtf.example.com. Then click Apply Changes.

Anypoint Platform Runtime Fabric Ingress

Test TLS configuration

1 - Call the existing hello-world endpoint we deployed in the previous tutorial. Replace with your own based on the previous steps.

To access the endpoint for the hello-world we again need to resolve the domain name rtf.example.com. This time we will also include a flag to include a more verbose response.

1
curl --insecure -v https://rtf.example.com/hello-world-2921/helloWorld --resolve rtf.example.com:443:<IP address of ingress controller>

Key lines in the output are shown.

Output

1
2
3
4
5
6
7
* Added rtf.example.com:443:34.87.216.113 to DNS cache
* TLSv1.2 (IN), TLS handshake, Certificate (11):
...
* Server certificate:
*  subject: C=US; ST=CA; L=San Francisco; O=MuleSoft; OU=SE; CN=rtf.example.com
* Connection #0 to host rtf.example.com left intact
Hello World!

Congrats. We’ve now enabled TLS in the Ingress and successfully called our previously deployed hello world application on port 443. You can also verify the k8s Ingress is returning the correct certificate by checking the details in the output above. The Common Name (CN) included in the server certificate section should be the value you specified when creating the self signed certificate. In our case above rtf.example.com.

Enable last-mile security

By default NGINX Ingress assumes that the last-mile (traffic from the Ingress to the backend API) is unencrypted (HTTP). In order for NGINX to route traffic to a last-mile protected Mule application we must add an annotation to the Ingress configuration to specify HTTPS as our backend protocol.

1 - Update the custom Ingress configuration (ingress-tls.yaml) with the line nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" and save the file as ingress-tls-and-last-mile.yaml. For additional details refer to the following help article

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
    nginx.ingress.kubernetes.io/configuration-snippet: |
      rewrite ^/app-name(/|$)(.*) /$2 break;
  name: rtf-ingress-template
  namespace: rtf
spec:
  tls:
  - hosts:
    - rtf.example.com
    secretName: example-tls
  ingressClassName: rtf-nginx
  rules:
  - host: rtf.example.com
    http:
      paths:
      - path: /app-name
        pathType: Prefix
        backend:
          service:
            name: service-name
            port:
              name: service-port

2 - Apply the configuration using the following command. Update the path and name where appropriate.

1
kubectl apply -f path\ingress-tls-and-last-mile.yaml

Output

1
ingress.networking.k8s.io/rtf-ingress-template configured

Your existing Hello World Mule application deployment may still work if tested. The application specific Ingress will be picked up once you redeploy the Hello World application in the next few steps.

To allow https traffic to be sent from the NGINX Ingress to our Hello World Mule application we need to configure a key store, update a sample Hello World application to use the key store then export a jar file that can be uploaded to overwrite our existing implementation.

Generate certificate and key store

1 - Use openssl to create a self-signed certificate and corresponding private key for the hello-world application by using the following command.

1
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 365 -subj '/C=AU/ST=NSW/L=Sydney/O=MuleSoft/OU=SE/CN=hello-world' -nodes

Output

1
2
3
4
5
Generating a 4096 bit RSA private key
....................................++
...
writing new private key to 'key.pem'
-----

2 - Create a PKCS12 file using both the private key and the public certificate that was generated when creating our self-signed certificate from the previous step. Run the following command.

1
openssl pkcs12 -export -out keystore.p12 -inkey key.pem -in cert.pem

Create a memorable password when running the above command as we’ll be using it later on in the tutorial.

Output

1
2
Enter Export Password: <your-memorable-password>
Verifying - Enter Export Password: <your-memorable-password>

Configure Mule application for TLS

In this section we’ll update a Hello World Mule sample application to use the key store from the previous step to specify a TLS context allowing the NGINX Ingress to securely send an encrypted payload to our Hello World application.

1 - Create a new Mule Project by opening Anypoint Studio and selecting File > New > Project from Example.

Anypoint Studio Project From Example

2 - In the Exchange window that appears select ‘Provided by MuleSoft’ in the asset sidebar then search for hello world. And select the example project.

Anypoint Studio Project Project

3 - To download the project into Anypoint Studio click the Open button

Anypoint Studio Project Open

4 - In Anypoint Studio find the keystore.p12 file you created above and copy it into the src/main/resources folder of your new project.

Select Copy files when prompted.

Anypoint Studio Keystore Copy

5 - Open the src/main/mule/hello-world.xml file. Navigate to the Global Elements tab, click Create and select Component configurations > TLS Context. Navigate to the Key Store Configuration and enter the values shown then click OK.

Anypoint Studio Keystore Config

Make sure you use the memorable password you used when generating the keystore file.

6 - Navigate to the Global Elements tab and click create and select Global configurations > Global Property. Create a new global property with the details below then click OK.

Anypoint Studio Keystore Config

Unlike CloudHub which listens on the port 8081 for HTTP and 8082 for HTTPS, a Runtime Fabric application has to listen on the port 8081 for both HTTP and HTTPS as edge-443 only forwards the request to this port.

7 - Navigate to the Global Elements tab and then click Edit on the HTTP Listener config global element and modify the following parameters.

Anypoint Studio Keystore Config

This is where we will update the configuration to use the TLS context we setup.

8 - Whilst still in the HTTP Listener config properties screen select the tab TLS and update the TLS Configuration option to Global reference. Then in the Global reference picklist select TLS_Context we setup earlier with our key store configuration.

Anypoint Studio Keystore Config

9 - Click Test Connection to verify settings then click OK and save all changes.

10 - Generate a deployable jar file. Right click on the project in Package Explorer and select Export.

Anypoint Studio Keystore Config

11 - In the export wizard dialog select Mule > Anypoint Studio Project to Mule Deployable Archive (includes Studio metadata) and click Next.

Anypoint Studio Keystore Config

12 - In the Export Settings dialog check the boxes for Attach project sources and Include project modules and dependencies. Then rename the JAR File to be hello-world-https and click Finish.

Anypoint Studio Keystore Config

Deploy updated Mule application

In this section you will update the existing Hello World application we have been using with the JAR file created.

1 - Deploy the updated Hello World application to Runtime Manager. In Anypoint Platform go to Runtime Manager click Applications then click the existing hello-world-2921 application. Update the Application File by clicking Choose File > Upload File from the menu options and select the JAR file you created in the previous step. Then click Apply Changes.

Anypoint Studio Keystore Config

Wait for the deployment to complete successfully before continuing.

Test last-mile security

1 - Call the secured hello-world application endpoint.

To access the endpoint for the hello-world application we need to resolve the domain name rtf.example.com. For this tutorial we will not create a domain address or use a local file - instead we’ll use the resolve switch to pass the hostname IP mapping on the command line. These steps were completed in the last tutorial.

1
curl --insecure https://rtf.example.com/hello-world-2921/helloWorld --resolve rtf.example.com:443:<IP address of ingress controller>

Output

1
Hello World!

The deployed application should return the string ‘Hello World!’ as highlighted in the output above proving that the application received and processed your request.

To confirm that the last-mile traffic is now encrypted we can interrogate the application log files.

2 - Get the namespace and pod that your Mule application is deployed to by running the following command.

1
kubectl get pods -l type=MuleApplication -A

Output

1
2
NAMESPACE                              NAME                                READY   STATUS    RESTARTS   AGE
c811ba25-ffc0-4614-bf7e-11515a21a030   hello-world-2921-5647fc7445-cqg7g   2/2     Running   0          55m

3 - Retrieve the application logs by executing the following command. Substituting the values for namespace and pod and running the following command.

1
kubectl logs -n c811ba25-ffc0-4614-bf7e-11515a21a030 hello-world-2921-5647fc7445-cqg7g -c app

Output

For conciseness not all lines in the output have been included.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
* Mule Runtime and Integration Platform                              *
* Version: 4.4.0-20211227 Build: 6f6c60e6                            *
* MuleSoft, Inc.                                                     *
* For more information go to                                         *
* https://www.mulesoft.com/platform/soa/mule-esb-enterprise          *
*                                                                    *
* Server started: 1/6/22 2:40 AM                                     *
...
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Starting app 'hello-world-2921'                                              +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
[2022-01-06 02:40:58.954] INFO  GrizzlyHttpServer [ArtifactDeployer.start.01] [event: ]: Listening for connections on 'https://0.0.0.0:8081'
...
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Mule is up and kicking (every 5000ms)                                        +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[2022-01-06 02:41:00.040] INFO  AbstractConnector [WrapperListener_start_runner] [event: ]: Started ServerConnector@489f4e63{HTTP/1.1, (http/1.1)}{0.0.0.0:7777}
[2022-01-06 02:41:00.047] INFO  LogUtil [WrapperListener_start_runner] [event: ]:
**********************************************************************
*              - - + DOMAIN + - -               * - - + STATUS + - - *
**********************************************************************
* default                                       * DEPLOYED           *
**********************************************************************

*******************************************************************************************************
*            - - + APPLICATION + - -            *       - - + DOMAIN + - -       * - - + STATUS + - - *
*******************************************************************************************************
* hello-world-2921                              * default                        * DEPLOYED           *
*******************************************************************************************************

[2022-01-06 02:41:21.649] INFO  LoggerMessageProcessor [[MuleRuntime].uber.02: [hello-world-2921].hello-worldFlow.CPU_LITE @4cdbc4b6] [event: 21d970c0-6e9a-11ec-bd34-da2acbb36f57]: /helloWorld

4 - Review the output of the previous step to confirm that the Mule application is using HTTPS and that there is traffic hitting the endpoint successfully by looking for the following lines:

a) [ArtifactDeployer.start.01] [event: ]: Listening for connections on 'https://0.0.0.0:8081' (line 12 above)

This verifies that the http listener configured on the Hello World application is now using https.

b) [2022-01-06 02:41:21.649] INFO LoggerMessageProcessor [[MuleRuntime].uber.02: [hello-world-2921].hello-worldFlow.CPU_LITE @4cdbc4b6] [event: 21d970c0-6e9a-11ec-bd34-da2acbb36f57]: /helloWorld (line 31 above)

This verifies that the Hello World application is receiving traffic.

Cue the confetti! - You now completed the steps to secure a Runtime Fabric deployment on either AKS, EKS or GKE.

Next Steps

In this tutorial, we walked you through configuring TLS and last-mile security for a hello world application deployed using Runtime Fabric v1.10 on Self-Managed Kubernetes. You learned how to:

  • Configure TLS for an NGINX Ingress
  • Update an existing Hello World Mule app to use a TLS context
  • Update an NGINX Ingress to use last-mile security
  • Deploy and test a simple, secured, Hello World Mule app

The following documentation topics help you to further expand your Runtime Fabric knowledge.

Runtime Fabric runs as a service on Azure Kubernetes Service (AKS), Google Kubernetes Engine (GKE), Red Hat OpenShift and Amazon Elastic Kubernetes Services (EKS). Check out their tutorials below.

Try Anypoint Platform for free

Start free trial