← Back to Blog

Introducing Enclaver: an open-source tool for building, testing and running code within secure enclaves

Today we introduce a new open source tool, Enclaver to aid engineers in building, testing and running code within secure enclaves, starting with AWS Nitro Enclaves.

Enclaver is the start of the technological foundation for achieving EdgeBit’s mission: to empower cloud services to consume and process data securely – in a way that maintains customer control over data, without getting in the way.

Enclaver feels like running a Docker container, but it’s actually running within an AWS Nitro Enclave. Jump to Using Enclaver below or straight to running the example No-Fly-List app or running Vault in an enclave.

# run with docker
$ docker run -p 443:8001 us-docker.pkg.dev/edgebit-containers/containers/no-fly-list:latest
* Serving Flask app "/opt/app/server.py"
...app logs...

# build same app into enclave image
$ enclaver build -f enclaver.yaml
Built Release Image: sha256:da0dea...0aba7b55 (no-fly-list:enclave-latest)

# run in enclave
$ enclaver run no-fly-list:enclave-latest
 INFO  enclave         >  * Serving Flask app "/opt/app/server.py"
 ...app logs...

Securing data “in-use” is now essential

Security of data “in-use” is poised to see a surge in adoption, just as security “in-transit” has since 2016. And just as Let’s Encrypt helped to drive massive increases in adoption of TLS, we now need tools which to provide a simple UX for security-in-use.

Enclaver aims to ease implementation of “in-use” security, and enable organizations to better protect customer data against sophisticated intrusions.

These attacks have bypassed Two-Factor Authentication (2FA) protections and allow the attacker to resemble an insider threat. The defense against this is clear: data should be encrypted when it is stored and protected at every place an attacker or insider could read it while “in-use” throughout your app.

Encryption at-rest is called out specifically in many security regulations. Securing or encrypting data in-use is less explicit but just as essential to preserving privacy and preventing unauthorized access to your customer’s data – all topics covered under SOC2, PCI and ISO 27001.

Protection of data with Secure Enclaves

Secure enclaves – like AWS Nitro Enclaves, Intel SGX2, and AMD SEV – are the building block to guaranteeing a SaaS customer’s ultimate control over their data. The core promise of an enclave is to guarantee that sensitive data inserted, processed or decrypted can never be read by an attacker and leave the enclave. This is the basis for the “magic formula” – trusted runtime, network policy, app code and identity.

Taken together, these 4 parts form a cryptographic identity, called an attestation, which unlocks security and privacy capabilities that aren’t possible in other systems.

An enclave’s hardware protection is formed by isolated RAM, dedicated CPU cores, reduced default networking and Trusted Platform Modules (TPM). Software features like cryptographic attestation, ingress/egress policies and a reduced Linux userland complete the protection.

New privacy capabilities with secure enclaves

An enclave fulfills the exact definition of privacy: being free from observation or disruption by others. EdgeBit believes that all sensitive data should be highly protected, but your encryption keys deserve perfect privacy.

Protecting Encryption Keys

If you have the magic formula – trusted runtime, network policy, app code – encryption keys can be used safely in the enclave and the plaintext being encrypted also remains private. Completing the workflow is an access guarantee, using the cryptographic attestation, that any data decrypted by the Key Management Service (KMS) stays in the enclave. That means you’re exclusively trusting the identity of the code and the enclave but no humans will ever have access whether attacker or otherwise.

Protecting all sensitive data

If you are asking yourself, “can all sensitive operations gain the same protection?” The answer is yes. Enclaver makes it easy to migrate any sensitive workflow. This might be an entire microservice or just a portion of it. You can think of using an enclave the same way you would a sidecar. A simpler, focused chunk of code running beside the main parts of your app.

Moving sensitive workflows into an enclave can address many items of compliance for SOC2, PCI, ISO 27001 around data confidentiality, integrity, unauthorized removal, access controls, risk and more.

Using Enclaver

Enclaver should be familiar to anyone that uses containers. Jump to the getting started guide.

Build an Enclave Image

First, enclaver build takes an existing container image and transforms it into an enclave-enabled image based on a manifest file you provide. This works by:

  1. Adding a layer to the source image, containing Enclaver’s supervisor, enclave proxy and a copy of the manifest file.
  2. Transforming the layered source image into a Nitro Enclaves enclave image file (EIF).
  3. Building a new image, which bundles together the EIF with the tools necessary to run it, for distribution.

Here’s the manifest for the No-Fly list app, enclaver.yaml:

version: v1
name: "test"
target: "no-fly-list:enclave-latest"
sources:
  app: "us-docker.pkg.dev/edgebit-containers/containers/no-fly-list:latest"
defaults:
  memory_mb: 4096
kms_proxy:
  listen_port: 9999
egress:
  allow:
    - kms.*.amazonaws.com
    - s3.amazonaws.com
    - 169.254.169.254
ingress:
  - listen_port: 8001

The manifest is referenced when we build our enclave image:

$ enclaver build --file enclaver.yaml
 INFO  enclaver::images > latest: Pulling from edgebit-containers/containers/no-fly-list
 INFO  enclaver::images > latest: Pulling from edgebit-containers/containers/odyn
 INFO  enclaver::images > latest: Pulling from edgebit-containers/containers/nitro-cli
 INFO  enclaver::build  > starting nitro-cli build-eif in container: 40bcc4...847972
 INFO  nitro-cli::build-eif > Start building the Enclave Image...
 INFO  nitro-cli::build-eif > Using the locally available Docker image...
 INFO  nitro-cli::build-eif > Enclave Image successfully created.
 INFO  enclaver::build      > packaging EIF into release image
Built Release Image: sha256:da0dea2c...0aba7b55 (no-fly-list:enclave-latest)
EIF Info: EIFInfo {
    measurements: EIFMeasurements {
        pcr0: "85aaa37e85a0b7178bb5700a8c1ae584bf4f994996db6f18503e215cf35b65f737b19e822b3f10eb634317bd4f11deee",
        pcr1: "bcdf05fefccaa8e55bf2c8d6dee9e79bbff31e34bf28a99aa19e6b29c37ee80b214a414b7607236edf26fcb78654e63f",
        pcr2: "cb64e00fce6987d7484c18cc4c19d92ec80955d86f6b43b2d4794f9edc1a9d0200d72cf3e876566e9d888bc971413f46",
    },
}

Run the Enclave

The second step is to use enclaver run on an adequate EC2 (see Deploy on AWS) machine to start the enclave. Since dedicated cores and RAM are allocated to the enclave, the instance type needs to be similar to an c6a.xlarge with 4+ vCPUs. The run command will use the manifest file to configure the enclave so it’s ready to be used by the other parts of your application.

$ enclaver run no-fly-list:enclave-latest
 INFO  enclaver::run   > starting egress proxy on vsock port 17002
 INFO  enclaver::vsock > Listening on vsock port 17002
 INFO  enclaver::run   > starting enclave
 INFO  enclaver::run   > started enclave i-00e43bfc030dd8469-enc1840fa584262e1a
 INFO  enclaver::run   > waiting for enclave to boot
 INFO  enclaver::run   > connected to enclave, starting log stream
 INFO  enclave         >  INFO  enclaver::vsock > Listening on vsock port 17001
 INFO  enclave         >  INFO  enclaver::vsock > Listening on vsock port 17000
 INFO  enclave         >  INFO  odyn::enclave   > Bringing up loopback interface
 INFO  enclave         >  INFO  odyn::enclave   > Seeding /dev/random with entropy from nsm device
 INFO  enclave         >  INFO  odyn            > Enclave initialized
 INFO  enclave         >  INFO  odyn            > Startng egress
 INFO  enclave         >  INFO  odyn            > Startng ingress
 INFO  enclave         >  INFO  enclaver::vsock > Listening on vsock port 8001
 INFO  enclave         >  INFO  odyn            > Starting KMS proxy
 INFO  enclave         >  INFO  odyn::kms_proxy > Generating public/private keypair
 INFO  enclave         >  INFO  enclaver::vsock > Connection accepted
 INFO  enclave         >  INFO  enclaver::vsock > Connection accepted
 INFO  enclave         >  INFO  odyn::kms_proxy > Fetching credentials from IMDSv2
 INFO  enclave         >  INFO  odyn::kms_proxy > Credentials fetched
 INFO  enclave         >  INFO  odyn            > Starting ["python", "-m", "flask", "run", "--host=0.0.0.0", "--port=8001"]
 INFO  enclave         >  * Serving Flask app "/opt/app/server.py"
 ...your app logs...

Configure KMS Policy

Last, if you are doing Amazon KMS operations within your enclave, you can scope a key access policy to the attestation of the enclave image. This is the value of PCR0 printed at the end of our build above.

"StringEqualsIgnoreCase": {
    "kms:RecipientAttestation:PCR0": "85aaa37e85a0b...17bd4f11deee"
}
View the complete access policy

The Principal may stand out to you — it allows any AWS account to use this key. Anyone can run this demo, so anyone can use the key…well, anyone inside of this exact Enclave image can use the key.

For real use-cases, you would lock down this policy to your AWS accounts and you could target higher PCR values for greater specificity.

{
    "Version": "2012-10-17",
    "Id": "key-noflylist",
    "Statement": [
        {
            "Sid": "Allow public use of the key for no-fly-list demo",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "*",
            "Condition": {
                "StringEqualsIgnoreCase": {
                    "kms:RecipientAttestation:PCR0": "85aaa37e85a0b7178bb5700a8c1ae584bf4f994996db6f18503e215cf35b65f737b19e822b3f10eb634317bd4f11deee"
                }
            }
        }
    ]
}

The manifest shown above includes configuration for the KMS proxy, which automatically attaches the enclave’s attestation document to KMS API calls that can use it.

kms_proxy:
  listen_port: 9999

This allows apps that don’t understand enclaves, but do use KMS, to benefit from this powerful policy feature without modification. Simply configure them to talk to localhost:9999 or the environment variable $AWS_KMS_ENDPOINT.

Enclaver Architecture

Enclaver consists of 3 interrelated pieces of software:

  • enclaver CLI for building distributable enclave container images
  • “Outer Proxy” + Enclave Supervisor
  • “Inner Proxy” + Process Supervisor

The beauty of it is that you don’t have to worry about any of this, because your experience is simply enclaver build - Enclaver handles all of the orchestration needed to make your app work in a Nitro Enclave.

If you’re interested in learning more about cryptographic attestation or Amazon KMS integration, read the architecture doc for all the technical details.

More from EdgeBit in the future

Enclaver fills a gap in usability and access to secure enclaves, but it doesn’t complete our mission to empower SaaS services to consume and process data securely – and in a way that maintains customer control over data.

We’re looking for design partners to influence how we tackle the wider journey of building security-centric and privacy-preserving features of their SaaS applications. We would love to chat about your ideas and test out our software.

If you’re a customer of a SaaS platform and want to influence the platforms you are already using, we would also love to hear from you.