@cfxlabsinc/b2b-services
    Preparing search index...

    Module @cfxlabsinc/waf

    waf

    Pulumi stack (cfx-waf) owning the AWS WAF web ACLs the CloudFront distributions use, and the log group they write to. Design: DASHBOARD_WAF.md § 2.1 and § 5. This stack attaches an ACL to nothing: each distribution's own stack sets an ACL's ARN as its webAclId.

    Resource prod dev
    wafv2.WebAcl, scope CLOUDFRONT, shared cfx-cloudfront-prod cfx-cloudfront-dev
    wafv2.WebAcl, scope CLOUDFRONT, admin cfx-cloudfront-admin-prod cfx-cloudfront-admin-dev
    wafv2.IpSet, admin's allowlist cfx-admin-allowlist-prod cfx-admin-allowlist-dev
    cloudwatch.LogGroup, 365 days aws-waf-logs-cfx-cloudfront-prod aws-waf-logs-cfx-cloudfront-dev
    cloudwatch.LogResourcePolicy cfx-waf-log-delivery-prod cfx-waf-log-delivery-dev
    wafv2.WebAclLoggingConfiguration, one each on both ACLs same

    All are in us-east-1, the only Region a CloudFront-scope web ACL exists in; the rest of the estate is us-west-2. Both ACLs log to the one group; each record names its ACL in webaclId.

    On the shared ACL every rule counts and none blocks, and the default action is allow, so attaching it changes no response. pulumi/rules.ts is the list and test/webAcl.test.ts fails if a rule could block.

    Priority Rule Action
    0 rate-limit-per-ip count, above 2,000 requests in 5 minutes per address
    1 AWSManagedRulesAmazonIpReputationList group overridden to count
    2 AWSManagedRulesAnonymousIpList group overridden to count
    3 AWSManagedRulesKnownBadInputsRuleSet group overridden to count
    4 AWSManagedRulesCommonRuleSet group overridden to count
    5 AWSManagedRulesSQLiRuleSet group overridden to count
    • The five groups are the ones the regional Firewall Manager policy runs on API Gateway. Its two exclusions, HostingProviderIPList and NoUserAgent_HEADER, are per-rule count overrides here, so they keep counting when their group is later allowed to block.
    • The rate limit is a starting point. DASHBOARD_WAF.md sets no number, and the count-mode review of § 5 step 3 tunes it.
    • Moving a rule to block is that review's decision, one dashboard at a time. It is a change to rules.ts and to the test that holds every rule to count.

    The admin dashboard has its own ACL, which makes WARP the only way in. Admin's hostnames are proxied to the WARP tunnel, where a Cloudflare Access app requires the Gateway posture check, and the tunnel's connector forwards to the distribution from its NAT EIP (packages/warp/admin_dashboard.tf).

    Priority Rule Action
    0 off-allowlist block a viewer outside the egress VPC's three NAT EIPs (cfx-admin-allowlist-*)
    1–5 the managed groups above counting, as on the shared ACL
    • No rate rule: every operator arrives from the one connector address.
    • The block is also what lets packages/ui/src/lib/session-client.ts trust the cf-* headers a NAT EIP viewer carries, the operator's address and location from Cloudflare's edge. Never move it to count while that holds.

    Every request the ACL evaluates is logged. The cookie and authorization headers and the query string are redacted, for the reason the customer dashboard's access logs omit them: they carry sessions, search text and account ids. Sampled requests are off, because log redaction does not apply to them.

    • A Pulumi stack reads webAclArn through a StackReference it declares itself.
    • An SST app cannot read this stack's state, so it looks the ACL up by name at deploy: aws.wafv2.getWebAclOutput({ name, scope: "CLOUDFRONT", region: "us-east-1" }), with the name from cloudfrontWebAclName (or adminWebAclName for admin) in src/webAclName.ts, outside pulumi/ so a change to it redeploys those apps. The name is therefore load-bearing: renaming the ACL replaces it, which fails while a distribution still holds it.

    Outputs: webAclArn, webAclName, adminWebAclArn, adminAclName, logGroupName.

    cfx-role-devops, the role CI applies this stack with and the dashboards deploy as, holds wafv2:* in its policy and in its boundary in both workload accounts (packages/aft/account-customizations/workloads-{nonprod,prod}/terraform/iam.tf). A dashboard deploy needs it too: the lookup by name is wafv2:ListWebACLs.

    CD does not order this stack ahead of the dashboards' SST jobs. That only matters when the ACL does not exist yet or is being replaced: apply this stack first, then deploy the dashboards.

    bun nx run waf:pulumi-preview        # dev
    bun nx run waf:pulumi-preview:prod
    aws wafv2 list-web-acls --scope CLOUDFRONT --region us-east-1
    aws wafv2 get-logging-configuration --region us-east-1 --resource-arn <webAclArn>