;;; Tyreunom's system administration and configuration tools.
;;;
;;; Copyright © 2019 Julien Lepiller <julien@lepiller.eu>
;;;
;;; This program is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation, either version 3 of the License, or
;;; (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;
;; DNS services
;;

(define-module (config dns)
  #:use-module (data dns)
  #:use-module (gnu services)
  #:use-module (gnu services dns)
  #:use-module (srfi srfi-1)
  #:use-module (ice-9 textual-ports)
  #:export (ipv4-reverse-master-zone
            ipv6-reverse-master-zone
            lepiller-master-zone
            lepiller-slave-zone
            master-acl
            slave-acl
            hermes
            ene))

(define public-dkim
  (apply
    string-append
    (string-split
      (call-with-input-file "/etc/mail/dkim/public.key" get-string-all)
      #\newline)))

(define-zone-entries lepiller.eu.zone
;; Name         TTL Class Type Data
  ("ene"        ""  "IN"  "A"     ene-ip4)
  ("hermes"     ""  "IN"  "A"     hermes-ip4)
  ("hermes"     ""  "IN"  "AAAA"  hermes-ip6)
  ("xana"       ""  "IN"  "A"     xana-ip4)
  ("@"          ""  "IN"  "A"     hermes-ip4)
  ("@"          ""  "IN"  "AAAA"  hermes-ip6)
  ("www"        ""  "IN"  "CNAME" "lepiller.eu.")

  ("avatar"     ""  "IN"  "CNAME" "ene")
  ("git"        ""  "IN"  "CNAME" "ene")
  ("i18n"       ""  "IN"  "CNAME" "xana")
  ("nani"       ""  "IN"  "CNAME" "xana")
  ("offlate"    ""  "IN"  "CNAME" "xana")
  ("rennes"     ""  "IN"  "CNAME" "ene")
  ("social"     ""  "IN"  "CNAME" "ene")

  ("@"          ""  "IN"  "NS"    "ns")
  ("@"          ""  "IN"  "NS"    "ns2")
  ("ns"         ""  "IN"  "A"     hermes-ip4)
  ("ns"         ""  "IN"  "AAAA"  hermes-ip6)
  ("ns2"        ""  "IN"  "A"     ene-ip4)

  ("@"          ""  "IN"  "MX"    "10 courriel")
  ("@"          ""  "IN"  "MX"    "50 b.courriel")
  ("@"          ""  "IN"  "MX"    "20 wio6sja633kwuybkyqex7vvnzqvrhrtzjix6cjhsqi42hx3n2qjfmzid.onion.")
  ("@"          ""  "IN"  "MX"    "60 5g33mrv2rp2onyvte2b3ge5a44fxansxwt4sajmmae7lgorxjgz5czad.onion.")
  ("b.courriel" ""  "IN"  "A"     hermes-ip4)
  ("b.courriel" ""  "IN"  "AAAA"  hermes-ip6)
  ("courriel"   ""  "IN"  "A"     ene-ip4)
  ("imap"       ""  "IN"  "CNAME" "courriel")
  ("smtp"       ""  "IN"  "CNAME" "b.courriel")
  ("@"          ""  "IN"  "TXT"   "\"v=spf1 mx a ~all\"")
  ("@"          ""  "IN"  "SPF"   "\"v=spf1 mx a ~all\"")
  
  ("dkim._domainkey" "" "IN" "TXT" (string-append "v=DKIM1\\; p=" public-dkim "\\; s=email\\; t=s"))
  ("_dmarc"     ""  "IN"  "TXT"   "v=DMARC1\\; p=none\\; sp=reject\\; rua=mailto:rua@lepiller.eu!10m\\; ruf=mailto:ruf@lepiller.eu!10m\\; rf=afrf\\; pct=100\\; ri=86400"))

(define-zone-entries ipv4-reverse.zone
  ("@" "" "IN" "PTR" "lepiller.eu.")
  ("@"          ""  "IN"  "NS"    "ns.lepiller.eu.")
  ("@"          ""  "IN"  "NS"    "ns2.lepiller.eu."))

(define-zone-entries ipv6-reverse.zone
  ("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0" "" "IN" "PTR" "lepiller.eu.")
  ("@"          ""  "IN"  "NS"    "ns.lepiller.eu.")
  ("@"          ""  "IN"  "NS"    "ns2.lepiller.eu."))

(define ene
  (knot-remote-configuration
    (id "ene")
    (address (list ene-ip4))
    (key "lepiller-key")))

(define hermes
  (knot-remote-configuration
    (id "hermes")
    (address (list hermes-ip4 hermes-ip6))
    (key "lepiller-key")))

(define master-acl
  (knot-acl-configuration
    (id "master-acl")
    (address (list hermes-ip4))
    (key '("lepiller-key"))
    (action '(transfer))))

(define slave-acl
  (knot-acl-configuration
    (id "slave-acl")
    (address (list ene-ip4))
    (key '("lepiller-key"))
    (action '(notify))))

(define lepiller-master-zone
  (knot-zone-configuration
    (domain "lepiller.eu")
    (notify '("hermes"))
    (dnssec-policy "default")
    (acl '("master-acl"))
    (zonefile-load 'difference)
    (zone (zone-file
            (origin "lepiller.eu")
            (entries lepiller.eu.zone)
            (serial 2020101201)))))

(define lepiller-slave-zone
  (knot-zone-configuration
    (domain "lepiller.eu")
    (acl '("slave-acl"))
    (master '("ene"))))

(define ipv6-reverse-master-zone
  (let* ((ip6 (string->list (substring (string-delete #\: hermes-ip6) 0 12)))
         (rev-ip6-lst (fold (lambda (elem acc)
                          (cons* #\. elem acc))
                        '()
                        ip6))
         (rev-ip6 (list->string (cdr rev-ip6-lst)))
         (domain (string-append rev-ip6 ".ip6.arpa")))
    (knot-zone-configuration
      (domain domain)
      (zone (zone-file
              (origin domain)
              (entries ipv6-reverse.zone)
              (ns "ns.lepiller.eu.")
              (mail "hostmaster.lepiller.eu.")
              (serial 1))))))

(define ipv4-reverse-master-zone
  (let ((domain (string-append
                  (string-join (reverse (string-split hermes-ip4 #\.)) ".")
                  ".in-addr.arpa")))
    (knot-zone-configuration
      (domain domain)
      (zone (zone-file
              (origin domain)
              (entries ipv4-reverse.zone)
              (ns "ns.lepiller.eu.")
              (mail "hostmaster.lepiller.eu.")
              (serial 1))))))