---
title: "Using Fortanix Confidential Computing Manager to Build an Enclave OS Application that Talks Over TLS from Within an Enclave"
slug: "using-fortanix-confidential-computing-manager-to-build-an-enclave-os-application-that-talks-over-tls-from-within-an-enclave"
updated: 2026-05-11T16:19:24Z
published: 2026-05-11T16:19:24Z
---

> ## Documentation Index
> Fetch the complete documentation index at: https://support.fortanix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using Fortanix Confidential Computing Manager to Build an Enclave OS Application that Talks Over TLS from Within an Enclave

## Introduction

In this example, we will describe how to create two Python Flask applications that run securely within an AWS Nitro enclave and can communicate over a secure connection using TLS. Each application will first receive a TLS certificate signed by the Fortanix Confidential Computing Manager (CCM). The corresponding private key is generated from within the enclave and is never exposed outside the enclave. The TLS connection itself is terminated within the enclave, thereby achieving end-to-end security.

![](https://cdn.us.document360.io/c3bd85d2-4ad8-4d85-9f60-f1c168a3aad9/Images/Documentation/image(91).png)

## Create Client/Server Applications

Let us start by creating the two applications.

### Python Server Application

Create a file named `server.py` containing the following code:

```python
import ssl
import uuid
from flask import jsonify, Flask
from flask_api import status

app = Flask("Python Flask TLS Server")

@app.route('/random')
def get_random_token():
    random_token = uuid.uuid4().hex[:6]
    return jsonify({
        "token": random_token
    }), status.HTTP_200_OK

if __name__ == "__main__":
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    context.verify_mode = ssl.CERT_REQUIRED
    context.load_verify_locations("/app/cert/ca.crt")
    context.load_cert_chain("/app/cert/server.crt", "/app/cert/server.key")
    app.run(host="0.0.0.0", port=2222, use_reloader=False, threaded=True, ssl_context=context)
```

This is a very simple server listening on port `2222`, accepts GET requests at path `/random`, and returns a random token. The server is configured to use the HTTPS protocol using a certificate at location "`/app/cert/server.crt`", with its corresponding key at "`/app/cert/server.key`". The certificate of the Certificate Authority that signed the `server.crt` certificate is located at "`/app/cert/ca.crt`". The line `context.verify_mode = ssl.CERT_REQUIRED` indicates that the sender of requests (in this case the client) needs to be verified using its certificate, thereby establishing a mutual TLS connection.

When this application is deployed using Enclave OS, Enclave OS will first generate the certificate key and store it at the location "`/app/cert/server.key`" within the enclave. It will then submit a Certificate Signing Request (CSR) to Fortanix CCM and receive back a signed certificate which will be stored at "`/app/cert/server.crt`".

Next, let us turn this application into a docker container. First, create a file called `dockerfile.server` with the following contents:

```dockerfile
FROM python:3.7
RUN mkdir /app
RUN mkdir /app/cert
COPY server.py /app/
RUN pip3 install flask Flask-API
WORKDIR /app
ENTRYPOINT ["python3", "server.py"]
```

Then build the container and push it to a registry using the commands:

```bash
docker build -t fortanix/python-tls-server -f dockerfile.server .
docker push fortanix/python-tls-server
```

In the above commands, you can adjust the tag to point to your own container registry, or simply skip this step (you do not have permission to push to the Fortanix docker hub registry) since this container is already pushed to the Fortanix public registry ([https://hub.docker.com/r/fortanix/python-tls-server](https://hub.docker.com/r/fortanix/python-tls-server)).

### Python Client Application

Similar to the server application above, the client application will receive a signed certificate from Fortanix CCM. In response to receiving requests from a user, the client application uses this certificate to establish a mutual TLS connection with the server and submit a request to the server. The server response, which is a random token in our simple example, will be sent back to the user.

Create a file called `client.py` containing the following code:

```python
import os
import requests
import ssl
from flask import Flask

SERVER_DOMAIN = "flask-server.domain"
ENDPOINT = "https://" + SERVER_DOMAIN + ":2222"
app = Flask("Python Flask TLS Client")

@app.route("/submit")
def submit_request():
    path = ENDPOINT + "/random"
    req = requests.get(url=path, verify='/app/cert/ca.crt', cert=("/app/cert/client.crt", "/app/cert/client.key"))
    return req.content

if __name__ == '__main__':
    os.system("echo '0.0.0.0 " + SERVER_DOMAIN + "' >> /etc/hosts")
    context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
    context.load_verify_locations("/app/cert/ca.crt")
    context.load_cert_chain("/app/cert/client.crt", "/app/cert/client.key")
    app.run(host="0.0.0.0", port=3333, use_reloader=False, threaded=True, ssl_context=context)
```

Next, create a docker file named `dockerfile.client` with these contents:

```dockerfile
FROM python:3.7
RUN mkdir /app
RUN mkdir /app/cert
COPY client.py /app/
RUN pip3 install flask Requests
WORKDIR /app
ENTRYPOINT ["python3", "client.py"]
```

Build and push the client container using the commands:

```bash
docker build -t fortanix/python-tls-client -f dockerfile.client .
docker push fortanix/python-tls-client
```

The client container is already available here: [https://hub.docker.com/r/fortanix/python-tls-client](https://hub.docker.com/r/fortanix/python-tls-client).

### Create Fortanix CCM applications

Now that we have the containers of both applications available to a registry, let us create Fortanix CCM applications for both the client and the server, so we can convert the containers into ones that run within enclaves, using Fortanix Enclave OS.

Follow the same steps described in [this example](/v1/docs/using-fortanix-confidential-computing-manager-to-build-an-enclave-os-application-from-scratch#40-option-2-build-an-enclave-os-application-using-rest-api-calls) to issue REST API request to:

1. Authenticate to Fortanix CCM.
2. Select an account.
3. Recall that session tokens are short-lived and you will occasionally have to issue a refresh API request whenever you get `{"message": "Forbidden", "code": "FORBIDDEN"}.`

When you reach the step for creating an application, use the following `server.json` (replace the `output_image_name` with your private registry) file shown below with the API request:

```bash
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" -H "Content-Type: application/json" -d @server.json -X POST https://ccm.fortanix.com/v1/apps
```

```json
{
    "name": "Python TLS Server",
    "description": "A python server using Flask and a CCM certificate",
    "input_image_name": "fortanix/python-tls-server",
    "output_image_name": "fortanix-private/python-tls-server-nitro",
    "default_build_settings": {
        "sgx": {},
        "nitro_enclaves": {
            "cpu_count": 2,
            "mem_size": 1024,
            "enable_overlay_filesystem_persistence": true
        }
    },
    "group_id": "a8e8395e-096d-4eb8-9017-2098f2ab8327",
    "allowed_domains": [
        "flask-server.domain"
    ],
    "advanced_settings": {
        "entrypoint": [],
        "manifestEnv": [],
        "encryptedDirs": [],
        "certificate": {
            "issuer": "MANAGER_CA",
            "subject": "flask-server.domain",
            "keyType": "RSA",
            "keyParam": {
                "size": 2048
            },
            "keyPath": "/app/cert/server.key",
            "certPath": "/app/cert/server.crt"
        },
        "caCertificate": {
            "caPath": "/app/cert/ca.crt",
            "system": "false"
        },
        "rw_dirs": [
            "/app/cert"
        ]
    },
 "custom_metadata": {
        "app_type": "ENCLAVE_OS"
    }
}
```

Make a note of the `&lt;app_id&gt;` and the (`pending_task_id`) in the response since we will be using these in the next two requests.

```json
{
    "name":"Python TLS Server",
    "app_id":"1ef7d352-28b6-4560-a714-a503435455bc",
    "pending_task_id":"d5550480-697e-4782-9bc5-58aaaa97e712",
    "domains_added":["flask-server.domain"],
    ...
}
```

Since this application contains a certificate with a domain, you will need to whitelist the application domain:

```bash
curl -b $cpath -c $cpath -H "X-CSRF-Header:true" -H "Content-Type: application/json" -d '{"status":"APPROVED"}' -X PATCH https://ccm.fortanix.com/v1/tasks/<task_id>
```

Finally, follow the steps in [this example](/v1/docs/using-fortanix-confidential-computing-manager-to-build-an-enclave-os-application-from-scratch#44-create-an-image-using-an-api-call) to create and whitelist an image. You will need to use the `&lt;app_id&gt;` as part of these steps.

Follow the exact same steps to create a Fortanix CCM application for the client application, as well as create and whitelist an image. Use the `client.json` file when creating your client application:

```json
{
    "name": "Python TLS Client",
    "description": "A python client using Flask and a CCM certificate",
    "input_image_name": "fortanix/python-tls-client",
    "output_image_name": "fortanix-private/python-tls-client-nitro",
    "default_build_settings": {
        "sgx": {},
        "nitro_enclaves": {
            "cpu_count": 2,
            "mem_size": 1024,
            "enable_overlay_filesystem_persistence": true
        }
    },
    "group_id": "a8e8395e-096d-4eb8-9017-2098f2ab8327",
    "allowed_domains": [
        "flask-client.domain"
    ],
    "advanced_settings": {
        "entrypoint": [],
        "manifestEnv": [],
        "encryptedDirs": [],
        "certificate": {
            "issuer": "MANAGER_CA",
            "subject": "flask-client.domain",
            "keyType": "RSA",
            "keyParam": {
                "size": 2048
            },
            "keyPath": "/app/cert/client.key",
            "certPath": "/app/cert/client.crt"
        },
        "caCertificate": {
            "caPath": "/app/cert/ca.crt",
            "system": "false"
        },
        "rw_dirs": [
            "/app/cert"
        ]
    },
 "custom_metadata": {
        "app_type": "ENCLAVE_OS"
    }
}
```

## Run the converted applications

At this point, we have everything we need to deploy and test our converted applications on [a compute node that has been enrolled in CCM](/v1/docs/quickstart-guide) that will run securely within an enclave.

Let us start by running the server application using the following command, replacing the <ip_addr> with the IP address of your compute node and the image name to your image in your private registry:

```bash
docker run --privileged --volume /dev:/dev -v /run/nitro_enclaves:/run/nitro_enclaves -e NODE_AGENT=http://<ip_addr>:9092/v1 -p 2222:2222 fortanix-private/python-tls-server-nitro:latest
```

On the same compute node, run the client application on a separate terminal window using:

```bash
docker run --privileged --volume /dev:/dev -v /run/nitro_enclaves:/run/nitro_enclaves -e NODE_AGENT=http://:9092/v1 -p 3333:3333 --network host fortanix-private/python-tls-client-nitro:latest
```

Now that both the server and the client are running, we can use yet another terminal window to submit a request using curl:

```bash
curl -k --cacert ca.pem https://localhost:3333/submit
```

`ca.pem` is the certificate of the authority that signed the `server.crt` and `client.crt` certificates delivered to the applications. The `ca.pem` file is also called the Zone Certificate and it is specific to your Fortanix CCM account. All applications under the same account receive certificates signed by the same Zone certificate.

To get the CA certificate, you can use the attached script: `fetch_ca.sh`

## Conclusion

In this example, we have created two applications that run securely within an enclave. Both applications receive TLS certificates from the Fortanix Confidential Computing Manager which they then use to establish secure channels through which they can communicate with each other but also with external users.

## Related

- [Using Fortanix Confidential Computing Manager to Build an Enclave OS Application from Scratch](/using-fortanix-confidential-computing-manager-to-build-an-enclave-os-application-from-scratch.md)
- [Using Fortanix Confidential Computing Manager for Easy Deployment of Elasticsearch on AWS Nitro](/using-fortanix-confidential-computing-manager-for-easy-deployment-of-elasticsearch-on-aws-nitro.md)
