AWS Security Blog
Using AWS CloudHSM-backed certificates with Microsoft Internet Information Server
SSL/TLS certificates are used to create encrypted sessions to endpoints such as web servers. If you want to get an SSL certificate, you usually start by creating a private key and a corresponding certificate signing request (CSR). You then send the CSR to a certificate authority (CA) and receive a certificate. When a user seeks to securely browse your website, the web server presents the certificate to the user’s browser. The user’s browser verifies that the certificate is associated with a trusted root certificate, and then uses the certificate to encrypt the session data. The web server then uses the private key to decrypt the user’s data. The security of this protocol relies on the private key remaining private.
A common problem with web servers, however, is that the private key and the certificate reside on the web server itself. If an attacker compromises the server and steals both the private key and certificate, the attacker could potentially use them to intercept the session or create an imposter server. If your business requires the use of hardware security modules for key storage, you can use AWS CloudHSM to generate and hold the private keys for web server certificates rather than placing them on the web server directly and reduce your exposure. On Windows, AWS CloudHSM integrates with Microsoft Internet Information Server (IIS) through the Key Storage Provider extensions to the Microsoft Cryptography Next Generation API (KSP/CNG). In this blog post, I will show you how to leverage CloudHSM KSP/CNG capabilities to secure the private key within the hardware security module (HSM), if you are using Microsoft Internet Information Server (IIS) to host your website.
Prerequisites and assumptions
You need the following for this walkthrough.
- An AWS account and permissions to provision Amazon Virtual Private Cloud (Amazon VPC), Amazon Elastic Compute Cloud (Amazon EC2) instances, Amazon Route 53, and Amazon CloudHSM. I recommend using an AWS user account ID that has full administrative privileges.
- A region that supports CloudHSM. I’m using the eu-west-1 (Ireland) region.
- A domain to use for certificate generation. I’m using the domain example.com.
- A trusted public certificate authority (CA).
- A working knowledge of the Amazon VPC, Amazon EC2, and Amazon CloudHSM services.
- Familiarity with the administration of Windows Server 2012 R2
Important: You will incur charges for the services used in this example. You can find the cost of each service on that service’s pricing page. You can also use the Simple Monthly Calculator to estimate the cost.
Architectural overview
I’ll go over a few diagrams before I start building. I’ll start with a diagram of the infrastructure.
![Figure 1: CloudHSM infrastructure](https://d2908q01vomqb2.cloudfront.net/22d200f8670dbdb3e253a90eee5098477c95c23d/2018/08/01/CloudHSM-CNG-img-1v3.png)
Figure 1: CloudHSM infrastructure
This diagram shows a VPC in the eu-west-1 (Ireland) region. An Amazon EC2 instance running Windows Server 2012 R2 resides on a public subnet. This instance will run both the CloudHSM client software and IIS to host a website. The instance has an Elastic IP and can be accessed via the Internet Gateway. I’ll also have security groups that enable RDP, HTTP, and HTTPS access. The private subnet hosts the Elastic Network Interface (ENI) for CloudHSM cluster that has a single HSM.
And here’s the certification hierarchy:
![Figure 2: Certification hierarchy](https://d2908q01vomqb2.cloudfront.net/22d200f8670dbdb3e253a90eee5098477c95c23d/2018/08/03/CloudHSM-CNG-img-2-new-1.png)
Figure 2: Certification hierarchy
The Amazon EC2 instance will run Windows Server 2012 R2 (WS2012R2) and IIS. I’ll use the KSP/CNG capabilities of CloudHSM to request a CSR from the WS2012R2 instance. The KSP/CNG integration will reach out to CloudHSM that will, in turn, create a private/public key pair. The private key will remain within CloudHSM while the public key will be used to create the CSR. I’ll then submit the CSR to a CA. The CA will sign the CSR with the CA‘s private key and return a certificate. I’ll then accept the CSR with the certificate that will make it available to IIS. I’ll then secure the default IIS website with the certificate. Finally, I’ll browse to the website and show how it uses the CNG/KSP integration.
Now that you’ve seen what I’m building, we can get started!
Build the CloudHSM infrastructure
You’ll need to set up a CloudHSM environment. This environment will consist of a VPC, a CloudHSM cluster with a single HSM, and a Windows 2012 R2 EC2 instance that will run both the CloudHSM client and IIS. For each of the steps below, I have provided a link to the relevant documentation, as well as any additional instructions to build out the infrastructure to match my sample environment.
- Select a region that offers AWS CloudHSM. I’m using the eu-west-1 (Ireland) region.
- Create a Virtual Private Cloud (VPC). Use the following values:
VPC IPv4 CIDR block: 10.0.0.0/16
VPC Name: cloudhsm-vpc
Public subnet IPv4 CIDR block: 10.0.0.0/24
Public subnet Availability Zone: eu-west-1b
Public subnet name: cloudhsm-public - Create a private subnet. Use the following values:
IPv4 CIDR block: 10.0.1.0/24
Availability Zone: eu-west-1b
Name: cloudhsm-private - Create a cluster. Use the following values:
HSM Availability Zone: eu-west-1b
Subnet: Use the private subnet you just created in eu-west-1b.
Number of HSMs: 1 - Launch an Amazon EC2 client instance. Use the following values:
AMI: Microsoft Windows Server 2012 R2 Base
Instance type: t2.medium
VPC: cloudhsm-vpc
Subnet: cloudhsm-public
Auto-assign Public IP: Enable
Name tag: cloudhsm
Security group: The CloudHSM cluster security group
Once the instance is running, create an additional administrative Windows user because the built-in Administrator account has restrictions. - Create an additional security group to allow you to connect to the instance and attach the security group to the instance in addition to the security group of the CloudHSM cluster.
- Allocate and associate an Elastic IP address to the instance so that the instance’s IP address persists if you need to stop and start the instance.
- Create a DNS “A record” to map the host name to the Elastic IP. In this example, I’m mapping www.example.com to the Elastic IP that I allocated.
- Create an HSM. After the HSM is created, note the HSM Id in the form of hsm- followed be an alphanumeric string; for example, hsm-1234abcd.
- Initialize the cluster.
- Install and configure the AWS CloudHSM client (Windows).
You might need to use a command window with administrative privileges to do this. - Activate the cluster.
- Create a crypto user. You will need to specify the ID and the password of the crypto user in the environment variables that you will create in the next section.
Define environment variables
We now need to define some Windows system environment variables (not user variables) used by the CNG/KSP integration. You can modify the environment variables by selecting System from the Control Panel, selecting Advanced System Settings, and selecting Environment Variables.
- Go into the Windows Control Panel and enter the following definitions:
liquidsecurity_daemon_id 1
liquidsecurity_daemon_socket_type TCPSOCKET
liquidsecurity_daemon_tcp_port 1111
n3fips_username USER
n3fips_password USER:PASSWORD
n3fips_partition hsm-ABCDEFGHIJK - Substitute the user ID and password that you specified in step 12 for the USER and PASSWORD values.
- Substitute the HSM ID value you got from step 8 for hsm-ABCDEFGHIJK.
- Reboot the EC2 instance to ensure that the environment variables are in place for all process.
Your Windows Control Panel configuration should look like the image below, not including the above substitutions.
![Figure 3: Environment variable settings](https://d2908q01vomqb2.cloudfront.net/22d200f8670dbdb3e253a90eee5098477c95c23d/2018/08/01/CloudHSM-CNG-img-3v2.png)
Figure 3: Environment variable settings
Launch the CloudHSM client
You must start the CloudHSM client in order to enable the CNG/KSP integration.
- Open a command prompt window on the Windows instance.
- Enter the following commands:
cd \ProgramData\Amazon\CloudHSM\data
\Program Files\Amazon\CloudHSM\cloudhsm_client.exe cloudhsm_client.cfgThe cloudhsm_client.exe command will continue to run. Important note: Do not close the window! The output at the bottom of the window looks similar to the following:
Figure 4: CloudHSM client output
Launch key_mgmt_util
We are now going to launch the key_mgmt_util client and confirm that no keys are present in the CloudHSM cluster.
- Open a new command window. Do not use the window that you opened in the previous section.
- Enter the following commands.
cd “\Program files\Amazon\CloudHSM”
key_mgmt_util.exe
loginHSM –u CU –s USER –p PASSWORD(replace USER and PASSWORD with the crypto user and password that you created above)
findKey
You should see a message saying that there are no keys present, as shown in the figure below.
![Figure 5: findKey output showing no keys present](https://d2908q01vomqb2.cloudfront.net/22d200f8670dbdb3e253a90eee5098477c95c23d/2018/08/01/CloudHSM-CNG-img-5v2.png)
Figure 5: findKey output showing no keys present
Important note: Do not exit from key_mgmt_util! You’ll return to this window later.
Install IIS
Here’s how:
- Follow the steps of this tutorial to install IIS. When installing IIS, make the following changes:
- Use the Windows Server 2012 instructions as a guideline.
- Do not install MySQL and PHP because you won’t need these services for this walkthrough.
- From your workstation’s web browser, browse the Elastic IP or the DNS “A Record” of the web server using the HTTP protocol. You should see the default Microsoft IIS page as shown below. If you don’t see the page, check the security groups for the server and verify that port 80 (HTTP) and port 443 (HTTPS) are open.
Figure 6: http://www.example.com
- If you browse to the same IP using the HTTPS protocol, you should not get a response because you haven’t configured HTTPS on the EC2 instance.
Provision a server certificate using the CNG/KSP integration
I’m now going to show how to provision a server certificate. I will do this with the certreq program that’s included with Windows Server 2012 R2. Certreq generates a CSR that I’ll submit to a CA. Certreq supports the KSP/CNG standard and can place certificates into the Windows certificate store.
- Create a file named request.inf that contains the lines below. Note that the Subject line may wrap onto the following line. It begins with Subject and ends with Washington and a closing quotation mark (“).
Note the presence of the extensions section that allows you to specify SANs (Subject Alternative Names). SANs are now required by some browsers. Remember to substitute your own domain for example.com in the above example.
- Create a certificate request with certreq.exe.
certreq.exe -new request.inf request.csr.pemCertreq returns a message saying that the certificate request has been created.
- In the same command window where you ran key_mgmt_util, run findKey again to see if there are any new keys. Use the findKey command by itself to display all keys. This shows that two keys have been added with handles 7 and 8. Use the -c 2 parameter to display only public keys (handle 262214) and -c 3 to display private keys (handle 262154). The two keys are part of the public/private key pair that were just created with certreq.
Figure 8: findKey output showing two new keys
- Submit the CSR you just created to the CA using the procedures provided by the CA. The CA will return a certificate that is named request.crt.pem (or similar).
If the certificate authority doesn’t accept the CSR provided by certreq.exe, try the following:
- If the certificate authority asks you to provide the domains for the certificate, make sure you enter all of the SANs included in the request.inf file.
- Check the first and last lines of the CSR and see if the word “NEW” appears. If so, remove the word in both lines.
- Use the certreq command to accept the new certificate and insert it into the certificate store where IIS can access it.
certreq.exe -accept request.crt.pem
![Figure 7: Output from certreq.exe showing that the CSR has been created](https://d2908q01vomqb2.cloudfront.net/22d200f8670dbdb3e253a90eee5098477c95c23d/2018/07/31/CloudHSM-CNG-img-7.png)
Figure 7: Output from certreq.exe showing that the CSR has been created
Configure and test the secure website
- Start the IIS Manager. You can do this through the Server Manager or by running the following command:
Inetmgr
- Under Connections, expand the local server, and then expand the Sites folder below. Select the site named Default Web Site.
Figure 9: IIS Manager settings
- On the right, under Actions, select Edit Site-> Bindings, and then add a binding with the following fields making sure to substitute your domain name in place of example.com:
Type: https
Host name: www.example.com
SSL certificate: www.example.com - Select OK to save the new binding, and then select Close.
Figure 10: Adding site bindings
- Select Manage Website -> Restart. This will restart the website and ensure the new binding is active.
- Browse to https://www.example.com, remembering to substitute your own domain. You’ll see the default website with a secure connection as shown below. If you get a warning message from your workstation’s browser, make sure you added the root-level certificate to the trusted certificate store. (Note: This should not be an issue if you’re using a commercial CA supported by major web browsers)
Figure 11: https://www.example.com
- Examine the certificate information being reported to the browser. For my example, I’m using the Chrome browser so I’ll select the padlock icon, then Certificates, then Detail.
Figure 12: Server certificate details
Figure 12 shows that the Subject field contains the same information that I provided before. You can check out the other fields for information about the Subject Alternative Names and other fields and verify that the correct certificate is being used.
Conclusion
For projects that have special requirements regarding the storage of keys, AWS CloudHSM supports the Microsoft KSP/CNG standard that enables you to store the private key of an SSL/TLS certificate within an HSM. Since the private key no longer has to reside on the server, it’s no longer at risk if the server itself were to be compromised.
If you have feedback about this blog post, submit comments in the “Comments” section below. If you have questions about this blog post, start a new thread on the Amazon CloudHSM forum or contact AWS Support.
Want more AWS Security news? Follow us on Twitter.