1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CloudFrontとLambda@EdgeによるBASIC認証をセットで作るCloudFormation

Last updated at Posted at 2023-12-03

こんにちは。Kaneyasuです。
最近はIoTまわりをやったり、フロントエンドやったりと幅広く頑張らせていただいています。
今回はLambda@EdgeによるBASIC認証付きのCloudFrontを作るCloudFormationテンプレートを書いてみました。
フロントエンドのお仕事でデプロイ先をサクッと用意するために作ったものです。

CloudFormationテンプレート

ポイント

バージニアリージョンで実行する

上側のCloudFormationテンプレートはバージニアリージョンで実行します。
Lambda@Edgeとして使えるLambdaはバージニアのみだからです。

US-East-1 (バージニア北部) リージョン (us-east-1) にいることを確認します。Lambda@Edge 関数を作成するには、このリージョンに設定されている必要があります。

BASIC認証用のID・パスワードをコードに埋め込む

  Code:
    ZipFile: !Sub |
      import base64
      from typing import Dict, Any, List, Optional

      BASIC_AUTH_USER = "${BasicAuthUser}"
      BASIC_AUTH_PASSWORD = "${BasicAuthPassword}"

LambdaのコードはPythonで書いて、CloudFormationテンプレート内に埋め込んでいます。
BASIC認証のパスワードは、CloudFormationのパラメータとしました。
環境変数にしておこうと思いましたが、環境変数を用いたLambdaはLambda@Edgeとして使用できないようです。
環境変数を使ったLambdaでLambda@Edgeを設定するCloudFormationテンプレートを書いてみましたが、実行時にエラーになることを確認しました。
というわけで、CloudFormationパラメータから持ってきた値を埋め込む形にしました。

Lambdaのバージョンを作っておく

  LambdaEdgeFunctionVersion:
    Type: AWS::Lambda::Version
    Properties:
      FunctionName: !Ref LambdaEdgeFunction
      Description: v1

Lambda@Edgeとして使う場合、バージョンを作っておくことが必要なので作成しています。

CloudFormationテンプレートのパラメータでLambdaのバージョンのARNを渡す

  LambdaEdgeFunctionVersionArn:
    Type: String
    Description: Lambda Edge Function Version ARN

下側のCloudFormationテンプレートは、LambdaのバージョンのARNをCloudFormationテンプレートのパラメータで受け取り、それを後述のビューワーリクエストにセットしています。

下側のCloudFormationテンプレートは、S3・CloudFront、Lambda@Edgeの設定をしています。
こちらのCloudFormationテンプレートは、東京リージョンで実行しそうなので、Lambda関数のバージョンのARNはOutputsではなくパラメータで渡す形にしています。
リージョンをまたぐと、Outputsを経由した渡し方は機能しないのが理由です。

リージョン間でクロススタック参照を作成することはできません。組み込み関数 Fn::ImportValue を使用して、同じリージョン内にエクスポートされた値のみをインポートできます。

S3と、CloudFront+Lambda@Edgeで分けたらこの問題は解決しそうな気もしますが、あまり分けるのも煩雑なのでこのままでいいかなと思っています。

バケットポリシーの設定を行う

CloudFrontディストリビューションからのみアクセスを許可するよう指定しています。
これがないと、デプロイ後にアクセスしても権限エラーが出ます。

  S3BucketPolicyForWebsite:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3BucketForWebsite
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: AllowCloudFrontServicePrincipal
            Effect: Allow
            Principal:
              Service: 'cloudfront.amazonaws.com'
            Action:
              - s3:GetObject
            Resource: !Sub arn:aws:s3:::${SystemName}-${Environment}-s3-bucket-for-website/*
            Condition:
              StringEquals:
                'aws:SourceArn': !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${CloudFrontDistribution}

OACの設定を行う

  OriginAccessControl:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Description: ''
        Name: !Sub ${SystemName}-${Environment}-origin-access-control-for-website
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        DefaultRootObject: 'index.html'
        Origins:
          - DomainName: !GetAtt S3BucketForWebsite.RegionalDomainName
            Id: !Sub ${SystemName}-${Environment}-s3-bucket-for-website
            OriginAccessControlId: !GetAtt OriginAccessControl.Id
            S3OriginConfig: {}

CloudFrontの画面で言う、ディストリビューション>オリジンのこの部分を設定しています。

image.png

DefaultRootObjectの設定

        DefaultRootObject: 'index.html'

これがないと、ファイル名を指定せずにアクセスすると何も表示されるエラーとなります。
ただし、この設定マネジメントコンソール側に見当たらないんですがどこにあるんですかね?

ビューワーリクエストにLambdaのバージョンのARNをセット

  LambdaFunctionAssociations:
    - EventType: viewer-request
      LambdaFunctionARN: !Ref LambdaEdgeFunctionVersionArn

Lambda@Edgeを設定しているのはここです。
ビューワーリクエストにLambdaのバージョンのARNをセットします。

まとめ

Lambda@Edgeの設定は手動で行うと、なかなか成功しないので今回テンプレートにしてみました。
BASIC認証ID・パスをLambdaにハードコーディングしてる部分は、他にやりようがある気がするのでまた調べてみようと思います。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?