Importing the updated Certificate Revocation List (CRL) for AWS Client Virtual Private Network (AWS Client VPN) Endpoint becomes a challenge, especially when the AWS Private Certificate Authority (AWS PCA) is used to generate and manage the client certificates. Normally, an Admin has to manually import the CRL file to Client VPN Endpoint before it expires or whenever a new certificate revocation call is made to revoke the access for a particular user. Keeping the track of all the changes and versioning of CRL could be very time consuming and critical task, as any misconfiguration can lead to the authentication failure.
For example, consider a scenario where an admin is configuring the CRL, and sets the number of days PCA CRL will remain valid to 7 days (default value). Now, the Admin has to download the CRL from the configured Amazon Simple Storage Service (Amazon S3) bucket, convert it to .PEM format and then has to import the CRL it to the Client VPN Endpoint. This process needs to be repeated every 7 days, before the CRL gets expired. In case, CRL has expired and Admin has not imported the updated CRL, Client VPN Endpoint will move to “Open-Fail” state and all the mutual authentication requests for Client VPN Endpoint will be unsuccessful.
To improve the administration experience for AWS Client VPN Endpoint, we can use AWS CloudWatch Events and AWS Lambda to automate this whole process of importing the latest version of AWS PCA CRL into the AWS Client VPN Endpoint.
In this blog, I show how to use AWS PCA’s CloudWatch Metrics to set up an event rule, which triggers a Lambda function as an action. Whenever a change is carried out in AWS PCA’s CRL, this Lambda function downloads the latest version of CRL from Amazon S3 and then uploads this CRL to the AWS Client VPN Endpoint.
The major components of this solution are CloudWatch Event Rule and a Python Lambda Function. Once you configure the CRL for your AWS PCA, AWS Certificate Manager (ACM) creates a CRL file in “<defined_bucket>/crl/” folder in S3 bucket. This CRL is updated in S3 when:
- Admin revokes a client certificate.
- CRL updates by ACM PCA, before it expires.
The following flow diagram shows how Automated CRL update process looks like for AWS Client VPN.
After the solution is deployed, the following is the breakdown of whole process, when an Administrator revokes the access for a user.
- Admin revokes a certificate with the below AWS CLI command.
aws acm-pca revoke-certificate –certificate-authority-arn arn:aws:acm-pca:region:account:certificate-authority/cxxxx47-xxxf-4xx6-xxxx-5xxx9xxxfxxx –certificate-serial <Certificate_serial_no.> –revocation-reason “KEY_COMPROMISE”
- Due to “RevokeCertificate” API call, AWS ACM updates the CRL in S3, using “CrlConfiguration” API call. You can see the new CRL in S3 at “bucket_name/crl/cxxxx47-xxxf-4xx6-xxxx-5xxx9xxxfxxx.crl”.
- When the “CrlConfiguration” API call returns “success” as a result, a data point is added to the “Private CA Metric” for that particular CA, under ACMPrivateCA > Private CA > CRLGenerated Metrics. If the call fails, then a data point is added to the “MisconfiguredCRLBucket” metric under same namespace.
- We configured the Event Rule having “Lambda” as target.
- Configured Event Rule triggers the alarm that invokes the Lambda function, when the “CRLGenerated” Metric has a new data point.
- Python Lambda function downloads the CRL from S3, converts the file from <file>.crl to <file>.pem
- After converting the file, Lambda uploads/imports this new <file>.pem to AWS Client VPN Endpoint.
Once this process is completed, revoked user will not be able to get authenticated, as user’s certificate has been revoked.
Before implementing this solution, please consider the following and make sure that:
- CRL is configured in AWS PCA settings.
- ACM has enough permissions to put CRL on S3.
- AWS Lambda has enough permission to download the <file>.crl from S3 bucket.
- AWS Lambda has enough permission to upload/import the <file>.pem CRL to AWS Client VPN.
Creating the Lambda Function
First you need to Create Python Lambda function with appropriate permissions, so that it can be used as target for CloudWatch Event Rule.
To create a Lambda function:
- Open the AWS Lambda console.
- Choose Create a function.
- For Function name, enter any name for your function.
- For Runtime, Choose Python 3.8.
- Choose Create function.The following screenshot shows the create Lambda Function console.
- After creating the lambda function, Configuration page will be opened. In Function code section, enter the following Python code.
import json import json import os import subprocess import sys from os import listdir from os.path import join, isfile from pip._internal import main main(['install', 'pyOpenSSL', '--target', '/tmp/' ]) main(['install', 'boto3', '--target', '/tmp/' ]) sys.path.insert(0, '/tmp/') from OpenSSL import crypto import boto3 s3 = boto3.resource('s3') client = boto3.client('ec2',region_name="Region_Name") def lambda_handler(event, context): os.chdir('/tmp') filename='AWS_PCA_CRL.crl' #crl uploaded by AWS PCA bucket = s3.Bucket('Bucket_Name') object = bucket.Object('crl/AWS_PCA_CRL.crl') #CRL filename along with path to file object.download_file(‘AWS_PCA_CRL.crl') #downloading CRL directory_path = '/tmp/' with open('/tmp/'+filename, "rb") as in_file: crl_obj = crypto.load_crl(crypto.FILETYPE_ASN1, in_file.read()) #loading .crl pem_crl_data = crypto.dump_crl(crypto.FILETYPE_PEM, crl_obj) #converting to .pem f = open("/tmp/converted_crl.pem", "wb") #creating .pem file f.write(pem_crl_data) f.close() with open(‘converted_crl.pem', 'r') as file: crl_in_pem_format = file.read() #writing content of .pem file to a string client.import_client_vpn_client_certificate_revocation_list(ClientVpnEndpointId='cvpn-endpoint-id',CertificateRevocationList=crl_in_pem_format) #API call to upload CRL to Client VPN Endpoint
- Scroll down, in Basic settings section, choose Edit.
- For Timeout, set the value to 30 Seconds.
- Choose Save.
The following screenshot shows the Edit basic setting section for Lambda Function.
Creating the CloudWatch Event Rule:
Now Create a CloudWatch Event Rule with shown Custom Event Pattern with your Lambda function as target.
To create a rule that triggers on an event:
- Open the CloudWatch console
- In the navigation pane, choose Events, Create rule.
- For Event source, do the following:
a. Choose Event Pattern, Build event pattern to match events by service.
b. For Service Name, choose Certificate Manager Private CA.
c. For Event Type, choose ACM Private CA CRL Generation.
d. For Event Pattern Preview, and choose edit to enter custom event pattern as shown in the below image.
e. Choose Save.
- For Targets, choose Add target, Lambda function.
- For Function, select the Lambda function that you created.
- Choose Configure details. For Rule definition, type a name and description for the rule. The rule name must be unique within this Region.
- Choose Create rule.
The following screenshot shows how event rule looks like with custom event pattern.
Remove any components added in the walk through. Leaving AWS services enabled can incur costs.
In this blog post I showed you how to use a CloudWatch Rule event and Lambda to automate an important process of updating the CRL, when using AWS PCA.
We hope that you’ve found this post informational and helpful. If you enjoyed this blog post, share it with a friend and we look forward to hearing how you used it!