176 lines
7.9 KiB
Terraform
176 lines
7.9 KiB
Terraform
# =============================================================================
|
|
# CLOUDFLARE : Traffic Policies : Firewall Policies : HTTP
|
|
# =============================================================================
|
|
|
|
#==========================================================
|
|
# Local Variables
|
|
#==========================================================
|
|
locals {
|
|
precedence_http = {
|
|
# HTTP (L7) Policies - AI Application Governance
|
|
ai_tools_redirect = 24000 # Redirect unreviewed AI tools to Claude
|
|
chatgpt_allow_log = 24100 # Allow ChatGPT with prompt logging
|
|
|
|
# HTTP (L7) Policies - Content Filtering & DLP
|
|
pdf_block = 25000 # Block PDF downloads for Sales Eng (identity-based DLP)
|
|
gambling_block = 25100 # Block gambling websites (category blocking)
|
|
|
|
# HTTP (L7) Policies - Remote Browser Isolation
|
|
webmail_isolate = 25300 # Isolate personal webmail in a remote browser (RBI)
|
|
|
|
# HTTP (L7) Policies - Do Not Inspect (évaluées avant l'inspection)
|
|
dni_privacy = 12500 # Ne pas déchiffrer banque/santé (confidentialité)
|
|
}
|
|
|
|
# Common rule settings for block policies
|
|
default_block_settings_http = {
|
|
block_page_enabled = false
|
|
ip_categories = false
|
|
ip_indicator_feeds = false
|
|
insecure_disable_dnssec_validation = false
|
|
}
|
|
|
|
# Gateway policies configuration
|
|
# Organized by policy type: then HTTP (L7) policies
|
|
# Following Cloudflare best practices with 1000-spacing between major groups
|
|
# Integrates with dashboard-managed policies at precedence: 1000-3000, 5000-20000, 36000-40000
|
|
gateway_policies_http = {
|
|
#==========================================================
|
|
# HTTP (L7) POLICIES
|
|
# Application/Content-based filtering
|
|
# Terraform precedence ranges: 24000-25100
|
|
# Dashboard precedence ranges: 13000-20000
|
|
# Note: Dashboard Do-Not-Inspect policies (13000-15000) evaluated before Terraform HTTP policies
|
|
#==========================================================
|
|
|
|
# Do Not Inspect - Confidentialité (Precedence: 12500)
|
|
# Bonne pratique : NE PAS déchiffrer le trafic vers les sites bancaires
|
|
# et de santé (obligations de confidentialité + certains sites cassent
|
|
# avec l'inspection TLS : certificate pinning). action = "off" est le
|
|
# "Do Not Inspect" du dashboard ; seuls les champs http.conn.* (basés
|
|
# sur le SNI, sans déchiffrement) sont utilisables ici.
|
|
# NOTE : vérifier les IDs de catégories dans le dashboard (Gateway >
|
|
# politiques > sélecteur Content Categories) et ajuster si besoin.
|
|
do_not_inspect_privacy = {
|
|
name = "HTTP - Do Not Inspect: Banque & Sante"
|
|
description = "Ne pas dechiffrer le trafic vers les sites bancaires et de sante (confidentialite)"
|
|
enabled = true
|
|
action = "off"
|
|
precedence = local.precedence_http.dni_privacy
|
|
filters = ["http"]
|
|
traffic = "any(http.conn.content_category[*] in {113 156})"
|
|
notification_enabled = false
|
|
}
|
|
|
|
# AI Application Governance (Precedence: 24000-24100)
|
|
redirect_ai_to_claude = {
|
|
name = "HTTP - Redirect: Redirect users to claude.ai"
|
|
description = "Redirect any unreviewed AI application to claude.ai instead"
|
|
enabled = true
|
|
action = "redirect"
|
|
precedence = local.precedence_http.ai_tools_redirect
|
|
filters = ["http"]
|
|
traffic = "any(app.type.ids[*] in {25}) and any(app.statuses[*] == \"unreviewed\")"
|
|
redirect_url = "https://claude.ai"
|
|
notification_enabled = false
|
|
}
|
|
|
|
# Content Filtering & DLP (Precedence: 25000-25100)
|
|
block_pdf_download = {
|
|
name = "HTTP - Block: PDF Files download"
|
|
description = "Block Downloading PDF Files for Sales Engineering group"
|
|
enabled = false
|
|
action = "block"
|
|
precedence = local.precedence_http.pdf_block
|
|
filters = ["http"]
|
|
traffic = "any(http.download.file.types[*] in {\"pdf\"})"
|
|
identity = "any(identity.saml_attributes[*] == \"groups=${var.okta_sales_eng_saml_group_name}\")"
|
|
block_reason = "This download is blocked because it is a pdf file (not approved)"
|
|
notification_enabled = true
|
|
}
|
|
|
|
block_gambling = {
|
|
name = "HTTP - Block: Gambling websites"
|
|
description = "Block Gambling website according to corporate policies (HTTP)."
|
|
enabled = true
|
|
action = "block"
|
|
precedence = local.precedence_http.gambling_block
|
|
filters = ["http"]
|
|
traffic = "any(http.request.uri.content_category[*] in {99})"
|
|
identity = "not(any(identity.saml_attributes[*] == \"groups=${var.okta_contractors_saml_group_name}\")) or not(identity.email == \"${var.okta_bob_user_login}\")"
|
|
block_reason = "This website is blocked according to corporate policies (HTTP)"
|
|
notification_enabled = true
|
|
}
|
|
|
|
# Remote Browser Isolation (Precedence: 25300)
|
|
# BRIQUE RBI : le site s'ouvre dans un navigateur distant exécuté chez
|
|
# Cloudflare ; seul le rendu (pixels) atteint le poste. Le webmail
|
|
# personnel reste accessible mais ne peut plus exfiltrer de fichiers.
|
|
# NOTE : RBI est une fonctionnalité sous licence — politique livrée
|
|
# enabled = false, à activer une fois l'abonnement disponible
|
|
# (et décommenter browser_isolation dans
|
|
# Traffic_Policies-Traffic_Settings-Policy_Setting.tf).
|
|
isolate_webmail = {
|
|
name = "HTTP - Isolate: Webmails personnels"
|
|
description = "Ouvre les webmails personnels dans un navigateur distant isole (RBI)"
|
|
enabled = false
|
|
action = "isolate"
|
|
precedence = local.precedence_http.webmail_isolate
|
|
filters = ["http"]
|
|
traffic = "any(http.request.uri.content_category[*] in {155})"
|
|
notification_enabled = false
|
|
}
|
|
|
|
allow_chatgpt_log = {
|
|
name = "HTTP - Allow: ChatGPT logging"
|
|
description = "Log ChatGPT requests"
|
|
enabled = true
|
|
action = "allow"
|
|
precedence = local.precedence_http.chatgpt_allow_log
|
|
filters = ["http"]
|
|
traffic = "any(app.ids[*] == 1199) and any(app_control.controls[*] in {1652})"
|
|
notification_enabled = false
|
|
gen_ai_prompt_log = true
|
|
}
|
|
}
|
|
}
|
|
|
|
#==========================================================
|
|
# Gateway Policies
|
|
#==========================================================
|
|
resource "cloudflare_zero_trust_gateway_policy" "policies_http" {
|
|
for_each = local.gateway_policies_http
|
|
|
|
account_id = local.cloudflare_account_id
|
|
name = each.value.name
|
|
description = each.value.description
|
|
enabled = each.value.enabled
|
|
action = each.value.action
|
|
precedence = each.value.precedence
|
|
filters = each.value.filters
|
|
traffic = each.value.traffic
|
|
|
|
# Optional fields
|
|
identity = try(each.value.identity, null)
|
|
device_posture = try(each.value.device_posture, null)
|
|
|
|
rule_settings = merge(
|
|
local.default_block_settings_http,
|
|
{
|
|
block_reason = try(each.value.block_reason, "")
|
|
notification_settings = {
|
|
enabled = try(each.value.notification_enabled, false)
|
|
msg = try(each.value.block_reason, "")
|
|
}
|
|
redirect = try(each.value.redirect_url, null) != null ? {
|
|
target_uri = each.value.redirect_url
|
|
preserve_path_and_query = false
|
|
include_context = false
|
|
} : null
|
|
gen_ai_prompt_log = try(each.value.gen_ai_prompt_log, null) != null ? {
|
|
enabled = each.value.gen_ai_prompt_log
|
|
} : null
|
|
}
|
|
)
|
|
}
|