Nitro Enclaves Are Trusted Execution Environments
How exactly do Nitro Enclaves give trust to their users? Let's start by explaining what exactly they do and then we can dig into how they are useful.
If you are familiar with EC2, you are likely familiar with the idea of running a virtual machine. When you spin up an EC2 instance, from your perspective Amazon gives you a server that you can access, configure and run programs on via ssh.
However, they don't actually give you a full physical computer (unless you are using a "bare metal" instance) they give you a virtual machine (VM) running on a server with other VMs. In essence, they carve out a number of CPUs and some RAM for your virtual machine to use. Their hypervisor runs under the hood and manages the VMs running on each server, providing security and access to the network and PCI devices like GPUs, volume memory, etc.
Say you are running an EC2 with 4 cores (CPUs) and 8 GB of RAM, Nitro Enclaves allow you to give back to Amazon 2 cores and 4 GBs of RAM for example. More specifically, you tell AWS to take these resources and run a docker container with them.
The docker container can run anything you like, but when you hand it over to Nitro you lose access to it other than a single socket connection using Virtual Sockets. You can't see any internal console messages, logs, or anything. Only the input and output of the sockets.
Further, only the parent instance (ie the EC2 that created the enclave) can communicate with the docker container running inside the enclave.
So basically this is just a worse EC2 instance inside an instance? Not quite. The enclave itself has two superpowers that make it exceptionally useful:
- The enclave can speak directly to Amazon's KMS (key management service) over TLS. So if you encrypt data of any kind and the code running inside the enclave needs to decrypt, then it can do so without talking explicitly via the parent instance.
- The enclave creates a hash of the docker container (called an attestation) inside the enclave when it communicates to the KMS. This allows you to create access rules within the KMS so only enclaves with a particular hash (ie a specific pre-agreed docker container, running pre-agreed code) get to decrypt data. This can actually be used to talk to custom KMS or equivalent too, proving what's running in the enclave.
Admittedly neither of these superpowers sounds that impressive at first glance. But give it a minute or two and you begin to see the power it creates.
Traditionally, when we use a KMS we create rules about who can encrypt and decrypt data based on IAM roles in Amazon. Basically, you can say Alice is allowed to encrypt and decrypt data with some key, or the EC2 instance with ID XYZ can use the key and so forth. The problem with this is that you are trusting Alice or the specified EC2 instance to only use the data for a particular use. You don't have any guarantees they will actually do that though. Alice may be malicious and the EC2 you chose may have been corrupted.
You also don't really have any reasonable verifiable log of what the data was used for. Perhaps the EC2 is running some code from GitHub, but which version was it running on June 7th, 2020? Not always an easy question to answer. You may have tried to solve this with logs throughout your CI/CD pipeline but you don't actually have any guarantees.
Now you do with Nitro Enclaves because only the version of code (and every other minute detail of how it runs in a docker container) will have the attestation (hash) that is required to decrypt the data using the KMS.