{"id":4651,"date":"2025-10-06T18:52:54","date_gmt":"2025-10-06T18:52:54","guid":{"rendered":"https:\/\/geekmungus.co.uk\/?p=4651"},"modified":"2025-10-06T18:52:54","modified_gmt":"2025-10-06T18:52:54","slug":"aws-web-application-firewall-waf-reconciling-aws-firewall-manager-applied-webacl-to-cloudfront-distribution","status":"publish","type":"post","link":"https:\/\/geekmungus.co.uk\/?p=4651","title":{"rendered":"AWS Web Application Firewall (WAF) &#8211; Reconciling AWS Firewall Manager Applied WebACL to CloudFront Distribution"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">We use IaC (Infrastructure as Code) for the deployment and management of all cloud (AWS) workloads to ensure we can manage and update infrastructure and applications that are deployed in the cloud rapidily and on an ongoing basis, while maintaining flexibility, security and availability. However issues may occur when changes are made using automated processes, such as the AWS Firewall Manager to &#8220;retrofit&#8221; or &#8220;enforce&#8221; particular configurations on infrastructure\/applications that are managed via IaC through Terraform (for example). The issue that can occour is that the Terraform dictates &#8220;what we want the world to look like&#8221;, if something changes the configration (within scope of the Terraform template) out-of-band of this, it is considered &#8220;drift&#8221;, and needs to be either expicitly excluded (ignored), imported into Terraform, or instead acknowledged.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconsilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-Issue\">Issue<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The example we are considering is a workload which uses the AWS CloudFront distribution to publish a web application. An AWS Firewall Manager Policy has been centrally managed and deployed to all CloudFront Distributions within the AWS Organisation. The problem is with this is that this has changed a resource that is within scope of an existing IaC (Terraform) template&#8217;s configuration. The implication of this is that because this configuration is missing from the template it is considered a &#8220;drift&#8221; from the desired configuration as denoted in the Terraform template.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We don&#8217;t want to import the FMS-managed Web ACL into the member account\u2019s Terraform. We want to let Firewall Manager (FMS) keep ownership, but in the member account (workload account), just \u201cadopt\u201d the association on the CloudFront resource so Terraform stops trying to remove it; because it thinks it is drift. An example of this if\/when it occurs can be found below. As you can see Terraform wants to remove this because its not declared in the template.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"478\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-1024x478.png\" alt=\"\" class=\"wp-image-4652\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-1024x478.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-300x140.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-768x358.png 768w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image.png 1444w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconcilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-Resolution(Recommended)\">Resolution (Recommended)<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">To resolve the issue we are going to &#8220;Adopt&#8221; the assocation into our IaC (Terraform).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconcilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-Step1-DetermineName\">Step 1 &#8211; Determine Name<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">First determine the &#8220;Name&#8221; of the WebACL that is being applied to your CloudFront Distribution. You can do this by running this command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>aws wafv2 list-web-acls --scope CLOUDFRONT --region us-east-1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We then get the output like this, and it is the &#8220;Name&#8221; attribute we are interested in.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"212\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-1-1024x212.png\" alt=\"\" class=\"wp-image-4653\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-1-1024x212.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-1-300x62.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-1-768x159.png 768w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-1.png 1173w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In our example it is:&nbsp;<strong>FMManagedWebACLV2-fms-cf-waf-policy-1758643214119<\/strong>, names start with FMManagedWebACLV2-&lt;policy-name&gt;-&lt;timestamp&gt;; because it is CloudFront the scope is&nbsp;<strong>global, i.e. us-east-1<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconcilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-Step2-AdopttheWebACLtoCloudFrontDistribution\">Step 2 &#8211; Adopt the WebACL to CloudFront Distribution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In the workload account\u2019s Terraform, read that ACL via a data source and wire it into your aws_cloudfront_distribution.web_acl_id (which expects the ARN, not the ID).&nbsp;The &#8220;data&#8221; will require you to enter the policy name (not ARN), i.e. FMManagedWebACLV2-&lt;policy-name&gt;-&lt;timestamp&gt;, but then it uses this to discover the ARN, which&nbsp;in this used within the CloudFront.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We obtained this value in the previous step, so we&#8217;ll then add to the relevant Terraform template containing our AWS CloudFront definition the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>...\n\n\/\/ AWS CloudFront Distribution - AWS Firewall Manager Deployed WAF (WebACL) ---------------------------------------------------------------------------------\n# The CloudFront distribution is subject to AWS Firewall Manager policy (or policies), therefore these need to be discovered and \"adopted\" to the configuration to avoid\n# being seen as \"drift\".\n\ndata \"aws_wafv2_web_acl\" \"fms_acl\" {\n  provider = aws.useast1\n  name  = \"FMManagedWebACLV2-fms-cf-waf-policy-1758643214119\"\n  scope = \"CLOUDFRONT\"\n}\n\n\/\/ AWS CloudFront Distribution ------------------------------------------------------------------------------------------------------------------------------\n\n# Create an AWS CloudFront distribution\nresource \"aws_cloudfront_distribution\" \"simple-cf\" {\n  ... your existing distribution config ...\n\n  # Adopt the association so Terraform doesn't try to remove it\n  web_acl_id = data.aws_wafv2_web_acl.fms_acl.arn\n\n  # Optional: if FMS might rotate the ACL (new ARN), avoid drift\n  #lifecycle {\n  #  ignore_changes = &#91;web_acl_id]\n  #}\n\n  ... your existing distribution config ...\n}\n\n...<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconcilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-RegionsandtheirImpact\">Regions and their Impact<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">You&#8217;ll notice that on the data resource above&nbsp;<strong>aws_wafv2_web_acl<\/strong>, that we&#8217;ve added a&nbsp;<strong>provider = aws.useast1<\/strong>, this is because without this the Terraform will default to whatever your current region is. If it is not us-east-1 then it will be attempting to find a resource in the wrong region, therefore the following is required in your&nbsp;<strong>providers.tf<\/strong>&nbsp;file (alongside your existing &#8220;provider&#8221; definition &#8211; if not us-east-1):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>...\nprovider \"aws\" {\n  alias   = \"useast1\"\n  region  = \"us-east-1\"\n  profile = \"ids-imt-sandbox\"\n}\n...<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you fail to deal with this you&#8217;ll see an error like:\u00a0<strong>Error: list WAFv2 WebACLs: operation error WAFV2: ListWebACLs, https response error StatusCode: 400, RequestID: 9c3cfaeb-dd9e-455f-a2a0-c1469cb7d689, WAFInvalidParameterException: Error reason: The scope is not valid., field: SCOPE_VALUE, parameter: CLOUDFRONT<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"135\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-2-1024x135.png\" alt=\"\" class=\"wp-image-4654\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-2-1024x135.png 1024w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-2-300x40.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-2-768x101.png 768w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-2-1536x203.png 1536w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-2.png 1630w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconcilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-Step3-VerifyWebACLisAdopted\">Step 3 &#8211; Verify WebACL is Adopted<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Verifying if the WebACL is as simple as running a &#8220;terraform plan&#8221;, assuming you have no outstanding changes, you should see the &#8220;No changes. Your infrastructure matches the configuration&#8221; output, which shows that the WebACL has been successfully adopted.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"977\" height=\"196\" src=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-3.png\" alt=\"\" class=\"wp-image-4655\" srcset=\"https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-3.png 977w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-3-300x60.png 300w, https:\/\/geekmungus.co.uk\/wp-content\/uploads\/2025\/10\/image-3-768x154.png 768w\" sizes=\"auto, (max-width: 977px) 100vw, 977px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconcilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-Resolution(AnotherWay)\">Resolution (Another Way)<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If you prefer not to reference the ACL at all:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>resource \"aws_cloudfront_distribution\" \"this\" {\n  # ... your existing distribution config ...\n\n  lifecycle {\n    # Leave association entirely to FMS\n    ignore_changes = &#91;web_acl_id]\n  }\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This stops Terraform from trying to disassociate the FMS-applied ACL during plan\/apply (useful when FMS might replace ACLs). There\u2019s even an open provider issue discussing drift with FMS-managed associations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"AWSWebApplicationFirewall(WAF)ReconcilingAWSFirewallManagerAppliedWebACLtoCloudFrontDistribution-AdditionalInformation\">Additional Information<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/stackoverflow.com\/questions\/73731278\/getting-error-as-the-scope-is-not-valid-field-scope-value-parameter-cloudf\">https:\/\/stackoverflow.com\/questions\/73731278\/getting-error-as-the-scope-is-not-valid-field-scope-value-parameter-cloudf<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>We use IaC (Infrastructure as Code) for the deployment and management of all cloud (AWS) workloads to ensure we can manage and update infrastructure and applications that are deployed in the cloud rapidily and on an ongoing basis, while maintaining flexibility, security and availability. However issues may occur when changes are made using automated processes, &#8230; <a title=\"AWS Web Application Firewall (WAF) &#8211; Reconciling AWS Firewall Manager Applied WebACL to CloudFront Distribution\" class=\"read-more\" href=\"https:\/\/geekmungus.co.uk\/?p=4651\" aria-label=\"Read more about AWS Web Application Firewall (WAF) &#8211; Reconciling AWS Firewall Manager Applied WebACL to CloudFront Distribution\">Read more<\/a><\/p>\n","protected":false},"author":4,"featured_media":3925,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[28,45],"tags":[],"class_list":["post-4651","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aws","category-terraform"],"_links":{"self":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4651"}],"version-history":[{"count":1,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4651\/revisions"}],"predecessor-version":[{"id":4656,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4651\/revisions\/4656"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/media\/3925"}],"wp:attachment":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4651"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4651"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}