Use CloudFront Proxy to access Lambda APIs

Hi,
I’m using serverless to create APIs that are exposed via Api Gateway. I want a 3rd party vendor to call it via Api Gateway, but he currently has a bug with ssl_handshake with AWS, probably because of SNI. So I want to expose my Lambda functions in HTTP without SSL.
So I’ve understood I can use CloudFront for that.
I wanted to know if anyone did that, and how.
I saw this guide for proxy with ColudFront but I’m fully sure that this is what I’m looking for, and how to customize it for my needs.
E.g. I have https://SOMETHING.execute-api.REGION.amazonaws.com/dev/person/info API that I want to expose with HTTP.

Any help would be appreciated.

Thanks,
Yishai

In case it would help anyone, I’ve managed to configure what I needed, with much help of this json from the awsm-cloudfront project:

At serverless.yml I’ve added
resources:
Resources: ${file(cloudformation-resources.json)}

and the json files consists the following:

{
    "CloudFrontDistribution": {
        "Type" : "AWS::CloudFront::Distribution",
        "Properties" : {
            "DistributionConfig" : {
            "DefaultRootObject" : "index.html",
            "Enabled" : true,
            "DefaultCacheBehavior" : {
                "AllowedMethods" : ["GET", "HEAD"],
                "CachedMethods" : ["HEAD", "GET"],
                "ForwardedValues" : {
                    "QueryString" : true
                },
                "MinTTL" : "0",
                "TargetOriginId" : "MY_SERVICE_serverlessdeploymentbucket-ID",
                "ViewerProtocolPolicy" : "allow-all"
            },
            "CacheBehaviors" : [
                {
                    "AllowedMethods" : ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"],
                    "CachedMethods" : ["HEAD", "GET"],
                    "ForwardedValues" : {
                    "QueryString" : true
                    },
                    "MinTTL" : "0",
                    "PathPattern" : "*",
                    "TargetOriginId" : "MY_FUNCTION-api-gateway",
                    "ViewerProtocolPolicy" : "allow-all"
                }
            ],
            "Origins" : [
                {
                "CustomOriginConfig" : {
                    "HTTPSPort" : "443",
                    "OriginProtocolPolicy" : "https-only"
                },
                "DomainName" : "SOMETHING.execute-api.REGION.amazonaws.com",
                "Id" : "MY_FUNCTION-api-gateway",
                "OriginPath" : ""
                },
                {
                "DomainName" : "MY_SERVICE_serverlessdeploymentbucket-ID.s3.amazonaws.com",
                "Id" : "MY_SERVICE_serverlessdeploymentbucket-ID",
                "OriginPath" : "",
                "S3OriginConfig" : {}
                }
            ],
            "PriceClass" : "PriceClass_100"
            }
        }
    }
}

The only bummer right now is that I have to specify the s3 bucket name and the api gateway endpoint, so it can be created only after these resources were deployed. If anyone has an idea of how to connect these to the resources I’m going to deploy in the new environment and do not exist yet, I’ll be happy to hear.

1 Like

Nice work with the CF setup.

You can get the logical id’s of your bucket and endpoints from this page in the docs. With that you should be able to use Refs to avoid hardcoding values.

Hope that helps.

Thanks! It helped. In case it would help anyone, here’s the updated json. I still have to check some things but for now it works.

{
    "CloudFrontDistribution": {
        "Type" : "AWS::CloudFront::Distribution",
        "Properties" : {
            "DistributionConfig" : {
            "DefaultRootObject" : "",
            "Enabled" : true,
            "DefaultCacheBehavior" : {
                "AllowedMethods" : ["GET", "HEAD"],
                "CachedMethods" : ["HEAD", "GET"],
                "ForwardedValues" : {
                    "QueryString" : true
                },
                "MinTTL" : "0",
                "TargetOriginId" : "MY_SERVICE-${opt:stage}-serverlessdeploymentbucket-s3.amazonaws.com",
                "ViewerProtocolPolicy" : "allow-all"
            },
            "CacheBehaviors" : [
                {
                    "AllowedMethods" : ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"],
                    "CachedMethods" : ["HEAD", "GET"],
                    "ForwardedValues" : {
                    "QueryString" : true
                    },
                    "MinTTL" : "0",
                    "PathPattern" : "*",
                    "TargetOriginId" : "MY_FUNCTION-${opt:stage}-api-gateway",
                    "ViewerProtocolPolicy" : "allow-all"
                }
            ],
            "Origins" : [
                {
                "CustomOriginConfig" : {
                    "HTTPSPort" : "443",
                    "OriginProtocolPolicy" : "https-only"
                },
                "DomainName" : {
                    "Fn::Join": [
                        "",
                        [
                            {
                                "Ref": "ApiGatewayRestApi"
                            },
                            ".execute-api.us-west-2.amazonaws.com"
                        ]
                    ]
                },
                "Id" : "MY_FUNCTION-${opt:stage}-api-gateway",
                "OriginPath" : ""
                },
                {
                "DomainName" : {
                    "Fn::Join": ["", [{"Ref": "ServerlessDeploymentBucket"}, ".s3.amazonaws.com"]]
                },
                "Id" : "MY_SERVICE-${opt:stage}-serverlessdeploymentbucket-s3.amazonaws.com",
                "OriginPath" : "",
                "S3OriginConfig" : {}
                }
            ],
            "PriceClass" : "PriceClass_100"
            }
        }
    }
}

If anyone is also trying to achieve this, we created and open-sourced plugin that automatically sets-up CloudFront distribution in front of API gateway - https://github.com/Droplr/serverless-api-cloudfront :slight_smile:
Greetings!

1 Like