Getting Started
Welcome to the Cosmian Enclave Bare Metal deployment tutorial
To launch your first confidential microservice, follow this tutorial in your favorite terminal. This is the bare metal tutorial: you will need to configure an SGX machine either on premise or at your cloud provider first.
Cosmian Enclave Bare Metal used to be called MSE Home
There are quite a few locations where the old MSE name is still in use.
Cosmian Enclave Bare Metal is designed to start an application on SGX hardware either on-premise or at a cloud provider. This solution does not require the use of the Cosmian Enclave SaaS Infrastructure.
This tutorial goes into the details of the deployment flow. If you want to quickly deploy an application, you can chain all the subcommands, as shown later.
The tutorial defines two roles:
- The code provider (who may also consume the result of the application)
- The SGX operator (who also owns the data to run against the application)
Read the flow page to get more details about each role and the overall flow.
Pre-requisites¶
You have to install and configure an SGX machine either on-premise or at a cloud provider first. Cosmian provides hardware and OS requirements, as well as Ansible scripts to facilitate the deployment.
Install the Cosmian Enclave Bare Metal CLI¶
The CLI tool requires at least Python 3.8 and OpenSSL 1.1.1 series. It is recommended to use pyenv to manage different Python interpreters.
$ pip3 install mse-cli
$ mse home --help
usage: mse home [-h]
{decrypt,evidence,scaffold,list,localtest,logs,package,restart,run,status,seal,spawn,stop,test,verify}
...
options:
-h, --help show this help message and exit
operations:
{decrypt,evidence,scaffold,list,localtest,logs,package,restart,run,status,seal,spawn,stop,test,verify}
decrypt decrypt a file using Fernet symmetric encryption
evidence collect the evidences to verify on offline mode the application
and the enclave
scaffold create a new boilerplate application
list list the running applications
localtest test locally a Cosmian Enclave app in a development context
logs print the Cosmian Enclave docker logs
package generate a package containing the Docker image and the code to
run on Cosmian Enclave
restart restart an stopped Cosmian Enclave docker
run finalise the configuration of the application docker and run the
application code
status print the Cosmian Enclave docker status
seal seal the secrets to be share with an Cosmian Enclave app
spawn spawn a Cosmian Enclave docker
stop stop and optionally remove a running Cosmian Enclave docker
test test a deployed Cosmian Enclave app
verify verify the trustworthiness of a running Cosmian Enclave web application and
get the RA-TLS certificate
Pre-requisites
Before deploying the app, verify that the Docker service is up and your current user is part of Docker group (current user may use the Docker client without privilege)
Scaffold your app¶
User
This command is designed to be used by the code provider
$ mse home scaffold example
$ tree -a example
example/
├── mse.toml
├── Dockerfile
├── mse_src
├── app.py
│ └── .mseignore
├── README.md
├── secrets.json
├── secrets_to_seal.json
└── tests
├── conftest.py
└── test_app.py
2 directories, 9 files
The mse_src
is your application directory designed to be started by mse home
cli.
The Dockerfile
should inherit from the mse-docker-base
and include all dependencies required to run your app. This
docker will be run by the SGX operator.
The file app.py
is a basic Flask application with no extra code. Adapting your own application to Cosmian Enclave
does not require any modification to your Python code.
Example of a basic Flask application (a FastAPI application would work too!):
from http import HTTPStatus
from flask import Flask, Response
app = Flask(__name__)
@app.get("/health")
def health_check():
"""Health check of the application."""
return Response(response="OK", status=HTTPStatus.OK)
@app.route('/')
def hello():
"""Get a simple example."""
return "Hello world"
# other endpoints
# ...
The configuration file is a TOML file used to give information to the SGX operator, allowing to start correctly the application:
name = "example"
python_application = "app:app"
healthcheck_endpoint = "/health"
tests_cmd = "pytest"
tests_requirements = [
"cryptography>=40.0.2,<41.0",
"intel-sgx-ra",
"pytest==7.2.0",
]
This project also contains a test directory enabling you to test this project locally and enabling the SGX operator to test the deployed application.
Compatibility with WSGI/ASGI
To be compliant with Cosmian Enclave your Python application must be an ASGI or WSGI application. It is not possible to deploy a standalone Python program. In the next example, this documentation will describe how to deploy Flask applications. You can also use other ASGI applications, for instance: FastAPI.
Examples
Visit Cosmian Enclaves Applications Examples to find sample application examples.
Test your app, your docker and your configuration¶
User
This command is designed to be used by the code provider
$ mse home localtest --code example/mse_src/ \
--dockerfile example/Dockerfile \
--config example/mse.toml \
--test example/tests/
or more concisely:
Testing your code before sending it to the SGX operator is recommended. Be aware that any error will require to restart the deployment flow from scratch.
Create the application package with the code and the docker image¶
User
This command is designed to be used by the code provider
This command generates a tarball named package_<app_name>_<timestamp>.tar
.
The generated package can now be sent to the SGX operator.
$ mse home package --code example/mse_src/ \
--dockerfile example/Dockerfile \
--config example/mse.toml \
--test example/tests/ \
--output code_provider/
or more concisely:
Spawn the application docker image¶
User
This command is designed to be used by the SGX operator
$ mse home spawn --san myapp.fr \
--port 7777 \
--size 4096 \
--package code_provider/package_mse_src_1683276327723953661.tar \
--output sgx_operator/ \
app_name
Mandatory arguments are:
san
: Subject Alternative Name to use for routing with SSL pass-through (domain name, IP address or localhost)port
: port used by Docker to bind the applicationsize
: memory size (in MB) of the enclave to spawn. Must be a power of 2 greater than 1024. This size is bounded by the SGX EPC memory.pccs
: the URL of the PCCS (Provisioning Certificate Caching Service) used to generate certificatepackage
: the application package containing the Docker images and the codeoutput
: directory to write the evidence file
This command first unpacks the tarball specified by the --package
argument. Note that a lot of files are created
in output
folder.
The generated file sgx_operator/evidence.json
contains cryptographic proofs related to the enclave. It can be shared
with other participants.
This evidence file is helpful for the code provider to verify the running app.
The application is now started in an intermediate state waiting for any secret: we call that the configuration server.
Collect the evidences to verify the application¶
User
This command is designed to be used by the SGX operator
This command collects cryptographic proofs related to the enclave and serialize them as a file named evidence.json
.
This command will determine your PCCS URL by parsing the aesmd
service configuration
file: /etc/sgx_default_qcnl.conf
. You can choose another PCCS by specifying the --pccs
parameter.
The file sgx_operator/evidence.json
and the previous file sgx_operator/args.toml
can now be shared with other
participants.
Check the trustworthiness of the application¶
User
This command is designed to be used by the code provider
The trustworthiness is established based on multiple information:
- the full code package (tarball)
- evidences captured from the running microservice
Verification of the enclave information:
$ mse home verify --package code_provider/package_mse_src_1683276327723953661.tar \
--evidence output/evidence.json \
--output /tmp
If the verification succeeds, the RA-TLS certificate is written as a file named ratls.pem
, and you can now seal the
code’s key to share it with the SGX operator.
Seal your secrets¶
User
This command is designed to be used by the code provider
A sealed secrets file is designed to be shared with the application by hiding them from the SGX operator.
$ mse home seal --input example/secrets_to_seal.json \
--cert /tmp/ratls.pem \
--output code_provider/secrets_to_seal.json.seal
In this example, sealed secrets file is generated as secrets_to_seal.json.seal
file.
Share the sealed secrets file with the SGX operator.
Finalize the configuration and run the application¶
User
This command is designed to be used by the SGX operator
$ mse home run --sealed-secrets code_provider/secrets_to_seal.json.seal \
--secrets example/secrets.json \
app_name
From now, the initial application developed by the code provider is fully operational and running. The configuration
server which started during the previous spawn
step has been shutdown. Therefore, if you want to change the
configuration or the secrets, you need to stop & remove this application and restart the deployment flow from scratch.
Test the deployed application¶
User
This command is designed to be used by the SGX operator
This step is mandatory to check that the application is executed properly as the code provider expects.
Always run this step before communicating to the users about the deployment completion.
Decrypt the results¶
User
This command is designed to be used by the code provider
Fetching /result/secrets
endpoint¶
First, the SGX operator collects the result (which is encrypted):
Hostname and certificate
At the spawn step, remember that the parameter --san
has been set to myapp.fr
and Subject Alternative Name (SAN) is added to /tmp/ratls.pem
.
If Common Name (CN) or Subject Alternative Name is different from hostname, a SSL message
will legitimately complain and no secure connection can be established.
This encrypted result is then sent by external means to the code provider.
Finally, the code provider can decrypt the result:
$ # key.bin contains the URL Safe Base64 encoded key
$ mse home decrypt --input result.enc \
--key key.bin
--output code_provider/result.plain
$ cat code_provider/result.plain
secret message with secrets.json
Note that the --key
parameter contains the same key as in secrets.json
.
Looking back at the Flask code shows that the /result/secrets
endpoint loads
the env variable SECRETS_PATH
to get the key
value, using it to encrypt a text message.
This demonstrates that secrets.json
file has been well setup for the enclave and is easily accessible through an env
variable.
Fetching /result/sealed_secrets
endpoint¶
Sealed secrets
From a user perspective, this is exactly the same as fetching /result/secrets
endpoint.
Under the hoods, the original JSON file secrets_to_seal.json
is transferred
sealed to the enclave (see how to seal secrets).
When starting,
the app seamlessly decrypts this file with the enclave’s private key,
as sealed secrets are encrypted using the enclave’s public key.
Data from secrets_to_seal.json
is then accessible from the Flask app, through SEALED_SECRETS_PATH
env variable.
This is the way to protect secrets from the SGX operator.
First, the SGX operator collects the encrypted result:
Then this encrypted result is sent to the code provider by external means.
Finally, the code provider can decrypt the result:
$ mse home decrypt --input result.enc
--key key.bin \
--output code_provider/result.plain
$ cat code_provider/result.plain
Note that the --key
parameter is the key contained in secrets_to_seal.json
.
The decrypt
command only supports Fernet algorithm. If the code
provider implements another way to encrypt the result in its microservice, another decryption code must also be
written outside Cosmian Enclave Bare Metal.
Fix or Update
In case of errors at any step of the deployment flow or if the code/the configuration needs to be updated, you shall stop and remove the current running application and restart from scratch the whole deployment flow.