[{"data":1,"prerenderedAt":165},["ShallowReactive",2],{"pattern-lambda-web-cloudfront-oac-nodejs-sam":3,"pattern-group-lambda-web-cloudfront-oac-nodejs-sam":73},{"id":4,"title":5,"architectureURL":6,"cleanup":7,"contributors":11,"deploy":13,"description":17,"extension":18,"framework":19,"gitHub":20,"highlight":24,"introBox":25,"language":32,"level":33,"meta":34,"patternArch":35,"patternGroup":56,"patternGroupLabel":6,"resources":57,"stem":68,"testing":69,"videoId":6,"__hash__":72},"patterns\u002Fpatterns\u002Flambda-web-cloudfront-oac-nodejs-sam.json","AWS Lambda Web Function behind Amazon CloudFront with Origin Access Control",null,{"text":8},[9,10],"Delete the stack with \u003Ccode>sam delete --stack-name lambda-web-cloudfront-oac-sam\u003C\u002Fcode>. CloudFormation disables and removes the distribution, the cache policy, the OAC and the function with its endpoint and resource policy.","See the GitHub repo for removing the log groups and the code bucket.",[12],"content\u002Fcontributors\u002Fjon-loinaz-anton.json",{"text":14},[15,16],"Create a versioning-enabled S3 bucket whose policy lets lambda.amazonaws.com read objects, zip \u003Ccode>src\u002F\u003C\u002Fcode> and upload it, then run \u003Ccode>sam deploy --stack-name lambda-web-cloudfront-oac-sam --capabilities CAPABILITY_IAM --s3-bucket &lt;bucket&gt; --parameter-overrides CodeBucket=&lt;bucket&gt; CodeKey=&lt;key&gt;\u003C\u002Fcode>.","One template creates the Web Function with an \u003Ccode>IamAuth\u003C\u002Fcode> endpoint, the OAC, a cache policy that forwards the viewer's Authorization header, the CloudFront distribution and the resource policy; see the GitHub repo for the bucket setup.","Serve a Lambda Web Function only through a CloudFront distribution: an IamAuth endpoint, an OAC that signs origin requests, and a resource policy that trusts one distribution.","json","AWS SAM",{"template":21},{"patternPath":22,"templateFile":23},"lambda-web-cloudfront-oac\u002Fnodejs\u002Fsam","template.yaml","true",{"headline":26,"text":27},"How it works",[28,29,30,31],"This pattern deploys a plain Node.js HTTP server as an AWS Lambda Web Function and puts an Amazon CloudFront distribution in front of it. The function's endpoint uses the \u003Ccode>IamAuth\u003C\u002Fcode> authentication type, so Lambda accepts only requests signed with AWS Signature Version 4 and returns 403 to everything else before your code runs.","CloudFront signs each origin request through an Origin Access Control of type \u003Ccode>lambda\u003C\u002Fcode> with \u003Ccode>SigningBehavior: always-amz-auth\u003C\u002Fcode>. A resource policy on the function allows \u003Ccode>lambda:InvokeWebFunctionEndpoint\u003C\u002Fcode> for the CloudFront service principal only when \u003Ccode>AWS:SourceArn\u003C\u002Fcode> matches your distribution, so a different distribution using the same origin is also denied.","After validating the signature, Lambda removes the Authorization header it used and forwards the viewer's own headers, so the application has no authentication code of its own and existing sign-in flows keep working. The app returns \u003Ccode>Cache-Control\u003C\u002Fcode> headers that CloudFront honours, which the pattern uses to show edge caching.","With CloudFront in front you can add a custom domain, AWS WAF, compression and caching to a Web Function without changing the application.","Node.js","200",{},{"icon1":36,"icon2":41,"icon3":45,"line1":49,"line2":53},{"x":37,"y":38,"service":39,"label":40},15,50,"icon-internet","Client",{"x":42,"y":38,"service":43,"label":44},45,"cloudfront","Amazon CloudFront",{"x":46,"y":38,"service":47,"label":48},83,"lambda-web-functions","AWS Lambda Web Function",{"from":50,"to":51,"label":52},"icon1","icon2","HTTPS",{"from":51,"to":54,"label":55},"icon3","SigV4 (OAC)","lambda-web-cloudfront-oac",{"bullets":58},[59,62,65],{"text":60,"link":61},"AWS Lambda Web Functions networking","https:\u002F\u002Fdocs.aws.amazon.com\u002Flambda\u002Flatest\u002Fdg\u002Fweb-functions-networking.html",{"text":63,"link":64},"Lambda Web Function endpoint access control","https:\u002F\u002Fdocs.aws.amazon.com\u002Flambda\u002Flatest\u002Fdg\u002Fweb-functions-endpoint-access-control.html",{"text":66,"link":67},"Restricting access to an origin with CloudFront Origin Access Control","https:\u002F\u002Fdocs.aws.amazon.com\u002FAmazonCloudFront\u002Flatest\u002FDeveloperGuide\u002Fprivate-content-restricting-access-to-origin.html","patterns\u002Flambda-web-cloudfront-oac-nodejs-sam",{"text":70},[71],"See the GitHub repo for detailed testing instructions.","VEVQpyyfsjkNFikipBP3CdSXS4fidn0LCEWrTXfWJY0",[74,108,141],{"id":75,"title":5,"architectureURL":6,"cleanup":76,"contributors":80,"deploy":81,"description":17,"extension":18,"framework":85,"gitHub":86,"highlight":24,"introBox":90,"language":32,"level":33,"meta":92,"patternArch":93,"patternGroup":56,"patternGroupLabel":6,"resources":99,"stem":104,"testing":105,"videoId":6,"__hash__":107},"patterns\u002Fpatterns\u002Flambda-web-cloudfront-oac-nodejs-awscli.json",{"text":77},[78,79],"Disable and delete the CloudFront distribution, then delete the cache policy and the OAC, then \u003Ccode>aws lambda-web delete-web-function --function-name lambda-web-cloudfront-oac\u003C\u002Fcode>.","See the GitHub repo for removing the execution role and log groups.",[12],{"text":82},[83,84],"Set your Region, \u003Ccode>export AWS_REGION=us-east-1\u003C\u002Fcode>, then run \u003Ccode>.\u002Fdeploy.sh\u003C\u002Fcode>.","The script deploys the Web Function with \u003Ccode>aws lambda-web deploy --auth-type IamAuth\u003C\u002Fcode>, creates the OAC, a cache policy that forwards the viewer's Authorization header, and the distribution, attaches the resource policy and waits for the distribution to deploy.","AWS CLI",{"template":87},{"patternPath":88,"templateFile":89},"lambda-web-cloudfront-oac\u002Fnodejs\u002Fawscli","deploy.sh",{"headline":26,"text":91},[28,29,30,31],{},{"icon1":94,"icon2":95,"icon3":96,"line1":97,"line2":98},{"x":37,"y":38,"service":39,"label":40},{"x":42,"y":38,"service":43,"label":44},{"x":46,"y":38,"service":47,"label":48},{"from":50,"to":51,"label":52},{"from":51,"to":54,"label":55},{"bullets":100},[101,102,103],{"text":60,"link":61},{"text":63,"link":64},{"text":66,"link":67},"patterns\u002Flambda-web-cloudfront-oac-nodejs-awscli",{"text":106},[71],"WgPAtEW0Qv0HTGML9HyRK2FzwSslk2lkPd1-hO-y44U",{"id":109,"title":5,"architectureURL":6,"cleanup":110,"contributors":113,"deploy":114,"description":17,"extension":18,"framework":118,"gitHub":119,"highlight":24,"introBox":123,"language":32,"level":33,"meta":125,"patternArch":126,"patternGroup":56,"patternGroupLabel":6,"resources":132,"stem":137,"testing":138,"videoId":6,"__hash__":140},"patterns\u002Fpatterns\u002Flambda-web-cloudfront-oac-nodejs-cdk.json",{"text":111},[112],"Run \u003Ccode>cdk destroy\u003C\u002Fcode>. The stack disables and deletes the distribution and the cache policy, empties and deletes the code bucket and removes the log group.",[12],{"text":115},[116,117],"Run \u003Ccode>npm install\u003C\u002Fcode>, then \u003Ccode>cdk deploy\u003C\u002Fcode> in the pattern directory (bootstrap the account and Region first if needed).","The stack creates the versioned code bucket, uploads the application, and defines the Web Function, its revision and \u003Ccode>IamAuth\u003C\u002Fcode> endpoint, the OAC, a cache policy that forwards the viewer's Authorization header, the CloudFront distribution and the resource policy.","AWS CDK",{"template":120},{"patternPath":121,"templateFile":122},"lambda-web-cloudfront-oac\u002Fnodejs\u002Fcdk","lib\u002Flambda-web-cloudfront-oac-stack.ts",{"headline":26,"text":124},[28,29,30,31],{},{"icon1":127,"icon2":128,"icon3":129,"line1":130,"line2":131},{"x":37,"y":38,"service":39,"label":40},{"x":42,"y":38,"service":43,"label":44},{"x":46,"y":38,"service":47,"label":48},{"from":50,"to":51,"label":52},{"from":51,"to":54,"label":55},{"bullets":133},[134,135,136],{"text":60,"link":61},{"text":63,"link":64},{"text":66,"link":67},"patterns\u002Flambda-web-cloudfront-oac-nodejs-cdk",{"text":139},[71],"jnCXLk3Onw1ynAYFtYARwbv1Bq7MY5MNVn0wRQT1NkU",{"id":4,"title":5,"architectureURL":6,"cleanup":142,"contributors":144,"deploy":145,"description":17,"extension":18,"framework":19,"gitHub":147,"highlight":24,"introBox":149,"language":32,"level":33,"meta":151,"patternArch":152,"patternGroup":56,"patternGroupLabel":6,"resources":158,"stem":68,"testing":163,"videoId":6,"__hash__":72},{"text":143},[9,10],[12],{"text":146},[15,16],{"template":148},{"patternPath":22,"templateFile":23},{"headline":26,"text":150},[28,29,30,31],{},{"icon1":153,"icon2":154,"icon3":155,"line1":156,"line2":157},{"x":37,"y":38,"service":39,"label":40},{"x":42,"y":38,"service":43,"label":44},{"x":46,"y":38,"service":47,"label":48},{"from":50,"to":51,"label":52},{"from":51,"to":54,"label":55},{"bullets":159},[160,161,162],{"text":60,"link":61},{"text":63,"link":64},{"text":66,"link":67},{"text":164},[71],1792146879011]