Skip to content

Commit 233cb4d

Browse files
authored
Merge pull request #1 from phuonghuynh/dev
Separate Lambda@Edge module
2 parents d0866d6 + 9343ef4 commit 233cb4d

File tree

6 files changed

+211
-0
lines changed

6 files changed

+211
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.archive*
2+
.idea/
3+
.iml

main.tf

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
resource "template_dir" "this" {
2+
source_dir = "${path.module}/src"
3+
destination_dir = "${path.module}/.archive"
4+
5+
vars {
6+
BUCKET_NAME = "${var.bucket_name}"
7+
BUCKET_KEY = "${var.bucket_key}"
8+
9+
BASIC_USER = "${var.basic_user}"
10+
BASIC_PWD = "${var.basic_password}"
11+
}
12+
}
13+
14+
data "archive_file" "this" {
15+
depends_on = [
16+
"template_dir.this",
17+
]
18+
19+
type = "zip"
20+
output_path = "${path.module}/.archive.zip"
21+
source_dir = "${template_dir.this.destination_dir}"
22+
}
23+
24+
resource "aws_lambda_function" "this" {
25+
description = "Basic HTTP authentication module/function"
26+
role = "${aws_iam_role.this.arn}"
27+
runtime = "nodejs8.10"
28+
29+
filename = "${data.archive_file.this.output_path}"
30+
source_code_hash = "${data.archive_file.this.output_base64sha256}"
31+
32+
function_name = "${var.name}"
33+
handler = "basic_auth.handler"
34+
35+
timeout = "${var.fn_timeout}"
36+
memory_size = "${var.fn_memory_size}"
37+
publish = true
38+
}

outputs.tf

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
output "fn_name" {
2+
value = "${aws_lambda_function.this.function_name}"
3+
}
4+
5+
output "arn" {
6+
value = "${aws_lambda_function.this.arn}"
7+
}
8+
9+
output "qualified_arn" {
10+
value = "${aws_lambda_function.this.qualified_arn}"
11+
}
12+
13+
output "invoke_arn" {
14+
value = "${aws_lambda_function.this.invoke_arn}"
15+
}
16+
17+
output "id" {
18+
value = "${aws_lambda_function.this.id}"
19+
}
20+
21+
output "version" {
22+
value = "${aws_lambda_function.this.version}"
23+
}

src/basic_auth.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
const AWS = require('aws-sdk');
3+
const s3 = new AWS.S3();
4+
5+
//https://medium.com/@yagonobre/automatically-invalidate-cloudfront-cache-for-site-hosted-on-s3-3c7818099868
6+
exports.handler = async (event, context, callback) => {
7+
const request = event.Records[0].cf.request;
8+
const uri = request.uri;
9+
10+
if (!'${BUCKET_NAME}') {
11+
console.log(`Bucket not defined (key is empty) => ignore`);
12+
return callback(null, request);
13+
}
14+
15+
try {
16+
const filesStr = await readRestrictedFiles();
17+
if (!filesStr) {
18+
throw new Error(`empty protect files => ignore`);
19+
}
20+
21+
const rawFiles = JSON.parse(await readRestrictedFiles());
22+
if (!Array.isArray(rawFiles)) {
23+
throw new Error('${BUCKET_KEY} is not any array => ignore')
24+
}
25+
const files = rawFiles.map(f => f.startsWith('/') ? f : '/' + f);
26+
if (!files.includes(uri)) {
27+
throw new Error(uri + ` not protected`);
28+
}
29+
30+
const headers = request.headers;
31+
32+
const authUser = '${BASIC_USER}';
33+
const authPass = '${BASIC_PWD}';
34+
35+
const authString = 'Basic ' + new Buffer(authUser + ':' + authPass).toString('base64');
36+
if (typeof headers.authorization === 'undefined' || headers.authorization[0].value !== authString) {
37+
const body = 'Unauthorized';
38+
const response = {
39+
status: '401',
40+
statusDescription: 'Unauthorized',
41+
body: body,
42+
headers: {
43+
'www-authenticate': [{key: 'WWW-Authenticate', value:'Basic'}]
44+
},
45+
};
46+
return callback(null, response);
47+
}
48+
}
49+
catch(e) {
50+
console.error(e);
51+
}
52+
return callback(null, request);
53+
};
54+
55+
async function readRestrictedFiles() {
56+
const params = { Bucket: '${BUCKET_NAME}', Key: '${BUCKET_KEY}' };
57+
const data = await s3.getObject(params).promise();
58+
return data.Body.toString();
59+
}

sts_role.tf

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
data "aws_iam_policy_document" "sts" {
2+
statement {
3+
effect = "Allow"
4+
5+
actions = [
6+
"sts:AssumeRole",
7+
]
8+
9+
principals {
10+
type = "Service"
11+
12+
identifiers = [
13+
"lambda.amazonaws.com",
14+
"edgelambda.amazonaws.com",
15+
]
16+
}
17+
}
18+
}
19+
20+
data "aws_iam_policy_document" "this" {
21+
statement {
22+
effect = "Allow"
23+
24+
actions = [
25+
"s3:GetBucketLocation",
26+
"s3:ListBucket",
27+
"s3:GetObject",
28+
"logs:CreateLogGroup",
29+
"logs:CreateLogStream",
30+
"logs:DescribeLogGroups",
31+
"logs:DescribeLogStreams",
32+
"logs:PutLogEvents",
33+
"logs:GetLogEvents",
34+
"logs:FilterLogEvents",
35+
]
36+
37+
resources = [
38+
"arn:aws:logs:*:*:*"
39+
]
40+
}
41+
42+
statement {
43+
effect = "Allow"
44+
45+
actions = [
46+
"lambda:GetFunction",
47+
]
48+
49+
resources = [
50+
"${aws_lambda_function.this.arn}:*",
51+
]
52+
}
53+
}
54+
55+
resource "aws_iam_role_policy" "this" {
56+
name = "${var.name}"
57+
role = "${aws_iam_role.this.id}"
58+
policy = "${data.aws_iam_policy_document.this.json}"
59+
}
60+
61+
resource "aws_iam_role" "this" {
62+
name = "${var.name}"
63+
assume_role_policy = "${data.aws_iam_policy_document.sts.json}"
64+
}

vars.tf

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
variable "name" {
2+
default = "terraform-aws-lambda-edge-authentication"
3+
}
4+
5+
// Lambda limits https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html
6+
variable "fn_timeout" {
7+
default = 3
8+
}
9+
10+
variable "fn_memory_size" {
11+
default = 128
12+
}
13+
14+
variable "bucket_name" {
15+
}
16+
17+
variable "bucket_key" {
18+
}
19+
20+
variable "basic_user" {
21+
}
22+
23+
variable "basic_password" {
24+
}

0 commit comments

Comments
 (0)