89 lines
2.8 KiB
Python
89 lines
2.8 KiB
Python
import time
|
|
|
|
import dns.exception
|
|
import dns.resolver
|
|
from dyn.tm.errors import DynectCreateError
|
|
from dyn.tm.session import DynectSession
|
|
from dyn.tm.zones import Node, Zone
|
|
from flask import current_app
|
|
from tld import get_tld
|
|
|
|
|
|
def get_dynect_session():
|
|
dynect_session = DynectSession(
|
|
current_app.config.get('ACME_DYN_CUSTOMER_NAME', ''),
|
|
current_app.config.get('ACME_DYN_USERNAME', ''),
|
|
current_app.config.get('ACME_DYN_PASSWORD', ''),
|
|
)
|
|
return dynect_session
|
|
|
|
|
|
def _has_dns_propagated(name, token):
|
|
txt_records = []
|
|
try:
|
|
dns_resolver = dns.resolver.Resolver()
|
|
dns_resolver.nameservers = ['8.8.8.8']
|
|
dns_response = dns_resolver.query(name, 'TXT')
|
|
for rdata in dns_response:
|
|
for txt_record in rdata.strings:
|
|
txt_records.append(txt_record.decode("utf-8"))
|
|
except dns.exception.DNSException:
|
|
return False
|
|
|
|
for txt_record in txt_records:
|
|
if txt_record == token:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def wait_for_dns_change(change_id, account_number=None):
|
|
fqdn, token = change_id
|
|
while True:
|
|
status = _has_dns_propagated(fqdn, token)
|
|
current_app.logger.debug("Record status for fqdn: {}: {}".format(fqdn, status))
|
|
if status:
|
|
break
|
|
time.sleep(20)
|
|
return
|
|
|
|
|
|
def create_txt_record(domain, token, account_number):
|
|
get_dynect_session()
|
|
zone_name = get_tld('http://' + domain)
|
|
zone_parts = len(zone_name.split('.'))
|
|
node_name = '.'.join(domain.split('.')[:-zone_parts])
|
|
fqdn = "{0}.{1}".format(node_name, zone_name)
|
|
zone = Zone(zone_name)
|
|
try:
|
|
zone.add_record(node_name, record_type='TXT', txtdata="\"{}\"".format(token), ttl=5)
|
|
except DynectCreateError:
|
|
delete_txt_record(None, None, domain, token)
|
|
zone.add_record(node_name, record_type='TXT', txtdata="\"{}\"".format(token), ttl=5)
|
|
node = zone.get_node(node_name)
|
|
zone.publish()
|
|
current_app.logger.debug("TXT record created: {0}".format(fqdn))
|
|
change_id = (fqdn, token)
|
|
return change_id
|
|
|
|
|
|
def delete_txt_record(change_id, account_number, domain, token):
|
|
get_dynect_session()
|
|
if not domain:
|
|
current_app.logger.debug("delete_txt_record: No domain passed")
|
|
return
|
|
|
|
zone_name = get_tld('http://' + domain)
|
|
zone_parts = len(zone_name.split('.'))
|
|
node_name = '.'.join(domain.split('.')[:-zone_parts])
|
|
fqdn = "{0}.{1}".format(node_name, zone_name)
|
|
|
|
zone = Zone(zone_name)
|
|
node = Node(zone_name, fqdn)
|
|
all_txt_records = node.get_all_records_by_type('TXT')
|
|
for txt_record in all_txt_records:
|
|
if txt_record.txtdata == ("{}".format(token)):
|
|
current_app.logger.debug("Deleting TXT record name: {0}".format(fqdn))
|
|
txt_record.delete()
|
|
zone.publish()
|