First steps with AWS Nitro: hello-world

At its core, the process of starting an AWS Nitro Enclave includes the following steps:

  • identify a Docker image that contains an application,

  • convert the Docker image into an Enclave Image File (EIF),

  • start an AWS Nitro Enclave using the previously created Enclave Image File.

Using the Anjuna Nitro Runtime, you can automatically start many of the existing containers in an AWS Nitro Enclave, even if the applications in those containers were not updated to run on AWS Nitro. The first benefit of using the Anjuna Nitro Runtime tools is that it allows you to lift-and-shift many of the existing containers into an AWS Nitro Enclave. Without the Anjuna Nitro Runtime, the applications in those containers would have to be modified to be compatible with AWS Nitro.

Depending on the needs of the application, other optional steps will be needed:

  • starting and configuring specific services (networking, configuration) designed to securely support the software running in the AWS Nitro Enclaves

  • creating secrets (using KMS) that can securely be passed into the enclave for the application to use

  • automatically creating enclaves in an AWS EKS cluster

In this section, you will learn about the basic usage of the Anjuna Nitro Runtime tools to build and run a simple enclave.

Identify a simple Docker image

The Anjuna Nitro Runtime includes a sample application (hello) to get started with AWS Nitro. It is a minimal application that continuously prints Hello from the enclave side every 5 seconds, until the enclave is terminated.

Build the Docker image

The sample application is located in the following folder:

/usr/share/nitro_enclaves/examples/hello

To build the container, run the following command:

$ docker build /usr/share/nitro_enclaves/examples/hello -t hello-enclave

If the command succeeded, you should see the newly built Docker image (which was tagged as hello-enclave) when running this command:

$ docker image ls hello-enclave

Build an enclave image file (EIF)

Once the Docker image is available, you can build an Enclave Image File from it:

If you haven’t already, use your license by putting the license file at /opt/anjuna/license.yaml.

Then, run the following command to build the enclave:

$ anjuna-nitro-cli build-enclave --docker-uri hello-enclave:latest --output-file hello-enclave.eif

The command above should produce output that looks like this:

Start building the Enclave Image...
Enclave Image successfully created.
{
  "Measurements": {
    "HashAlgorithm": "Sha384 { ... }",
    "PCR0": "00bad9b9d306537bc8b7059fa2f9c9e8a6501552f1325bda0454f28b0d2eb45c0782055f11c86275281f5b54be53511c",
    "PCR1": "cde04bd3a43c742edee3a7e9a323f67cbbaca4c765221419d1b53dd5eea1998ffaf65b324947f26655c25ebba2deec0a",
    "PCR2": "413bd40f7184f9ec42599ea2113da16eb8408f8491245e8aef05c3f3fcb435eb01a1f36b71f8716b379bf9e2b18cadcd"
  }
}

If the command succeeds, it will print the enclave measurements, which are the hashes that uniquely identify an enclave. Learn more about enclave measurements.

Any combination of the measurement values can be used to create policies that describe which operations are allowed by this enclave on AWS objects stored in services that are integrated with AWS Nitro Attestation (AWS KMS, for example).

Enable networking for the AWS Nitro Enclave

Launch the parent side Network Proxy, using the --daemonize (or -d) flag to run it in the background.

$ anjuna-nitro-netd-parent --enclave-name hello-world --daemonize

The enclave name is a user-provided identifier that the Anjuna Nitro Runtime uses to connect running enclaves with supporting services (networking, persistent storage, etc). It is important that the same enclave name is provided to the network proxy and to the run-enclave command described below, or the enclave will not work as expected.

Run the enclave

Now that you have built the Enclave Image File, you can create and start an enclave that will run this hello-enclave application:

$ anjuna-nitro-cli run-enclave --enclave-name hello-world --cpu-count 2 --memory 1024 --eif-path hello-enclave.eif --debug-mode
The previous command is reserving 2 vCPUs for running the enclave, as well as 1024MB of RAM. These values are appropriate for the sample application. The number of vCPU cores must be an even number due to hyperthreading.

If the command above succeeded, your should see some output that looks like this:

Start allocating memory...
Started enclave with enclave-cid: 17, memory: 1024 MiB, cpu-ids: [1, 3]
{
  "EnclaveID": "i-0f2c4b721470e92c4-enc1776bc0278e90b9",
  "ProcessID": 13823,
  "EnclaveCID": 17,
  "NumberOfCPUs": 2,
  "CPUIDs": [
    1,
    3
  ],
  "MemoryMiB": 1024
}

Since the enclave was started in debug mode (the anjuna-nitro-cli run-enclave command was invoked with the --debug-mode flag), you can view the output of the application using the following command:

$ anjuna-nitro-cli console --enclave-name hello-world

If the enclave is running, you will see some output that looks like this:

[  40] Hello from the enclave side!
[  41] Hello from the enclave side!
[  42] Hello from the enclave side!
[  43] Hello from the enclave side!
[  44] Hello from the enclave side!
[  45] Hello from the enclave side!

Press CTRL+C to stop watching the application output (this won’t stop the enclave, it will just stop inspecting the console log).

Congratulations, you have created a simple AWS Nitro Enclave!

Finally, to terminate the enclave, run the following command:

$ anjuna-nitro-cli terminate-enclave --enclave-name hello-world

Then run the following command to terminate the Anjuna Nitro Network Proxy:

$ pkill -f 'anjuna-nitro-netd-parent --enclave-name hello-world'
pkill requires -f to match the Network Proxy associated with the correct enclave. Note that pkill matches against the command line used to run the service, so any flags must be given in the same order as the original command.

Next steps

The next step is to run a real application to explore some of the capabilities of the Anjuna Nitro Runtime.