provider "aws" {
  region = var.region
}

provider "cloudflare" {
}

terraform {
  backend "s3" {
    bucket  = "prod-songwhip-terraform-state"
    key     = "prod/songwhip/cloudflare/waf/custom-rules/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

locals {
  trusted_ips = [
    "3.213.73.88",
    "3.81.188.77",
    "34.196.231.107",
    "52.202.238.54",
    "34.198.230.207",
    "3.211.234.92",
    "52.200.83.186",
    "3.213.8.167",
    "52.4.166.11"
  ]
  blocked_ips = [
    "35.204.78.97",
    "34.34.14.13"
  ]
}

data "cloudflare_zone" "songwhip" {
  name       = var.cloudflare_zone
  account_id = var.cloudflare_account_id
}

resource "cloudflare_ruleset" "http_ratelimit" {
  kind    = "zone"
  name    = "default"
  phase   = "http_ratelimit"
  zone_id = data.cloudflare_zone.songwhip.id
  rules {
    action = "block"
    action_parameters {
      response {
        content      = "You have exceeded the Songwhip public/developer API rate limit (5 requests per min). You have been blocked for 5 minutes."
        content_type = "text/plain"
        status_code  = 429
      }
    }
    description = "songwhip.com  public developer API rate limit"
    enabled     = true
    expression = "(http.host eq \"songwhip.com\" and http.request.method eq \"POST\" and starts_with(http.request.uri.path, \"/api/songwhip/create\") and not ip.src in {${join(" ", local.trusted_ips)}} and not ip.src in $github_actions_ips)"
    ratelimit {
      characteristics     = ["ip.src", "cf.colo.id"]
      mitigation_timeout  = 300
      period              = 60
      requests_per_period = 20
    }
  }
  rules {
    action      = "block"
    description = "Limit FB crawler"
    enabled     = true
    expression  = "(http.user_agent contains \"facebookexternalhit\")"
    ratelimit {
      characteristics     = ["ip.geoip.asnum", "cf.colo.id"]
      mitigation_timeout  = 60
      period              = 60
      requests_per_period = 100
    }
  }
}

resource "cloudflare_ruleset" "http_request_firewall_custom" {
  kind    = "zone"
  name    = "default"
  phase   = "http_request_firewall_custom"
  zone_id = data.cloudflare_zone.songwhip.id
  rules {
    action      = "block"
    description = "Block IP Addresses"
    enabled     = true
    expression  = "ip.src in {${join(" ", local.blocked_ips)}}"
  }
  rules {
    action = "skip"
    action_parameters {
      products = ["uaBlock", "bic", "securityLevel", "rateLimit", "waf"]
    }
    description = "Allow Songwhip trusted clients"
    enabled     = true
    expression  = "(http.user_agent contains \"songwhip-trusted-client\")"
    logging {
      enabled = true
    }
  }
  rules {
    action = "skip"
    action_parameters {
      products = ["rateLimit"]
    }
    description = "GET / bypass rate limiter"
    enabled     = false
    expression  = "(http.request.uri.path eq \"/\" and http.request.method ne \"POST\")"
    logging {
      enabled = true
    }
  }
  rules {
    action = "skip"
    action_parameters {
      products = ["rateLimit"]
    }
    description = "Bypass rate-limitter"
    enabled     = false
    expression  = "(http.request.uri.path eq \"/api/event\") or (http.request.uri contains \"/api/?q=\")"
    logging {
      enabled = true
    }
  }
  rules {
    action      = "challenge"
    description = "Blocked pages"
    enabled     = true
    expression  = "(http.request.uri.path eq \"/album/mr-foster/hits-the-collection\") or (http.request.uri.path eq \"/song/davage/blacklist\")"
  }
  rules {
    action      = "js_challenge"
    description = "Suspicious pages"
    enabled     = true
    expression  = <<EOF
(http.request.uri.path eq "/album/ralo/free-ralo")
or (http.request.uri.path eq "/album/22gz/the-blixky-tape")
or (http.request.uri.path eq "/album/pouya/the-south-got-something-to-say")
or (http.request.uri.path eq "/album/03-greedo/meet-the-drummers")
or (http.request.uri.path eq "/album/booka600/word-to-la")
or (http.request.uri.path eq "/album/ballout/ballin-no-nba-2")
or (http.request.uri.path eq "/album/jaydayoungan/cant-speak-on-it")
or (http.request.uri.path eq "/album/project-youngin/project-6")
or (http.request.uri.path eq "/album/yung-bans/misunderstood")
or (http.request.uri.path eq "/album/polo-g/die-a-legend")
or (http.request.uri.path eq "/album/various-artists/i-got-the-hook-up-2")
or (http.request.uri.path eq "/album/quando-rondo/from-the-neighborhood-to-the-stage")
or (http.request.uri.path eq "/album/gucci-mane/delusions-of-grandeur")
or (http.request.uri.path eq "/album/moneybagg-yo/43va-heartless")
or (http.request.uri.path eq "/album/kevin-gates/only-the-generals-gon-understand")
or (http.request.uri.path eq "/album/yfn-lucci/650luc-gangsta-grillz")
or (http.request.uri.path eq "/album/young-dolph/dum-and-dummer")
or (http.request.uri.path eq "/album/jim-jones/el-capo")
or (http.request.uri.path eq "/album/tj-porter/voice-of-the-trenches")
or (http.request.uri.path eq "/album/ras-kass/soul-on-ice-2")
or (http.request.uri.path eq "/album/cousin-stizz/trying-to-find-my-next-thrill")
or (http.request.uri.path eq "/album/blueface/dirt-bag")
or (http.request.uri.path eq "/album/peewee-longway/the-blue-mandm-4")
or (http.request.uri.path eq "/album/lil-tjay/fn-ep")
or (http.request.uri.path eq "/album/lil-tjay/fn")
or (http.request.uri.path eq "/album/saint-jhn/ghetto-lennys-love-songs")
or (http.request.uri.path contains "/album/milk-mob/")
or (http.request.uri.path contains "/song/milk-mob/")
or (http.request.uri.path eq "/album/mr-foster/hits-the-collection")
or (http.request.uri.path eq "/song/davage/blacklist")
EOF
  }
  rules {
    action      = "block"
    description = "Block various artists refresh"
    enabled     = true
    expression  = "(http.request.method eq \"POST\" and http.request.uri eq \"https://api.songwhip.com/artists/514/refresh\")"
  }
  rules {
    action      = "block"
    description = "Block Artists URLs"
    enabled     = true
    expression  = <<EOF
(http.request.full_uri wildcard r"https://songwhip.com/kelsea-ballerini*")
or (http.host eq "kelsea-ballerini.sng.to")
or (http.host eq "kelsea-ballerini.orch.stream")
or (http.request.full_uri wildcard r"https://songwhip.com/scottyhasting")
or (http.request.full_uri eq "https://scottyhasting.orch.stream")
or (http.request.full_uri eq "scottyhasting.orch.stream")
EOF
  }
}
