Compare commits

...

5 commits

Author SHA1 Message Date
1ab4a4bfde Print subdomain 2020-02-23 20:27:56 +01:00
6827656655 Fix ) 2020-02-23 20:26:05 +01:00
057dbb8510 More verbose 2020-02-23 20:24:18 +01:00
6433bbdd1f Cleaned script 2020-02-23 20:00:37 +01:00
root
b9fbafc392 Added hook scripts 2020-02-23 19:59:56 +01:00
4 changed files with 112 additions and 28 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
certbot-auto
etc/
#.*#
.*~

View file

@ -11,9 +11,9 @@ import mysql.connector
# Query for IMAP/POP3 certificate
mbox_list_stmt = "SELECT DISTINCT(name) FROM records WHERE content in ({}) and (name LIKE 'imap.%' or name LIKE 'pop3.%' or name LIKE 'mail.%')"
# Query for SMTP certificate
# Query for SMTP certificate
smtp_list_stmt = "SELECT DISTINCT(name) FROM records WHERE content in ({}) and (name LIKE 'smtp.%' or name LIKE 'mail.%')"
# Get list of defined domains in vhosts configuration database
domains_list_stmt = """SELECT DISTINCT(SUBSTRING_INDEX(urls.dns_name, '.', -2)) AS domain_names
@ -30,8 +30,6 @@ subdomains_list_stmt = "SELECT DISTINCT(urls.dns_name) AS domain_names "\
"ON (urls.url_id = hosts_urls.url_id and urls.url_id = vhosts.url_id and vhosts.vhost_id = vhosts_features.vhost_id) "\
"WHERE (hosts_urls.http = 'Y' and hosts.hostname = %(webserver)s and "\
"urls.dns_name LIKE %(domain)s)"
default_conf_file="./etc/ot_certs.ini"
logging.basicConfig(level=logging.INFO)
@ -42,7 +40,7 @@ def init_prog(argv):
"""
Parse command line args and config file
"""
parser = argparse.ArgumentParser(
description="Manage LetsEncrypt certificates")
parser.add_argument("-c", "--config", type=open,
@ -91,7 +89,7 @@ def get_subdomain_list(config, domain, ot_conn, ex_subdomains=tuple()):
"""
Return a Python list containing subdomain of domain paramer
eg: ['app.arkiwi.org']
"""
"""
result_dict=dict()
@ -102,11 +100,8 @@ def get_subdomain_list(config, domain, ot_conn, ex_subdomains=tuple()):
subdomains_res = ot_cursor.fetchall()
ot_cursor.close()
#if filtered:
subdomains_filtered = [s[0].decode('utf-8') for s in subdomains_res
if not(s[0].decode('utf-8').startswith(ex_subdomains))]
# else:
# subdomains_filtered = [s[0].decode('utf-8') for s in subdomains_res]
return subdomains_filtered
@ -121,7 +116,7 @@ def get_domain_list(config, ot_conn, dns_conn):
ot_cursor=ot_conn.cursor()
ot_cursor.execute(domains_list_stmt, {'webserver':config['main']['webserver'].strip(" '\"")})
dns_cursor=dns_conn.cursor()
for domain_barr, in ot_cursor:
domain_name = domain_barr.decode("utf-8")
@ -137,7 +132,7 @@ def get_domain_list(config, ot_conn, dns_conn):
result_dict.update({domain_name: {'managed_ns':False, 'domain_id':None}})
else:
logger.error('Unexpected result for domain {}'.format(domain_name))
dns_cursor.close()
ot_cursor.close()
return result_dict
@ -148,7 +143,7 @@ def get_alias_list(config, dns_conn, query, aliases):
"""
result_list = list()
dns_cursor=dns_conn.cursor()
try:
dns_cursor.execute(query, aliases)
@ -168,7 +163,7 @@ def acme_request(config, domain_name, acme_test='DNS-01', webroot=None, dryrun=F
args += "--server {} ".format(config['certbot']['server'])
if dryrun:
args += "--dry-run "
args += "--dry-run "
if acme_test == 'DNS-01':
args += " --manual certonly "
args += "--preferred-challenges dns-01 "
@ -176,17 +171,17 @@ def acme_request(config, domain_name, acme_test='DNS-01', webroot=None, dryrun=F
args += "--manual-cleanup-hook {} ".format(config['certbot']['cleanup_hook'])
args += "-d {},*.{}".format(domain_name, domain_name)
elif acme_test == 'HTTP-01':
args += " --webroot certonly "
args += " --webroot certonly "
args += "--preferred-challenges http-01 "
if webroot is None:
args += "-w {}/{}/htdocs ".format(config['apache']['webroot'], domain_name)
else:
args += "-w {} ".format(webroot)
if domains_list is None:
args += "-d {}".format(domain_name)
else:
args += "--expand --cert-name {} ".format(domain_name)
args += "--expand --cert-name {} ".format(domain_name)
args += "-d {}".format(",".join(domains_list))
else:
logger.error('acme test {} not supported'.format(acme_test))
@ -195,7 +190,7 @@ def acme_request(config, domain_name, acme_test='DNS-01', webroot=None, dryrun=F
logging.info("{} {}".format(config['certbot']['bin'], args))
else:
os.system("{} {}".format(config['certbot']['bin'], args))
return True
def symlink_force(target, link_name):
@ -217,25 +212,26 @@ def link_cert(config, source, dest, dryrun=False):
else:
symlink_force(src_name, link_name)
if __name__ == '__main__':
args, config = init_prog(sys.argv)
dryrun=config['main'].getboolean('dryrun')
ot_conn=connect_db(dict(config['ot_db']))
dns_conn=connect_db(dict(config['dns_db']))
if dryrun:
print("DRYRUN, nessun certificato verra' richiesto, nessun link/file creato o modificato")
# Caso speciale per le webmail
if args.webmail:
logging.info('Asking certificates for webmail')
vhost_name = config['webmail']['vhost'].strip()
webmails_list = ["webmail.{}".format(d.strip()) for d in config['webmail']['domains'].split(',') if len(d.strip())>0]
if acme_request(config, vhost_name, acme_test='HTTP-01', dryrun=dryrun, domains_list=webmails_list):
logging.info('vhost {}, domains_list {}'.format(vhost_name, webmails_list))
if acme_request(config, vhost_name, acme_test='HTTP-01', dryrun=dryrun, domains_list=webmails_list):
link_cert(config, vhost_name, vhost_name, dryrun=dryrun)
else:
logger.error('Error asking certificate for {}'.format(vhost_name))
@ -250,8 +246,9 @@ if __name__ == '__main__':
alias_list = get_alias_list(config, dns_conn, mbox_query, server_addresses)
# Per usi futuri, aggiungo l'alias 'mail.indivia.net'
alias_list.append('mail.indivia.net')
logging.info('vhost {}, domains_list {}'.format(vhost_name, alias_list))
if acme_request(config, vhost_name, acme_test='HTTP-01', webroot=config['mail']['mbox_webroot'].strip(),
dryrun=dryrun, domains_list=alias_list):
dryrun=dryrun, domains_list=alias_list):
# non e' richiesto il link, punto direttamente le configurazioni alle dir di letsencrypt
# link_cert(config, vhost_name, vhost_name, dryrun=dryrun)
pass
@ -266,6 +263,7 @@ if __name__ == '__main__':
smtp_fmt = ','.join(['%s'] * len(server_addresses))
smtp_query = smtp_list_stmt.format(smtp_fmt)
alias_list = get_alias_list(config, dns_conn, smtp_query, server_addresses)
logging.info('vhost {}, domains_list {}'.format(vhost_name, alias_list))
if acme_request(config, vhost_name, acme_test='HTTP-01', webroot=config['mail']['smtp_webroot'].strip(),
dryrun=dryrun, domains_list=alias_list):
# non e' richiesto il link, punto direttamente le configurazioni alle dir di letsencrypt
@ -273,21 +271,22 @@ if __name__ == '__main__':
pass
else:
logger.error('Error asking certificate for {}'.format(vhost_name))
# Caso speciale per l'hosting
# Caso speciale per l'hosting
if args.hosting:
logging.info('Asking certificates for hosted web domains')
# Subdomains da escludere
ex_subdomains = tuple([s.strip() for s in config['main']['special_subdomains'].split(',') if len(s.strip())>0])
domains_dict = get_domain_list(config, ot_conn, dns_conn)
for domain_name, domain_feat in domains_dict.items():
domain_feat['subdomains']=get_subdomain_list(config, domain_name, ot_conn, ex_subdomains=ex_subdomains)
# Controlla se i nameserver sono gestiti da noi
if domain_feat['managed_ns']:
# Nel caso il nameserver sia gestito, chiedi certificati per il dominio e la wildcard
logger.info('Get certificates for {}, *.{}'.format(domain_name, domain_name))
if acme_request(config, domain_name, acme_test='DNS-01', dryrun=dryrun):
link_cert(config, domain_name, domain_name, dryrun=dryrun)
link_cert(config, domain_name, domain_name, dryrun=dryrun)
# Crea il link per ogni subdomain
for subdomain in domain_feat['subdomains']:
link_cert(config, domain_name, subdomain, dryrun=dryrun)
@ -295,17 +294,18 @@ if __name__ == '__main__':
# Nel caso i nameserver NON siano gestiti, allora chiedi un certificato per ogni sottodominio
# Crea il link per ogni subdomain
for subdomain in domain_feat['subdomains']:
logger.info('Get certificates for {}'.format(subdomain))
if acme_request(config, subdomain, acme_test='HTTP-01', dryrun=dryrun):
link_cert(config, subdomain, subdomain, dryrun=dryrun)
ot_conn.close()
dns_conn.close()
# Genero il certificato per l'interfaccia di mailman
# Genero il certificato per l'interfaccia di mailman
if args.liste:
logging.info('Asking certificates for liste.indivia.net')
vhost_name = config['mailman']['vhost'].strip()
liste_list = ["liste.{}".format(d.strip()) for d in config['mailman']['domains'].split(',') if len(d.strip())>0]
if acme_request(config, vhost_name, acme_test='HTTP-01', dryrun=dryrun, domains_list=liste_list):
if acme_request(config, vhost_name, acme_test='HTTP-01', dryrun=dryrun, domains_list=liste_list):
link_cert(config, vhost_name, vhost_name, dryrun=dryrun)
else:
logger.error('Error asking certificate for {}'.format(vhost_name))

View file

@ -0,0 +1,42 @@
LOG_FILE='/tmp/lets_auth.log'
DNS_DB_MYCNF="/usr/local/ortiche/otcerts/etc/dns_db.conf"
echo "Auth $CERTBOT_DOMAIN"
echo "" >> $LOG_FILE
date >> $LOG_FILE
RECORD_NAME='_acme-challenge'
RECORD_FQDN="$RECORD_NAME.$CERTBOT_DOMAIN"
DOMAIN_ID=`mysql --defaults-extra-file=$DNS_DB_MYCNF -s -N << END_QUERY
SELECT domains.id FROM domains WHERE domains.name='$CERTBOT_DOMAIN'
END_QUERY`
if [ -z "$DOMAIN_ID" ]; then
echo "ERROR: Nameservers are not managed for domain $CERTBOT_DOMAIN" >> $LOG_FILE
exit 255
fi
echo "Selected domain_id $DOMAIN_ID" >> $LOG_FILE
echo "Creating $RECORD_FQDN TXT entry with value $CERTBOT_VALIDATION" >> $LOG_FILE
QUERY_RES=`mysql --defaults-extra-file=$DNS_DB_MYCNF -s -N << END_QUERY
INSERT INTO records (domain_id, name, type, content, ttl, prio, label)
VALUES ($DOMAIN_ID, '$RECORD_FQDN', 'TXT', '"$CERTBOT_VALIDATION"', 5, 60, '"$CERTBOT_VALIDATION"')
END_QUERY`
# echo "Done updating" >> $LOG_FILE
RECORD_ID=`mysql --defaults-extra-file=$DNS_DB_MYCNF -s -N << END_QUERY
SELECT id FROM records WHERE (type='TXT' and name='$RECORD_FQDN')
END_QUERY`
echo "After update $RECORD_ID ." >> $LOG_FILE
echo "Done updating, sleeping 10 secs .. " >> $LOG_FILE
sleep 5
echo "Done sleeping." >> $LOG_FILE
# dig @172.19.0.102 $RECORD_FQDN TXT +short >> $LOG_FILE
# dig @dns.contaminati.net $RECORD_FQDN TXT +short >> $LOG_FILE
# dig @dns.ortiche.net $RECORD_FQDN TXT +short >> $LOG_FILE
exit 0

41
letsencrypt/lets_cleanup.sh Executable file
View file

@ -0,0 +1,41 @@
LOG_FILE='/tmp/lets_clean.log'
DNS_DB_MYCNF="/usr/local/ortiche/otcerts/etc/dns_db.conf"
echo "" >> $LOG_FILE
date >> $LOG_FILE
echo "CERTBOT_AUTH_OUTPUT = $CERTBOT_AUTH_OUTPUT" >> $LOG_FILE
RECORD_NAME='_acme-challenge'
RECORD_FQDN="$RECORD_NAME.$CERTBOT_DOMAIN"
DOMAIN_ID=`mysql --defaults-extra-file=$DNS_DB_MYCNF -s -N << END_QUERY
SELECT domains.id FROM domains WHERE domains.name='$CERTBOT_DOMAIN'
END_QUERY`
if [ -z "$DOMAIN_ID" ]; then
echo "ERROR: Nameservers are not managed for domain $CERTBOT_DOMAIN" >> $LOG_FILE
exit 255
fi
RECORD_ID=`mysql --defaults-extra-file=$DNS_DB_MYCNF -s -N << END_QUERY
SELECT id FROM records WHERE (type='TXT' and name='$RECORD_FQDN')
END_QUERY`
echo "Cleaning $RECORD_FQDN TXT entry, record id $RECORD_ID" >> $LOG_FILE
# QUERY_RES=`mysql --defaults-extra-file=$DNS_DB_MYCNF -s -N << END_QUERY
# UPDATE records SET content='""' WHERE id=$RECORD_ID
# END_QUERY`
# To complete delete
DELETE_RES=`mysql --defaults-extra-file=$DNS_DB_MYCNF -s -N << END_QUERY
DELETE FROM records WHERE (domain_id=$DOMAIN_ID AND name='$RECORD_FQDN')
END_QUERY`
echo "Done cleaning, sleeping 5 secs .. " >> $LOG_FILE
sleep 5
echo "Done sleeping." >> $LOG_FILE
exit 0