# /etc/haproxy/haproxy.cfg

frontend FE-multiple-applications
  mode http
  bind :80
  # ssl offloading on port 443 using a certificate from /etc/haproxy/ssl/ directory
  bind :443 ssl crt /etc/haproxy/ssl/ alpn h2,http/1.1 ssl-min-ver TLSv1.2 no-tls-tickets

  # set X-Real-IP header required for Anubis
  http-request set-header X-Real-IP "%[src]"

  # redirect HTTP to HTTPS
  http-request redirect scheme https code 301 unless { ssl_fc }
  # add HSTS header
  http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

  # only force Anubis challenge for app1 and app2
  acl acl_anubis_required hdr(host) -i "app1.example.com"
  acl acl_anubis_required hdr(host) -i "app2.example.com"

  # exclude Anubis for a specific path
  acl acl_anubis_ignore path /excluded/path

  # use Anubis if auth cookie not found
  use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ req.cook(techaro.lol-anubis-auth) -m found }

  # get payload of the JWT such as algorithm, expire time, restrictions
  http-request set-var(txn.anubis_jwt_alg) req.cook(techaro.lol-anubis-auth),jwt_header_query('$.alg') if acl_anubis_required !acl_anubis_ignore
  http-request set-var(txn.anubis_jwt_exp) cook(techaro.lol-anubis-auth),jwt_payload_query('$.exp','int') if acl_anubis_required !acl_anubis_ignore
  http-request set-var(txn.anubis_jwt_res) cook(techaro.lol-anubis-auth),jwt_payload_query('$.restriction') if acl_anubis_required !acl_anubis_ignore
  http-request set-var(txn.srcip) req.fhdr(X-Real-IP) if acl_anubis_required !acl_anubis_ignore
  http-request set-var(txn.now) date() if acl_anubis_required !acl_anubis_ignore

  # use Anubis if JWT has wrong algorithm, is expired, restrictions don't match or isn't signed with the correct key
  use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ var(txn.anubis_jwt_alg) -m str HS512 }
  use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore { var(txn.anubis_jwt_exp),sub(txn.now) -m int lt 0 }
  use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ var(txn.srcip),digest(sha256),hex,lower,strcmp(txn.anubis_jwt_res) eq 0 }
  use_backend BE-anubis if acl_anubis_required !acl_anubis_ignore !{ cook(techaro.lol-anubis-auth),jwt_verify(txn.anubis_jwt_alg,"<SECRET-HERE>") -m int 1 }

  # custom routing in HAProxy
  use_backend BE-app1 if { hdr(host) -i "app1.example.com" }
  use_backend BE-app2 if { hdr(host) -i "app2.example.com" }
  use_backend BE-app3 if { hdr(host) -i "app3.example.com" }

backend BE-app1
  mode http
  server app1-server 127.0.0.1:3000

backend BE-app2
  mode http
  server app2-server 127.0.0.1:4000

backend BE-app3
  mode http
  server app3-server 127.0.0.1:5000

BE-anubis
  mode http
  server anubis /run/anubis/default.sock
