Certificates are vital to maintaining trust and providing encryption to internal or external facing infrastructure and applications. AWS Certificate Manager (ACM) provides certificate services to any workload that requires them. Although ACM provides managed renewals that automatically renew certificates in most cases, there are exceptions, such as imported certs, where an automatic renewal isn’t possible. This post provides you with two options for monitoring certificate expirations by using events and metrics that are published into Amazon CloudWatch by ACM. This data is used to produce notifications through Amazon Simple Notification Service (Amazon SNS) as well as to log and report the findings into AWS Security Hub.

A certificate that isn’t renewed and then expires can lead to an unavailable website or application. This can result in an operational and business outage. Amazon Web Services (AWS) provides many options you can use to get alerts about expiring certificates, but some organizations get their certificates from other parties that don’t have access to the AWS account where these notifications are configured. And although Security Hub can be used to monitor certificate expirations without the solution described in this post, Security Hub is a Regional service, and monitoring of certificate expirations across Regions can be time-consuming. This solution consolidates all certificate notifications from all Regions in which the solution is deployed into the findings of a single Region.

The first of the two options I describe is to use the ACM built-in Certificate Expiration event, which is raised through Amazon EventBridge, to invoke a Lambda function. In this option, the function is configured to publish the result as a finding in Security Hub, and also as an SNS topic used for email subscriptions. As a result, an administrator can be notified of a specific expiring certificate, or an IT service management (ITSM) system can automatically open a case or incident through email or SNS.

The second option uses the recently launched DaysToExpiry metric to schedule a batch search of expiring certificates and to log all the findings. The metric also provides a single SNS notification for all expiring certificates.

Prerequisites

For this walkthrough, you should have the following:

Solution overview

This solution provides a Lambda function that makes use of CloudWatch rules to report back those certificates that are due to expire within a pre-defined amount of time. The Lambda function is written to respond to CloudWatch events in two ways. When the event is time-based, the function looks for all certificates that have a DaysToExpiry metric. When the event is based on an event that is raised from a specific certificate, the function examines the single certificate. In both cases, the function logs the findings to Security Hub and sends out an SNS notification.

Although the notification could simply be sent as an email, security event notifications are best integrated into ticketing or alerting systems. For that reason, this solution includes integration with Security Hub to make it easier to mobilize a response to the findings.

Figure 1 shows the workflow for Option 1, in which you use a CloudWatch event to identify an expiring certificate.

Figure 1: Workflow for Option 1

Figure 1: Workflow for Option 1

In Option 1, a raised CloudWatch event from ACM indicates that a certificate is approaching expiration, which initiates the solution. The option workflow is as follows:

  1. CloudWatch receives the event and invokes a Lambda function.
  2. The function examines the certificate indicated in the event.
  3. The function logs the finding in Security Hub.
  4. The function publishes a notification to an SNS topic with the expiration details.
  5. SNS creates a notification (most commonly, through email) to any subscribers of the topic.

Figure 2 shows the workflow for Option 2, in which you use a scheduled CloudWatch rule to identify all expiring certificates.

Figure 2: Workflow for Option 2

Figure 2: Workflow for Option 2

Option 2 provides a scheduled solution to examine all expiring certificates in ACM, log all the findings in Security Hub, and generate a single notification through SNS for all certificates that are found. The option workflow is as follows:

  1. CloudWatch runs the rule on a timer and invokes a Lambda function.
  2. The function finds all certificates that have a DaysToExpiry metric in CloudWatch.
  3. The function logs all the expiring certificates as findings in Security Hub.
  4. The function publishes a notification to an SNS topic with the expiration details.
  5. SNS creates a notification (most commonly, through email) to any subscribers of the topic.

Getting started

Both options begin with deploying the same Lambda function, along with the necessary AWS Identity and Access Management (IAM) roles and policies.

To configure IAM roles and policies and deploy the Lambda function

  1. Go to the Creating IAM policies (console) topic in the IAM User Guide, and review the section titled “Creating policies on the JSON tab.” Then, using those instructions, use the following template to create an IAM policy for the Lambda role to use. Replace “us-east-1” with the appropriate Region and <AWS-ACCT-NUMBER> with your AWS account ID.
    { "Version": "2012-10-17", "Statement": [ { "Sid":"LambdaCertificateExpiryPolicy1", "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:us-east-1:<AWS-ACCT-NUMBER>:*" }, { "Sid":"LambdaCertificateExpiryPolicy2", "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": [ "arn:aws:logs:us-east-1:<AWS-ACCT-NUMBER>:log-group:/aws/lambda/handle-expiring-certificates:*" ] }, { "Sid":"LambdaCertificateExpiryPolicy3", "Effect": "Allow", "Action": [ "acm:DescribeCertificate", "acm:GetCertificate", "acm:ListCertificates", "acm:ListTagsForCertificate" ], "Resource": "*" }, { "Sid":"LambdaCertificateExpiryPolicy4", "Effect": "Allow", "Action": "SNS:Publish", "Resource": "*" }, { "Sid":"LambdaCertificateExpiryPolicy5", "Effect": "Allow", "Action": [ "SecurityHub:BatchImportFindings", "SecurityHub:BatchUpdateFindings", "SecurityHub:DescribeHub" ], "Resource": "*" }, { "Sid": "LambdaCertificateExpiryPolicy6", "Effect": "Allow", "Action": "cloudwatch:ListMetrics", "Resource": "*" } ]
    }
    

  2. After the policy is created, create a role for the Lambda function to use the policy, as described in Creating a role to delegate permissions to an AWS service. Choose Lambda as the service to assume the role and attach the policy that you created in step 1. (The policy is named lambda-certificate-expiry-function-policy in this example.) Specify a role name, and then create the role. (The role is named lambda-certificate-expiry-function-role in this example.)
  3. Review the topic Create a Lambda function with the console in the AWS Lambda Developer Guide. Then create the Lambda function, choosing the following options.
    1. Under Create function, choose the Author from scratch option to create the function.
    2. For the function name, enter handle-expiring-certificates, and for Runtime, choose python3.8.
    3. For Execution role, choose Use an existing role, and then select the role that you created in step 2.
    4. Choose Create function to bring up the Designer, and enter the function code, which you can download from https://awsiammedia.s3.amazonaws.com/public/sample/757-monitor-expirations-imported-certificates-ACM/acm-cert-expiry-sample-code.py
  4. After the Lambda function is created, you will need to adjust the timeout duration and can also create three environment variables, as follows.
    1. Set the Lambda timeout to 30 seconds. (For more information, see the timeout entry in Configuring functions in the console.)
    2. (Optional) Create an environment variable called EXPIRY_DAYS. (See Using AWS Lambda environment variables.)
    3. (Optional) Create a second environment variable called SNS_TOPIC_ARN.
    4. (Optional) Create a third environment variable called SECURITY_HUB_REGION.

    The default Lambda timeout is 3 seconds, but this function has run for as long as 20-25 seconds in development and testing, so 30 seconds appears to be a safe limit. This time might need to be adjusted if you have a lot of certificates in your environment.

    The EXPIRY_DAYS variable is used to specify how much lead time, in days, you want to have before the certificate expiration notification is sent. The function is written to run without this value, and defaults to 45 days, but editing this value will increase or decrease the search window for expiring certificates.

    The SNS_TOPIC_ARN variable is provided as an optional variable if you want to have a direct SNS notification. Be sure to put in the full Amazon Resource Name (ARN), in the format of arn:aws:sns:<region>:<account-number>:<topic-name>, and not just the SNS topic name. See Amazon Resource Names (ARNs) for more details on ARN formats. In the case of many government agencies, multiple groups are often engaged in certificate management, and SNS is a good way to notify the other groups that need to know about the upcoming expirations.

    The SECURITY_HUB_REGION variable is an optional variable to specify the Security Hub in a different Region. If this variable isn’t specified, the Region of the running Lambda function is used, but if this function is to be run in multiple Regions, it might be desirable to have all certificate messages go to Security Hub in a single Region.

  5. Deploy the Lambda function.

Deploy Option 1: Use a CloudWatch event to identify an expiring certificate

The first option is initiated by a CloudWatch rule that is invoked by the DaysToExpiry metric being raised for a specific certificate. The rule invokes a Lambda function within the Region that gathers up the certificate information. The information is used to publish a finding in Security Hub for the single certificate and create an SNS notification with the certificate details.

To set up an SNS topic and CloudWatch Events rule

  1. Create a standard SNS topic for the Lambda function to use to send out notifications, as described in Creating an Amazon SNS topic. Figure 3 shows an example where I create a Standard SNS topic titled expiring-certificate-topic.

    Figure 3: Create an SNS topic

    Figure 3: Create an SNS topic

  2. After you create the SNS topic, add subscribers to it. The steps to do so can be found at Subscribing to an Amazon SNS topic.
  3. The final step is to create a CloudWatch Events rule to invoke the Lambda function, using the instructions in Creating a CloudWatch Events Rule That Triggers on an Event. Figure 4 shows the Event Pattern to use, which is set up as follows.
    1. For Service Name, choose Certificate Manager.
    2. For Event Type, choose ACM Certificate Approaching Expiration.
    3. Under Targets, choose the Lambda function to invoke.

      Figure 4: Create an event-based CloudWatch rule

      Figure 4: Create an event-based CloudWatch rule

ACM will raise an event daily for each certificate that is 45 days or less from expiration, and this option provides a way to capture and act on each event for resolution. You only need to configure this option once, and this solution will notify all subscribers via the SNS topic when it is run.

Deploy Option 2: Use a scheduled CloudWatch rule to identify all expiring certificates

The second option uses a scheduled CloudWatch rule to invoke the deployed function. In this option, the Lambda function iterates through all of the ACM certificates within the Region, examining each certificate’s DaysToExpiry metric. Only certificates within 45 days of expiration have this metric generated daily. The Lambda function publishes each certificate expiration metric that it finds as a separate finding in Security Hub, and creates a single SNS notification that lists all the certificates found.

Use the instructions in Creating a CloudWatch Events Rule That Triggers on a Schedule to create the CloudWatch rule. Figure 5 shows the first step in creating the rule.

Figure 5: Create a scheduled CloudWatch rule

Figure 5: Create a scheduled CloudWatch rule

The Cron expression of 5 0 ? * 1 * sets the event to invoke weekly on Sunday at 12:05 AM GMT, but you can create whatever schedule you want to use.

When you have everything properly configured and Security Hub set up, you should see a Findings page similar to the one in Figure 6. Note that the Remediation text for each finding is a URL that will open the specific, expiring certificate in the ACM console.

Figure 6: An example of Security Hub findings

Figure 6: An example of Security Hub findings

Select the right option

Because customers have different processes for managing certificates, the two options that I presented can be used in a number of ways. Option 1 provides a single email for each expiring certificate at the moment that the event is raised through CloudWatch. Use this option if you want to manage each certificate individually, and are also considering using this solution as part of a larger automation for managing certificates. That automation could include integration with an ITSM or case management system. Option 2 produces a single email that lists all expiring certificates on a scheduled basis. This option can be used for a weekly or monthly listing of all certificates that might require action taken on them.

Cleanup

If you no longer require this process in your environment, delete the following resources to avoid incurring future charges:

  • The Lambda function
  • The CloudWatch Events rule
  • The CloudWatch Logs that are associated with the Lambda function
  • The SNS topic

From a security perspective, you should also delete the IAM role and policy that you created in the first two steps.

Conclusion

Amazon Certificate Manager (ACM) can perform automatic renewals of certificates that are generated within ACM, but when certificates are imported into ACM, a mechanism to track their expiration is necessary. This blog provides the steps to create notifications for administrators to act on expiring imported certificates. In addition, the solution presented here also publishes all the findings to Security Hub in a single Region for further action, and provides security teams with greater visibility into certificate status.

If you have feedback about this post, submit comments in the Comments section below. If you have questions about this post, start a new thread on the AWS Certificate Manager forum or contact AWS Support.

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.

Author

Dmitry Kagansky

Dmitry has spent over four years as a Senior Solutions Architect working with state and local governments to help them along their cloud journeys. Before joining AWS, he held a number of technical and management roles, including Federal CTO for Quest Software and EVP of Development for Star2Star Communications. Outside of work, Dmitry enjoys traveling and seeing live music worldwide.