From 105c11eb95337a53e5682b7185d48293320bcccc Mon Sep 17 00:00:00 2001 From: Mark Tearle <mtearle@ucc.asn.au> Date: Wed, 24 Nov 2021 19:05:30 +0800 Subject: [PATCH] Move quovadis over to dynu.com --- quovadis/config_sample.php | 4 +- quovadis/quovadis.php | 174 +++++++++++++++++++++++++++++++++++-- 2 files changed, 171 insertions(+), 7 deletions(-) diff --git a/quovadis/config_sample.php b/quovadis/config_sample.php index 8d431e7..3542d78 100644 --- a/quovadis/config_sample.php +++ b/quovadis/config_sample.php @@ -6,8 +6,8 @@ function get_config() { # email from address for emails generated by quovadis 'QV_FROM' => "quovadis@ucc.asn.au", - # API key for desec.io - 'QV_DESEC_API' => "ABCD1234", + # API key for dynu.com + 'QV_DYNU_API' => "ABCD1234", # Domain at desec.io 'QV_DOMAIN' => "quovadis-challenges.ucc.asn.au", diff --git a/quovadis/quovadis.php b/quovadis/quovadis.php index ce2ed90..435478a 100644 --- a/quovadis/quovadis.php +++ b/quovadis/quovadis.php @@ -34,6 +34,90 @@ function stripQuotes($text) { return preg_replace('/^(\'(.*)\'|"(.*)")$/', '$2$3', $text); } +function get_txt($config, $name) { + return get_dynu_txt($config, $name); +} + +function get_dynu_domainid($config, $name) { + $restService = new RestService(); + $path = "/v2/dns/getroot/" . $name . "." . $config['QV_DOMAIN']; + $auth_string = $config['QV_DYNU_API']; + + $response = $restService + ->setEndpoint('https://api.dynu.com') + ->setRequestHeaders([ + 'API-Key' => $auth_string + # accept: application/json + ]) + ->get($path, [], [], false); + + $result = json_decode($response->getBody(), true); + var_dump($result); + if (array_key_exists('id', $result)) { + return $result['id']; + } + + return 0; +} + +function get_dynu_txt($config, $name) { + $restService = new RestService(); + $path = "/v2/dns/record/" . $name . "." . $config['QV_DOMAIN']; + $query = [ + "recordType"=>"TXT", + ]; + $auth_string = $config['QV_DYNU_API']; + + $response = $restService + ->setEndpoint('https://api.dynu.com') + ->setRequestHeaders([ + 'API-Key' => $auth_string + # accept: application/json + ]) + ->get($path, $query, [], false); + + $result = json_decode($response->getBody(), true); + var_dump($result); + if (array_key_exists('dnsRecords', $result)) { + if (count($result['dnsRecords'])){ + if (array_key_exists('textData', $result['dnsRecords'][0])) { + return stripQuotes($result['dnsRecords'][0]['textData']); + } + } + } + + return ""; +} + +function get_dynu_txt_recordid($config, $name) { + $restService = new RestService(); + $path = "/v2/dns/record/" . $name . "." . $config['QV_DOMAIN']; + $query = [ + "recordType"=>"TXT", + ]; + $auth_string = $config['QV_DYNU_API']; + + $response = $restService + ->setEndpoint('https://api.dynu.com') + ->setRequestHeaders([ + 'API-Key' => $auth_string + # accept: application/json + ]) + ->get($path, $query, [], false); + + $result = json_decode($response->getBody(), true); + var_dump($result); + if (array_key_exists('dnsRecords', $result)) { + if (count($result['dnsRecords'])){ + if (array_key_exists('id', $result['dnsRecords'][0])) { + return stripQuotes($result['dnsRecords'][0]['id']); + } + } + } + + return 0; +} + function get_desec_txt($config, $name) { $restService = new RestService(); $path = "/api/v1/domains/" . $config['QV_DOMAIN'] . "/rrsets/" . $name . "/TXT/"; @@ -67,7 +151,7 @@ function encrypt_api_key($api_key) { function check_api_key($config, $username, $api_key) { // API keys need to be alpha numeric - $hash = hex2bin(get_desec_txt($config, $username)); + $hash = hex2bin(get_txt($config, $username)); return password_verify($api_key, $hash); } @@ -91,6 +175,86 @@ function check_challenge($challenge) { // EOF // +function update_txt($config, $name, $txt) { + return update_dynu_txt($config, $name, $txt); +} + +function update_dynu_txt($config, $name, $txt) { + $domainId = get_dynu_domainid($config, $name); + + # delete dynu txt + $recordid = get_dynu_txt_recordid($config, $name); + + while ($recordid) { + delete_dynu_record($config, $domainId, $recordid); + $recordid = get_dynu_txt_recordid($config, $name); + } + + # create dynu txt + # curl -s -X POST "https://api.dynu.com/v2/dns/$domainID/record" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"nodeName\":\"_acme-challenge\",\"recordType\":\"TXT\",\"ttl\":60,\"state\":true,\"group\":\"\",\"textData\":\"$CERTBOT_VALIDATION\"}" -H "API-Key: $api_key" + + $path = "/v2/dns/" . $domainId . "/record/" . $recordid; + $auth_string = $config['QV_DYNU_API']; + + $headers = [ + 'API-Key' => $auth_string, + 'Content-Type' => "application/json", + ]; + + + $val = [ + 'nodeName' => $name, + 'recordType' => 'TXT', + 'ttl' => 120, + 'state' => true, + 'group' => '', + 'textData' => $txt, + ]; + + $body = json_encode($val); + + + $client = new GuzzleHttp\Client([ + 'base_uri' => 'https://api.dynu.com', + 'timeout' => 2, + 'debug' => true + ]); + + try { + $response = $client->request('POST', $path, [ 'headers'=>$headers, 'body'=>$body ]); + } catch (ClientException $e) { + throw new Exception($e->getResponse()->getReasonPhrase(), $e->getResponse()->getStatusCode()); + } catch (BadResponseException $e) { + throw new Exception($e->getResponse()->getReasonPhrase(), $e->getResponse()->getStatusCode()); + } catch (Exception $e) { + throw new Exception($e->getMessage(), $e->getCode()); + } + + $result = json_decode($response->getBody(), true); + + return ""; + +} + +function delete_dynu_record($config, $domainId, $recordid) { + # curl -X DELETE "https://api.dynu.com/v2/dns/100000000/record/2" -H "accept: application/json" + $restService = new RestService(); + $path = "/v2/dns/" . $domainId . "/record/" . $recordid; + $auth_string = $config['QV_DYNU_API']; + $response = $restService + ->setEndpoint('https://api.dynu.com') + ->setRequestHeaders([ + 'API-Key' => $auth_string + # accept: application/json + ]) + ->delete($path, [], [], false); + + $result = json_decode($response->getBody(), true); + + return 0; +} + +# function update_desec_txt($config, $name, $txt) { $auth_string = "Token ". $config['QV_DESEC_API']; $headers = [ @@ -262,7 +426,7 @@ $leaf->post('/register', function () use($leaf) { } // Check there is no existing API key registered for the user - $a = get_desec_txt($config, $username); + $a = get_txt($config, $username); if ( $a <> "" ) { $leaf->response->json(["message" => $username." already registered"],200); return; @@ -272,7 +436,7 @@ $leaf->post('/register', function () use($leaf) { $api_key = Uuid::uuid4()->toString(); // Stick API key encrypted into the DNS - $u = update_desec_txt($config, $username, encrypt_api_key($api_key)); + $u = update_txt($config, $username, encrypt_api_key($api_key)); // Email API key email_api_key($username, $api_key); @@ -317,7 +481,7 @@ $leaf->post('/update-api-key', function () use($leaf) { // Encrypt API key // Stick API key encrypted into the DNS - $u = update_desec_txt($config, $username, encrypt_api_key($new_api_key)); + $u = update_txt($config, $username, encrypt_api_key($new_api_key)); $leaf->response->json(["message" => $username." API key has been updated"],200); @@ -374,7 +538,7 @@ $leaf->post('/update-challenge', function () use($leaf) { } // Stick challenge value prefixed by username into DNS - $u = update_desec_txt($config, $handle, $value); + $u = update_txt($config, $handle, $value); $leaf->response->json(["message" => $handle." has been updated"],200); -- GitLab