diff --git a/inwx-acme.md b/inwx-acme.md new file mode 100644 index 0000000..14bd2d9 --- /dev/null +++ b/inwx-acme.md @@ -0,0 +1,142 @@ +This hook utilizes the xml-rpc api of http://inwx.com for handling dns-01 type challenges. +Its only dependencies are bash, libxml2 and curl. + +The hook expects to find inwx credentials in `$BASEDIR/inwx-acme.auth`: + +``` +#!/usr/bin/bash +# inwx-acme.auth + +user='your inwx username' +pass='your inwx password' +``` + +``` bash +#!/usr/bin/bash +# inwx-acme + +# Copyright (c) Joakim Reinert. All rights reserved. +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +API_URL='https://api.domrobot.com/xmlrpc/' +TMPDIR='/tmp/inwx-acme' + +source "$BASEDIR/inwx-acme.auth" # contains user and pass variables + +USER=$user +PASS=$pass + +build_method_call() { + local method_name=$1 + shift + echo -n "" + echo -n "" + echo -n "$method_name" + echo -n "" + + for param in "$@"; do + echo -n "$param" + done + + echo -n "$(build_param "user" "$USER")" + echo -n "$(build_param "pass" "$PASS")" + + echo -n "" + echo -n "" +} + +build_param() { + local name=$1 + local value=$2 + local type=${3:-string} + echo -n '' + echo -n "$name" + echo -n "<$type>" + if [[ "$type" = 'string' ]]; then + echo -n "" + else + echo -n "$value" + fi + echo -n "" + echo -n "" +} + +build_create_record_call() { + local domain=$1 + local name=$2 + local type=$3 + local content=$4 + local ttl=3600 + + build_method_call 'nameserver.createRecord' \ + "$(build_param 'domain' $domain)" \ + "$(build_param 'name' $name)" \ + "$(build_param 'type' $type)" \ + "$(build_param 'content' $content)" \ + "$(build_param 'ttl' $ttl 'int')" +} + +build_list_call() { + build_method_call 'nameserver.list' +} + +build_delete_record_call() { + local id=$1 + build_method_call 'nameserver.deleteRecord' \ + "$(build_param 'id' $id)" +} + +method_call() { + local call=$1 + local result=$(curl -s -c "$TMPDIR/cookies" -d "$call" -H 'Content-Type: text/xml' "$API_URL") + local xpath='//methodResponse//params//member/name[text()="code"]/../value/int/text()' + local code=$(echo "$result" | xmllint --xpath "$xpath" -) + if [ $code = 1000 ]; then + echo "$result" + return 0 + else + echo "$result" >&2 + return 1 + fi +} + +deploy_challenge() { + local domain + local subdomain + if [[ -z "${1/*.*.*/}" ]]; then + domain=${1#*.} + subdomain=${1%%.*} + else + domain=$1 + subdomain='' + fi + local token=$2 + + local result=$(method_call \ + "$(build_create_record_call "$domain" "_acme-challenge.$subdomain" 'TXT' "$token")") + local code=$? + local xpath='//methodResponse//params//member/name[text()="id"]/../value/int/text()' + echo "$result" | xmllint --xpath "$xpath" - + return $code +} + +clean_challenge() { + local record_id=$1 + method_call \ + "$(build_delete_record_call "$record_id")" > /dev/null +} + +mkdir -p "$TMPDIR" + +case $1 in +'deploy_challenge') + deploy_challenge "$2" "$4" > "$TMPDIR/$2.id" + ;; +'clean_challenge') + clean_challenge "$(cat "$TMPDIR/$2.id")" || exit 1 + rm "$TMPDIR/$2.id" + ;; +esac +``` \ No newline at end of file