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' \