pythonaws-lambdaamazon-cloudfrontaws-lambda-edge

Can I return just HTML using a Lambda @ Edge?


I'm trying to use Lambda at Edge, and based on the status of the request, to return some HTML. Basically the following is my Lambda code (in Python):

def handler(event, context):
    clientIp = event['Records'][0]['cf']['request']['clientIp']
    status = event['Records'][0]['cf']['response']['status']
    headers  = event['Records'][0]['cf']['response']['headers']
    response = event['Records'][0]['cf']['response']

    html = f"""
    <!DOCTYPE html>
    <html>
    <head><title>Access Denied</title></head>
    <body>
        <h1>Access Denied</h1>
        <p>Your IP address is: {clientIp}</p>
    </body>
    </html>
    """

    if status == '403':
        new_response = {
        'status': '403',
        'statusDescription': 'Forbidden',
        'headers': headers,
        'body': html,
        'bodyEncoding': 'text',
        }

        return new_response
    else:
        return response

My cloudfront distribution has an AWS WAF associated with it (that should give the error 403) -- however this doesn't seem to trigger my Lambda at all. When I have the WAF associated with my distribution, it just gives me the standard 403, and when I remove the WAF it just directs forward to my domain -- in both cases my lambda doesn't seem to be triggered, despite the fact I've explicitly attached it to the distribution (using CDK) and explicitly mention the version of the Lambda.


Solution

  • The Viewer Response event doesn't get triggered on > 4xx response codes. And WAF will return the default block response to the client if neither WAF nor the protected resource (CloudFront in this case) is configured with a custom response. So I don't this is going to work as you're expecting.

    Your best bet - if you need it to be dynamic - is probably to configure CloudFront with a custom reponse for a 403 status code, create a behaviour (with caching disabled) for that path then connect your function to the Origin Request event for that behaviour. And you'll need to tweak the function to always return the dynamic 403 response because it won't have an origin response to work with.