Running Nginx in AWS Nitro
Nginx is a good example of an application that would benefit from running in an AWS Nitro Enclave. In a production environment, it needs to have access to sensitive data (the TLS certificate), and it can serve web applications that connect to other services. Being able to completely isolate and protect the Nginx application from malicious users (even those who might have elevated privileges to the parent instance) is very valuable.
In this example, you simplify the setup and ignore the TLS configuration, and instead focus on running Nginx as an HTTP server to learn how to configure the AWS Nitro Enclave to allow HTTP clients to connect to Nginx, even though it is running in the AWS Nitro Enclave.
The steps to run Nginx in an enclave are similar to the ones in the previous section, except that there a couple of new steps (indicated in bold):
-
identify a Docker image that contains an application,
-
convert the Docker image into an Enclave Image File (EIF),
-
configure the network interfaces on the parent instance
-
start the Anjuna Nitro Network proxy
-
start an AWS Nitro Enclave using the previously created Enclave Image File.
For Nginx to be able to communicate with clients outside the enclave, the anjuna-nitro-netd-parent
is
used to forward the network traffic to/from the enclave through the only data-exchange interface
available in AWS Nitro, which is the vsock
interface. Without this daemon, the
enclave would have no way to send/receive data from clients that are not in the enclave.
On this virtual interface, the enclave is assigned with the same IP address as the Parent VM.
For the Parent VM to communicate with the enclave, on the parent host, the command localhost:80
will connect to the application listening on port 80 inside the enclave.
In this example, you will start an Nginx server in the enclave, configured to listen on port 80
(HTTP), and you will verify that the Nginx server is running by sending a curl
command from the
parent instance.
Let’s get started!
Identify a Simple Docker Image
You will use the official Nginx Docker image on Docker Hub: https://hub.docker.com/_/nginx
Build an enclave image file (EIF)
Since the Docker image is already built and published in Docker Hub, you can convert it into an Enclave Image File.
If you haven’t already, use your license
by putting the license file at /opt/anjuna/license.yaml
.
Then, run the following command to automatically pull the Nginx Docker image from Docker Hub and convert it into an EIF.
$ anjuna-nitro-cli build-enclave --docker-uri nginx:latest --output-file nginx.eif
Start the Anjuna Nitro Network proxy
Run the following command:
$ /opt/anjuna/nitro/bin/anjuna-nitro-netd-parent --expose 80 --daemonize
This command is responsible for moving the network packets between the enclave and the parent instance, and must be running for the enclave to communicate with the outside world.
This command needs to be executed only once, unless the system is rebooted, or there is a need to expose a different set of ports, and in the latter case, you need to kill the current running process and run it again with the new set of ports.
Start the AWS Nitro Enclave
$ anjuna-nitro-cli run-enclave --cpu-count 2 --memory 1024 --eif-path nginx.eif --debug-mode
The number of vCPU cores must be an even number due to hyperthreading. |
Verify that Nginx is running
$ curl localhost:80
You should see the following output:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Congratulations! Nginx is running and is accessible from outside the AWS Nitro Enclave.
Exposing the AWS Nitro Enclave to external hosts
In the previous section, you started an AWS Nitro Enclave running Nginx and connected
to it from the parent instance, using the IP address localhost
.
In a typical scenario, Nginx should be reachable from other hosts:
-
If the AWS Nitro parent instance is on an AWS VPC, other hosts on this VPC might try to connect to Nginx.
-
This AWS Nitro parent instance might be reachable from the internet (your web browser for example).
This is only an example for going through this tutorial. In most cases, you should never expose the port 80 to serve HTTP content, and you should use TLS on port 443. In that case, the command will become:
|
If your application exposes multiple ports (for example port 80 and port 8080), you can use the --expose parameter multiple times.
After you expose port 80, you can terminate and restart the AWS Nitro Enclave running Nginx, and it will become reachable through the host’s external IP address.
$ anjuna-nitro-cli terminate-enclave --all
$ anjuna-nitro-cli run-enclave --cpu-count 2 --memory 1024 --eif-path nginx.eif --debug-mode
The number of vCPU cores must be an even number due to hyperthreading. |
Run the following command on another host (replace <nitro-instance-ip> with the actual IP address of your AWS Nitro parent instance):
$ curl <nitro-instance-ip>:80
You might need to update the security rules (inbound rules) to allow such traffic to be accepted by the AWS Nitro host. |