# CrowdSec Security Engine Deployment
# Monitors and protects against malicious traffic on NGINX Ingress

resource "kubernetes_namespace" "crowdsec" {
  metadata {
    name = "crowdsec"
  }
}

# PersistentVolume for LAPI config on host path
resource "kubernetes_persistent_volume" "crowdsec_lapi_config" {
  metadata {
    name = "crowdsec-lapi-config-pv"
  }
  spec {
    capacity = {
      storage = "1Gi"
    }
    access_modes       = ["ReadWriteOnce"]
    storage_class_name = "local-path"
    persistent_volume_source {
      host_path {
        path = "/mnt/k8s/crowdsec/lapi-config"
        type = "DirectoryOrCreate"
      }
    }
    node_affinity {
      required {
        node_selector_term {
          match_expressions {
            key      = "kubernetes.io/hostname"
            operator = "In"
            values   = ["server-3"]
          }
        }
      }
    }
  }
}

# PersistentVolume for LAPI data on host path
resource "kubernetes_persistent_volume" "crowdsec_lapi_data" {
  metadata {
    name = "crowdsec-lapi-data-pv"
  }
  spec {
    capacity = {
      storage = "2Gi"
    }
    access_modes       = ["ReadWriteOnce"]
    storage_class_name = "local-path"
    persistent_volume_source {
      host_path {
        path = "/mnt/k8s/crowdsec/lapi-data"
        type = "DirectoryOrCreate"
      }
    }
    node_affinity {
      required {
        node_selector_term {
          match_expressions {
            key      = "kubernetes.io/hostname"
            operator = "In"
            values   = ["server-3"]
          }
        }
      }
    }
  }
}

resource "helm_release" "crowdsec" {
  name       = "crowdsec"
  repository = "https://crowdsecurity.github.io/helm-charts"
  chart      = "crowdsec"
  version    = "0.24.0"
  namespace  = kubernetes_namespace.crowdsec.metadata[0].name

  wait    = true
  timeout = 600

  values = [
    yamlencode({
      container_runtime = "containerd"

      image = {
        repository = "crowdsecurity/crowdsec"
        tag        = "v1.7.8"
        pullPolicy = "IfNotPresent"
      }

      lapi = {
        enabled  = true
        replicas = 1

        resources = {
          limits = {
            memory = "512Mi"
            cpu    = "500m"
          }
          requests = {
            memory = "256Mi"
            cpu    = "100m"
          }
        }

        persistentVolume = {
          config = {
            enabled          = true
            accessModes      = ["ReadWriteOnce"]
            storageClassName = "local-path"
            size             = "1Gi"
          }
          data = {
            enabled          = true
            accessModes      = ["ReadWriteOnce"]
            storageClassName = "local-path"
            size             = "2Gi"
          }
        }

        metrics = {
          enabled = true
        }

        env = [
          {
            name  = "ENROLL_KEY"
            value = "cmgcsgn14000e02l1xmme5qnm"
          },
          {
            name  = "ENROLL_INSTANCE_NAME"
            value = "junv-home-k3s-cluster"
          },
          {
            name  = "ENROLL_TAGS"
            value = "junv k3s homelab nginx"
          }
        ]
      }

      agent = {
        enabled      = true
        isDeployment = false

        resources = {
          limits = {
            memory = "512Mi"
            cpu    = "500m"
          }
          requests = {
            memory = "256Mi"
            cpu    = "100m"
          }
        }

        hostVarLog = true

        metrics = {
          enabled = true
        }

        # Monitor NGINX Ingress Controller logs and SSH logs
        acquisition = [
          {
            namespace              = "ingress-nginx"
            podName                = "ingress-nginx-controller-*"
            program                = "nginx"
            poll_without_inotify   = true  # Container logs are symlinks, need polling
          }
        ]

        # Additional acquisition for host SSH logs and firewall logs
        additionalAcquisition = [
          {
            source    = "file"
            filenames = ["/var/log/auth.log"]
            labels = {
              type = "syslog"
            }
          },
          {
            source    = "file"
            filenames = ["/var/log/kern.log", "/var/log/syslog"]
            labels = {
              type = "syslog"
            }
          }
        ]

        # Install NGINX, SSH, and iptables/firewall collections
        env = [
          {
            name  = "COLLECTIONS"
            value = "crowdsecurity/nginx crowdsecurity/base-http-scenarios crowdsecurity/linux crowdsecurity/sshd crowdsecurity/iptables crowdsecurity/endlessh"
          }
        ]

        persistentVolume = {
          config = {
            enabled = false
          }
        }
      }

      config = {
        "config.yaml.local" = <<-EOT
          api:
            server:
              auto_registration:
                enabled: true
                token: "$${REGISTRATION_TOKEN}"
                allowed_ranges:
                  - "127.0.0.1/32"
                  - "10.0.0.0/8"
                  - "172.16.0.0/12"
                  - "192.168.0.0/16"
              log_level: info
              listen_uri: 0.0.0.0:8080
            client:
              insecure_skip_verify: false
          common:
            daemonize: false
            log_media: stdout
            log_level: info
        EOT

        "profiles.yaml.local" = <<-EOT
          name: default_ip_remediation
          filters:
            - Alert.Remediation == true && Alert.GetScope() == "Ip"
          decisions:
            - type: ban
              duration: 24h
          on_success: break
        EOT
      }
    })
  ]

  depends_on = [
    kubernetes_namespace.crowdsec,
    kubernetes_persistent_volume.crowdsec_lapi_config,
    kubernetes_persistent_volume.crowdsec_lapi_data
  ]
}

# Wait for CrowdSec to be ready and create bouncer
resource "null_resource" "crowdsec_bouncer_setup" {
  depends_on = [helm_release.crowdsec]

  provisioner "local-exec" {
    command = <<-EOT
      echo "Waiting for CrowdSec LAPI to be ready..."
      kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=crowdsec,app.kubernetes.io/component=lapi -n crowdsec --timeout=300s

      echo "Creating NGINX bouncer..."
      BOUNCER_KEY=$(kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli bouncers add nginx-ingress-bouncer -o raw 2>/dev/null || echo "")

      if [ -z "$BOUNCER_KEY" ]; then
        echo "Bouncer may already exist, retrieving existing key..."
        kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli bouncers list
      else
        echo "Bouncer created successfully!"
        echo "Creating Kubernetes secret with bouncer key..."
        kubectl create secret generic crowdsec-bouncer-tls -n ingress-nginx \
          --from-literal=crowdsec-api=http://crowdsec-service.crowdsec.svc.cluster.local:8080 \
          --from-literal=crowdsec-key="$BOUNCER_KEY" \
          --dry-run=client -o yaml | kubectl apply -f -
        echo "Bouncer API Key: $BOUNCER_KEY"
      fi

      echo ""
      echo "CrowdSec setup complete!"
      echo "To view status: kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli metrics"
    EOT
  }

  triggers = {
    crowdsec_version = helm_release.crowdsec.version
  }
}

# DISABLED: iptables logging was causing connectivity issues with kubectl
# The rules were blocking legitimate Kubernetes traffic
# CrowdSec will still monitor logs without iptables integration

# resource "ssh_resource" "iptables_logging" {
#   depends_on = [helm_release.crowdsec]
#
#   host        = local.ssh_host
#   user        = local.ssh_user
#   port        = local.ssh_port
#   private_key = local.ssh_private_key
#   timeout     = "5m"
#
#   when = "create"
#
#   commands = [
#     "echo 'Setting up iptables logging for CrowdSec...'",
#
#     # Create chain for suspicious activity logging
#     "sudo iptables -N CROWDSEC_SUSPICIOUS 2>/dev/null || true",
#     "sudo iptables -F CROWDSEC_SUSPICIOUS 2>/dev/null || true",
#
#     # IMPORTANT: Exclude local network (192.168.1.0/24) from ALL port scan detection
#     "sudo iptables -I INPUT 1 -s 192.168.1.0/24 -j ACCEPT || true",
#
#     # Track connection attempts for port scan detection (only for external traffic)
#     "sudo iptables -A INPUT -p tcp -m state --state NEW -m recent --set --name portscan || true",
#
#     # If more than 10 connection attempts in 60 seconds from external IPs, log it as suspicious
#     "sudo iptables -A INPUT -p tcp -m state --state NEW -m recent --update --seconds 60 --hitcount 10 --name portscan -j CROWDSEC_SUSPICIOUS || true",
#
#     # Log suspicious activity
#     "sudo iptables -A CROWDSEC_SUSPICIOUS -j LOG --log-prefix 'iptables_SCAN: ' --log-level 4 --log-tcp-options --log-ip-options || true",
#
#     # Drop the suspicious packets
#     "sudo iptables -A CROWDSEC_SUSPICIOUS -j DROP || true",
#
#     # Log invalid packets from external sources only (often used in attacks)
#     "sudo iptables -A INPUT -m state --state INVALID -j LOG --log-prefix 'iptables_INVALID: ' --log-level 4 || true",
#     "sudo iptables -A INPUT -m state --state INVALID -j DROP || true",
#
#     # Install iptables-persistent to save rules
#     "sudo DEBIAN_FRONTEND=noninteractive apt-get install -y iptables-persistent 2>/dev/null || true",
#
#     # Save the rules
#     "sudo mkdir -p /etc/iptables",
#     "sudo iptables-save | sudo tee /etc/iptables/rules.v4 > /dev/null",
#
#     "echo '✅ iptables logging configured!'",
#     "echo 'Port scans and suspicious activity will now be logged and detected by CrowdSec'"
#   ]
# }

output "crowdsec_info" {
  value = <<-EOT
    CrowdSec deployed successfully!

    Monitoring:
    - ✅ NGINX Ingress (ingress-nginx namespace)
    - ✅ SSH attempts (port 22422)
    - ✅ Port scans (iptables logging enabled)
    - ✅ System logs

    Commands:
    - Status: kubectl get pods -n crowdsec
    - Metrics: kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli metrics
    - Decisions: kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli decisions list
    - Bouncers: kubectl exec -n crowdsec deployment/crowdsec-lapi -- cscli bouncers list

    Storage: /mnt/k8s/crowdsec/ on server-3 (192.168.1.2)
    Web Dashboard: https://app.crowdsec.net

    Quick view: ./view_crowdsec.sh
  EOT
}
