# fail2ban focuses banning IP addresses at the application level rather than
# TCP-level packet inspection. This means that most ban filters require setting
# up highly specific listeners or parsers for ban criteria

# In the event of an offending action by an IP address, we drop all future 
# packets from IP until the ban expires

# Test failregex parsing:
# k -n kube-system exec -it deploy/fail2ban -- fail2ban-regex 'STRING' 'REGEX'

# View fail2ban logs:
# k -n kube-system exec -it deploy/fail2ban -- tail -f /var/log/fail2ban.log

# Manual IP bans (run cmd in pod)
# fail2ban-client set manban banip 172.58.35.209 (also supports CIDR)
# fail2ban-client status manban

# Further reading
# https://github.com/crazy-max/docker-fail2ban
# https://github.com/fail2ban/fail2ban

apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    component: fail2ban
  name: fail2ban
  namespace: kube-system
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fail2ban
  namespace: kube-system
spec:
  selector:
    matchLabels:
      component: fail2ban
  template:
    metadata:
      labels:
        component: fail2ban
    spec:
      containers:
        - command:
            - /bin/sh
            - -c
            - |
              # TODO: Create scheme for persisted bans (write file, cloud, etc)
              # and sync it across different Kubernetes nodes
              # if [ -n "$(cat /denylist.txt)" ]; then
              #   gcloud ...
              # fi
              mkdir -p /data/jail.d; # Required for fail2ban to start
              touch /manban.log;     # Required for manban jail to work

              cat << EOF > /etc/fail2ban/action.d/iptables-ipset-proto4.local
              [Init]
              blocktype = DROP
              chain = PREROUTING
              lockingopt = -w -t raw
              EOF

              cat << EOF > /etc/fail2ban/action.d/iptables-ipset-proto6-allports.local
              [Init]
              blocktype = DROP
              chain = PREROUTING
              lockingopt = -w -t raw
              EOF

              cat << EOF > /etc/fail2ban/jail.local
              [DEFAULT]
              bantime  = 3600 # One hour ban
              maxretry = 2
              action = %(action_)s # action only
              # action = %(action_mwl)s # action + mail with logs
              # destemail = octo-berkeleytime@asuc.org
              # sender = noreply@berkeleytime.com

              [manban]
              enabled  = true
              action = iptables-ipset-proto6-allports[protocol="all"]
              bantime  = -1
              filter   = manban

              [psql]
              enabled  = true
              filter   = psql
              action   = iptables-ipset-proto6-allports[protocol="all"]
              findtime = 100 # 100-second rolling search window for logins
              logpath  = /var/log/containers/bt-psql-staging.log

              [ssh]
              enabled  = true
              filter   = sshd
              logpath  = /var/log/auth.log
              action   = iptables-ipset-proto6-allports[protocol="all"]
              EOF

              cat << EOF > /etc/fail2ban/filter.d/manban.conf
              [Definition]
              failregex =
              ignoreregex =
              EOF

              cat << EOF > /etc/fail2ban/filter.d/psql.conf
              [Definition]
              failregex = <HOST> FATAL
              EOF

              fail2ban-server -f -x -v start;
          env:
            - name: F2B_DB_PURGE_AGE
              value: 1d
            - name: F2B_LOG_TARGET
              value: STDOUT
            - name: F2B_LOG_LEVEL
              value: DEBUG
            - name: TZ
              value: America/Los_Angeles
          image: crazymax/fail2ban:0.10.5
          name: fail2ban
          securityContext:
            capabilities:
              add:
                - "NET_ADMIN"
                - "NET_RAW"
                - "SYS_TIME"
          volumeMounts:
            - mountPath: /var/log
              name: var-log
      hostNetwork: true
      volumes:
        - name: var-log
          hostPath:
            path: /var/log
