Browse Source

Add support for Knot DNS API

The script is actually an adapted version of the `dns_nsupdate.sh` script,
as the `knsupdate` utility is quite similar to `nsupdate`.
csmk 8 years ago
parent
commit
9c87a5890d
3 changed files with 141 additions and 0 deletions
  1. 1 0
      README.md
  2. 45 0
      dnsapi/README.md
  3. 95 0
      dnsapi/dns_knot.sh

+ 1 - 0
README.md

@@ -295,6 +295,7 @@ You don't have to do anything manually!
 1. cyon.ch
 1. cyon.ch
 1. Domain-Offensive/Resellerinterface/Domainrobot API
 1. Domain-Offensive/Resellerinterface/Domainrobot API
 1. Gandi LiveDNS API
 1. Gandi LiveDNS API
+1. Knot DNS API
 
 
 **More APIs coming soon...**
 **More APIs coming soon...**
 
 

+ 45 - 0
dnsapi/README.md

@@ -349,6 +349,51 @@ Ok, let's issue a cert now:
 acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com
 acme.sh --issue --dns dns_gandi_livedns -d example.com -d www.example.com
 ```
 ```
 
 
+## 19. Use Knot (knsupdate) DNS API to automatically issue cert
+
+First, generate a TSIG key for updating the zone.
+
+```
+keymgr tsig generate acme_key algorithm hmac-sha512 > /etc/knot/acme.key
+```
+
+Include this key in your knot configuration file.
+
+```
+include: /etc/knot/acme.key
+```
+
+Next, configure your zone to allow dynamic updates.
+
+Dynamic updates for the zone are allowed via proper ACL rule with the `update` action. For in-depth instructions, please see [Knot DNS's documentation](https://www.knot-dns.cz/documentation/).
+
+```
+acl:
+  - id: acme_acl
+    address: 192.168.1.0/24
+    key: acme_key
+    action: update
+
+zone:
+  - domain: example.com
+    file: example.com.zone
+    acl: acme_acl
+```
+
+Finally, make the DNS server and TSIG Key available to `acme.sh`
+
+```
+export KNOT_SERVER="dns.example.com"
+export KNOT_KEY=`grep \# /etc/knot/acme.key | cut -d' ' -f2`
+```
+
+Ok, let's issue a cert now:
+```
+acme.sh --issue --dns dns_knot -d example.com -d www.example.com
+```
+
+The `KNOT_SERVER` and `KNOT_KEY` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
+
 # Use custom API
 # Use custom API
 
 
 If your API is not supported yet, you can write your own DNS API.
 If your API is not supported yet, you can write your own DNS API.

+ 95 - 0
dnsapi/dns_knot.sh

@@ -0,0 +1,95 @@
+#!/usr/bin/env sh
+
+########  Public functions #####################
+
+#Usage: dns_knot_add   _acme-challenge.www.domain.com   "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
+dns_knot_add() {
+  fulldomain=$1
+  txtvalue=$2
+  _checkKey || return 1
+  [ -n "${KNOT_SERVER}" ] || KNOT_SERVER="localhost"
+  # save the dns server and key to the account.conf file.
+  _saveaccountconf KNOT_SERVER "${KNOT_SERVER}"
+  _saveaccountconf KNOT_KEY "${KNOT_KEY}"
+
+  if ! _get_root "$fulldomain"; then
+    _err "Domain does not exist."
+    return 1
+  fi
+
+  _info "Adding ${fulldomain}. 60 TXT \"${txtvalue}\""
+
+  knsupdate -y "${KNOT_KEY}" <<EOF
+server ${KNOT_SERVER}
+zone ${_domain}.
+update add ${fulldomain}. 60 TXT "${txtvalue}"
+send
+quit
+EOF
+
+  if [ $? -ne 0 ]; then
+    _err "Error updating domain."
+    return 1
+  fi
+
+  _info "Domain TXT record successfully added."
+  return 0
+}
+
+#Usage: dns_knot_rm   _acme-challenge.www.domain.com
+dns_knot_rm() {
+  fulldomain=$1
+  _checkKey || return 1
+  [ -n "${KNOT_SERVER}" ] || KNOT_SERVER="localhost"
+
+  if ! _get_root "$fulldomain"; then
+    _err "Domain does not exist."
+    return 1
+  fi
+
+  _info "Removing ${fulldomain}. TXT"
+
+  knsupdate -y "${KNOT_KEY}" <<EOF
+server ${KNOT_SERVER}
+zone ${_domain}.
+update del ${fulldomain}. TXT
+send
+quit
+EOF
+
+  if [ $? -ne 0 ]; then
+    _err "error updating domain"
+    return 1
+  fi
+
+  _info "Domain TXT record successfully deleted."
+  return 0
+}
+
+####################  Private functions below ##################################
+# _acme-challenge.www.domain.com
+# returns
+# _domain=domain.com
+_get_root() {
+  domain=$1
+  i="$(echo "$fulldomain" | tr '.' ' ' | wc -w)"
+  i=$(_math $i - 1)
+
+  while true; do
+    h=$(printf "%s" "$domain" | cut -d . -f $i-100)
+    if [ -z "$h" ]; then
+      return 1
+    fi
+    _domain="$h"
+    return 0
+  done
+  _debug "$domain not found"
+  return 1
+}
+
+_checkKey() {
+  if [ -z "${KNOT_KEY}" ]; then
+    _err "You must specify a TSIG key to authenticate the request."
+    return 1
+  fi
+}