Skip to content

How do I resolve SSL certificate verification failures when my Lambda function makes HTTPS requests to external endpoints or AWS services?

6 minute read
0

I receive SSL certificate verification errors when my AWS Lambda function makes HTTPS requests to external endpoints or AWS Services.

Short description

When your Lambda function HTTPS requests to external endpoints or AWS services fail, you receive one of the following error messages:

"SSLError(SSLCertVerificationError: certificate verify failed: unable to get local issuer certificate)"

"SSL: CERTIFICATE_VERIFY_FAILED"

This issue occurs because of incorrect certificates or incorrect network configurations.

Resolution

A Lambda function that you configured with a Python requests library

When the certificate configuration isn't valid for Lambda functions that use a Python requests library to connect to external HTTPS endpoints, verification fails.

Check the certificate chain

To check the certificate chain, run the following s_client OpenSSL command:

openssl s_client -connect your-domain:443

Note: Replace your-domain with your domain name.

The output shows whether the dates and signing authorities are valid for the root certificate, intermediate certificate, and end-entity certificate.

If the dates or signing authorities aren't valid, then use a default certificate verification or a custom CA bundle.

Use default certificate verification

If the server uses certificates from a CA, then run the following Python command to use the default certificate verification:

import requests
response = requests.get(https://your-api-endpoint.com/path)

Note: Replace your-api-endpoint.com/path with the path of your API endpoint.

Use a custom CA bundle

To use a custom CA bundle, complete the following steps:

  1. Bundle your CA certificate in PEM format with your Lambda deployment package.

  2. Confirm that your PEM file includes the full certificate chain with root and intermediates.

  3. Run the following Python command to specify the path to your custom CA bundle:

    import requests
    response = requests.get(
        'https://your-api-endpoint.com/path',
        verify='your-path-custom-ca-bundle.pem'
    )

    Note: Replace your-api-endpoint.com/path with your API endpoint path and your-path-custom-ca-bundle.pem with your CA path.

  4. Store the certificate file in your Lambda deployment package in a valid directory path, for example /var/task/certificates/ca-bundle.pem.

A Lambda function that you configured in a VPC

The verification for a Lambda function that you configured in an Amazon  Virtual Private Cloud (Amazon VPC) can fail because of network connectivity issues. To resolve this issue, create VPC endpoints or configure internet access from a NAT gateway or NAT instance.

Create VPC endpoints

Create VPC endpoints for the AWS services that your Lambda function must access. VPC endpoints allow traffic to pass through the AWS private network instead of the public internet.

Note: Make sure that the VPC endpoint is in the same VPC and AWS Region as your Lambda function.

Configure internet access from a NAT gateway

If VPC endpoints aren't available for the AWS service in your Region, then configure your Lambda function VPC to use a NAT gateway or instance.

Note: If you use a VPC endpoint, then make sure that the AWS service supports the VPC endpoint. If you use a transit gateway instead of a NAT gateway, then check your configuration requirements. Make sure that the routing configuration allows access to the required AWS service endpoints.

A Lambda function that you configured through a proxy server

A Lambda function that you configured through a proxy server can fail because the Lambda function's Boto3 client doesn't trust the proxy server's certificate.

To resolve this issue, include a CA certificate bundle or configure proxy forwarding.

Include CA certificate bundle

If the Boto3 client doesn't trust the proxy server certificate, then include the following CA certificate bundle in your Lambda function:

import boto3
from botocore.config import Config

proxy_definitions = {
    'http': 'http://proxy.example.com:1234',
    'https': 'https://proxy.example.com:1234'
}

my_config = Config(
    region_name='your-region',
    signature_version='v4',
    proxies=proxy_definitions,
    proxies_config={
        'proxy_ca_bundle': '/var/task/certificates/proxy-ca.pem'
    }
)

client = boto3.client('your-service', config=my_config)

Note: Replace proxy.example.com:1234 with your proxy URL and port number, your-region with your Region, and your-service with your AWS service.

In the preceding code, the proxy_ca_bundle path points to the CA certificate of your proxy server, bundled in PEM format inside your Lambda deployment package. The Boto3 client then trusts the proxy certificate and allows the HTTPS connection.

Configure proxy forwarding

To configure proxy forwarding, add the following configuration to your Lambda function:

import boto3
from botocore.config import Config

proxy_definitions = {
    'http': 'http://proxy.example.com:1234',
    'https': 'https://proxy.example.com:1234'
}

my_config = Config(
    region_name='your-region',
    signature_version='v4',
    proxies=proxy_definitions,
    proxies_config={
        'proxy_use_forwarding_for_https': True
    }
)

client = boto3.client('your-service', config=my_config)

Note: Replace proxy.example.com:1234 with your proxy URL and port number, your-region with your Region, and your-service with your AWS service.

A Lambda function that you configured to Amazon EKS clusters

A Lambda function that you configured to Amazon Elastic Kubernetes Service (Amazon EKS) clusters can fail because Lambda can't reference the cluster certificate for SSL verification.

To resolve this issue, add the following code to your Lambda function to get the cluster's certificate:

import boto3, base64, requests

eks_client = boto3.client('eks', region_name='your-region')
response = eks_client.describe_cluster(name='your-cluster-name')

# Decode base64-encoded PEM and write to Lambda's writable temp space
cert_path = '/tmp/eks-ca.pem'
with open(cert_path, 'wb') as f:
    f.write(base64.b64decode(
        response['cluster']['certificateAuthority']['data']
    ))

# Use cert for SSL verification — get cluster endpoint from same response
endpoint = response['cluster']['endpoint']
api_response = requests.get(
    f"{endpoint}/api/v1/namespaces",
    headers={"Authorization": f"Bearer {your_token}"},
    verify=cert_path
)

Note: Replace your-region with your Region, your-cluster-name with your cluster name, and your-token with your authentication token. The preceding command uses the describe_cluster Boto3 API to get the cluster's certificate.

A Lambda function that you connected to public API Gateway endpoints

A Lambda function that's in a VPC that connects to a public Amazon API Gateway endpoint can fail because you activated private DNS on the VPC endpoint. The DNS resolution can interfere with SSL certificate validation for public API Gateway endpoints.

To resolve this issue, turn off private DNS for your VPC endpoint. If you must keep DNS activated, then you can set up a custom domain name to connect to your public APIs.

Turn off private DNS for your VPC endpoint

Complete the following steps:

  1. Open the Amazon VPC console.
  2. In the navigation pane, under PrivateLink and Lattice, choose Endpoints, and then select your interface VPC endpoint.
  3. Choose Actions.
  4. Choose Modify Private DNS names.
  5. Under Modify private DNS name settings, clear Enable for this endpoint, and then choose Save changes.

Set up a custom domain name for your public APIs

Set up an edge-optimized custom domain names. Or, set up a Regional custom domain names to connect to your public APIs. Then, invoke the API Gateway public API with the custom domain name, such as api.example.com. Your private REST APIs remain accessible through the private REST API endpoint.

For more information, see Why do I get an HTTP "403 Forbidden" error when I try to connect to my API Gateway public APIs from a VPC?

AWS OFFICIALUpdated a month ago