AWS日記23 (CloudFront)

# はじめに
今回は AWS CloudFront を試します。
[AWS サポートの記事](https://aws.amazon.com/jp/premiumsupport/knowledge-center/api-gateway-cloudfront-distribution/)を参考に、独自の CloudFront ディストリビューションで API Gateway を設定しました。

[Lambda関数・SAMテンプレート]
(https://github.com/tanaka-takurou/serverless-cloudfront-page-go)


# 準備
[AWS SAM の準備をします](https://qiita.com/tanaka_takurou/items/cae7c19fc3aaf0031abb)

[AWS CloudFrontの資料]
[AWS CloudFront](https://aws.amazon.com/jp/cloudfront/)


# AWS SAM テンプレート作成

AWS SAM テンプレートで API-Gateway , Lambda, AWS CloudFront の設定をします。

[参考資料]
[AWS SAM テンプレートを作成する](https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/tutorial-lambda-sam-template.html)

### AWS CloudFront の設定は以下の部分
```yaml
  CloudFrontCachePolicy:
    Type: AWS::CloudFront::CachePolicy
    Properties:
      CachePolicyConfig:
        DefaultTTL: 86400
        MaxTTL: 31536000
        MinTTL: 0
        Name: !Ref CloudFrontCachePolicyName
        ParametersInCacheKeyAndForwardedToOrigin:
          CookiesConfig:
            CookieBehavior: 'none'
          EnableAcceptEncodingBrotli: false
          EnableAcceptEncodingGzip: false
          HeadersConfig:
            HeaderBehavior: 'none'
          QueryStringsConfig:
            QueryStringBehavior: 'none'
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        DefaultCacheBehavior:
          CachePolicyId: !Ref CloudFrontCachePolicy
          TargetOriginId: !Ref DistributionOriginId
          ViewerProtocolPolicy: 'redirect-to-https'
        Enabled: true
        Origins:
          - Id: !Ref DistributionOriginId
            DomainName: !Join [ '', [ !Ref FrontPageApi, '.execute-api.',!Ref 'AWS::Region','.amazonaws.com'] ]
            OriginPath: !Join [ '', [ '/',!Ref FrontPageApiStageName] ]
            CustomOriginConfig:
              OriginProtocolPolicy: 'https-only'
              OriginKeepaliveTimeout: 5
              OriginReadTimeout: 30
```


# Lambda関数作成

※ Lambda関数は aws-lambda-go を利用しました。
AWS CloudFront の操作は aws-sdk-go-v2/service/cloudfront を利用しました。


### Distribution の一覧を取得するには ListDistributions を使う
```golang
func getDistribution(ctx context.Context)(string, error) {
	if cloudfrontClient == nil {
		cloudfrontClient = cloudfront.NewFromConfig(getConfig(ctx))
	}
	input := &cloudfront.ListDistributionsInput{}

	result, err := cloudfrontClient.ListDistributions(ctx, input)
	if err != nil {
		log.Print(err)
		return "", err
	}

	distributionSummaries := result.DistributionList.Items
	if len(distributionSummaries) < 1 {
		return "", errors.New("No DistributionSummary")
	}
	originsString := ""
	for _, v := range distributionSummaries[0].Origins.Items {
		originsString = originsString + aws.ToString(v.DomainName) + ","
	}
	originsString = originsString[:len(originsString) - 1]
	resultJson, err := json.Marshal(DistributionSummaryData{
		DomainName: aws.ToString(distributionSummaries[0].DomainName),
		Origins: originsString,
		Status: aws.ToString(distributionSummaries[0].Status),
	})
	if err != nil {
		log.Print(err)
		return "", err
	}
	return string(resultJson), nil
}
```

# 注意点
 - 東京リージョンの設定で進めたところ、CloudFront ディストリビューションを作成時にエラーが発生したため、米国東部 (バージニア北部) リージョンに変更しました。
[AWS サポートの参考記事](https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudfront-invalid-viewer-certificate/)

 - AWS::CloudFront::Distribution の LambdaFunctionAssociations を設定して進めたところ、Go言語はサポートしていない旨のエラーが発生したため、設定を消しました。

# 終わりに
独自の CloudFront ディストリビューションで API Gateway を設定しました。
[API Gateway でエッジ最適化された API エンドポイント](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-basic-concept.html#apigateway-definition-edge-optimized-api-endpoint) よりも詳細に制御できます。

<details><summary>参考資料</summary><div>
[カスタム CloudFront ディストリビューションで API Gateway をセットアップする](https://aws.amazon.com/jp/premiumsupport/knowledge-center/api-gateway-cloudfront-distribution/)

[CloudFormationでAPI Gateway＋LambdaなAPIを作成する](https://qiita.com/hir00/items/c5c0ca61658d4c8949c2)

[AWS::CloudFront::Distribution](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-distribution.html)

[AWS::CloudFront::CachePolicy](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cloudfront-cachepolicy.html)

[cloudfront · pkg.go.dev](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/cloudfront)

[ファイルの無効化](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html)