Using Lambda@Edge to fix permalink in Jekyll
Origin Access Identity (OAI) is a secure way to access S3 buckets from CloudFront, think of it as letting CloudFront use the S3 APIs to request objects instead of H. The alternative is to make the bucket publicly available via bucket policy or ACLs, but that's not ideal.
On S3 you can configure a default index document, which is requested if the specified path doesn't resolve to anything. This is handy, since static site generators like Jekyll relies on sub-directories for generating "clean URLs". But with Open Access Identity CloudFront will request the literal object using the S3 APIs, and in this case S3 doesn't know what to respond.
sequenceDiagram
participant Client
participant CloudFront
participant Lambda
participant S3 as S3 Bucket
Client->>CloudFront: Client Request GET /foobar/zoo/
CloudFront->>Lambda: Invoke
Lambda-->>CloudFront: Return
CloudFront->>S3: S3 Object Request /foobar/zoo/index.html
S3-->>CloudFront: S3 Object Response
CloudFront-->>Client: Client Response GET /foobar/zoo/
In this flowchart the users request is intercepted at the origin-request, which means before CloudFront requests the object from the origin, in our case, a S3 bucket. This lets us manipulate the request header to include index.html so that CloudFront will request the correct object.
import re
def lambda_handler(event, context):
request = event['Records'][0]['cf']['request']
request['uri'] = re.sub(r'/$', '/index.html', request['uri'])
return request