added loopia method

This commit is contained in:
Fredrik Eriksson 2020-12-02 13:54:33 +01:00
parent 4f740233f7
commit f4e79adc89
Signed by: feffe
GPG Key ID: 18524638BE25530A
6 changed files with 247 additions and 6 deletions

View File

@ -1,2 +1,9 @@
--- ---
certbot::package: py37-certbot certbot::params::package: py37-certbot
certbot::params::bin_dir: /usr/local/sbin
certbot::params::etc_dir: /usr/local/etc
certbot::params::certbot_bin: /usr/local/bin/certbot
certbot::loopia::api: https://api.loopia.se/RPCSERV
#certbot::loopia::user:
#certbot::loopia::password:

109
files/acme-auth-loopia.py Executable file
View File

@ -0,0 +1,109 @@
#!/usr/bin/env python3.7
import argparse
import configparser
import os
import sys
import time
import xmlrpc.client
import http.client
class ProxiedTransport(xmlrpc.client.Transport):
def set_proxy(self, host, port=None, headers=None):
self.proxy = host, port
self.proxy_headers = headers
def make_connection(self, host):
connection = http.client.HTTPSConnection(*self.proxy)
connection.set_tunnel(host, headers=self.proxy_headers)
self._connection = host, connection
return connection
def main():
if all([x in os.environ for x in ['CERTBOT_DOMAIN', 'CERTBOT_VALIDATION']]):
domain = os.environ['CERTBOT_DOMAIN']
subdomain = '_acme-challenge'
token = os.environ['CERTBOT_VALIDATION']
waittime = 600
else:
parser = argparse.ArgumentParser(description='Update acme-record for subdomain')
parser.add_argument('--domain', '-d', nargs=1, required=True, help='domain to update')
parser.add_argument('--token', '-t', nargs=1, required=True, help='token to set as txt record')
args = parser.parse_args()
domain = args.domain[0]
subdomain = '_acme-challenge'
token = args.token[0]
waittime = 0
new_record = {
'type': 'TXT',
'ttl': '300',
'rdata': token,
'record_id': 0,
'priority': 0
}
config = configparser.ConfigParser()
config.read('/usr/local/etc/loopiaapi.ini')
url = config.get('default', 'url')
user = config.get('default', 'username')
pwd = config.get('default', 'password')
proxy = os.environ.get('http_proxy')
if not proxy:
proxy = os.environ.get('HTTP_PROXY')
if proxy:
transport = ProxiedTransport()
proto, host, port = proxy.split(':')
transport.set_proxy(host.strip('/'), int(port))
client = xmlrpc.client.ServerProxy(uri = url, encoding='utf-8', transport=transport)
else:
client = xmlrpc.client.ServerProxy(uri = url, encoding='utf-8')
while domain:
res = client.getSubdomains(user, pwd, domain)
if 'UNKNOWN_ERROR' not in res:
break
subdomain, domain = domain.split('.', maxsplit=1)
subdomain = '_acme-challenge.{}'.format(subdomain)
if 'UNKNOWN_ERROR' in res:
print("Failed to find domain in loopiadns")
return 1
if subdomain not in res:
res = client.addSubdomain(user, pwd, domain, subdomain)
if res != 'OK':
print('Adding subdomain failed with status: {}'.format(res))
return 1
res = client.getZoneRecords(user, pwd, domain, subdomain)
for rec in res:
if rec['type'] == 'TXT':
if rec['rdata'] == token:
return 0
new_record['record_id'] = rec['record_id']
break
if new_record['record_id']:
res = client.updateZoneRecord(user, pwd, domain, subdomain, new_record)
else:
res = client.addZoneRecord(user, pwd, domain, subdomain, new_record)
if res != 'OK':
print('Setting zone record failed with status: {}'.format(res))
return 1
time.sleep(waittime)
return 0
if __name__ == '__main__':
sys.exit(main())

93
files/acme-cleanup-loopia.py Executable file
View File

@ -0,0 +1,93 @@
#!/usr/bin/env python3.7
import argparse
import configparser
import os
import sys
import time
import xmlrpc.client
import http.client
class ProxiedTransport(xmlrpc.client.Transport):
def set_proxy(self, host, port=None, headers=None):
self.proxy = host, port
self.proxy_headers = headers
def make_connection(self, host):
connection = http.client.HTTPSConnection(*self.proxy)
connection.set_tunnel(host, headers=self.proxy_headers)
self._connection = host, connection
return connection
def main():
if all([x in os.environ for x in ['CERTBOT_DOMAIN', 'CERTBOT_VALIDATION']]):
domain = os.environ['CERTBOT_DOMAIN']
subdomain = '_acme-challenge'
token = os.environ['CERTBOT_VALIDATION']
else:
parser = argparse.ArgumentParser(description='Update acme-record for subdomain')
parser.add_argument('--domain', '-d', nargs=1, required=True, help='domain to update')
parser.add_argument('--token', '-t', nargs=1, required=True, help='token to set as txt record')
args = parser.parse_args()
domain = args.domain[0]
subdomain = '_acme-challenge'
token = args.token[0]
config = configparser.ConfigParser()
config.read('/usr/local/etc/loopiaapi.ini')
url = config.get('default', 'url')
user = config.get('default', 'username')
pwd = config.get('default', 'password')
proxy = os.environ.get('http_proxy')
if not proxy:
proxy = os.environ.get('HTTP_PROXY')
if proxy:
transport = ProxiedTransport()
proto, host, port = proxy.split(':')
transport.set_proxy(host.strip('/'), int(port))
client = xmlrpc.client.ServerProxy(uri = url, encoding='utf-8', transport=transport)
else:
client = xmlrpc.client.ServerProxy(uri = url, encoding='utf-8')
while domain:
res = client.getSubdomains(user, pwd, domain)
if 'UNKNOWN_ERROR' not in res:
break
subdomain, domain = domain.split('.', maxsplit=1)
subdomain = '_acme-challenge.{}'.format(subdomain)
if 'UNKNOWN_ERROR' in res:
print("Failed to find domain in loopiadns")
return 1
if subdomain not in res:
return 0
res = client.getZoneRecords(user, pwd, domain, subdomain)
ret = 0
for rec in res:
if rec['type'] == 'TXT':
if rec['rdata'] == token:
res = client.removeZoneRecord(user, pwd, domain, subdomain, rec['record_id'])
if res != 'OK':
print('Failed to clean up record, loopia response: {}'.format(res))
ret = 1
res = client.removeSubdomain(user, pwd, domain, subdomain)
if res != 'OK':
print('Failed to clean up subdomain, loopia response: {}'.format(res))
ret = 1
return ret
return ret
if __name__ == '__main__':
sys.exit(main())

View File

@ -1,11 +1,10 @@
# install and configure certbot # install and configure certbot
class certbot( class certbot inherits certbot::params {
String[1] $package,
) {
package { package {
$package: 'certbot':
ensure => present; ensure => present,
name => $certbot::params::package;
} }
} }

25
manifests/loopia.pp Normal file
View File

@ -0,0 +1,25 @@
# use loopiaapi for dns challange using certbot
class certbot::loopia (
String[1] $api_url,
String[1] $user,
Sensitive[String[1]] $password,
) inherits certbot::params {
file {
"${certbot::params::bin_dir}/acme-auth-loopia.py":
source => "puppet:///modules/${module_name}/acme-auth-loopia.py",
mode => '0750';
"${certbot::params::bin_dir}/acme-cleanup-loopia.py":
source => "puppet:///modules/${module_name}/acme-cleanup-loopia.py",
mode => '0750';
"${certbot::params::etc_dir}/loopiaapi.ini":
content => inline_epp("[default]\n<% \$params.each |key,val| { %><%= \$key %> = <%= \$val %>\n<% } %>\n", {
'params' => {
'url' => $api_url,
'username' => $user,
'passowrd' => unwrap($password),
} }),
show_diff => false,
mode => '0400';
}
}

8
manifests/params.pp Normal file
View File

@ -0,0 +1,8 @@
# parameters for certbot
class certbot::params(
String[1] $package,
String[1] $bin_dir,
String[1] $etc_dir,
String[1] $certbot_bin,
) {
}