0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS初学者がCloudFormationでインフラ構築に挑戦③!WAFを構築するよ

0
Posted at

はじめに

RaiseTechの課題で、CloudFormationで環境構築をしました。
自分の理解を深めるために作成した環境のアウトプットをします。
参考:AWS CloudFormation テンプレートリファレンス

前々回の記事ではVPC、EC2、RDS、ALBについてアウトプットをしました。

前回の記事ではCloudWatch AlarmとSNSについてアウトプットをしました。

今回は、WAFについてアウトプットを行います。

テンプレート(抜粋)

#WAF
  WebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Name: aws-study-alb-waf
      Scope: REGIONAL
      DefaultAction:
        Allow: {}
      VisibilityConfig:
        CloudWatchMetricsEnabled: true
        MetricName: aws-study-alb-waf
        SampledRequestsEnabled: true
      Rules:
        - Name: AWS-AWSManagedRulesCommonRuleSet
          Priority: 1
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesCommonRuleSet
          OverrideAction:
            None: {}
          VisibilityConfig:
            MetricName: AWS-AWSManagedRulesCommonRuleSet
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
  WebACLAssociation:
    Type: AWS::WAFv2::WebACLAssociation
    Properties:
      ResourceArn: !Ref ApplicationLoadBalancer
      WebACLArn: !GetAtt WebACL.Arn
#WAF Log
  WAFLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: aws-waf-logs-alb-alc
      RetentionInDays: 1
      Tags:
        - Key: Name
          Value: aws-waf-logs-alb-alc
  WAFLogConfig:
    DependsOn:
      - WAFToCloudWatchLogsPolicy
    Type: AWS::WAFv2::LoggingConfiguration
    Properties:
      ResourceArn: !GetAtt WebACL.Arn
      LogDestinationConfigs:
        - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${WAFLogGroup}
  WAFToCloudWatchLogsPolicy:
    Type: AWS::Logs::ResourcePolicy
    Properties:
      PolicyName: WAFToCloudWatchLogsPolicy
      PolicyDocument: !Sub |
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "AllowWAFToLog",
              "Effect": "Allow",
              "Principal": {
                "Service": "delivery.logs.amazonaws.com"
              },
              "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Resource": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${WAFLogGroup}:*"
            }
          ]
        }

解説

AWS WAF(Web Application Firewall)

  • セキュリティを強化するためのサービスの一つで、Webアプリを守るための防御フィルター
  • WebサイトやAPIに届くリクエストをチェックして、悪意のあるアクセスをブロックする
  • 例えば、ボット(自動攻撃プログラム)を検知して止めたり、特定の国やIPアドレスからのアクセスを拒否したりできる
  • 例えるなら、Webアプリの入り口で検問してくれる門番。今回は、前回作成したALBの目の前に設置

Resources

WAFの作成

#WAF
  WebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Name: aws-study-alb-waf
      Scope: REGIONAL
      DefaultAction:
        Allow: {}
      VisibilityConfig:
        CloudWatchMetricsEnabled: true
        MetricName: aws-study-alb-waf
        SampledRequestsEnabled: true
      Rules:
        - Name: AWS-AWSManagedRulesCommonRuleSet
          Priority: 1
          Statement:
            ManagedRuleGroupStatement:
              VendorName: AWS
              Name: AWSManagedRulesCommonRuleSet
          OverrideAction:
            None: {}
          VisibilityConfig:
            MetricName: AWS-AWSManagedRulesCommonRuleSet
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true

Web ACLの作成。
Web ACLとは、Web Access Control Listの略で、Webサイトへのアクセスを「どのルール(List)」で「制御(Control)」するかをまとめたルールセットのこと。
「海外からの怪しいアクセスは止める」「ボットは止める」といった個別のルールを1つのWeb ACLというリストにまとめ、それをALBなどに適用する。

  • Name:Web ACLの名前
  • Scope:Amazon CloudFrontディストリビューション用かリージョンアプリケーション用かを指定する。今回はリージョンアプリケーション用なので、REGIONALを指定
  • DefaultAction:Webサイトへのアクセスが、Web ACLに載っているどのルールにも当てはまらなかった時に、実行するアクションを決める。Allowは通す、Blockは止める。「Allow: {}」で、どのルールにも当てはまらなかったアクセスを、原則として通す設定になる
  • VisibilityConfig:WAFが攻撃をブロックしたときに、あとで人間が確認できるように、証拠を残すための設定。具体的には、CloudWatchでグラフを表示するための設定
  • CloudWatchMetricsEnabled:「何件ブロックしたか」という数を、CloudWatchのグラフに表示するかどうかを決める
  • MetricName:グラフの名前
  • SampledRequestsEnabled:アクセスをブロックしたときに、「具体的にどんな変なリクエストが来たのか」というデータを保存して、コンソール画面で見られるようにするかどうかの設定
  • Rules:ルールセットの具体的な中身
  • Name:ルールの名前
  • Priority:ルールの優先順位。複数のルールがある場合、数字が小さいものから順番にチェックされる。今回は1つだけなので1を指定
  • Statement:チェックする項目
  • ManagedRuleGroupStatement:AWSが用意しているルールセットを呼び出すための合図。一から自分でチェック項目を書くのは大変なので、既存のものを使用。使用するには、ベンダー名とルールグループ名を指定する必要がある
  • VendorName:管理対象ルールグループのベンダー名。ルールグループ名と併せて使用して、ルールグループを識別する
  • Name:管理対象ルールグループの名前。ベンダー名と併せて使用してルールグループを識別する
  • AWSManagedRulesCommonRuleSet:コアルールセット。Webサイトを運用する上で最低限防いでおきたい、一般的な攻撃(OWASP Top 10など)をまとめてガードしてくれる(参考:Baseline rule groups
  • OverrideAction:ルールグループ内のルールに適用するオーバーライドアクション。デフォルトアクション以外のものを適用するかどうかを決める。「None: {}」でなしの設定
  • VisibilityConfig:CloudWatchでグラフを表示するための設定。ここで設定するのは、ルール単体でのブロックグラフを表示する設定。「WAF全体のグラフ」と、「そのルール単体でのグラフ」を、それぞれ別々に名前をつけて管理できるようになっているので、個々のルール内でも設定する
  • MetricName:グラフの名前
  • SampledRequestsEnabled:アクセスをブロックしたときに、「具体的にどんな変なリクエストが来たのか」というデータを保存して、コンソール画面で見られるようにするかどうかの設定
  • CloudWatchMetricsEnabled:「何件ブロックしたか」という数を、CloudWatchのグラフに表示するかどうかを決める
  WebACLAssociation:
    Type: AWS::WAFv2::WebACLAssociation
    Properties:
      ResourceArn: !Ref ApplicationLoadBalancer
      WebACLArn: !GetAtt WebACL.Arn

リソースとWeb ACLを紐付ける。
紐付けることで、WAFが機能するようになる。

  • ResourceArn:Web ACLに紐付けるリソースのARN
  • WebACLArn:リソースに紐付けるウェブACLのARN

WAF Logの作成

WAFのログをCloudWatch Logsに出力する設定も行いました。

#WAF Log
  WAFLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: aws-waf-logs-alb-alc
      RetentionInDays: 1
      Tags:
        - Key: Name
          Value: aws-waf-logs-alb-alc

ロググループの作成。
ロググループは、ログの保存先のこと。

  • LogGroupName:ロググループの名前。必ず「aws-waf-logs-」で始まる必要がある
  • RetentionInDays:指定されたロググループにログイベントを保持する日数。今回は学習用なので1日
  WAFLogConfig:
    DependsOn:
      - WAFToCloudWatchLogsPolicy
    Type: AWS::WAFv2::LoggingConfiguration
    Properties:
      ResourceArn: !GetAtt WebACL.Arn
      LogDestinationConfigs:
        - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${WAFLogGroup}

ログの保存先とWeb ACLを紐付ける。

  • DependsOn:WAFToCloudWatchLogsPolicy(許可証)が作成された後に、WAFLogConfig(ログ設定)を作成するよう順番を指定。CloudFormationは通常、自動で作成順序を判断してくれるが、「権限(ポリシー)」と「それを利用するリソース」の間では、順番が前後してエラー(「ログを送る権限がありません」)になる恐れがあるため、安全策として
  • ResourceArn:ログの保存先に紐付けるWeb ACLのARN
  • LogDestinationConfigs:Web ACLに紐付けるログの保存先。ARNを指定
    !GetAtt関数でARNを取得すると末尾に「: *」がつく。「: *」がついていると、「ロググループ内のすべてのログストリーム」を指してしまい、「ロググループそのもの」であることを示せずに、設定エラーになることがある。そのため!Sub関数を使用して、LogGroupのARNを渡すようにしている。
  WAFToCloudWatchLogsPolicy:
    Type: AWS::Logs::ResourcePolicy
    Properties:
      PolicyName: WAFToCloudWatchLogsPolicy
      PolicyDocument: !Sub |
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "AllowWAFToLog",
              "Effect": "Allow",
              "Principal": {
                "Service": "delivery.logs.amazonaws.com"
              },
              "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Resource": "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${WAFLogGroup}:*"
            }
          ]
        }

WAFがCloudWatch Logsにログを書き込むための権限設定。
WAFというサービスが、CloudWatch Logsという別のサービスに、勝手にログを書き込むことはできない。そのため、「このサービス(delivery.logs.amazonaws.com)なら書き込んでもいい」という特別な許可証(ResourcePolicy)をあらかじめ発行しておく必要がある。

  • PolicyName:リソースポリシーの名前
  • PolicyDocument:ポリシーの詳細。JSON形式で記述する必要がある

組み込み関数

!GetAtt

  • 指定した特定の属性値(ARN, IP, DNS等)を返してくれる関数

!Sub

  • 文字列の一部を指定した変数の値に置き換えてくれる関数

終わりに

WAFの作成もコンソール画面の偉大さを思い知らされました。難しかった...でも、一度テンプレートにしてしまえば、次からはボタン一つでこの複雑な設定が再現できるので、それがCloudFormationの強みだと思いました。
作成している時は勢いで作っているところもありましたが、時間をおいて改めて見返してみると、確かになぁと思うところがありました。VisibilityConfigをなぜ2回書くのかなど。それから、公式ドキュメントの読み込みもテクニックが必要。
CloudFormationで構築した環境のアウトプットは、今回で以上です。
次回は、CloudFormationで構築した環境をTerraformで再現してみたものをアウトプットします。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?