はじめに
IAM認証や、ACM,Route53などの検証の際に、自分でよく利用する構築をCloudFormation化していなかったと思い着手してみました。
まずは背骨となる、 CloudFront から APIGateway - Lambdaを呼び出す構築部分のCFn化を行なっていきたいと思います。
構成図
ハンズオン
構築の流れ
1.Lambda作成
2.APIGateway作成
3.CloudFront作成
上記の順番で構築を行なっていきます。
最終的には、CloudFrontのディストリビューションドメインから、Lambdaを呼び出せるまでを行なっていきます。
1.Lambda作成
特別な設定はせずstatusCode
が200
を返す、Lambdaを構築します。
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!')
}
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"
2.APIGateway作成
2.1 APIGateway作成
次はAPIGatewayを構築します。
順次構築できるようにするため、それぞれのリソースにDependsOn
を設定しています。
1.で構築したLambdaに対して"AWS::Lambda::Permission"
でリソースベースポリシーの追加を行なっています。
AWSTemplateFormatVersion: '2010-09-09'
Description:
APIGateway Create
# ------------------------------------------------------------#
# Metadata
# ------------------------------------------------------------#
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "APIGateway Configuration"
Parameters:
- Name
- FunctionName
- StageName
# ------------------------------------------------------------#
# InputParameters
# ------------------------------------------------------------#
Parameters:
Name:
Type: String
Default: "cfn-agw-inamura"
FunctionName:
Type: String
Default: "cfn-lmd-inamura"
StageName:
Type: String
Default: "dev"
# ------------------------------------------------------------#
# Resources
# ------------------------------------------------------------#
Resources:
# ------------------------------------------------------------#
# APIGateway
# ------------------------------------------------------------#
Api:
Type: "AWS::ApiGateway::RestApi"
Properties:
Name: !Ref Name
EndpointConfiguration:
Types:
- REGIONAL
Resource:
Type: "AWS::ApiGateway::Resource"
Properties:
RestApiId: !Ref Api
ParentId: !GetAtt Api.RootResourceId
PathPart: !Ref FunctionName
DependsOn: Api
LambdaPermission:
Type: "AWS::Lambda::Permission"
Properties:
FunctionName: !Ref FunctionName
Action: "lambda:InvokeFunction"
Principal: "apigateway.amazonaws.com"
DependsOn: Resource
ResourceMethod:
Type: "AWS::ApiGateway::Method"
Properties:
RestApiId: !Ref Api
ResourceId: !Ref Resource
AuthorizationType: None
HttpMethod: ANY
Integration:
Type: "AWS_PROXY"
IntegrationHttpMethod: POST
Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${FunctionName}/invocations"
DependsOn: LambdaPermission
Deployment:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref Api
DependsOn: ResourceMethod
Stage:
Type: AWS::ApiGateway::Stage
Properties:
StageName: !Ref StageName
Description: dev stage
RestApiId: !Ref Api
DeploymentId: !Ref Deployment
DependsOn: Deployment
# ------------------------------------------------------------#
# Output Parameters
#------------------------------------------------------------#
Outputs:
Endpoint:
Value: !Sub 'https://${Api}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${StageName}/${FunctionName}'
Export:
Name: Endpoint
OriginDomain:
Value: !Sub '${Api}.execute-api.${AWS::Region}.${AWS::URLSuffix}'
Export:
Name: OriginDomain
StageName:
Value: !Sub '${StageName}'
Export:
Name: StageName
2.2.構築されたAPIGatewayのエンドポイントを押下する
CloudFormation > スタック > 2.1.で構築したスタック > タブ『出力』 に移動する
下記画面のように Endpoint にエンドポイントが出力されているので、URIを押下する
URI押下後、下記のような画面が表示されることを確認する
※自分だけの現象か、上記構築後Lambdaを確認してもトリガー
にはAPIGatewayが表示されませんでした
3.CloudFront作成
2.で構築したAPIGatewayをオリジンにしたCloudFrontを構築していきます。
CachePolicyId
はマネージドポリシーを利用しているので、AWS公式:Using the managed cache policiesからId番号を確認しました。
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-lmd-inamura-name
ViewerProtocolPolicy: https-only
Enabled: true
HttpVersion: http2and3
Origins:
- Id: !ImportValue cfn-lmd-inamura-name
DomainName: !ImportValue OriginDomain
CustomOriginConfig:
HTTPSPort: '443'
OriginProtocolPolicy: https-only
OriginPath: !Sub
- /${StageName}/${FunctionName}
- StageName: {'Fn::ImportValue': StageName}
FunctionName: {'Fn::ImportValue': cfn-lmd-inamura-name}
PriceClass: PriceClass_All
# ------------------------------------------------------------#
# Output Parameters
#------------------------------------------------------------#
Outputs:
DomainName:
Value: !GetAtt Distribution.DomainName
Export:
Name: cln-domainname-inamura