はじめに
先日CloudFrontからAPIGateway経由でLambdaへの構築を行なったので、そしたらセットでALB経由でLambdaこ構築に関してもCFn化しておこうと思い立ち、さっそくハンズオンしていきます。
構成図
ハンズオン
構築の流れ
1.VPC作成
2.Lambda作成
3.ALB作成
4.CloudFront作成
上記の順番で構築を行なっていきます。
最終的には、CloudFrontのディストリビューションドメインから、ALB経由でLambdaのメッセージ部分をダウンロードできるまでを行なっていきます。
1.VPC作成
以前記載したブログCloudFormationを使ってVPC構築に沿って、VPCを構築します。
2.Lambda作成
特別な設定はせずstatusCode
が200
を返す、Lambdaを構築します。
ALB経由でアクセスした際にダウンロードされる、body
部分のメッセージを一部修正しています。
AWSTemplateFormatVersion: '2010-09-09'
Description:
Lambda Create
# ------------------------------------------------------------#
# Metadata
# ------------------------------------------------------------#
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "Lambda Configuration"
Parameters:
- FunctionName
- Description
- Handler
- MemorySize
- Runtime
- Timeout
# ------------------------------------------------------------#
# InputParameters
# ------------------------------------------------------------#
Parameters:
FunctionName:
Type: String
Default: "cfn-lmd-inamura"
Description:
Type: String
Default: "cfn-lmd-inamura"
Handler:
Type: String
Default: "index.lambda_handler"
MemorySize:
Type: String
Default: "128"
Runtime:
Type: String
Default: "python3.9"
Timeout:
Type: String
Default: "10"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# Lambda
# ------------------------------------------------------------#
Lambda:
Type: 'AWS::Lambda::Function'
Properties:
Code:
ZipFile: |
import json
def lambda_handler(event, context):
# TODO implement
print(event)
return {
'statusCode': 200,
'body': json.dumps('Hello CloudFront-ALB!')
}
Description: !Ref Description
FunctionName: !Ref FunctionName
Handler: !Ref Handler
MemorySize: !Ref MemorySize
Runtime: !Ref Runtime
Timeout: !Ref Timeout
Role: !GetAtt LambdaRole.Arn
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${FunctionName}-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "sts:AssumeRole"
Principal:
Service: lambda.amazonaws.com
Policies:
- PolicyName: !Sub "${FunctionName}-policy"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- "logs:CreateLogStream"
- "logs:PutLogEvents"
- "logs:CreateLogGroup"
Resource: !Sub "arn:${AWS::Partition}:logs:*:*:*"
# ------------------------------------------------------------#
# Output Parameters
#------------------------------------------------------------#
Outputs:
LambdaArn:
Value: !GetAtt Lambda.Arn
Export:
Name: !Sub "${FunctionName}-arn"
LambdaName:
Value: !Ref FunctionName
Export:
Name: !Sub "${FunctionName}-name"
3.ALB作成
##### 3.1.この後作成するCloudFrontのCustom-Header
を利用して、CloudFront経由でアクセスしたユーザにはLambdaへのアクセスを許可して、直接ALBへアクセスしたユーザには【ERROR】ページを表示するようにします。
AWSTemplateFormatVersion: "2010-09-09"
Description:
ALB Create
# ------------------------------------------------------------#
# Metadata
# ------------------------------------------------------------#
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "ALB Configuration"
Parameters:
- ALBName
- Type
- Scheme
- IpAddressType
- label:
default: "ALB TargetGroup"
Parameters:
- TGName1
- TargetType
- label:
default: "ALB SecurityGroup"
Parameters:
- GroupName
# ------------------------------------------------------------#
# InputParameters
# ------------------------------------------------------------#
Parameters:
ALBName:
Type: String
Default: "cfn-alb-inamura"
Type:
Type: String
Default: "application"
Scheme:
Type: String
Default: "internet-facing"
IpAddressType:
Type: String
Default: "ipv4"
TGName1:
Type: String
Default: "cfn-tgg1-inamura"
TargetType:
Type: String
Default: "lambda"
GroupName:
Type: String
Default: "cfn-sg-alb-inamura"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# ALB
# ------------------------------------------------------------#
ALB:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: !Ref ALBName
Type: !Ref Type
Scheme: !Ref Scheme
IpAddressType: !Ref IpAddressType
Subnets:
- !ImportValue cfn-inamura-public-subneta
- !ImportValue cfn-inamura-public-subnetc
SecurityGroups:
- !Ref ALBSecurityGroup
ListenerHTTP:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref TargetGroup1
LoadBalancerArn: !Ref ALB
Port: 80
Protocol: HTTP
ListenerRule1:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: forward
TargetGroupArn: !Ref TargetGroup1
Conditions:
- Field: path-pattern
Values:
- '*'
- Field: http-header
HttpHeaderConfig:
HttpHeaderName: Custom-Header
Values:
- inamura
ListenerArn: !Ref ListenerHTTP
Priority: 1
ListenerRule2:
Type: AWS::ElasticLoadBalancingV2::ListenerRule
Properties:
Actions:
- Type: "fixed-response"
FixedResponseConfig:
ContentType: 'text/html'
MessageBody: |
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>【ERROR】</title>
</head>
<body>
<h1>CloudFront経由でアクセスください</h1>
</body>
</html>
StatusCode: 503
Conditions:
- Field: path-pattern
Values:
- '*'
ListenerArn: !Ref ListenerHTTP
Priority: 2
TargetGroup1:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
DependsOn: LambdaInvokePermission
Properties:
Name: !Ref TGName1
TargetType: !Ref TargetType
Targets:
- Id: !ImportValue cfn-lmd-inamura-arn
# ------------------------------------------------------------#
# ALB SG
# ------------------------------------------------------------#
ALBSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupDescription: "ALB SG"
GroupName: !Ref GroupName
VpcId: !ImportValue cfn-inamura-vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
# ------------------------------------------------------------#
# リソースベースポリシー
# ------------------------------------------------------------#
LambdaInvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !ImportValue cfn-lmd-inamura-arn
Action: lambda:InvokeFunction
Principal: elasticloadbalancing.amazonaws.com
# ------------------------------------------------------------#
# Output Parameters
# ------------------------------------------------------------#
Outputs:
ALBURL:
Description: ALB endpoint URL
Value: !Join
- ""
- - http://
- !GetAtt ALB.DNSName
ALBDomain:
Description: ALB Domain
Value: !GetAtt ALB.DNSName
Export:
Name: cfn-alb-dns
HostedZoneID:
Description: The ID of the Amazon Route 53 hosted zone associated with the load balancer.
Value: !GetAtt ALB.CanonicalHostedZoneID
Export:
Name: cfn-alb-id
3.2.CFnのタブ『出力』から、下記赤枠部分の『ALBURL』を押下する
3.3.下記画面に遷移する
Custom-Header
が付与されていないアクセスのためALBで【ERROR】ページに遷移されてしまう
4.CloudFront作成
3.で構築したALBをオリジンとして、Custom-Header
を設定しています。
AWSTemplateFormatVersion: '2010-09-09'
Description:
CloudFront Create
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# CloudFront
# ------------------------------------------------------------#
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Comment: "Create CloudFront with CloudFormation"
PriceClass: PrinceClass_All
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
Compress: true
TargetOriginId: !ImportValue cfn-alb-id
ViewerProtocolPolicy: allow-all
Enabled: true
HttpVersion: http2and3
Origins:
- CustomOriginConfig:
HTTPSPort: '80'
OriginProtocolPolicy: http-only
DomainName: !ImportValue cfn-alb-dns
Id: !ImportValue cfn-alb-id
OriginCustomHeaders:
- HeaderName: Custom-Header
HeaderValue: inamura
PriceClass: PriceClass_All
# ------------------------------------------------------------#
# Output Parameters
#------------------------------------------------------------#
Outputs:
DomainName:
Value: !GetAtt Distribution.DomainName
Export:
Name: cfn-clf-dns