CloudFormation에서 WAF 설정(CloudFront/APIGateway)

소개



AWS에서 서버리스 아키텍처를 채택하고 있으며 각 엔드포인트(CloudFront 및 API Gateway)에 IP 제한을 적용하려는 경우 AWS WAF을 사용하는 경우가 많을 것입니다.
이 기사에서는 CloudFormation에서 각 리소스와 WAF 리소스를 생성할 때 흠집이 많았기 때문에 요약해 보았습니다.

AWS::WAF 및 AWS::WAFRegional



우선 빠지기 쉬운 것이, 이 2개의 자원 타입이 있는 것.
구성할 수 있는 리소스나 매개변수에는 그다지 차이가 ​​없지만, 구분으로는 리전이 있는 서비스에 연결할지, 리전이 없는 서비스(CloudFront)에 연결할지, 로 어느 쪽을 선택할지 결정합니다.
  • AWS::WAFRegional→API Gateway, ALB, etc...
  • AWS::WAF→CloudFront

  • 라고 생각해 두면 OK라고 생각합니다. (이것을 반대로하면 권한 오류로 실패합니다.)

    AWS WAF 및 AWS WAF Classic



    이 두 가지 차이도 첫견인은 주의가 필요합니다.
    AWS WAF는 2019년 11월로 업데이트되었으며 콘솔에서 서비스를 사용하는 경우 처음에는 새 버전의 서비스가 표시됩니다.
    이전 버전의 AWS WAF를 사용하는 경우 왼쪽 메뉴에서 몰래 Switch to AWS WAF Classic를 클릭하여 전환합니다.


    여기서 빠르고 싶은 것은 CloudFormation 리소스 유형인 AWS::WAFAWS::WAFRegional가 모두 이전 버전(AWS WAF Classic) 리소스를 생성한다는 것입니다.
    AWS Support를 확인한 것은 아니므로 확실하지는 않지만 현재(2019년 12월부터) CloudFormation에서 새 버전의 AWS WAF 리소스를 생성할 수 없습니다. (향후 대응될 것)

    template 파일



    이번에는 CloudFormation에서 실제로 CloudFront와 API Gateway에 각각 연결된 AWS WAF(Classic)를 생성했습니다.
    그 때, template 의 기술에 관해서도 주의해야 할 점이 있었으므로, 코멘트를 추기한 template.yaml 를 실어 둡니다.

    공통



    IP 제한을 할 때, WebACL + Rule + IPSet 의 자원을 세트로 사용하는 것은, AWS::WAFAWS::WAFRegional 도 마찬가지.

    AWS::CloudFront + AWS::WAF 패턴


    AWS::WAF 의 경우 CloudFront 의 리소스 측에서 연결합니다.

    template.yaml(CloudFront)
    Parameters:
      AppName:
        Type: String
      AllowedIP:
        Type: String
    
    Resources:
      MyDistribution:
        Type: AWS::CloudFront::Distribution
        Properties:
          # 〜その他のプロパティは省略〜
          DistributionConfig:
            WebACLId: !Ref MyWebACL #紐付けはここで行う
    
      # AWS::WAF の場合、リソースの紐付けに WebACLAssociation は使用しない
    
      MyWebACL:
        Type: AWS::WAF::WebACL
        Properties:
          Name: !Sub ${AppName}WebACL #ハイフンやアンスコは使用不可
          DefaultAction:
            Type: BLOCK
          MetricName: !Sub ${AppName}WebACL
          Rules:
            -
              Action:
                Type: ALLOW
              Priority: 1
              RuleId: !Ref MyRule
    
      MyRule:
        Type: AWS::WAF::Rule
        Properties:
          Name: !Sub ${AppName}AllowedRule #ハイフンやアンスコは使用不可
          MetricName: !Sub ${AppName}AllowedRule
          Predicates:
            -
              DataId: !Ref MyIPSet
              Negated: false
              Type: IPMatch
    
      MyIPSet:
        Type: AWS::WAF::IPSet
        Properties:
          Name: !Sub ${AppName}AllowedIPSet #ハイフンやアンスコは使用不可
          IPSetDescriptors:
            -
              Type: IPV4
              Value: !Sub ${AllowedIP}/32 #IPは末尾に「/32」を付与
    
    

    AWS::Serverless::Api + AWS::WAFRegional 패턴


    AWS::WAFRegional 의 경우, WebACLAssociation 라고 하는 자원을 이용해 연결을 실시합니다.
    공식 문서 에서는, 로드 밸런서와의 연계의 예 밖에 없습니다만, API Gateway 와 연계를 실시하는 경우는 다음과 같이 기술합니다.

    template.yaml(+APIGateway)
    Parameters:
      AppName:
        Type: String
      Stage:
        Type: String
      AllowedIP:
        Type: String
    
    Resources:
      MyApi:
        Type: AWS::Serverless::Api
        Properties:
          # 〜その他のプロパティは省略〜
          StageName: !Ref Stage
    
      MyWebACLAssociation: #紐付けはこのリソースで行う
        Type: "AWS::WAFRegional::WebACLAssociation"
        Properties:
          ResourceArn: !Sub arn:aws:apigateway:${AWS::Region}::/restapis/${MyApi}/stages/${Stage}
          # ResourceArn は !Ref MyApi ではないので注意
          WebACLId: !Ref MyWebACL
    
      MyWebACL:
        Type: AWS::WAFRegional::WebACL
        Properties:
          Name: !Sub ${AppName}APIWebACL #ハイフンやアンスコは使用不可
          DefaultAction:
            Type: BLOCK
          MetricName: !Sub ${AppName}APIWebACL
          Rules:
            -
              Action:
                Type: ALLOW
              Priority: 1
              RuleId: !Ref MyRule
    
      MyRule:
        Type: AWS::WAFRegional::Rule
        Properties:
          Name: !Sub ${AppName}APIAllowedRule #ハイフンやアンスコは使用不可
          MetricName: !Sub ${AppName}APIAllowedRule
          Predicates:
            -
              DataId: !Ref MyIPSet
              Negated: false
              Type: IPMatch
    
      MyIPSet:
        Type: AWS::WAFRegional::IPSet
        Properties:
          Name: !Sub ${AppName}APIAllowedIPSet #ハイフンやアンスコは使用不可
          IPSetDescriptors:
            -
              Type: IPV4
              Value: !Sub ${AllowedIP}/32 #IPは末尾に「/32」を付与
    

    마지막으로



    이번에는 서버리스 아키텍처에서 CloudFormation을 사용한 WAF 설정의 빠짐없는 포인트를 설명했습니다.
    AWS의 공식 문서는 정말 알기 어려우므로, 같은 일로 빠져 있는 사람은 참고로 해 주시면 감사하겠습니다.

    좋은 웹페이지 즐겨찾기