diff --git a/assets/libraries/cloudformation.rego b/assets/libraries/cloudformation.rego index 506afa4ce77..cdf08ec82fe 100644 --- a/assets/libraries/cloudformation.rego +++ b/assets/libraries/cloudformation.rego @@ -140,6 +140,49 @@ get_name(targetName) = name { name := targetName } +# Check if WAF ResourceArn uses a Ref object to point to the target load balancer +waf_resource_arn_matches_ref(resource_arn, target_alb) { + resource_arn.Ref == target_alb +} + +# Check if WAF ResourceArn is a direct string equal to the target load balancer logical ID +waf_resource_arn_matches_name(resource_arn, target_alb) { + is_string(resource_arn) + resource_arn == target_alb +} + +# Check if WAF ResourceArn uses Fn::GetAtt array syntax for the target load balancer +waf_resource_arn_matches_getatt(resource_arn, target_alb) { + resource_arn["Fn::GetAtt"][0] == target_alb +} + +# Check if WAF ResourceArn is a YAML GetAtt-resolved string (LogicalId.Attribute) +waf_resource_arn_matches_getatt_string(resource_arn, target_alb) { + is_string(resource_arn) + startswith(resource_arn, sprintf("%s.", [target_alb])) +} + +# Check if a WAF association resource targets the given load balancer with supported syntax +waf_association_targets_load_balancer(resource, target_alb) { + resource_arn := resource.Properties.ResourceArn + waf_resource_arn_matches_ref(resource_arn, target_alb) +} + +waf_association_targets_load_balancer(resource, target_alb) { + resource_arn := resource.Properties.ResourceArn + waf_resource_arn_matches_name(resource_arn, target_alb) +} + +waf_association_targets_load_balancer(resource, target_alb) { + resource_arn := resource.Properties.ResourceArn + waf_resource_arn_matches_getatt(resource_arn, target_alb) +} + +waf_association_targets_load_balancer(resource, target_alb) { + resource_arn := resource.Properties.ResourceArn + waf_resource_arn_matches_getatt_string(resource_arn, target_alb) +} + get_resource_accessibility(nameRef, type, key) = info { document := input.document policy := document[_].Resources[_] diff --git a/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/query.rego b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/query.rego index 191d00735f3..59caa6b4198 100644 --- a/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/query.rego +++ b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/query.rego @@ -26,14 +26,10 @@ internal_alb(resource) { scheme == "internal" } -associated_waf(target_alb) { - resource := input.document[_].Resources[_] - resource.Type == "AWS::WAFRegional::WebACLAssociation" - resource.Properties.ResourceArn.Ref == target_alb -} +waf_association_types := {"AWS::WAFRegional::WebACLAssociation", "AWS::WAFv2::WebACLAssociation"} associated_waf(target_alb) { resource := input.document[_].Resources[_] - resource.Type == "AWS::WAFRegional::WebACLAssociation" - resource.Properties.ResourceArn == target_alb + waf_association_types[resource.Type] + cf_lib.waf_association_targets_load_balancer(resource, target_alb) } diff --git a/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative3.yaml b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative3.yaml new file mode 100644 index 00000000000..66e1cdd077a --- /dev/null +++ b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative3.yaml @@ -0,0 +1,12 @@ +AWSTemplateFormatVersion: 2010-09-09 +Resources: + MyLoadBalancerV2: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + Name: myloadbalancerv2 + Scheme: internet-facing + MyWebACLAssociation: + Type: "AWS::WAFv2::WebACLAssociation" + Properties: + ResourceArn: !GetAtt MyLoadBalancerV2.LoadBalancerArn + WebACLArn: !Ref MyWebACL diff --git a/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative4.json b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative4.json new file mode 100644 index 00000000000..b4d49f782ed --- /dev/null +++ b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative4.json @@ -0,0 +1,23 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", + "Resources": { + "MyLoadBalancerV2": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "Name": "myloadbalancerv2", + "Scheme": "internet-facing" + } + }, + "MyWebACLAssociation": { + "Type": "AWS::WAFv2::WebACLAssociation", + "Properties": { + "ResourceArn": { + "Ref": "MyLoadBalancerV2" + }, + "WebACLArn": { + "Ref": "MyWebACL" + } + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative5.yaml b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative5.yaml new file mode 100644 index 00000000000..71e3667d20a --- /dev/null +++ b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative5.yaml @@ -0,0 +1,12 @@ +AWSTemplateFormatVersion: 2010-09-09 +Resources: + MyLoadBalancerV2b: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + Name: myloadbalancerv2b + Scheme: internet-facing + MyWebACLAssociation: + Type: "AWS::WAFv2::WebACLAssociation" + Properties: + ResourceArn: !Ref MyLoadBalancerV2b + WebACLArn: !Ref MyWebACL diff --git a/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative6.json b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative6.json new file mode 100644 index 00000000000..96fb6da7693 --- /dev/null +++ b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative6.json @@ -0,0 +1,23 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z", + "Resources": { + "MyLoadBalancerV2c": { + "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", + "Properties": { + "Name": "myloadbalancerv2c", + "Scheme": "internet-facing" + } + }, + "MyWebACLAssociation": { + "Type": "AWS::WAFv2::WebACLAssociation", + "Properties": { + "ResourceArn": { + "Fn::GetAtt": ["MyLoadBalancerV2c", "LoadBalancerArn"] + }, + "WebACLArn": { + "Ref": "MyWebACL" + } + } + } + } +} diff --git a/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative7.yaml b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative7.yaml new file mode 100644 index 00000000000..e66990d4e20 --- /dev/null +++ b/assets/queries/cloudFormation/aws/alb_is_not_integrated_with_waf/test/negative7.yaml @@ -0,0 +1,12 @@ +AWSTemplateFormatVersion: 2010-09-09 +Resources: + MyLoadBalancerV2d: + Type: AWS::ElasticLoadBalancingV2::LoadBalancer + Properties: + Name: myloadbalancerv2d + Scheme: internet-facing + MyWebACLAssociation: + Type: "AWS::WAFv2::WebACLAssociation" + Properties: + ResourceArn: MyLoadBalancerV2d.LoadBalancerArn + WebACLArn: !Ref MyWebACL