Attestation is a powerful feature of Enclaves that allow the end user to be confident of the exact software and OS running on an enclave before sending sensitive data to it.
When building a Nitro Enclave, a set of hashes called Platform Configuration Registers (PCRs) are returned that describe what will be running on the enclave. They are useful for version tracking but are more valuable when it's possible to reproduce them on different machines to prove trust to external parties.
In order for an EIF to be reproducible across different machines, the underlying Dockerfile must be reproducible. One of the biggest issues with build reproducibility is that time stamps are added in Docker layers and by package managers so rebuilding from the same source will produce different hashes even if they are built moments apart.
A lot of work has been done to overcome this, with more left to do but we highly recommend having a look at Akihiro Suda's blog post explaining how it's possible with Buildkit as it's the approach we took for Enclaves.
Buildx version v0.10.0(Buildkit version v0.11.0) is the minimum version needed for reproducible Enclave builds. Earlier versions will still build Enclaves successfully but reproducible PCRs won’t be guaranteed.
You can check your Buildx version by running:
If it’s lower than v0.10.0 upgrading your Docker desktop/engine version will pull in a compatible version of Buildx.
You will also need an Evervault account to follow this guide. If you don't have one yet, you can sign up here.
If you haven't already installed the Enclaves CLI, you can do so using the following command:
First you'll need an app with a Dockerfile. We have a hello world one to get you started.
Start by initializing the Enclave with the CLI:
Next, build the Enclave:
The build step will take your
Dockerfile and create a new one with the required Evervault related directives. These directives include installing the data plane, required packages such as Runit and also including Enclave specific environments variables that make running your app on an enclave possible. The intermediate
enclave.Dockerfile is then converted to an EIF so that it can be run on an enclave.
You should see a file named
enclave.Dockerfile in your folder at this point and the enclave.toml should have PCRs like this:
These measurements will be reproducible by any third party on their machine. To test it out trying running the rebuild process in CI.
You can rebuild an enclave with the following command:
If your Dockerfile is pulling in source code during build you'll need to run the command from the same commit as it was initally generated. We store the git hash associated with the deployment along with the PCRs so you can easily access them in the dashboard under Enclave versions if you need to cross reference PCRs with commits.
enclave.Dockerfile must be used for build reproducibility instead of the original
Dockerfile. Different versions of the Enclave CLI will inject different scripts/values that would affect the PCRs if the other party uses a different version to you.
The default behaviour is to use Unix epoch 0 as the timestamp to build the Dockerfile with. If you wish to set it to a specific time such as the time of the commit, you can export
SOURCE_DATE_EPOCH with the time in milliseconds and the CLI will use that during the build process.
In order to ensure that your Enclave is reproducible, all the packages that are installed in your Dockerfile must always use the same binary. Package managers don’t guarantee reproducibility so if you are using one you’ll need to work around this.
We created an installer where dependencies are compiled and packed into a binary that can be pinned by version in the
enclave.Dockerfile, the source code is here. Additionally, repro-get can also be used to achieve the same thing depending on your Dockerfile’s distro.
Now that you've built an Enclave that can be build bit for bit by multiple parties, its time to deploy