4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

CloudFormation から OriginAccessControl を設定する

Last updated at Posted at 2022-09-28

前置き

2022年8月末ごろにAWSより OriginAccessControl がリリースされました。
これに伴い、旧来の OriginAccessIdentity が非推奨と記載されるようになりました。

よし、では手元の cloudformation yaml をドキュメントに従って書き換えて OAC を使用するようにしよう。

  1. Amazon S3 オリジンへのアクセスの制限
  2. AWS::CloudFront::OriginAccessControl

おや?CloufFormation での OAC の作成方法は書いてあるが CloudFront に付ける方法が書いてないぞ。
Console, CLI, API は CloudFront へのアタッチ方も書いてあるのに。
不思議なこともあるもんだ。

まぁ誰か記事くらい書いてるやろ。
と思ったが無いんだなこれが。

誰も・・・
CloudFormation での OAC アタッチ方を書いていないのである!!!

というわけで CloufFormation で OAC の作成から CloudFormation へのアタッチまでをやったので記事を書きました。

OAC の強化点

折角なのでこれから使う OAC についても少し見ておきましょう。

AWS は OAC の注目すべき(OAIからの)強化点を以下としています。

  • セキュリティ – OAC は、短期間のクレデンシャル、頻繁なクレデンシャルのローテーション、およびリソースベースのポリシーのような強化されたセキュリティプラクティスで実装されています。これらは、ディストリビューションのセキュリティポスチャを強化し、混乱する代理のような攻撃に対してより良い保護を提供します。
  • 包括的な HTTP メソッドのサポート – OAC は GET、PUT、POST、PATCH、DELETE、OPTIONS、および HEAD をサポートしています。
  • SSE-KMS – OAC は、SSE-KMS で暗号化された S3 オブジェクトのダウンロードとアップロードをサポートしています。
  • すべての AWS リージョンでの S3 にアクセス – OAC は、既存のリージョンと将来のすべてのリージョンを含む、すべての AWS リージョンでの S3 へのアクセスをサポートしています。一方、OAI は既存の AWS リージョンと 2022 年 12 月までに開始されるリージョンでのみサポートされます。

逆に、現在の OAI でできないことは Amazon S3 オリジンへのアクセスの制限 - オリジンアクセスアイデンティティの使用 (レガシー、非推奨) で確認できます。

従来は cloudfront に OAI を設定して、S3 バケットポリシーにてこの OAI を許可することで S3 バケットやオブジェクトをパブリックにすることなく cloudfront からのアクセスのみを許可するようにアクセス制限を設けられました。

OAC ではこれに加えて S3 オブジェクトの SSE-KMS による暗号化に対応するようです。
(OAI では SSE-KMS で暗号化したオブジェクトを利用できなかった。(バケット内のオブジェクトが AWS Key Management Service (AWS KMS) を使用して暗号化されていないことを確認します))

実際の yaml

---
AWSTemplateFormatVersion: '2010-09-09'
Description: origin access control test.

Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: {bucket name}
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  OriginAccessControl:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Description: ''
        Name: {origin access contlor name}
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: !GetAtt S3Bucket.RegionalDomainName
            Id: oac-test-bucket
            OriginAccessControlId: !GetAtt OriginAccessControl.Id
            S3OriginConfig: {}
        DefaultCacheBehavior:
          ForwardedValues:
              QueryString: 'false'
              Cookies:
                Forward: none
          TargetOriginId: oac-test-bucket
          ViewerProtocolPolicy: allow-all
        Enabled: true

  BucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
        - Action: "s3:GetObject"
          Effect: Allow
          Resource: !Join
            - ''
            - - 'arn:aws:s3:::'
              - !Ref S3Bucket
              - /*
          Principal:
            Service: cloudfront.amazonaws.com
          Condition:
            StringEquals:
              AWS:SourceArn: !Join
                - ''
                - - 'arn:aws:cloudfront::{your AWS account ID}:distribution/'
                  - !Ref CloudFrontDistribution

あまり OAC と関係のない項目は適当に Amazon CloudFront テンプレートスニペット の 「Amazon S3 オリジンを使用した Amazon CloudFront Distribution リソース」 あたりから値を拝借している。

private な s3 bucket を作り、同時に作成する cloudfront からのアクセスのみを許可した。

それぞれの項目に軽く触れていく

S3Bucket

  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: {bucket name}
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

とりあえず PublicAccessBlockConfiguration はすべて true にしておいた。

  • BlockPublicAcls - 新たに、バケットやオブジェクトの ACL をパブリックにすることや、パブリックなオブジェクトを配置することを禁止する。(= 作成も更新も禁止)
  • IgnorePublicAcls - バケットとオブジェクトのパブリック ACL を無視する。
  • BlockPublicPolicy - パブリックなバケットポリシー、アクセスポイントポリシーへの変更を禁止する。
  • RestrictPublicBuckets - パブリックポリシーを持つバケットやアクセスポイントへのアクセスをバケット所有者のAWSサービスと承認されたユーザーのみに制限する。

総合して、現在のパブリック設定を無視し、新規にパブリック設定を作ることを禁止する。

OriginAccessControl

  OriginAccessControl:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Description: ''
        Name: {origin access contlor name}
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

これはほとんど Amazon S3 オリジンへのアクセスの制限 の例のまま。
詳細は AWS::CloudFront::OriginAccessControl

注意点

  1. 例では DisplayName と記載があるが、cloudformation ドキュメントでは Name となっているのでそっちに従った
  2. Description は非必須項目だが、空文字を許容するだけで項目自体が存在しないとエラーが出るようだ。

CloudFrontDistribution

  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: !GetAtt S3Bucket.RegionalDomainName
            Id: oac-test-bucket
            OriginAccessControlId: !GetAtt OriginAccessControl.Id
            S3OriginConfig: {}
        DefaultCacheBehavior:
          ForwardedValues:
              QueryString: 'false'
              Cookies:
                Forward: none
          TargetOriginId: oac-test-bucket
          ViewerProtocolPolicy: allow-all
        Enabled: true

とにかく、ここまでで作成した s3 origin へ oac を使ってアクセスする簡単な cloudfront を作成した。

S3 origin への OAC のアタッチだが、AWS::CloudFront::Distribution OriginOriginAccessControlId という項目が存在し、AWS::CloudFront::OriginAccessControl
にも Fn::GetAtt - Id が存在したので与えてみたところうまくいった。

BucketPolicy

  BucketPolicy:
    Type: "AWS::S3::BucketPolicy"
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Statement:
        - Action: "s3:GetObject"
          Effect: Allow
          Resource: !Join
            - ''
            - - 'arn:aws:s3:::'
              - !Ref S3Bucket
              - /*
          Principal:
            Service: cloudfront.amazonaws.com
          Condition:
            StringEquals:
              AWS:SourceArn: !Join
                - ''
                - - 'arn:aws:cloudfront::{your AWS account ID}:distribution/'
                  - !Ref CloudFrontDistribution

OAI では Principal に OAI を指定して、OAI を実行元サービスとして許容していたが、OAC では実行元サービスは cloudfront となる。
ConditionAmazon S3 オリジンへのアクセスの制限 の「S3 バケットへのアクセス許可をオリジンアクセスコントロールに付与する」 を参考に distribution を指定。

アクセスしてみる

作成された s3 へ適当なファイルを置いて、cloudfront のディストリビューションドメイン名を確認してブラウザからアクセスしてみます。

デフォルトルートオブジェクトは指定しなかったので適当にパスを付けて、

image.png

やったぜ。

念のため S3 オブジェクトへ直接アクセスもしておきましょう。

image.png

以上。
cloudformation での OAC 作成から cloudfront distribution へのアタッチまででした。

参考情報

  1. Amazon CloudFront でオリジンアクセスコントロール (OAC) をリリース
  2. Amazon CloudFront オリジンアクセスコントロール(OAC)のご紹介
  3. Amazon S3 オリジンへのアクセスの制限
  4. Amazon CloudFront テンプレートスニペット
  5. AWS::CloudFront::Distribution Origin
  6. AWS::CloudFront::OriginAccessControl
  7. CloudFront ディストリビューションのオリジンとして S3 ウェブサイトのエンドポイントを使用しています。403 Access Denied エラーが発生するのはなぜですか?
4
3
0

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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?