LoginSignup
22
9

More than 5 years have passed since last update.

TerraformでCloudFrontにLambda@Edgeを設定する

Last updated at Posted at 2018-08-23

TerraformでLambda@Edgeを登録する。
ここではBasic認証をサンプルとして設定する。

1. IAM Roleつくる

provider "aws" {
  profile = "my-profile"
}

resource "aws_iam_role" "lambda-edge" {
  name = "lambda-edge"

  assume_role_policy = "${data.aws_iam_policy_document.lambda-assume-role.json}"
}

data "aws_iam_policy_document" "lambda-assume-role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com", "edgelambda.amazonaws.com"]
    }
  }
}

resource "aws_iam_role_policy_attachment" "basic" {
  role       = "${aws_iam_role.lambda-edge.name}"
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}

resource "aws_iam_role_policy" "lambda-edge-cloudwatch-log-group" {
  name   = "lambda-edge-cloudwatch-log-group"
  role   = "${aws_iam_role.lambda-edge.name}"
  policy = "${data.aws_iam_policy_document.cloudwatch-log-group-lambda-edge.json}"
}

2. Lambda functionをつくる

usernameとpasswordのところは適宜書き換える。

lambda/basic_auth/index.js
'use strict';

exports.handler = (event, context, callback) => {
  const request = event.Records[0].cf.request;

  const credentials = [
    {user: 'username', pass:'password'}
  ];
  const headers = request.headers;
  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' }]
    }
  });
}

archive_fileでzip化して登録する。
publish = trueにしておくとバージョンが発行される。
Lambda@Edgeにはバージョンがないと設定できない。
Lambda@Edge用のLambda Functionはus-east-1に登録するのが必須。

provider "aws" {
  region = "us-east-1"
  profile = "my-profile"
  alias  = "virginia"
}

data "archive_file" "basic_auth" {
  type        = "zip"
  source_dir  = "lambda/basic_auth"
  output_path = "lambda/dst/basic_auth.zip"
}

resource "aws_lambda_function" "basic_auth" {
  provider         = "aws.virginia"
  filename         = "${data.archive_file.basic_auth.output_path}"
  function_name    = "basic_auth"
  role             = "${data.aws_iam_role.lambda-edge.arn}"
  handler          = "index.handler"
  source_code_hash = "${data.archive_file.basic_auth.output_base64sha256}"
  runtime          = "nodejs8.10"

  publish          = true

  memory_size = 128
  timeout     = 3
}

3. CloudFrontに設定

qualified_arnがバージョン付きのarnなのでこれを設定する。

resource "aws_cloudfront_distribution" "site" {
    # ...

    lambda_function_association = [
      {
        event_type = "viewer-request"
        lambda_arn = "${aws_lambda_function.basic_auth.qualified_arn}"
      }
    ]
  }
}
22
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
9