Skip to content

Instantly share code, notes, and snippets.

@maruware
Last active April 17, 2019 11:02
Show Gist options
  • Save maruware/49bf5f9c3f3541c31942e2e672f0d7a3 to your computer and use it in GitHub Desktop.
Save maruware/49bf5f9c3f3541c31942e2e672f0d7a3 to your computer and use it in GitHub Desktop.
Basic auth ss3+cloudfront
AWSTemplateFormatVersion: '2010-09-09'
Description: Static contents distribution using S3 and CloudFront with basic authentication by lambda@Edge
Parameters:
AuthUser:
Description: ID for basic authentication
Type: String
Default: user2018
AuthPass:
Description: Password for basic authentication
Type: String
Default: pass2018
CloudFrontAliase:
Description: CloudFront Alternate Domain Names (CNAMEs)
Type: String
Default: none
SelectLambdaDeployment:
Description: Select blue / green deployment
Type: String
Default: blue
AllowedValues:
- blue
- green
Conditions:
CloudFrontAliaseEnable: !Not [!Equals [!Ref 'CloudFrontAliase', 'none']]
LambdaVersionIsBlue: !Equals [!Ref 'SelectLambdaDeployment', 'blue']
LambdaVersionIsGreen: !Equals [!Ref 'SelectLambdaDeployment', 'green']
Resources:
S3Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketName: !Sub '${AWS::StackName}'
AccessControl: PublicRead
WebsiteConfiguration:
IndexDocument: index.html
ErrorDocument: error.html
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Origins:
- Id: S3Origin
DomainName: !Sub '${S3Bucket}.s3-website-${AWS::Region}.amazonaws.com'
CustomOriginConfig:
OriginProtocolPolicy: 'http-only'
Enabled: true
DefaultRootObject: index.html
Comment: !Sub '${AWS::StackName} distribution'
Aliases:
- !If
- CloudFrontAliaseEnable
- !Ref 'CloudFrontAliase'
- !Ref 'AWS::NoValue'
DefaultCacheBehavior:
TargetOriginId: S3Origin
ForwardedValues:
QueryString: true
Headers:
- If-Modified-Since
- If-None-Match
- Upgrade-Insecure-Requests
- User-Agent
Cookies:
Forward: all
ViewerProtocolPolicy: https-only
DefaultTTL: '0'
MaxTTL: '0'
MinTTL: '0'
LambdaFunctionAssociations:
- EventType: viewer-request
LambdaFunctionARN: !If
- LambdaVersionIsBlue
- !Ref 'LambdaFunctionVersionBlue'
- !Ref 'LambdaFunctionVersionGreen'
CacheBehaviors:
- AllowedMethods:
- GET
- HEAD
TargetOriginId: S3Origin
ForwardedValues:
QueryString: false
PathPattern: '/favicon.ico'
ViewerProtocolPolicy: allow-all
DefaultTTL: '86400'
MaxTTL: '86400'
MinTTL: '86400'
LogGroupLambda:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub '/aws/lambda/${LambdaFunction}'
RetentionInDays: 7
LambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- edgelambda.amazonaws.com
Action:
- sts:AssumeRole
Path: /service-role/
Policies:
- PolicyName: root
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: arn:aws:logs:*:*:*
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Role: !GetAtt 'LambdaRole.Arn'
Code:
ZipFile: !Sub |
'use strict';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers
// allow no auth to facebook and twitter bot
const ua = request.headers['user-agent'][0].value
if (ua.indexOf('facebookexternalhit') !== -1 || ua.indexOf('Twitterbot') !== -1) {
callback(null, request);
return;
}
// For no auth at a specific path
// if (request.uri.match(/^\/assets/)) {
// callback(null, request);
// return;
// }
const credentials = [
{user: '${AuthUser}', pass: '${AuthPass}'}
];
if (headers.authorization) {
const authorized = credentials.some(({user, pass}) => {
const secret = new Buffer(user + ':' + pass).toString('base64');
return headers.authorization[0].value.split(' ')[1] === secret;
});
if (authorized) {
callback(null, request);
return;
}
}
callback(null, {
status: '401',
statusDescription: '401 Unauthorized',
headers: {
'www-authenticate': [{ key: 'WWW-Authenticate', value: 'Basic' }]
}
});
}
Runtime: nodejs8.10
MemorySize: 128
Timeout: 1
Description: Basic authentication with Lambda@Edge
Tags:
- Key: CloudformationArn
Value: !Ref 'AWS::StackId'
LambdaFunctionVersionBlue:
Type: AWS::Lambda::Version
Condition: LambdaVersionIsBlue
Properties:
FunctionName: !Ref 'LambdaFunction'
LambdaFunctionVersionGreen:
Type: AWS::Lambda::Version
Condition: LambdaVersionIsGreen
Properties:
FunctionName: !Ref 'LambdaFunction'
Outputs:
URL:
Value: !Sub 'https://${CloudFrontDistribution.DomainName}'
@maruware
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment