Enclaves are designed to be flexible to fit your development process. Here are a few best practices to set you up for success.
Since Enclaves are built using Docker, a good place to start is making sure that you are formatting your Dockerfile correctly.
First you need to use the
FROM command which will create a layer from the Docker image you wish to use. It’s best to use one of the container images available on Docker Hub to ensure you are using a trusted source. You can also opt for using the
slim version of the container which can help reduce the image size, however the
slim versions may not contain all of the common packages in the default tag.
Next you will need to copy any files from your local source to the filesystem of the container. It’s best to use absolute paths in the Dockerfile. When your Docker container is converted to an Enclave, your commands might not be run in the directory you expect them to be, so it is safer to reference your files as absolute paths.
Make sure that you are exposing the non-reserved port you want to listen on since that is where traffic within the Enclave will be forwarded. The Enclaves documentation uses
PORT 8008 as an example, but this can be any available port that you define.
Here are some examples of what your Dockerfile might look like.
For Java and other compiled languages, you may need to use a multi-stage build that involves first creating a build stage and then a package stage.
Docker will then build images by reading the instructions from your Dockerfile. The default instance size supports up to 2GB Docker images.
You can check the size of your Docker image using the
docker inspect command
One helpful step you can take is to try containerizing your application before deploying the container inside a Enclave. If it can run with Docker, it should be able to run in a Enclave, and it will help you debug errors that may exist from the Docker build before you attempt to run it in a Enclave.
Once you have your app ready including the Dockerfile, navigate to the directory containing the Dockerfile, then run the following command:
Next, you can start the container using
docker run along with the name of your image and the container port that you exposed in the Dockerfile mapped to the host port.
Now if you go to the host port
http://localhost:8080 you should see your app running. You can also check the Docker Desktop app or CLI to confirm that the container is running.
Some of the instructions in your Dockerfile will install required packages. You can use whichever package manager makes sense for your application.
In some cases, you may want to use a manifest file that will contain the required packages and their versions, like a
package.json for Node or
requirements.txt for Python.
For Python specifically, it can also be helpful to use a virtual environment. You can run the virtual environment within the container and then install the packages within the environment. This will also help with minimizing image size.
Here is an example:
By design, data that is encrypted with Evervault that passes into the Enclave will automatically decrypt. There is no further action required to decrypt and start using the data.
You also can utilize
/decrypt endpoints that are exposed on an in-Enclave API listening on port
9999 within the enclave. These are not available outside of the enclave, so if you have publicly available endpoints within your app that use the same naming, there should not be any conflict.
These endpoints are available for all Enclaves. Here is an example of how you might implement it in Node.
To encrypt data, you can make a request to
/encrypt and pass in any data that you wish to encrypt as JSON.
The purpose of the decryption API is to offer flexibility with applications built inside the Enclave. Examples could be if you need to upload a list of large files of encrypted data to be decrypted on start up of the Enclave or a process that pulls in encrypted data from an external source.
Another point to note is that when TLS termination is turned off in the data plane, it’s not possible for the request to be scanned for encrypted strings. This is another instance where the Decrypt API could be used.
Here is an example of how to consume the Decrypt API.
To decrypt data you can make another request to
/decrypt and pass in the encrypted string as JSON.
The Evervault Client SDKs for Node, Python, Go, iOS and Android all expose attestation helpers which will perform attestation on every connection to your Enclave. This is done by pulling an attestation document from the Enclave, and comparing its signed PCRs against the set of PCRs provided to the SDKs. If the PCRs are found to match, the challenge from the attestation document is compared against the certificate public key to confirm that the TLS connection is being terminated inside the Enclave. A more detailed discussion of our attestation in TLS can be found here.
Note: When running your Enclave in debug mode, every value in the attestation document returned will be 0, so if you need to check the attestation measures do not use the
--debug flag when initializing the Enclave.
Below are code snippets showing how to configure your Evervault SDK to enable attestation.
This takes in a set of expected PCRs and validates they are returned in the TLS handshake of requests sent to the Enclave. You can pass in a single PCR value as an object or multiple PCR values as an array of objects.
This is the same behavior in Python. You can pass in a single PCR value as a dictionary or multiple PCR values as a list of dictionaries.
You can then validate it locally using the
ev-enclave attest command in the CLI. This will validate that the PCRs in the
enclave.toml file match the PCRs returned in the handshake.
The attestation doc for an Enclave is publicly accessible through the
/.well-known/attestation endpoint. This allows the Evervault SDKs to poll the attestation document and detect any changes resulting from deployments.
You can request the attestation document using the following curl command:
To turn logging off or on, you will need to define
trx_logging = true or
trx_logging = false in your
enclave.toml. You can also leave it undefined and it will be turned on because the default state is set to
From there you should be able to see all of your calls to the Enclave in the Enclaves Dashboard under Activity.
You can also find a unique ID from the request and can use that ID to search for a specific call in case you have many calls to look through.
There are two ways to see the original IP on the connection.
When using TLS Termination, the IP will be included in the HTTP
If you have TLS Termination disabled, you can receive the client IP via proxy protocol by setting the
FORWARD_PROXY_PROTOCOL environment variable in your Enclave.