A More Complex Example
In this section we’ll see how to configure NGINX, a popular HTTP server, to run in a secure enclave managed by the Anjuna SGX Runtime. Using the Anjuna SGX Runtime we can ensure that sensitive data used by the NGINX server are protected by strong encryption.
This section assumes that you’re using Ubuntu 18.04, and that OpenSSL, NGINX, and the Anjuna SGX Runtime are installed and configured.
To ensure that OpenSSL is installed, execute the following command:
$ sudo apt install openssl
For instructions on how to install NGINX, see the NGINX home page. For information about installing the Anjuna SGX Runtime, see Getting the Anjuna Runtime.
Stop NGINX
The installation of NGINX automatically starts the server process. In this section we will instead start the process manually from a secure enclave managed by the Anjuna SGX Runtime. To avoid comflicts between our manual process and the one started automatically by the installer, we must first stop the automatic one.
FIrst confirm that NGINX is properly installed by executing the following command:
$ nginx -v
If NGINX is installed then the command prints the installed version. If not, then it prints an error message.
Next, to ensure that the automatically-configured server is not running, execute the following command:
sudo service nginx stop
Setup NGINX
Next we’ll configure NGINX to support TLS. TLS enables clients to connect securely to NGINX without fear of eavesdroppers stealing their credentials or other sensitive data. After we configure NGINX to support TLS we’ll then configure the Anjuna SGX Runtime to run NGINX inside a secure enclave so that even insiders with privileged access to the server cannot steal its secrets.
Create a Working Directory
Create a directory for our work using the following command:
$ mkdir -p nginx-demo nginx-demo/certs nginx-demo/html nginx-demo/run nginx-demo/log $ cd nginx-demo
Generate a Self-signed Certificate
Normally you would configure NGINX for TLS using some enterprise PKI infrastructure or, in a small deployment, using an automated certificate service like Let’s Encrypt. For the sake of simplicity, we’ll instead generate a self-signed certificate. Note that this approach is not suitable for production deployments, but it differs from the recommended approach only in the details of obtaining a certificate. Once you have the certificate, the remaining configuration steps are the same as a recommended configuration.
Generate certificates to be used with NGINX:
$ openssl req -new -days 720 -newkey rsa:2048 -nodes -keyout certs/server.key -out certs/server.csr -subj "/C=US/ST=California/L=Palo Alto/O=Anjuna/OU=tutorial/CN=nginx.local.test" $ openssl x509 -in certs/server.csr -out certs/server.crt -req -signkey certs/server.key -days 720
Configure DNS for Testing
Modify your host’s /etc/hosts
file to provide a network route to the Common Name that we used to generate the certificates:
echo "127.0.0.1 nginx.local.test" | sudo tee -a /etc/hosts
Create the NGINX Configuration
NGINX takes its configuration from a file. Create a file in the working directory named nginx.conf
. Populate it with the following text:
pid run/nginx.pid; daemon off; worker_processes 1; master_process off; events { worker_connections 768; } http { server { listen 9443 ssl; root /root/nginx-demo/html; ssl_certificate /root/nginx-demo/certs/server.crt; ssl_certificate_key /root/nginx-demo/certs/server.key; ssl_protocols TLSv1.2 TLSv1.3; } ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log log/access.log; error_log log/error.log; ## # Gzip Settings ## gzip on; }
Create a Home Page
Now create a home page for yur NGINX server to serve.
First, create an html
directory:
$ mkdir -p html
Next, create a file named html/index.html
and popualte it with the following text:
<html> <head> <title>Secured Page</title> </head> <body> <h1>Welcome to this Secured Nginx Page!</h1> <p>This page is secured using the Anjuna Runtime</p> </body> </html>
Create the Anjuna SGX Runtime Manifest
Just as we did in the simpler example in Configuring a Simple Application, we’ll use anjuna-sgxrun
to generate a manifest template file, then edit it to configure the secure enclave to run NGINX.
First, use anjuna-sgxrun
to create a manifest template:
$ anjuna-sgxrun --setup nginx
If you check the files in your working directory, you’ll notice that anjuna-sgxrun
has created a manifest template named nginx.manifest.template.yaml
.
Next, edit the manifest template to tell the Anjuna SGX Runtime to automatically encrypt the home page and the server key that we created with OpenSSL. Edit nginx.manifest.template.yaml
and add the following entries to the encrypted_files:
key:
keys: - id: input_encryption_key source: enclave_generated encrypted_files: - path: <PASTE ABSOLUTE PATH TO index.html> key: input_encryption_key - path: <PASTE ABSOLUTE PATH TO server.key>./certs/server.key key: input_encryption_key
Replace the text <PASTE ABSOLUTE PATH TO index.html>
with the absolute pathname for the file ./html/index.html
. To get the absolute path, execute the following command:
$ echo $PWD/html/index.html
Replace the text <PASTE ABSOLUTE PATH TO server.keyl>
with the absolute pathname for the file ./certs/server.key
. To get the absolute path, execute the following command:
$ echo $PWD/certs/server.key
Encrypt Sensitive Files
Next we’ll use anjuna-sgxrun to encrypt the files that we added to the manifest template so that only our NGINX process can read them, and only when it runs in its secure enclave.
Use the following command to create the provisioning key that we’ll use to encrypt sensitive files:
$ anjuna-sgxrun --provision nginx
anjuna-sgxrun creates the files provision/nginx.pubkey
and provision/nginx.quote.bin
. You can use provision/nginx.pubkey
to encrypt files so that only the protected NGINX process can read them. You can use provision/nginx.quote.bin
to verify whether a key belongs to the NGINX secure enclave.
Use anjuna-check-attestation
now to verify that provision/nginx.pubkey
in fact belongs to the NGINX enclave:
$ anjuna-check-attestation --quote-file provision/nginx.quote.bin --rsa-key-file provision/nginx.pubkey
Next, use anjuna-encrypt
to encrypt the home page and the server key:
$ anjuna-encrypt --public-key provision/nginx.pubkey ./html/index.html -o ./html/index.html
$ anjuna-encrypt --public-key provision/nginx.pubkey ./certs/server.key -o ./certs/server.key
You can confirm that the home page and the server key are encrypted using the hexdump
tool:
For example:
$ hexdump -n 100 -C certs/server.key
A file encrypted by the Anjuna SGX Runtime starts with the characters "ANJUNAFS"
.
Run NGINX
Now we can use anjuna-sgxrun to run the NGINX server:
$ anjuna-sgxrun /usr/sbin/nginx -p ./ -c nginx.conf
NGINX takes its configuration from the nginx.conf
file that we created. The Anjuna SGX Runtime takes the secure enclave’s configuration from the manifest that we created. Because the manifest lists the server key and the home page as encrypted files, the secure enclave will automatically decrypt them when reading them.
Connect to NGINX
In a new terminal, use curl
to connect to the running NGINX server. Make sure that your curl
command uses the right pathname for the server certificate that we obtained in the section "Generate a Self-signed Certificate", above.
$ curl --cacert nginx-demo/certs/server.crt https://nginx.local.test:9443/index.html
curl
requests the home page from the NGINX server over an HTTPS connection using TLS. The NGINX server fetches index.html, relying on the Anjuna SGX Runtime to automatically decrypt it inside the secure enclave as it’s read. NGINX then returns the home page data over the secure TLS connection to curl
.
The home page never exists in clear text on the server’s disk or in its memory. The automatic decryption takes place entirely within the secure enclave, and so it remains encrypted to any process other than the protected NGINX server, even to priviliged processes running on the host.