Repository: Enterprise-CMCS/macpro-mdct-seds
Pull request #15080: CMDCT-4387 - updates to fix/standardize waf configuration
Author: login: peoplespete
Created: 2025-03-06T20:35:40Z | Merged: 2025-03-07T16:51:56Z

### Description
WAF was not attached in one spot and needed to remove firehose/s3 stuff

### Related ticket(s)
CMDCT-4387

---
### How to test
Use the app for a few minutes and then look at the cloudformation stack called seds-cmdct-4387 and poke around in the Waf logs. Make sure all 3 have entries.

### Notes
NA

---
### Pre-review checklist
<!-- Complete the following steps before opening for review -->
- [x] I have added [thorough](https://shorturl.at/aejkF) tests, if necessary
- [x] I have updated relevant documentation, if necessary
- [x] I have performed a self-review of my code
- [x] I have manually tested this PR in the deployed cloud environment

---
### Pre-merge checklist
<!-- Complete the following steps before merging -->

#### Review
- [x] Design: This work has been reviewed and approved by design, if necessary
- [x] Product: This work has been reviewed and approved by product owner, if necessary

#### Security
_If either of the following are true, notify the team's ISSO (Information System Security Officer)._

- [ ] These changes are significant enough to require an update to the SIA.
- [ ] These changes are significant enough to require a penetration test.
---

<!-- If deploying to val or prod, click 'Preview' and select template -->
_convert to a different template: [test → val](?expand=1&template=test-to-val-deployment.md)_ | _[val → prod](?expand=1&template=val-to-prod-deployment.md)_



Diff:
diff --git a/.github/waf-controller.sh b/.github/waf-controller.sh
index 0c3931a21..9c2d8aea6 100755
--- a/.github/waf-controller.sh
+++ b/.github/waf-controller.sh
@@ -1,134 +1,134 @@
-#!/usr/bin/env bash
-
-CIRCUIT_BREAKER=10
-AWS_RETRY_ERROR=254
-AWS_THROTTLING_EXCEPTION=252
-#0, 1, 2 are the levels of debug, with 0 being off
-DEBUG=1
-
-set -o pipefail -o nounset -u
-
-case ${1-} in
-  append)
-    OP=append
-    ;;
-  set)
-    OP=set
-    ;;
-  *)
-    echo "Error:  unkown operation"
-    echo "Usage: ${0} [append|set] [ip_set name] [ip_set id] [list of CIDR blocks]" && exit 1
-    ;;
-esac
-
-shift
-NAME="${1-}"
-ID="${2-}"
-shift; shift
-RUNNER_CIDRS="${@-}"
-
-[[ $DEBUG -ge 1 ]] && echo "Inputs:  NAME \"${NAME}\", ID \"${ID}\", RUNNER_CIDRS \"${RUNNER_CIDRS}\""
-
-[[ -z "${NAME}" ]] || [[ -z "${ID}" ]] || [[ -z "${RUNNER_CIDRS}" ]] && echo "Error:  one or more inputs are missing" && exit 1
-
-#Exponential backoff with jitter
-jitter() {
-  #.5 seconds
-  SHORTEST=50
-  #10 seconds
-  LONGEST=1000
-  DIV=100
-  EXP=$(perl -e "use bigint; print $SHORTEST**$1")
-  MIN=$(($EXP>$LONGEST ? $LONGEST : $EXP))
-  RND=$(shuf -i$SHORTEST-$MIN -n1)
-  perl -e "print $RND/$DIV"
-}
-
-#Attempt to avoid resource contention from the start
-sleep $(jitter $(shuf -i1-10 -n1))
-
-for ((i=1; i <= $CIRCUIT_BREAKER; i++)); do
-  #This loop is ONLY for retrying if the retries exceeded exception is thrown
-  for ((j=1; j <= $CIRCUIT_BREAKER; j++)); do
-    #Read WAF configuration from AWS
-    WAF_CONFIG=$(aws wafv2 get-ip-set --scope CLOUDFRONT --id ${ID} --name ${NAME} 2>&1)
-    CMD_CD=$?
-    [[ $DEBUG -ge 1 ]] && echo "AWS CLI Read Response Code:  ${CMD_CD}"
-    [[ $DEBUG -ge 2 ]] && echo "AWS CLI Read Response:  ${WAF_CONFIG}"
-
-    #If the retries exceeded error code is returned, try again, otherwise exit the loop
-    [[ $CMD_CD -eq $AWS_RETRY_ERROR ]] || break
-
-    SLEEP_FOR=$(jitter ${j})
-    echo "CLI retries exceed.  Waiting for ${SLEEP_FOR} seconds to execute read again...(${j})"
-    sleep ${SLEEP_FOR}
-  done
-
-  #Unable to get the lock tocken and IP set so there isn't any point in attempting the write op
-  [[ $j -ge $CIRCUIT_BREAKER ]] && echo “Attempts to read WAF IPSet exceeded” && sleep $(jitter ${i}) && continue
-
-  #The loop was short circuited with an error code other than 0, so something is wrong
-  [[ $CMD_CD -eq 0 ]] || ( echo "An unexpected read error occurred:  ${CMD_CD}" && exit 2 )
-
-  echo "Read was successful."
-
-  if [ ${OP} == "append" ]; then
-    ##If this is used to whitelist individual ips or cidrs, using an additive approach is what is required
-    #Parse out IP set addresses to array
-    IP_ADDRESSES=($(jq -r '.IPSet.Addresses | .[]' <<< ${WAF_CONFIG}))
-
-    #If CIDR is already present in IP set, eject
-    grep -q $RUNNER_CIDRS <<< ${IP_ADDRESSES}
-    [[ $? -ne 0 ]] || ( echo "CIDR is present in IP Set." && exit 0 )
-
-    #Add runner CIDR to array
-    IP_ADDRESSES+=("$RUNNER_CIDRS")
-  else 
-    ##If this is used to hard set the IP set, just clobber it
-    IP_ADDRESSES=("$RUNNER_CIDRS")
-  fi
-
-  #Stringify IPs
-  STRINGIFIED=$(echo $(IFS=" " ; echo "${IP_ADDRESSES[*]}"))
-  [[ $DEBUG -ge 2 ]] && echo "Ip Addresses:  ${STRINGIFIED}"
-
-  #Parse out optimistic concurrency control token
-  OCC_TOKEN=$(jq -r '.LockToken' <<< ${WAF_CONFIG})
-  [[ $DEBUG -ge 2 ]] && echo "LockToken:  ${OCC_TOKEN}"
-
-  #This loop is ONLY for retrying if the retries exceeded exception is thrown
-  for ((k=1; k <= $CIRCUIT_BREAKER; k++)); do
-    #Write updated WAF configuration to AWS
-    OUTPUT=$(aws wafv2 update-ip-set --scope CLOUDFRONT --id ${ID} --name ${NAME} --lock-token ${OCC_TOKEN} --addresses ${STRINGIFIED} 2>&1)
-    CMD_CD=$?
-    [[ $DEBUG -ge 1 ]] && echo "AWS CLI Write Response Code:  ${CMD_CD}"
-    [[ $DEBUG -ge 2 ]] && echo "AWS CLI Write Response:  ${OUTPUT}"
-
-    #If the retries exceeded error code is returned, try again, otherwise exit the loop
-    [[ $CMD_CD -eq $AWS_RETRY_ERROR ]] || break
-    #If WAFOptimisticLockException error code is returned, exit the loop
-    [[ "$OUTPUT" =~ "WAFOptimisticLockException" ]] && break
-
-    SLEEP_FOR=$(jitter ${k})
-    echo "CLI retries exceed.  Waiting for ${SLEEP_FOR} seconds to execute write again...(${k})"
-    sleep ${SLEEP_FOR}
-  done
-
-  [[ $CMD_CD -ne 0 ]] || break
-  #Still not having success, so try again
-
-  echo "Exit Code:  ${CMD_CD}"
-
-  SLEEP_FOR=$(jitter ${i})
-  echo "Waiting for ${SLEEP_FOR} seconds to execute main loop again...(${i})"
-  sleep ${SLEEP_FOR}
-done
-
-[[ $DEBUG -ge 1 ]] && echo "Attempts to update ip set:  $i"
-
-[[ $i -gt $CIRCUIT_BREAKER ]] && echo “Attempts to update WAF IPSet exceeded, exiting.” && exit 2
-
-echo "Applied the IP Set successfully."
-
-#Things should not have made it this far without being able to successfully write the IP Set
-exit $CMD_CD
+# #!/usr/bin/env bash
+
+# CIRCUIT_BREAKER=10
+# AWS_RETRY_ERROR=254
+# AWS_THROTTLING_EXCEPTION=252
+# #0, 1, 2 are the levels of debug, with 0 being off
+# DEBUG=1
+
+# set -o pipefail -o nounset -u
+
+# case ${1-} in
+#   append)
+#     OP=append
+#     ;;
+#   set)
+#     OP=set
+#     ;;
+#   *)
+#     echo "Error:  unkown operation"
+#     echo "Usage: ${0} [append|set] [ip_set name] [ip_set id] [list of CIDR blocks]" && exit 1
+#     ;;
+# esac
+
+# shift
+# NAME="${1-}"
+# ID="${2-}"
+# shift; shift
+# RUNNER_CIDRS="${@-}"
+
+# [[ $DEBUG -ge 1 ]] && echo "Inputs:  NAME \"${NAME}\", ID \"${ID}\", RUNNER_CIDRS \"${RUNNER_CIDRS}\""
+
+# [[ -z "${NAME}" ]] || [[ -z "${ID}" ]] || [[ -z "${RUNNER_CIDRS}" ]] && echo "Error:  one or more inputs are missing" && exit 1
+
+# #Exponential backoff with jitter
+# jitter() {
+#   #.5 seconds
+#   SHORTEST=50
+#   #10 seconds
+#   LONGEST=1000
+#   DIV=100
+#   EXP=$(perl -e "use bigint; print $SHORTEST**$1")
+#   MIN=$(($EXP>$LONGEST ? $LONGEST : $EXP))
+#   RND=$(shuf -i$SHORTEST-$MIN -n1)
+#   perl -e "print $RND/$DIV"
+# }
+
+# #Attempt to avoid resource contention from the start
+# sleep $(jitter $(shuf -i1-10 -n1))
+
+# for ((i=1; i <= $CIRCUIT_BREAKER; i++)); do
+#   #This loop is ONLY for retrying if the retries exceeded exception is thrown
+#   for ((j=1; j <= $CIRCUIT_BREAKER; j++)); do
+#     #Read WAF configuration from AWS
+#     WAF_CONFIG=$(aws wafv2 get-ip-set --scope CLOUDFRONT --id ${ID} --name ${NAME} 2>&1)
+#     CMD_CD=$?
+#     [[ $DEBUG -ge 1 ]] && echo "AWS CLI Read Response Code:  ${CMD_CD}"
+#     [[ $DEBUG -ge 2 ]] && echo "AWS CLI Read Response:  ${WAF_CONFIG}"
+
+#     #If the retries exceeded error code is returned, try again, otherwise exit the loop
+#     [[ $CMD_CD -eq $AWS_RETRY_ERROR ]] || break
+
+#     SLEEP_FOR=$(jitter ${j})
+#     echo "CLI retries exceed.  Waiting for ${SLEEP_FOR} seconds to execute read again...(${j})"
+#     sleep ${SLEEP_FOR}
+#   done
+
+#   #Unable to get the lock tocken and IP set so there isn't any point in attempting the write op
+#   [[ $j -ge $CIRCUIT_BREAKER ]] && echo “Attempts to read WAF IPSet exceeded” && sleep $(jitter ${i}) && continue
+
+#   #The loop was short circuited with an error code other than 0, so something is wrong
+#   [[ $CMD_CD -eq 0 ]] || ( echo "An unexpected read error occurred:  ${CMD_CD}" && exit 2 )
+
+#   echo "Read was successful."
+
+#   if [ ${OP} == "append" ]; then
+#     ##If this is used to whitelist individual ips or cidrs, using an additive approach is what is required
+#     #Parse out IP set addresses to array
+#     IP_ADDRESSES=($(jq -r '.IPSet.Addresses | .[]' <<< ${WAF_CONFIG}))
+
+#     #If CIDR is already present in IP set, eject
+#     grep -q $RUNNER_CIDRS <<< ${IP_ADDRESSES}
+#     [[ $? -ne 0 ]] || ( echo "CIDR is present in IP Set." && exit 0 )
+
+#     #Add runner CIDR to array
+#     IP_ADDRESSES+=("$RUNNER_CIDRS")
+#   else
+#     ##If this is used to hard set the IP set, just clobber it
+#     IP_ADDRESSES=("$RUNNER_CIDRS")
+#   fi
+
+#   #Stringify IPs
+#   STRINGIFIED=$(echo $(IFS=" " ; echo "${IP_ADDRESSES[*]}"))
+#   [[ $DEBUG -ge 2 ]] && echo "Ip Addresses:  ${STRINGIFIED}"
+
+#   #Parse out optimistic concurrency control token
+#   OCC_TOKEN=$(jq -r '.LockToken' <<< ${WAF_CONFIG})
+#   [[ $DEBUG -ge 2 ]] && echo "LockToken:  ${OCC_TOKEN}"
+
+#   #This loop is ONLY for retrying if the retries exceeded exception is thrown
+#   for ((k=1; k <= $CIRCUIT_BREAKER; k++)); do
+#     #Write updated WAF configuration to AWS
+#     OUTPUT=$(aws wafv2 update-ip-set --scope CLOUDFRONT --id ${ID} --name ${NAME} --lock-token ${OCC_TOKEN} --addresses ${STRINGIFIED} 2>&1)
+#     CMD_CD=$?
+#     [[ $DEBUG -ge 1 ]] && echo "AWS CLI Write Response Code:  ${CMD_CD}"
+#     [[ $DEBUG -ge 2 ]] && echo "AWS CLI Write Response:  ${OUTPUT}"
+
+#     #If the retries exceeded error code is returned, try again, otherwise exit the loop
+#     [[ $CMD_CD -eq $AWS_RETRY_ERROR ]] || break
+#     #If WAFOptimisticLockException error code is returned, exit the loop
+#     [[ "$OUTPUT" =~ "WAFOptimisticLockException" ]] && break
+
+#     SLEEP_FOR=$(jitter ${k})
+#     echo "CLI retries exceed.  Waiting for ${SLEEP_FOR} seconds to execute write again...(${k})"
+#     sleep ${SLEEP_FOR}
+#   done
+
+#   [[ $CMD_CD -ne 0 ]] || break
+#   #Still not having success, so try again
+
+#   echo "Exit Code:  ${CMD_CD}"
+
+#   SLEEP_FOR=$(jitter ${i})
+#   echo "Waiting for ${SLEEP_FOR} seconds to execute main loop again...(${i})"
+#   sleep ${SLEEP_FOR}
+# done
+
+# [[ $DEBUG -ge 1 ]] && echo "Attempts to update ip set:  $i"
+
+# [[ $i -gt $CIRCUIT_BREAKER ]] && echo “Attempts to update WAF IPSet exceeded, exiting.” && exit 2
+
+# echo "Applied the IP Set successfully."
+
+# #Things should not have made it this far without being able to successfully write the IP Set
+# exit $CMD_CD
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 893378873..9d3480fe5 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -94,99 +94,99 @@ jobs:
       BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION: ${{ steps.set_names.outputs.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION }}
       BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME: ${{ steps.set_names.outputs.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME }}
 
-  register-runner:
-    name: Register GitHub Runner
-    if: ${{ github.ref_name != 'master' && github.ref_name != 'val' && github.ref_name != 'production' }}
-    runs-on: ubuntu-latest
-    needs: deploy
-    env:
-      SLS_DEPRECATION_DISABLE: "*" # Turn off deprecation warnings in the pipeline
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v4
-
-      - name: set branch_name
-        run: |
-          BRANCH_NAME=$(./.github/setBranchName.sh ${{ github.ref_name }})
-          echo "branch_name=${BRANCH_NAME}" >> $GITHUB_ENV
-
-      - name: set branch specific variable names
-        id: set_names
-        run: ./.github/build_vars.sh set_names
-
-      - name: set variable values
-        id: set_values
-        run: ./.github/build_vars.sh set_values
-        env:
-          AWS_DEFAULT_REGION: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION] || secrets.AWS_DEFAULT_REGION }}
-          AWS_OIDC_ROLE_TO_ASSUME: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME] || secrets.AWS_OIDC_ROLE_TO_ASSUME }}
-
-      - name: Configure AWS credentials for GitHub Actions
-        uses: aws-actions/configure-aws-credentials@v4
-        with:
-          role-to-assume: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME] || secrets.AWS_OIDC_ROLE_TO_ASSUME }}
-          aws-region: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION] || secrets.AWS_DEFAULT_REGION }}
-
-      - name: output account id
-        id: output_account_id
-        run: |
-          #!/bin/bash
-          AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
-          echo "Current Account ID: ${AWS_ACCOUNT_ID}"
-
-      - name: Get Github Actions CIDR Blocks
-        id: get-gha-cidrs
-        shell: bash
-        run: |
-          #! /bin/bash
-          GHA_RESP=$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' https://api.github.com/meta)
-          echo "Response for GHA runner CIDR blocks:  $GHA_RESP"
-          IPV4_CIDR_ARR=($(echo $GHA_RESP | jq -r '.actions | .[]' | grep -v ':'))
-          GHA_CIDRS_IPV4=$(echo $(IFS=" "; echo ${IPV4_CIDR_ARR[*]}))
-          echo "GHA_CIDRS_IPV4=$GHA_CIDRS_IPV4" >> $GITHUB_OUTPUT
-
-      - name: Generate IP Set Name
-        id: gen-ip-set-name
-        run: |
-          #!/bin/bash
-          STAGE_GH_IPSET_NAME=$branch_name-gh-ipset
-          echo "Github IP Set name:  $STAGE_GH_IPSET_NAME"
-          echo "STAGE_GH_IPSET_NAME=$STAGE_GH_IPSET_NAME" >> $GITHUB_OUTPUT
-
-      - name: Fetch AWS IP Set Metadata
-        id: fetch-ip-set-info
-        run: |
-          #!/bin/bash
-          # Fetch AWS IP set ARNs using AWS CLI and store them in a variable
-          AWS_IP_SET_INFO=$(aws wafv2 list-ip-sets --scope=CLOUDFRONT)
-          echo "Outputting AWS IP Set Info:  ${AWS_IP_SET_INFO}"
-          # Store the IP set ARNs in an output variable using GITHUB_OUTPUT
-          IPSET_NAME=${{ steps.gen-ip-set-name.outputs.STAGE_GH_IPSET_NAME }}
-          IPSET=$(jq '.IPSets | map(select(.Name == "'${IPSET_NAME}'")) | .[]' <<< ${AWS_IP_SET_INFO})
-          [ -z "$IPSET" ] && echo "IP Set with name ${IPSET_NAME} was not located.  Exiting..." && exit 1
-          echo "IP Set metadata:  ${IPSET}"
-          #Get Values from the IP SET
-          IPSET_ID=$(jq -r '.Id' <<< ${IPSET})
-          echo "IPSET_ARN=$IPSET_ARN" >> $GITHUB_OUTPUT
-          echo "IPSET_NAME=$IPSET_NAME" >> $GITHUB_OUTPUT
-          echo "IPSET_ID=$IPSET_ID" >> $GITHUB_OUTPUT
-
-      - name: Update IP Set
-        id: update-ip-set
-        run: ./.github/waf-controller.sh set ${{ steps.fetch-ip-set-info.outputs.IPSET_NAME }} ${{ steps.fetch-ip-set-info.outputs.IPSET_ID }} ${{ steps.get-gha-cidrs.outputs.GHA_CIDRS_IPV4 }}
-        env:
-          AWS_RETRY_MODE: adaptive
-          AWS_MAX_ATTEMPTS: 10
-
-    outputs:
-      ipset_name: ${{ steps.fetch-ip-set-info.outputs.IPSET_NAME }}
-      ipset_id: ${{ steps.fetch-ip-set-info.outputs.IPSET_ID }}
+  # register-runner:
+  #   name: Register GitHub Runner
+  #   if: ${{ github.ref_name != 'master' && github.ref_name != 'val' && github.ref_name != 'production' }}
+  #   runs-on: ubuntu-latest
+  #   needs: deploy
+  #   env:
+  #     SLS_DEPRECATION_DISABLE: "*" # Turn off deprecation warnings in the pipeline
+  #   steps:
+  #     - name: Checkout
+  #       uses: actions/checkout@v4
+
+  #     - name: set branch_name
+  #       run: |
+  #         BRANCH_NAME=$(./.github/setBranchName.sh ${{ github.ref_name }})
+  #         echo "branch_name=${BRANCH_NAME}" >> $GITHUB_ENV
+
+  #     - name: set branch specific variable names
+  #       id: set_names
+  #       run: ./.github/build_vars.sh set_names
+
+  #     - name: set variable values
+  #       id: set_values
+  #       run: ./.github/build_vars.sh set_values
+  #       env:
+  #         AWS_DEFAULT_REGION: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION] || secrets.AWS_DEFAULT_REGION }}
+  #         AWS_OIDC_ROLE_TO_ASSUME: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME] || secrets.AWS_OIDC_ROLE_TO_ASSUME }}
+
+  #     - name: Configure AWS credentials for GitHub Actions
+  #       uses: aws-actions/configure-aws-credentials@v4
+  #       with:
+  #         role-to-assume: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME] || secrets.AWS_OIDC_ROLE_TO_ASSUME }}
+  #         aws-region: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION] || secrets.AWS_DEFAULT_REGION }}
+
+  #     - name: output account id
+  #       id: output_account_id
+  #       run: |
+  #         #!/bin/bash
+  #         AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
+  #         echo "Current Account ID: ${AWS_ACCOUNT_ID}"
+
+  #     - name: Get Github Actions CIDR Blocks
+  #       id: get-gha-cidrs
+  #       shell: bash
+  #       run: |
+  #         #! /bin/bash
+  #         GHA_RESP=$(curl --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' https://api.github.com/meta)
+  #         echo "Response for GHA runner CIDR blocks:  $GHA_RESP"
+  #         IPV4_CIDR_ARR=($(echo $GHA_RESP | jq -r '.actions | .[]' | grep -v ':'))
+  #         GHA_CIDRS_IPV4=$(echo $(IFS=" "; echo ${IPV4_CIDR_ARR[*]}))
+  #         echo "GHA_CIDRS_IPV4=$GHA_CIDRS_IPV4" >> $GITHUB_OUTPUT
+
+  #     - name: Generate IP Set Name
+  #       id: gen-ip-set-name
+  #       run: |
+  #         #!/bin/bash
+  #         STAGE_GH_IPSET_NAME=$branch_name-gh-ipset
+  #         echo "Github IP Set name:  $STAGE_GH_IPSET_NAME"
+  #         echo "STAGE_GH_IPSET_NAME=$STAGE_GH_IPSET_NAME" >> $GITHUB_OUTPUT
+
+  #     - name: Fetch AWS IP Set Metadata
+  #       id: fetch-ip-set-info
+  #       run: |
+  #         #!/bin/bash
+  #         # Fetch AWS IP set ARNs using AWS CLI and store them in a variable
+  #         AWS_IP_SET_INFO=$(aws wafv2 list-ip-sets --scope=CLOUDFRONT)
+  #         echo "Outputting AWS IP Set Info:  ${AWS_IP_SET_INFO}"
+  #         # Store the IP set ARNs in an output variable using GITHUB_OUTPUT
+  #         IPSET_NAME=${{ steps.gen-ip-set-name.outputs.STAGE_GH_IPSET_NAME }}
+  #         IPSET=$(jq '.IPSets | map(select(.Name == "'${IPSET_NAME}'")) | .[]' <<< ${AWS_IP_SET_INFO})
+  #         [ -z "$IPSET" ] && echo "IP Set with name ${IPSET_NAME} was not located.  Exiting..." && exit 1
+  #         echo "IP Set metadata:  ${IPSET}"
+  #         #Get Values from the IP SET
+  #         IPSET_ID=$(jq -r '.Id' <<< ${IPSET})
+  #         echo "IPSET_ARN=$IPSET_ARN" >> $GITHUB_OUTPUT
+  #         echo "IPSET_NAME=$IPSET_NAME" >> $GITHUB_OUTPUT
+  #         echo "IPSET_ID=$IPSET_ID" >> $GITHUB_OUTPUT
+
+  #     - name: Update IP Set
+  #       id: update-ip-set
+  #       run: ./.github/waf-controller.sh set ${{ steps.fetch-ip-set-info.outputs.IPSET_NAME }} ${{ steps.fetch-ip-set-info.outputs.IPSET_ID }} ${{ steps.get-gha-cidrs.outputs.GHA_CIDRS_IPV4 }}
+  #       env:
+  #         AWS_RETRY_MODE: adaptive
+  #         AWS_MAX_ATTEMPTS: 10
+
+  #   outputs:
+  #     ipset_name: ${{ steps.fetch-ip-set-info.outputs.IPSET_NAME }}
+  #     ipset_id: ${{ steps.fetch-ip-set-info.outputs.IPSET_ID }}
 
   e2e-tests:
     name: E2E Integration Tests (Cypress)
     needs:
       - deploy
-      - register-runner
+      # - register-runner
     if: ${{ always() && !cancelled() && needs.deploy.result == 'success' && github.ref_name != 'production' }}
     runs-on: ubuntu-latest
     steps:
@@ -212,31 +212,31 @@ jobs:
             ${{github.workspace}}/tests/cypress/videos/
           retention-days: 14
 
-  cleanup:
-    name: Delist GHA Runner CIDR Blocks
-    if: ${{ github.ref_name != 'master' && github.ref_name != 'val' && github.ref_name != 'production' }}
-    runs-on: ubuntu-latest
-    needs:
-      - register-runner
-      - e2e-tests
-    env:
-      SLS_DEPRECATION_DISABLE: "*" # Turn off deprecation warnings in the pipeline
-    steps:
-      - uses: actions/checkout@v4
-      - name: Configure AWS credentials for GitHub Actions
-        uses: aws-actions/configure-aws-credentials@v4
-        with:
-          role-to-assume: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME] || secrets.AWS_OIDC_ROLE_TO_ASSUME }}
-          aws-region: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION] || secrets.AWS_DEFAULT_REGION }}
-      - name: output account id
-        id: output_account_id
-        run: |
-          #!/bin/bash
-          AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
-          echo "Current Account ID: ${AWS_ACCOUNT_ID}"
-      - name: cleanup-ip-list
-        id: reset-ip-set
-        run: ./.github/waf-controller.sh set ${{ needs.register-runner.outputs.ipset_name }} ${{ needs.register-runner.outputs.ipset_id }} '[]'
-        env:
-          AWS_RETRY_MODE: adaptive
-          AWS_MAX_ATTEMPTS: 10
+  # cleanup:
+  #   name: Delist GHA Runner CIDR Blocks
+  #   if: ${{ github.ref_name != 'master' && github.ref_name != 'val' && github.ref_name != 'production' }}
+  #   runs-on: ubuntu-latest
+  #   needs:
+  #     - register-runner
+  #     - e2e-tests
+  #   env:
+  #     SLS_DEPRECATION_DISABLE: "*" # Turn off deprecation warnings in the pipeline
+  #   steps:
+  #     - uses: actions/checkout@v4
+  #     - name: Configure AWS credentials for GitHub Actions
+  #       uses: aws-actions/configure-aws-credentials@v4
+  #       with:
+  #         role-to-assume: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_OIDC_ROLE_TO_ASSUME] || secrets.AWS_OIDC_ROLE_TO_ASSUME }}
+  #         aws-region: ${{ secrets[env.BRANCH_SPECIFIC_VARNAME_AWS_DEFAULT_REGION] || secrets.AWS_DEFAULT_REGION }}
+  #     - name: output account id
+  #       id: output_account_id
+  #       run: |
+  #         #!/bin/bash
+  #         AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
+  #         echo "Current Account ID: ${AWS_ACCOUNT_ID}"
+  #     - name: cleanup-ip-list
+  #       id: reset-ip-set
+  #       # run: ./.github/waf-controller.sh set ${{ needs.register-runner.outputs.ipset_name }} ${{ needs.register-runner.outputs.ipset_id }} '[]'
+  #       env:
+  #         AWS_RETRY_MODE: adaptive
+  #         AWS_MAX_ATTEMPTS: 10
diff --git a/deployment/constructs/cloudwatch-to-s3.ts b/deployment/constructs/cloudwatch-to-s3.ts
deleted file mode 100644
index 43bfe4d85..000000000
--- a/deployment/constructs/cloudwatch-to-s3.ts
+++ /dev/null
@@ -1,109 +0,0 @@
-import { Construct } from "constructs";
-import {
-  aws_iam as iam,
-  aws_kinesisfirehose as kinesisfirehose,
-  aws_logs as logs,
-  aws_s3 as s3,
-  Aws,
-  Fn,
-  RemovalPolicy,
-} from "aws-cdk-lib";
-
-interface CloudWatchToS3Props {
-  readonly logGroup: logs.LogGroup;
-  readonly bucket: s3.Bucket;
-  readonly filePrefix?: string;
-  readonly filterPattern?: string;
-  iamPermissionsBoundary: iam.IManagedPolicy;
-  iamPath: string;
-}
-
-export class CloudWatchToS3 extends Construct {
-  public readonly deliveryStream: kinesisfirehose.CfnDeliveryStream;
-
-  constructor(scope: Construct, id: string, props: CloudWatchToS3Props) {
-    super(scope, id);
-
-    const { logGroup, bucket, filePrefix = "", filterPattern = "" } = props;
-
-    // Create a Firehose role
-    const firehoseRole = new iam.Role(this, "FirehoseRole", {
-      assumedBy: new iam.ServicePrincipal("firehose.amazonaws.com"),
-      permissionsBoundary: props.iamPermissionsBoundary,
-      path: props.iamPath,
-    });
-
-    firehoseRole.addToPolicy(
-      new iam.PolicyStatement({
-        actions: ["s3:PutObject", "s3:PutObjectAcl"],
-        resources: [`${bucket.bucketArn}/*`],
-      })
-    );
-
-    firehoseRole.addToPolicy(
-      new iam.PolicyStatement({
-        actions: ["logs:PutLogEvents"],
-        resources: [
-          `arn:aws:logs:${Aws.REGION}:${Aws.ACCOUNT_ID}:log-group:/aws/kinesisfirehose/*`,
-        ],
-      })
-    );
-
-    // Create a CloudWatch Log Group for Firehose logging
-    const firehoseLogGroup = new logs.LogGroup(this, "FirehoseLogGroup", {
-      removalPolicy: RemovalPolicy.DESTROY,
-    });
-
-    // Create a Kinesis Firehose delivery stream
-    this.deliveryStream = new kinesisfirehose.CfnDeliveryStream(
-      this,
-      "DeliveryStream",
-      {
-        deliveryStreamType: "DirectPut",
-        extendedS3DestinationConfiguration: {
-          bucketArn: bucket.bucketArn,
-          roleArn: firehoseRole.roleArn,
-          prefix: filePrefix,
-          cloudWatchLoggingOptions: {
-            enabled: true,
-            logGroupName: firehoseLogGroup.logGroupName,
-            logStreamName: `firehose-to-s3-log-stream`,
-          },
-        },
-      }
-    );
-
-    const subscriptionFilterRole = new iam.Role(
-      this,
-      "SubscriptionFilterRole",
-      {
-        assumedBy: new iam.ServicePrincipal("logs.amazonaws.com"),
-        permissionsBoundary: props.iamPermissionsBoundary,
-        path: props.iamPath,
-        inlinePolicies: {
-          PutRecordPolicy: new iam.PolicyDocument({
-            statements: [
-              new iam.PolicyStatement({
-                actions: ["firehose:PutRecord", "firehose:PutRecordBatch"],
-                resources: [
-                  Fn.getAtt(this.deliveryStream.logicalId, "Arn").toString(),
-                ],
-              }),
-            ],
-          }),
-        },
-      }
-    );
-
-    // Create a subscription filter to send logs from the CloudWatch Log Group to Firehose
-    new logs.CfnSubscriptionFilter(this, "SubscriptionFilter", {
-      logGroupName: logGroup.logGroupName,
-      filterPattern: filterPattern,
-      destinationArn: Fn.getAtt(
-        this.deliveryStream.logicalId,
-        "Arn"
-      ).toString(),
-      roleArn: subscriptionFilterRole.roleArn,
-    });
-  }
-}
diff --git a/deployment/constructs/waf.ts b/deployment/constructs/waf.ts
index 8130b85e3..ae8676592 100644
--- a/deployment/constructs/waf.ts
+++ b/deployment/constructs/waf.ts
@@ -8,10 +8,7 @@ import { LogGroup } from "aws-cdk-lib/aws-logs";
 
 interface WafProps {
   readonly name: string;
-  /**
-   * Should requests with large bodies be blocked?
-   * @default true
-   */
+  readonly blockByDefault?: boolean;
   readonly blockRequestBodyOver8KB?: boolean;
 }
 
@@ -29,6 +26,7 @@ export class WafConstruct extends Construct {
 
     const {
       name,
+      blockByDefault = true,
       blockRequestBodyOver8KB = true
     } = props;
 
@@ -47,7 +45,7 @@ export class WafConstruct extends Construct {
 
     this.webAcl = new CfnWebACL(this, "WebACL", {
       scope: scopeType,
-      defaultAction: { block: {} },
+      defaultAction: blockByDefault ? { block: {} } : { allow: {} },
       visibilityConfig: {
         cloudWatchMetricsEnabled: true,
         sampledRequestsEnabled: true,
diff --git a/deployment/stacks/api.ts b/deployment/stacks/api.ts
index d5e6e2f5a..0868ffd1a 100644
--- a/deployment/stacks/api.ts
+++ b/deployment/stacks/api.ts
@@ -13,7 +13,6 @@ import {
   Tags,
 } from "aws-cdk-lib";
 import { Lambda } from "../constructs/lambda";
-import { CloudWatchToS3 } from "../constructs/cloudwatch-to-s3";
 import { WafConstruct } from "../constructs/waf";
 import { addIamPropertiesToBucketAutoDeleteRole } from "../utils/s3";
 import { LambdaDynamoEventSource } from "../constructs/lambda-dynamo-event";
@@ -44,10 +43,11 @@ export function createApiComponents(props: CreateApiComponentsProps) {
     privateSubnets,
     tables,
     brokerString,
+    iamPermissionsBoundary,
+    iamPath,
   } = props;
 
   const service = "app-api";
-  const shortStackName = `${service}-${stage}`;
   Tags.of(scope).add("SERVICE", service);
 
   const kafkaSecurityGroup = new ec2.SecurityGroup(
@@ -165,12 +165,12 @@ export function createApiComponents(props: CreateApiComponentsProps) {
 
   const commonProps = {
     brokerString,
-    stackName: shortStackName,
+    stackName: `${service}-${stage}`,
     api,
     environment,
     additionalPolicies,
-    iamPermissionsBoundary: props.iamPermissionsBoundary,
-    iamPath: props.iamPath,
+    iamPermissionsBoundary,
+    iamPath,
   };
 
   new Lambda(scope, "ForceKafkaSync", {
@@ -439,7 +439,7 @@ export function createApiComponents(props: CreateApiComponentsProps) {
       scope,
       "ApiWafConstruct",
       {
-        name: `${project}-${stage}-${shortStackName}`,
+        name: `${project}-${stage}-${service}`,
         blockRequestBodyOver8KB: false,
       },
       "REGIONAL"
@@ -449,28 +449,12 @@ export function createApiComponents(props: CreateApiComponentsProps) {
       resourceArn: api.deploymentStage.stageArn,
       webAclArn: waf.webAcl.attrArn,
     });
-
-    if (!isDev) {
-      const logBucket = new s3.Bucket(scope, "WafLogBucket", {
-        encryption: s3.BucketEncryption.S3_MANAGED,
-        blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
-        removalPolicy: RemovalPolicy.RETAIN,
-        enforceSSL: true,
-      });
-
-      new CloudWatchToS3(scope, "CloudWatchToS3Construct", {
-        logGroup: waf.logGroup,
-        bucket: logBucket,
-        iamPermissionsBoundary: props.iamPermissionsBoundary,
-        iamPath: props.iamPath,
-      });
-    }
   }
 
   addIamPropertiesToBucketAutoDeleteRole(
     scope,
-    props.iamPermissionsBoundary.managedPolicyArn,
-    props.iamPath
+    iamPermissionsBoundary.managedPolicyArn,
+    iamPath
   );
 
   return {
diff --git a/deployment/stacks/ui-auth.ts b/deployment/stacks/ui-auth.ts
index a9ece3088..f2b711818 100644
--- a/deployment/stacks/ui-auth.ts
+++ b/deployment/stacks/ui-auth.ts
@@ -13,9 +13,11 @@ import {
 } from "aws-cdk-lib";
 import { WafConstruct } from "../constructs/waf";
 import { IManagedPolicy } from "aws-cdk-lib/aws-iam";
+import { isLocalStack } from "../local/util";
 
 interface CreateUiAuthComponentsProps {
   scope: Construct;
+  project: string;
   stage: string;
   isDev: boolean;
   applicationEndpointUrl: string;
@@ -32,6 +34,7 @@ interface CreateUiAuthComponentsProps {
 export function createUiAuthComponents(props: CreateUiAuthComponentsProps) {
   const {
     scope,
+    project,
     stage,
     isDev,
     applicationEndpointUrl,
@@ -71,7 +74,7 @@ export function createUiAuthComponents(props: CreateUiAuthComponentsProps) {
     customAttributes: {
       ismemberof: new cognito.StringAttribute({ mutable: true }),
     },
-    advancedSecurityMode: cognito.AdvancedSecurityMode.ENFORCED,
+    // advancedSecurityMode: cognito.AdvancedSecurityMode.ENFORCED, DEPRECATED WE NEED FEATURE_PLAN.plus if we want to use StandardThreatProtectionMode.FULL_FUNCTION which I think is the new way to do this
     removalPolicy: isDev ? RemovalPolicy.DESTROY : RemovalPolicy.RETAIN,
   });
 
@@ -261,17 +264,19 @@ export function createUiAuthComponents(props: CreateUiAuthComponentsProps) {
     );
   }
 
-  const webAcl = new WafConstruct(
-    scope,
-    "CognitoWafConstruct",
-    { name: `ui-auth-${stage}-webacl-waf` },
-    "REGIONAL"
-  ).webAcl;
+  if (!isLocalStack) {
+    const waf = new WafConstruct(
+      scope,
+      "CognitoWafConstruct",
+      { name: `${project}-${stage}-ui-auth` },
+      "REGIONAL"
+    );
 
-  new wafv2.CfnWebACLAssociation(scope, "CognitoUserPoolWAFAssociation", {
-    resourceArn: userPool.userPoolArn,
-    webAclArn: webAcl.attrArn,
-  });
+    new wafv2.CfnWebACLAssociation(scope, "CognitoUserPoolWAFAssociation", {
+      resourceArn: userPool.userPoolArn,
+      webAclArn: waf.webAcl.attrArn,
+    });
+  }
 
   new ssm.StringParameter(scope, "CognitoUserPoolIdParameter", {
     parameterName: `/${stage}/ui-auth/cognito_user_pool_id`,
diff --git a/deployment/stacks/ui.ts b/deployment/stacks/ui.ts
index 7eb2951eb..3272b7965 100644
--- a/deployment/stacks/ui.ts
+++ b/deployment/stacks/ui.ts
@@ -3,15 +3,15 @@ import {
   aws_cloudfront as cloudfront,
   aws_cloudfront_origins as cloudfrontOrigins,
   aws_iam as iam,
-  aws_kinesisfirehose as firehose,
   aws_s3 as s3,
-  aws_wafv2 as wafv2,
   Duration,
   RemovalPolicy,
   aws_certificatemanager as acm,
 } from "aws-cdk-lib";
+import { WafConstruct } from "../constructs/waf";
 import { addIamPropertiesToBucketAutoDeleteRole } from "../utils/s3";
 import { IManagedPolicy } from "aws-cdk-lib/aws-iam";
+import { isLocalStack } from "../local/util";
 
 interface CreateUiComponentsProps {
   scope: Construct;
@@ -36,9 +36,10 @@ export function createUiComponents(props: CreateUiComponentsProps) {
     iamPath,
     cloudfrontCertificateArn,
     cloudfrontDomainName,
-    vpnIpSetArn,
-    vpnIpv6SetArn,
+    // vpnIpSetArn,
+    // vpnIpv6SetArn,
   } = props;
+
   // S3 Bucket for UI hosting
   const uiBucket = new s3.Bucket(scope, "uiBucket", {
     encryption: s3.BucketEncryption.S3_MANAGED,
@@ -136,22 +137,17 @@ export function createUiComponents(props: CreateUiComponentsProps) {
       ],
     }
   );
+
   distribution.applyRemovalPolicy(
     isDev ? RemovalPolicy.DESTROY : RemovalPolicy.RETAIN
   );
 
-  const applicationEndpointUrl = `https://${distribution.distributionDomainName}/`;
-
-  setupWaf(scope, stage, project, vpnIpSetArn, vpnIpv6SetArn);
+  if (!isLocalStack) {
+    const waf = setupWaf(scope, stage, project); // vpnIpSetArn, vpnIpv6SetArn
+    distribution.attachWebAclId(waf.webAcl.attrArn)
+  }
 
-  createFirehoseLogging(
-    scope,
-    stage,
-    project,
-    logBucket,
-    iamPermissionsBoundary,
-    iamPath
-  );
+  const applicationEndpointUrl = `https://${distribution.distributionDomainName}/`;
 
   addIamPropertiesToBucketAutoDeleteRole(
     scope,
@@ -172,106 +168,64 @@ function setupWaf(
   scope: Construct,
   stage: string,
   project: string,
-  vpnIpSetArn?: string,
-  vpnIpv6SetArn?: string,
-) {
-  const wafRules: wafv2.CfnWebACL.RuleProperty[] = [];
-
-  const defaultAction = vpnIpSetArn
-    ? { block: {} }
-    : { allow: {} };
-
-  if (vpnIpSetArn) {
-    const githubIpSet = new wafv2.CfnIPSet(scope, "GitHubIPSet", {
-      name: `${stage}-gh-ipset`,
-      scope: "CLOUDFRONT",
-      addresses: [],
-      ipAddressVersion: "IPV4",
-    });
-
-    const statements = [
-      {
-        ipSetReferenceStatement: { arn: vpnIpSetArn },
-      },
-      {
-        ipSetReferenceStatement: { arn: githubIpSet.attrArn },
-      },
-    ];
-
-    if (vpnIpv6SetArn) {
-      statements.push({
-        ipSetReferenceStatement: {
-          arn: vpnIpv6SetArn,
-        },
-      });
-    }
-
-    wafRules.push({
-      name: "vpn-only",
-      priority: 0,
-      action: { allow: {} },
-      visibilityConfig: {
-        cloudWatchMetricsEnabled: true,
-        metricName: `${project}-${stage}-webacl-vpn-only`,
-        sampledRequestsEnabled: true,
-      },
-      statement: {
-        orStatement: {
-          statements,
-        },
-      },
-    });
-  }
-
-  new wafv2.CfnWebACL(scope, "WebACL", {
-    name: `${project}-${stage}-webacl-waf`,
-    scope: "CLOUDFRONT",
-    defaultAction,
-    visibilityConfig: {
-      sampledRequestsEnabled: true,
-      cloudWatchMetricsEnabled: true,
-      metricName: `${project}-${stage}-webacl`,
-    },
-    rules: wafRules,
-  });
-}
-
-function createFirehoseLogging(
-  scope: Construct,
-  stage: string,
-  project: string,
-  logBucket: s3.Bucket,
-  iamPermissionsBoundary: IManagedPolicy,
-  iamPath: string
+  // vpnIpSetArn?: string,
+  // vpnIpv6SetArn?: string,
 ) {
-  const firehoseRole = new iam.Role(scope, "FirehoseRole", {
-    permissionsBoundary: iamPermissionsBoundary,
-    path: iamPath,
-    assumedBy: new iam.ServicePrincipal("firehose.amazonaws.com"),
-    inlinePolicies: {
-      FirehoseS3Access: new iam.PolicyDocument({
-        statements: [
-          new iam.PolicyStatement({
-            actions: ["s3:PutObject"],
-            resources: [`${logBucket.bucketArn}/*`],
-            effect: iam.Effect.ALLOW,
-          }),
-        ],
-      }),
-    },
-  });
-
-  new firehose.CfnDeliveryStream(scope, "Firehose", {
-    deliveryStreamName: `aws-waf-logs-${project}-${stage}-firehose`,
-    extendedS3DestinationConfiguration: {
-      roleArn: firehoseRole.roleArn,
-      bucketArn: logBucket.bucketArn,
-      prefix: `AWSLogs/WAF/${stage}/`,
-      bufferingHints: {
-        intervalInSeconds: 300,
-        sizeInMBs: 5,
-      },
-      compressionFormat: "UNCOMPRESSED",
+  return new WafConstruct(
+    scope,
+    "CloudfrontWafConstruct",
+    {
+      name: `${project}-${stage}-ui`,
+      blockByDefault: false,
     },
-  });
+    "CLOUDFRONT"
+  );
+  // Additional Rules for this WAF only if CMS asks to have the application made vpn only
+  // const wafRules: wafv2.CfnWebACL.RuleProperty[] = [];
+
+  // const defaultAction = vpnIpSetArn
+  //   ? { block: {} }
+  //   : { allow: {} };
+
+  // if (vpnIpSetArn) {
+  //   const githubIpSet = new wafv2.CfnIPSet(scope, "GitHubIPSet", {
+  //     name: `${stage}-gh-ipset`,
+  //     scope: "CLOUDFRONT",
+  //     addresses: [],
+  //     ipAddressVersion: "IPV4",
+  //   });
+
+  //   const statements = [
+  //     {
+  //       ipSetReferenceStatement: { arn: vpnIpSetArn },
+  //     },
+  //     {
+  //       ipSetReferenceStatement: { arn: githubIpSet.attrArn },
+  //     },
+  //   ];
+
+  //   if (vpnIpv6SetArn) {
+  //     statements.push({
+  //       ipSetReferenceStatement: {
+  //         arn: vpnIpv6SetArn,
+  //       },
+  //     });
+  //   }
+
+  //   wafRules.push({
+  //     name: "vpn-only",
+  //     priority: 0,
+  //     action: { allow: {} },
+  //     visibilityConfig: {
+  //       cloudWatchMetricsEnabled: true,
+  //       metricName: `${project}-${stage}-webacl-vpn-only`,
+  //       sampledRequestsEnabled: true,
+  //     },
+  //     statement: {
+  //       orStatement: {
+  //         statements,
+  //       },
+  //     },
+  //   });
+  // }
 }
diff --git a/package.json b/package.json
index bfb4ec7e0..85aa83bf1 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
   "devDependencies": {
     "@types/node": "^20.12.7",
     "@types/yargs": "^15.0.10",
-    "aws-cdk": "^2.161.1",
+    "aws-cdk": "^2.182.0",
     "aws-cdk-local": "^2.19.2",
     "chromedriver": ">=88.0.0",
     "dotenv": "^8.2.0",
@@ -43,7 +43,7 @@
     "@aws-sdk/client-lambda": "^3.678.0",
     "@aws-sdk/client-s3": "^3.670.0",
     "@aws-sdk/client-secrets-manager": "^3.670.0",
-    "aws-cdk-lib": "^2.161.1",
+    "aws-cdk-lib": "^2.182.0",
     "constructs": "^10.3.0",
     "source-map-support": "^0.5.21"
   }
diff --git a/yarn.lock b/yarn.lock
index 904e16fa0..1fc6a1a4b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,28 +2,23 @@
 # yarn lockfile v1
 
 
-"@aws-cdk/asset-awscli-v1@^2.2.202":
-  version "2.2.207"
-  resolved "https://registry.yarnpkg.com/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.207.tgz#c145967f88db58065369929084a39629c6f99306"
-  integrity sha512-5oRh5Ad7hGSqwM3+/X8MmIkUjBMGU9sd1g+pa3L0s8IL15OQcFW0ZT0gsUdEb/N/JV663jUUpSbtD7pLO65O4Q==
-
-"@aws-cdk/asset-kubectl-v20@^2.1.2":
-  version "2.1.3"
-  resolved "https://registry.yarnpkg.com/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.3.tgz#80e09004be173995e91614e34d947da11dd9ff4d"
-  integrity sha512-cDG1w3ieM6eOT9mTefRuTypk95+oyD7P5X/wRltwmYxU7nZc3+076YEVS6vrjDKr3ADYbfn0lDKpfB1FBtO9CQ==
+"@aws-cdk/asset-awscli-v1@^2.2.208":
+  version "2.2.226"
+  resolved "https://registry.yarnpkg.com/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.226.tgz#84dcd7bf1a677dbc652d37e4c9862c51a704efd8"
+  integrity sha512-dlf8mTsW6ulV9pUxiYHSRHtQfZhHX1gmLEbHGE1sPI//skgkma+p5CVBeSiou9QEdcHOvOVruYzxY9OZ/GDS7g==
 
 "@aws-cdk/asset-node-proxy-agent-v6@^2.1.0":
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.0.tgz#6d3c7860354d4856a7e75375f2f0ecab313b4989"
   integrity sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==
 
-"@aws-cdk/cloud-assembly-schema@^38.0.0":
-  version "38.0.1"
-  resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-38.0.1.tgz#cdf4684ae8778459e039cd44082ea644a3504ca9"
-  integrity sha512-KvPe+NMWAulfNVwY7jenFhzhuLhLqJ/OPy5jx7wUstbjnYnjRVLpUHPU3yCjXFE0J8cuJVdx95BJ4rOs66Pi9w==
+"@aws-cdk/cloud-assembly-schema@^40.6.0":
+  version "40.7.0"
+  resolved "https://registry.yarnpkg.com/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-40.7.0.tgz#1d53d55fc616477965338f0de98192ec3a3ed9bc"
+  integrity sha512-00wVKn9pOOGXbeNwA4E8FUFt0zIB4PmSO7PvIiDWgpaFX3G/sWyy0A3s6bg/n2Yvkghu8r4a8ckm+mAzkAYmfA==
   dependencies:
-    jsonschema "^1.4.1"
-    semver "^7.6.3"
+    jsonschema "~1.4.1"
+    semver "^7.7.1"
 
 "@aws-crypto/crc32@5.2.0":
   version "5.2.0"
@@ -2448,15 +2443,14 @@ asynckit@^0.4.0:
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
   integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
 
-aws-cdk-lib@^2.161.1:
-  version "2.162.1"
-  resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.162.1.tgz#06454f1302a345dbd2a1866b0f170adbc93b1664"
-  integrity sha512-XiZLVE5ISNajNNmLye8l5w4EGqm6/d8C8shw63QwxaRVYdHl5e+EAaUEmZJpWc4sYtY/sS+GHOfhoKFLjha2rg==
+aws-cdk-lib@^2.182.0:
+  version "2.182.0"
+  resolved "https://registry.yarnpkg.com/aws-cdk-lib/-/aws-cdk-lib-2.182.0.tgz#9b2d51f41d1c7846a62c1d6f6a7da5e677db43d3"
+  integrity sha512-emymzTJiCpPz8oF++oiFvFuLH1QZjv6NRNQGn7VuDrEewZFTM4VpiVco5NrxH+KCWnXquDBPF5sQIUo6HY7jLg==
   dependencies:
-    "@aws-cdk/asset-awscli-v1" "^2.2.202"
-    "@aws-cdk/asset-kubectl-v20" "^2.1.2"
+    "@aws-cdk/asset-awscli-v1" "^2.2.208"
     "@aws-cdk/asset-node-proxy-agent-v6" "^2.1.0"
-    "@aws-cdk/cloud-assembly-schema" "^38.0.0"
+    "@aws-cdk/cloud-assembly-schema" "^40.6.0"
     "@balena/dockerignore" "^1.0.2"
     case "1.6.3"
     fs-extra "^11.2.0"
@@ -2476,10 +2470,10 @@ aws-cdk-local@^2.19.2:
   dependencies:
     diff "^5.0.0"
 
-aws-cdk@^2.161.1:
-  version "2.1000.2"
-  resolved "https://registry.yarnpkg.com/aws-cdk/-/aws-cdk-2.1000.2.tgz#5c89404f24b09880bc9f7e9b4f7bd721be02b4bd"
-  integrity sha512-QsXqJhGWjHNqP7etgE3sHOTiDBXItmSKdFKgsm1qPMBabCMyFfmWZnEeUxfZ4sMaIoxvLpr3sqoWSNeLuUk4sg==
+aws-cdk@^2.182.0:
+  version "2.1003.0"
+  resolved "https://registry.yarnpkg.com/aws-cdk/-/aws-cdk-2.1003.0.tgz#db3bcd839f86b9b7f0f3d2d3359cefb768458462"
+  integrity sha512-FORPDGW8oUg4tXFlhX+lv/j+152LO9wwi3/CwNr1WY3c3HwJUtc0fZGb2B3+Fzy6NhLWGHJclUsJPEhjEt8Nhg==
   optionalDependencies:
     fsevents "2.3.2"
 
@@ -2936,7 +2930,7 @@ jsonfile@^6.0.1:
   optionalDependencies:
     graceful-fs "^4.1.6"
 
-jsonschema@^1.4.1:
+jsonschema@^1.4.1, jsonschema@~1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab"
   integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==
@@ -3071,6 +3065,11 @@ semver@^7.6.3:
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
   integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
 
+semver@^7.7.1:
+  version "7.7.1"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
+  integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
+
 slice-ansi@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"


Reviews:
user: login: JonHolman
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T16:20:00Z
user: login: JonHolman
body: looks good, just one import suggested to be removed.
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T16:20:37Z
user: login: peoplespete
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T16:22:56Z
user: login: JonHolman
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T16:23:34Z
user: login: benmartin-coforma
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-07T16:37:22Z
user: login: peoplespete
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-07T16:45:43Z
user: login: benmartin-coforma
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-07T16:46:23Z

Review comments:
diff_hunk: @@ -3,15 +3,16 @@ import {
   aws_cloudfront as cloudfront,
   aws_cloudfront_origins as cloudfrontOrigins,
   aws_iam as iam,
-  aws_kinesisfirehose as firehose,
   aws_s3 as s3,
-  aws_wafv2 as wafv2,
   Duration,
   RemovalPolicy,
   aws_certificatemanager as acm,
 } from "aws-cdk-lib";
+import { WafConstruct } from "../constructs/waf";
 import { addIamPropertiesToBucketAutoDeleteRole } from "../utils/s3";
 import { IManagedPolicy } from "aws-cdk-lib/aws-iam";
+import { isLocalStack } from "../local/util";
+import { it } from "node:test";
path: deployment/stacks/ui.ts
user: login: JonHolman
body: ```suggestion
```
created_at: 2025-03-07T16:20:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,15 +3,16 @@ import {
   aws_cloudfront as cloudfront,
   aws_cloudfront_origins as cloudfrontOrigins,
   aws_iam as iam,
-  aws_kinesisfirehose as firehose,
   aws_s3 as s3,
-  aws_wafv2 as wafv2,
   Duration,
   RemovalPolicy,
   aws_certificatemanager as acm,
 } from "aws-cdk-lib";
+import { WafConstruct } from "../constructs/waf";
 import { addIamPropertiesToBucketAutoDeleteRole } from "../utils/s3";
 import { IManagedPolicy } from "aws-cdk-lib/aws-iam";
+import { isLocalStack } from "../local/util";
+import { it } from "node:test";
path: deployment/stacks/ui.ts
user: login: peoplespete
body: Fixed good catch!
created_at: 2025-03-07T16:22:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,10 +8,7 @@ import { LogGroup } from "aws-cdk-lib/aws-logs";
 
 interface WafProps {
   readonly name: string;
-  /**
-   * Should requests with large bodies be blocked?
-   * @default true
-   */
+  readonly blocked?: boolean;
path: deployment/constructs/waf.ts
user: login: benmartin-coforma
body: Request: Could you rename this to `blockByDefault` please?
created_at: 2025-03-07T16:36:16Z
author_association: COLLABORATOR
diff_hunk: @@ -8,10 +8,7 @@ import { LogGroup } from "aws-cdk-lib/aws-logs";
 
 interface WafProps {
   readonly name: string;
-  /**
-   * Should requests with large bodies be blocked?
-   * @default true
-   */
+  readonly blocked?: boolean;
path: deployment/constructs/waf.ts
user: login: peoplespete
body: Fixed!
created_at: 2025-03-07T16:45:42Z
author_association: CONTRIBUTOR

PR comments:
user: login: qlty-cloud-legacy[bot]
created_at: 2025-03-07T16:46:31Z
body: Code Climate has analyzed commit 0dc3dd2d and detected **0 issues** on this pull request.

The test coverage on the diff in this pull request is **100.0%** (**90%** is the threshold).

This pull request will bring the total coverage in the repository to **82.5%** (**0.0%** change).

View more on [Code Climate](https://codeclimate.com/repos/64497017eab34100ce938fe6/pull/15080).

author_association: NONE