CloudFront + Lambda@Edge에서 Basic 인증을 위한 CloudFormation 템플릿

14425 단어 CloudFormationAWS
Lambda@Edge로 Basic 인증하고 싶었지만 손으로 ​​포치포치 만드는 것도 번거롭기 때문에 CloudFormation의 템플릿화했다.
Lambda@Edge 용 Lambda 함수는 us-east-1로 작성해야하므로 템플릿이 두 개로 분리됩니다.

Lambda 함수를 추가하는 템플릿


  • 이 템플릿은 us-east-1에서 실행해야합니다
  • Lambda@edge는 별칭을 사용할 수 없지만 SAM에서 Lambda 버전을 발행하고 싶었기 때문에 AutoPublishAlias를 지정하여 버전을 만들고 있습니다
  • 코드의 authUserauthPass는 임의의 값을 넣고 실행합니다
  • AWSTemplateFormatVersion: 2010-09-09
    Transform: "AWS::Serverless-2016-10-31"
    
    Resources:
      LambdaRole:
        Type: AWS::IAM::Role
        Properties:
          RoleName: basic-auth-lambda-role
          Path: /
          AssumeRolePolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Principal:
                  Service:
                    - edgelambda.amazonaws.com
                    - lambda.amazonaws.com
                Action:
                  - sts:AssumeRole
          ManagedPolicyArns:
            - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
    
      LambdaFunction:
        Type: AWS::Serverless::Function
        Properties:
          FunctionName: basic-auth
          Handler: index.handler
          Runtime: nodejs8.10
          MemorySize: 128
          Timeout: 5
          Role: !GetAtt LambdaRole.Arn
          AutoPublishAlias: prod
          InlineCode: |
            exports.handler = (event, context, callback) => {
                const request = event.Records[0].cf.request;
                const headers = request.headers;
                const authUser = 'user';
                const authPass = 'pass';
                const authString = 'Basic ' + new Buffer(`${authUser}:${authPass}`).toString('base64');
                if (typeof headers.authorization == 'undefined' || headers.authorization[0].value != authString) {
                    const response = {
                        status: '401',
                        statusDescription: 'Unauthorized',
                        body: 'Unauthorized',
                        headers: {
                            'www-authenticate': [{ key: 'WWW-Authenticate', value:'Basic' }],
                        },
                    };
                    callback(null, response);
                } else {
                    callback(null, request);
                }
            };
    
      LogGroup:
        Type: AWS::Logs::LogGroup
        DependsOn:
          - LambdaFunction
        Properties:
          RetentionInDays: 1
          LogGroupName: !Sub "/aws/lambda/${LambdaFunction}"
    

    CloudFront를 설정하는 템플릿


  • S3 + CloudFront 구성
  • 이 템플릿은 어느 리전에서 실행해도 괜찮습니다만 이번은 다른 리전에서 실행하는 가정으로 만들고 있습니다
  • LambdaFunctionAssociations가 Lambda@Edge를 사용하기위한 설정입니다.
  • 이것을 지우면 Basic 인증이 빠집니다
  • 여기서 Lambda 함수 이름과 버전이 필요하기 때문에 Parameter에서받을 수 있습니다

  • 액세스 할 때 Lambda 로그가 /aws/lambda/us-east-1.関数名에 출력됩니다.
  • 나중에 삭제했을 때 쓰레기 남기 때문에 여기에서 로그 그룹을 만들어 버립니다

  • AWSTemplateFormatVersion: 2010-09-09
    
    Parameters:
      BucketName:
        Type: String
      LambdaEdgeFunctionName:
        Type: String
      LambdaEdgeFunctionVersion:
        Type: String
    
    Resources:
      S3Bucket:
        Type: AWS::S3::Bucket
        Properties:
          AccessControl: PublicRead
          BucketName: !Ref BucketName
          WebsiteConfiguration:
            IndexDocument: index.html
            ErrorDocument: error.html
    
      S3BucketPolicy:
        Type: AWS::S3::BucketPolicy
        DependsOn:
          - S3Bucket
          - CloudFrontOriginAccessIdentity
        Properties:
          Bucket: !Ref S3Bucket
          PolicyDocument:
            Version: 2008-10-17
            Statement:
              - Action:
                  - s3:GetObject
                Effect: Allow
                Resource: !Sub "${S3Bucket.Arn}/*"
                Principal:
                  AWS: !Sub "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}"
    
      CloudFrontOriginAccessIdentity:
        Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
        Properties:
          CloudFrontOriginAccessIdentityConfig:
            Comment: "access identity"
    
      CloudFrontDistribution:
        Type: AWS::CloudFront::Distribution
        DependsOn:
          - S3Bucket
          - CloudFrontOriginAccessIdentity
        Properties:
          DistributionConfig:
            Enabled: true
            DefaultCacheBehavior:
              AllowedMethods:
                - HEAD
                - GET
              CachedMethods:
                - HEAD
                - GET
              DefaultTTL: 0
              MaxTTL: 0
              MinTTL: 0
              TargetOriginId: !Sub "${BucketName}-Origin"
              ViewerProtocolPolicy: redirect-to-https
              ForwardedValues:
                QueryString: false
              LambdaFunctionAssociations:
                - EventType: viewer-request
                  LambdaFunctionARN: !Sub "arn:aws:lambda:us-east-1:${AWS::AccountId}:function:${LambdaEdgeFunctionName}:${LambdaEdgeFunctionVersion}"
            IPV6Enabled: true
            HttpVersion: http2
            DefaultRootObject: index.html
            ViewerCertificate:
              CloudFrontDefaultCertificate: true
            Origins:
              - Id: !Sub "${BucketName}-Origin"
                DomainName: !Sub "${BucketName}.s3.${AWS::Region}.amazonaws.com"
                S3OriginConfig:
                  OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}"
            CustomErrorResponses:
              - ErrorCachingMinTTL: 0
                ErrorCode: 403
    
      LogGroup:
        Type: AWS::Logs::LogGroup
        Properties:
          RetentionInDays: 1
          LogGroupName: !Sub "/aws/lambda/us-east-1.${LambdaEdgeFunctionName}"
    

    확인


  • 생성된 CloudFront Distribution의 Domain Name을 두드려 다음과 같이 되면 OK
  • 나머지는 Lambda로 설정 한 User/Pass를 넣고 로그인 할 수 있으면 OK

  • 좋은 웹페이지 즐겨찾기