christoph ender's
blog
wednesday the 3rd of april, 2024
minimal inwx certbot handler
I've been trying to implement the ACME DNS-01 challenge with certbot and INWX. I'm doing this for a MFA / MobileTAN protected account, which limits the choice of API clients to the INWX PHP client.
⚠
This is a prototype. Don't use in production. It's in a “works-for-me”
state, but there's no error checking and not even any thourough testing
involved.
Installation of this PHP API client is best done via composer:
apt-get install composer composer require inwx/domrobot
Install certbot and certbot-external-auth plugin – no idea if “future” is required everywhere, however I got an error complaining about a missing “past” module without it.
apt install certbot pip3 install future pip3 install certbot-external-auth
Minimum handler for Let's Encrypt/INWX, to be placed above Composer's
vendor
directory:
certbot-inwx-minimum-handler.php
#!/usr/bin/php <?php error_reporting(E_ALL); require 'vendor/autoload.php'; function login() { $username = 'my-username'; $password = 'my-password'; $token = 'my-token'; $domrobot = new \INWX\Domrobot(); $result = $domrobot->setLanguage('en') ->useJson() ->useLive() ->setDebug(true) ->login($username, $password, $token); return $domrobot; } function getLeftAndRightSide($domain) { $domainParts = explode('.', $domain); $domainPartCount = count($domainParts); $leftSide = ""; $i=0; while ($i < $domainPartCount - 2) { if (strlen($leftSide) > 0) { $leftSide .= "."; } $leftSide .= $domainParts[$i]; $i++; } $rightSide = $domainParts[$domainPartCount - 2] . "." . $domainParts[$domainPartCount - 1]; return [ 'leftSide' => $leftSide, 'rightSide' => $rightSide ]; } if ($argv[1] == "perform") { $validation = getenv('validation'); $bothSides = getLeftAndRightSide(getenv('txt_domain')); $domrobot = login(); $result = $domrobot->call('nameserver', 'createRecord', [ 'domain' => $bothSides['rightSide'], 'type' => 'TXT', 'name' => $bothSides['leftSide'], 'content' => $validation, 'ttl' => 300, 'testing' => false ]); $domrobot->logout(); sleep(30); } elseif ($argv[1] == "cleanup") { $bothSides = getLeftAndRightSide(getenv('domain')); $domrobot = login(); $validation = getenv('validation'); $result = $domrobot->call('nameserver', 'info', [ 'domain' => $bothSides['rightSide'], 'type' => 'TXT', 'content' => $validation ]); $resData = $result['resData']; if (count($resData['record'] == 1)) { $id = $resData['record'][0]['id']; $result = $domrobot->call('nameserver', 'deleteRecord', [ 'id' => $id ]); } $domrobot->logout(); } ?>
The script above can be used in certbot's “handler mode“ like this:
run-certbot.sh
#!/bin/sh certbot \ certonly \ --text \ --keep-until-expiring --configurator certbot-external-auth:out \ --preferred-challenges dns \ --certbot-external-auth:out-public-ip-logging-ok \ --certbot-external-auth:out-handler ${MY_DIR}/certbot-external-handler.php -d 'example.org' \