Nitro Enclaves application: AWS Certificate Manager for Nitro Enclaves - AWS

Nitro Enclaves application: AWS Certificate Manager for Nitro Enclaves

Note

AWS Certificate Manager for Nitro Enclaves is available for Linux instances only. It is currently not supported on Windows instances.

AWS Certificate Manager (ACM) for Nitro Enclaves allows you to use public and private SSL/TLS certificates with your web applications and web servers running on Amazon EC2 instances with AWS Nitro Enclaves. SSL/TLS certificates are used to secure network communications and to establish the identity of websites over the internet, as well as resources on private networks.

Previously, when running a web server on an EC2 instance, you would have created SSL certificates and stored them as plaintext on your instance. With ACM for Nitro Enclaves, you can now bind AWS Certificate Manager certificates to an enclave and use those certificates directly with your web server, without exposing the certificates in plaintext form to the parent instance and its users.

ACM for Nitro Enclaves removes the time-consuming and error-prone manual process of purchasing, uploading, and renewing SSL/TLS certificates. ACM for Nitro Enclaves creates secure private keys, distributes the certificate and its private key to your enclave, and manages certificate renewals. With ACM for Nitro Enclaves, the certificate's private key remains isolated in the enclave, preventing the instance, and its users, from accessing it.

Currently, ACM for Nitro Enclaves works with NGINX servers running on Amazon EC2 instances to install the certificate and seamlessly replace expiring certificates. Support for additional web servers will be added over time.

Note

ACM for Nitro Enclaves uses the standardized PKCS11 cryptographic interface between the parent instance and the enclave. Any application that supports the PKCS11 protocol can be adapted to use ACM for Nitro Enclaves for protecting certificates and keys.

ACM for Nitro Enclaves also includes a “helper” p11-kit based module for using the PKCS11 protocol over the Nitro Enclaves vsock socket.

At this time, Apache HTTP server's built-in support for PKCS11 does not work with ACM for Nitro Enclaves.

Public SSL/TLS certificates that you provision through ACM for Nitro Enclaves are free. You pay only for the AWS resources that you create to run your application, such as Amazon EC2 instances.

Installing and configuring ACM for Nitro Enclaves

Prerequisites

The IAM user performing this configuration must have permission to use the ec2:AssociateEnclaveCertificateIamRole, ec2:GetAssociatedEnclaveCertificateIamRoles, and ec2:DisassociateEnclaveCertificateIamRole actions. To grant the IAM user the required permissions, use the following IAM policy.

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "ec2:AssociateEnclaveCertificateIamRole", "ec2:GetAssociatedEnclaveCertificateIamRoles", "ec2:DisassociateEnclaveCertificateIamRole" ], "Resource": [ "arn:aws:acm:region:account_id:certificate/*", "arn:aws:iam::account_id:role/*" ], "Effect": "Allow" } ] }

Step 1: Create the AWS Certificate Manager certificate

Create the AWS Certificate Manager (ACM) certificate that you want use with your NGINX server. ACM for Nitro Enclaves supports both private and public certificates. For more information about creating a certificate, see the following resources in the AWS Certificate Manager User Guide.

After you have created the certificate, make a note of the certificate ARN; as you'll need it later.

Step 2: Launch the enclaves-enabled parent instance

Launch an enclave enabled instance that you will use as the parent instance. You can choose to use the ACM for Nitro Enclaves AMI, which comes with all of the required software preinstalled, or you can use an Amazon Linux 2 AMI and then manually install the required software from the Amazon Linux Extras repository.

After you launch the instance, make a note of the instance ID, as you'll need it later.

Option 1: Using the ACM for Nitro Enclaves AMI from AWS Marketplace

Use an ACM for Nitro Enclaves AMI that you select from AWS Marketplace.

To launch an instance using the ACM for Nitro Enclaves AMI

  1. Open the AWS Certificate Manager for Nitro Enclaves page in the AWS Marketplace.

  2. Find the ACM for Nitro Enclaves AMI for your Region, and note the AMI ID. You need the AMI ID for the next step.

  3. Launch the instance using the AMI from the AWS Marketplace and enable it for Nitro Enclaves using the following command.

    $ aws ec2 run-instances --image-id ami_id --count 1 --instance-type supported_instance_type --key-name your_key_pair --enclave-options 'Enabled=true'

Option 2: Installing ACM for Nitro Enclaves from the Amazon Linux Extras repository

To install ACM for Nitro Enclaves from the Amazon Linux Extras repository

  1. Launch the parent instance using an Amazon Linux 2 AMI.

    $ aws ec2 run-instances --image-id ami_id --count 1 --instance-type supported_instance_type --key-name your_key_pair --enclave-options 'Enabled=true'
  2. Connect to the instance.

  3. Enable the aws-nitro-enclaves-cli and nginx1 topics in the Amazon Linux Extras library.

    $ sudo amazon-linux-extras enable aws-nitro-enclaves-cli nginx1
  4. Install NGINX from the Amazon Linux Extras library.

    $ sudo amazon-linux-extras install nginx1 -y
  5. Install ACM for Nitro Enclaves from the Amazon Linux Extras library.

    $ sudo yum install aws-nitro-enclaves-acm -y
  6. Restart ACM for Nitro Enclaves.

    $ sudo systemctl restart nitro-enclaves-acm.service

Step 3: Prepare the IAM role

To grant the instance permission to use the ACM certificate, you must create an IAM role with the required permissions. The IAM role is later attached to the instance and the ACM certificate.

Create a JSON file named acm-role and add the following policy statement.

{ "Version":"2012-10-17", "Statement":[ { "Effect":"Allow", "Principal":{ "Service":"ec2.amazonaws.com" }, "Action":"sts:AssumeRole" } ] }

Use the create-role command to create a role named acm-role, and specify the path to the JSON policy file.

$ aws iam create-role --role-name acm-role --assume-role-policy-document file://acm-role.json

After you have created the role, make a note of the role ARN, as you'll need it in the next step.

Step 4: Associate the role with the ACM certificate

Attach the IAM role that you created in the previous step to the ACM certificate. To do this, use the associate-enclave-certificate-iam-role command, and specify the ARN of the role to attach, and the ARN of the certificate to attach it to.

$ aws ec2 --region region associate-enclave-certificate-iam-role --certificate-arn certificate_ARN --role-arn role_ARN

For example

$ aws ec2 --region us-east-1 associate-enclave-certificate-iam-role --certificate-arn arn:aws:acm:us-east-1:123456789012:certificate/d4c3b2a1-e5d0-4d51-95d9-1927fEXAMPLE --role-arn arn:aws:iam::123456789012:role/acm-role

Example output

{ "CertificateS3BucketName": "aws-ec2-enclave-certificate-us-east-1", "CertificateS3ObjectKey": "arn:aws:iam::123456789012:role/acm-role/arn:aws:acm:us-east-1:123456789012:certificate/d4c3b2a1-e5d0-4d51-95d9-1927fEXAMPLE", "EncryptionKmsKeyId": "a1b2c3d4-354d-4e51-9190-b12ebEXAMPLE" }

After running the command, make a note of CertificateS3BucketName and EncryptionKmsKeyId, as you'll need them for the next step.

Step 5: Grant the role permission to access the certificate and encryption key

You must now grant the IAM role (acm-role) permission to do the following:

  • Retrieve the ACM certificate from the Amazon S3 bucket returned in the previous step

  • Perform kms:Decrypt using the AWS KMS key returned in the previous step

  • Retrieve information about itself, including its path, GUID, and ARN.

Create a JSON file named acm-role-policies, add the following policy statement, and specify the values of CertificateS3BucketName and EncryptionKmsKeyId from the previous step.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetObject" ], "Resource": ["arn:aws:s3:::CertificateS3BucketName/*"] }, { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "kms:Decrypt" ], "Resource": "arn:aws:kms:region:*:key/EncryptionKmsKeyId" }, { "Effect": "Allow", "Action": "iam:GetRole", "Resource": "arn:aws:iam::123456789012:role/acm-role" } ] }

Use the put-role-policy command to add the additional policies to the acm-role role, and specify the path to the JSON policy file.

$ aws iam put-role-policy --role-name acm-role --policy-name acm-role-policy --policy-document file://acm-role-policies.json

Step 6: Attach the role to the instance

You must attach the IAM role to the instance to give it permission to use the certificate.

Create a new instance profile named acm-instance-profile using the create-instance-profile command.

$ aws iam create-instance-profile --instance-profile-name acm-instance-profile

Example output

{ "InstanceProfile": { "Path": "/", "InstanceProfileName": "acm-instance-profile", "InstanceProfileId": "ABCDUS6G56GWDIEXAMPLE", "Arn": "arn:aws:iam::123456789012:instance-profile/acm-instance-profile", "CreateDate": "2020-10-14T03:38:08+00:00", "Roles": [] } }

Add the acm-role that you created earlier to the acm-instance-profile that you just created. Use the add-role-to-instance-profile command.

$ aws iam add-role-to-instance-profile --instance-profile-name acm-instance-profile --role-name acm-role

Associate the instance profile with the instance that you launched previously. Use the associate-iam-instance-profile command and specify the instance profile to attach and the instance to attach it to.

$ aws ec2 --region region associate-iam-instance-profile --instance-id instance_id --iam-instance-profile Name=acm-instance-profile

Example output

{ "IamInstanceProfileAssociation": { "AssociationId": "iip-assoc-0a411083b4EXAMPLE", "InstanceId": "i-1234567890abcdef0", "IamInstanceProfile": { "Arn": "arn:aws:iam::123456789012:instance-profile/acm-instance-profile", "Id": "ABCDUS6G56GWDIEXAMPLE" }, "State": "associating" } }

Step 7: Configure NGINX to use ACM for Nitro Enclaves

Configure the NGINX web server to use the ACM certificate.

To configure NGINX

  1. SSH into the instance that you launched previously.

  2. Rename the sample ACM for Nitro Enclaves configuration file from /etc/nitro_enclaves/acm.example.yaml to /etc/nitro_enclaves/acm.yaml.

    $ sudo mv /etc/nitro_enclaves/acm.example.yaml /etc/nitro_enclaves/acm.yaml
  3. Using your preferred text editor, open /etc/nitro_enclaves/acm.yaml. In the Acm section, for certificate_arn, specify the ARN of the certificate. Save and close the file.

  4. Configure NGINX to use the pkcs11 SSL engine by setting the top-level ssl_engine directive.

    Using your preferred text editor, open /etc/nginx/nginx.conf. Add the following line below pid /run/nginx.pid;.

    ssl_engine pkcs11;

    Example

    # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; ssl_engine pkcs11;
  5. Enable the TLS server and configure the server to use your certificate.

    In /etc/nginx/nginx.conf, scroll to the bottom of the file and do the following:

    • Uncomment all of the lines below Settings for a TLS enabled server.

    • In the first block, for server_name, specify the host name, or the common name (CN), that you specified when you created the certificate.

    • In the second block, remove the following lines.

      ssl_certificate "/etc/pki/nginx/server.crt"; ssl_certificate_key "/etc/pki/nginx/private/server.key"; ssl_ciphers PROFILE=SYSTEM;

      And add the following line.

      ssl_protocols TLSv1.2;
    • Add the following as a new block below the second block.

      # Set this to the stanza path configured in /etc/nitro_enclaves/acm.yaml include "/etc/pki/nginx/nginx-acm.conf";

    The completed section should appear as follows.

    # Settings for a TLS enabled server. # server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name example.com; root /usr/share/nginx/html; ssl_protocols TLSv1.2; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_prefer_server_ciphers on; # Set this to the stanza path configured in /etc/nitro_enclaves/acm.yaml include "/etc/pki/nginx/nginx-acm.conf"; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
  6. Start the ACM for Nitro Enclaves service and ensure that it starts automatically at instance boot.

    $ sudo systemctl start nitro-enclaves-acm.service
    $ sudo systemctl enable nitro-enclaves-acm
  7. Test that the ACM for Nitro Enclaves is working as expected.

    If you used a public certificate, use the following command.

    $ curl https://host_name_or_IP

    If you used a private certificate, you must add the host name to /etc/hosts in the following format: 127.0.0.1 host_name, for example 127.0.0.1 example.com. And you must specify the certificate chain to use to validate the certificate. For more information about generating the certificate chain for your certificate, see Exporting a Private Certificate in the AWS Certificate Manager User Guide.

    $ curl --cacert path_to_pem_file https://host_name_or_IP

    A successful test displays the NGINX index.htm. The ACM for Nitro Enclaves service continuously polls and fetches the ACM certificate data and updates NGINX accordingly. It does this by generating an NGINX config snippet and including it in the main nginx.conf.

    If you renew the ACM certificate by running acm renew-certificate, the ACM for Nitro Enclaves automatically reconfigures the enclave and the NGINX web server. You can use the following command to check the log for update announcements and to diagnose possible issues.

    $ journalctl -u nitro-enclaves-acm.service

    If you encounter any unexpected errors, you can also check the NGINX service log for more details.

    $ journalctl -u nginx.service

Using multiple certificates

You can also add multiple ACM certificates; one for each PKCS#11 token. For each additional certificate that you need to add, repeat Step 4: Associate the role with the ACM certificate in order to associate your IAM role with the additional ACM certificates.

Then to add more PKCS#11 tokens, open /etc/nitro_enclaves/acm.yaml with your preferred text editor, and under the token section, add another label block and specify a label name, the ARN of the additional certificate, and a path for the NGINX stanza. For example, the following snippet shows the format to be used for three ACM certifictes (the initial certificate and two additional certificates):

tokens: # A label for this PKCS#11 token - label: nginx-acm-token # Configure a managed token, sourced from an ACM certificate. source: Acm: # The certificate ARN # Note: this certificate must have been associated with the # IAM role assigned to the instance on which ACM for # Nitro Enclaves is run. certificate_arn: "arn:aws:acm:us-east-1:123456789012:certificate/d4c3b2a1-e5d0-4d51-95d9-1927fEXAMPLE" target: NginxStanza: # Path to the nginx stanza to be written by the ACM service whenever # the certificate configuration changes (e.g. after a certificate renewal). # This file must be included from the main nginx config `server` section, # as it will contain the TLS nginx configuration directives. path: /etc/pki/nginx/nginx-acm.conf # Stanza file owner (i.e. the user nginx is configured to run as). user: nginx # PKCS#11 token 2 - label: token_2_name source: Acm: certificate_arn: "certificate_2_ARN" target: NginxStanza: path: /etc/pki/nginx/nginx-acm-2.conf user: nginx # PKCS#11 token 3 - label: token_3_name source: Acm: certificate_arn: "certificate_3_ARN" target: NginxStanza: path: /etc/pki/nginx/nginx-acm-3.conf user: nginx
Note

You also need to update the /etc/nginx/nginx.conf configuration file to include the additional ACM certificates. For more information about configuring NGINX for mutiple domains and bout different use cases, refer to the NGINX documentation.

After you have completed the necessary configuration, run the following command to restart the Start the ACM for Nitro Enclaves service.

$ sudo systemctl restart nitro-enclaves-acm.service

Updating ACM for Nitro Enclaves

If you have already installed ACM for Nitro Enclaves, use the following command to update it to the latest version.

$ sudo yum update aws-nitro-enclaves-acm

Uninstalling ACM for Nitro Enclaves

If you no longer want to use ACM for Nitro Enclaves, use the following steps to uninstall it.

To uninstall ACM for Nitro Enclaves

  1. Stop the NGINX service.

    $ sudo systemctl stop nginx
  2. Stop the ACM for Nitro Enclaves service.

    $ sudo systemctl stop nitro-enclaves-acm.service
  3. Uninstall ACM for Nitro Enclaves.

    $ sudo yum remove aws-nitro-enclaves-acm