[mod] autopep8

This commit is contained in:
Laurent Peuch 2016-10-30 04:24:54 +01:00
parent d47f5919d6
commit bec8f63479

View file

@ -38,11 +38,13 @@ from datetime import datetime
from tabulate import tabulate from tabulate import tabulate
from acme_tiny import get_crt as sign_certificate from acme_tiny import get_crt as sign_certificate
import yunohost.domain
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
import yunohost.domain
from yunohost.service import _run_service_command
from yunohost.app import app_ssowatconf from yunohost.app import app_ssowatconf
from yunohost.service import _run_service_command
logger = getActionLogger('yunohost.certmanager') logger = getActionLogger('yunohost.certmanager')
@ -73,7 +75,8 @@ intermediate_certificate_url = "https://letsencrypt.org/certs/lets-encrypt-x3-cr
# Status # Status
def certificate_status(auth, domainList, full = False):
def certificate_status(auth, domainList, full=False):
""" """
Print the status of certificate for given domains (all by default) Print the status of certificate for given domains (all by default)
@ -83,36 +86,39 @@ def certificate_status(auth, domainList, full = False):
""" """
# If no domains given, consider all yunohost domains # If no domains given, consider all yunohost domains
if (domainList == []) : domainList = yunohost.domain.domain_list(auth)['domains'] if (domainList == []):
domainList = yunohost.domain.domain_list(auth)['domains']
# Else, validate that yunohost knows the domains given # Else, validate that yunohost knows the domains given
else : else:
for domain in domainList : for domain in domainList:
# Is it in Yunohost dmomain list ? # Is it in Yunohost dmomain list ?
if domain not in yunohost.domain.domain_list(auth)['domains']: if domain not in yunohost.domain.domain_list(auth)['domains']:
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_unknown', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_unknown', domain=domain))
# Get status for each domain, and prepare display using tabulate # Get status for each domain, and prepare display using tabulate
if not full : if not full:
headers = [ "Domain", "Certificate status", "Authority type", "Days remaining"] headers = ["Domain", "Certificate status", "Authority type", "Days remaining"]
else : else:
headers = [ "Domain", "Certificate subject", "Certificate status", "Authority type", "Authority name", "Days remaining"] headers = ["Domain", "Certificate subject", "Certificate status", "Authority type", "Authority name", "Days remaining"]
lines = [] lines = []
for domain in domainList : for domain in domainList:
status = _get_status(domain) status = _get_status(domain)
line = [] line = []
line.append(domain) line.append(domain)
if (full) : line.append(status["subject"]) if (full):
line.append(status["subject"])
line.append(_summary_code_to_string(status["summaryCode"])) line.append(_summary_code_to_string(status["summaryCode"]))
line.append(status["CAtype"]) line.append(status["CAtype"])
if (full) : line.append(status["CAname"]) if (full):
line.append(status["CAname"])
line.append(status["validity"]) line.append(status["validity"])
lines.append(line) lines.append(line)
print(tabulate(lines, headers=headers, tablefmt="simple", stralign="center")) print(tabulate(lines, headers=headers, tablefmt="simple", stralign="center"))
def certificate_install(auth, domainList, force=False, no_checks=False, self_signed=False) : def certificate_install(auth, domainList, force=False, no_checks=False, self_signed=False):
""" """
Install a Let's Encrypt certificate for given domains (all by default) Install a Let's Encrypt certificate for given domains (all by default)
@ -123,25 +129,23 @@ def certificate_install(auth, domainList, force=False, no_checks=False, self_sig
before attempting the install before attempting the install
self-signed -- Instal self-signed certificates instead of Let's Encrypt self-signed -- Instal self-signed certificates instead of Let's Encrypt
""" """
if (self_signed) : if (self_signed):
certificate_install_selfsigned(domainList, force) certificate_install_selfsigned(domainList, force)
else : else:
certificate_install_letsencrypt(auth, domainList, force, no_checks) certificate_install_letsencrypt(auth, domainList, force, no_checks)
# Install self-signed # Install self-signed
def certificate_install_selfsigned(domainList, force=False) : def certificate_install_selfsigned(domainList, force=False):
for domain in domainList:
for domain in domainList :
# Check we ain't trying to overwrite a good cert ! # Check we ain't trying to overwrite a good cert !
status = _get_status(domain) status = _get_status(domain)
if (status != {}) and (status["summaryCode"] > 0) and (not force) : if (status != {}) and (status["summaryCode"] > 0) and (not force):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_attempt_to_replace_valid_cert', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_attempt_to_replace_valid_cert', domain=domain))
cert_folder_domain = cert_folder + "/" + domain
cert_folder_domain = cert_folder+"/"+domain
# Create cert folder if it does not exists yet # Create cert folder if it does not exists yet
try: try:
@ -173,53 +177,51 @@ def certificate_install_selfsigned(domainList, force=False) :
if os.system(command) != 0: if os.system(command) != 0:
raise MoulinetteError(errno.EIO, m18n.n('certmanager_domain_cert_gen_failed')) raise MoulinetteError(errno.EIO, m18n.n('certmanager_domain_cert_gen_failed'))
_set_permissions(cert_folder_domain, "root", "root", 0755); _set_permissions(cert_folder_domain, "root", "root", 0755)
_set_permissions(cert_folder_domain+"/key.pem", "root", "metronome", 0640); _set_permissions(cert_folder_domain + "/key.pem", "root", "metronome", 0640)
_set_permissions(cert_folder_domain+"/crt.pem", "root", "metronome", 0640); _set_permissions(cert_folder_domain + "/crt.pem", "root", "metronome", 0640)
_set_permissions(cert_folder_domain+"/openssl.cnf", "root", "root", 0600); _set_permissions(cert_folder_domain + "/openssl.cnf", "root", "root", 0600)
# Install ACME / Let's Encrypt certificate # Install ACME / Let's Encrypt certificate
def certificate_install_letsencrypt(auth, domainList, force=False, no_checks=False): def certificate_install_letsencrypt(auth, domainList, force=False, no_checks=False):
if not os.path.exists(account_key_file):
if not os.path.exists(account_key_file) :
_generate_account_key() _generate_account_key()
# If no domains given, consider all yunohost domains with self-signed # If no domains given, consider all yunohost domains with self-signed
# certificates # certificates
if (domainList == []) : if (domainList == []):
for domain in yunohost.domain.domain_list(auth)['domains'] : for domain in yunohost.domain.domain_list(auth)['domains']:
# Is it self-signed ? # Is it self-signed ?
status = _get_status(domain) status = _get_status(domain)
if (status["CAtype"] != "Self-signed") : continue if (status["CAtype"] != "Self-signed"):
continue
domainList.append(domain) domainList.append(domain)
# Else, validate that yunohost knows the domains given # Else, validate that yunohost knows the domains given
else : else:
for domain in domainList : for domain in domainList:
# Is it in Yunohost dmomain list ? # Is it in Yunohost dmomain list ?
if domain not in yunohost.domain.domain_list(auth)['domains']: if domain not in yunohost.domain.domain_list(auth)['domains']:
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_unknown', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_unknown', domain=domain))
# Is it self-signed ? # Is it self-signed ?
status = _get_status(domain) status = _get_status(domain)
if (not force) and (status["CAtype"] != "Self-signed") : if (not force) and (status["CAtype"] != "Self-signed"):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_cert_not_selfsigned', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_cert_not_selfsigned', domain=domain))
# Actual install steps # Actual install steps
for domain in domainList : for domain in domainList:
logger.info("Now attempting install of certificate for domain "+domain+" !") logger.info("Now attempting install of certificate for domain " + domain + " !")
try : try:
if not no_checks : _check_domain_is_correctly_configured(domain) if not no_checks:
_check_domain_is_correctly_configured(domain)
_backup_current_cert(domain) _backup_current_cert(domain)
_configure_for_acme_challenge(auth, domain) _configure_for_acme_challenge(auth, domain)
_fetch_and_enable_new_certificate(domain) _fetch_and_enable_new_certificate(domain)
@ -227,9 +229,9 @@ def certificate_install_letsencrypt(auth, domainList, force=False, no_checks=Fal
logger.success(m18n.n("certmanager_cert_install_success", domain=domain)) logger.success(m18n.n("certmanager_cert_install_success", domain=domain))
except Exception as e : except Exception as e:
logger.error("Certificate installation for "+domain+" failed !") logger.error("Certificate installation for " + domain + " failed !")
logger.error(str(e)) logger.error(str(e))
@ -250,23 +252,24 @@ def certificate_renew(auth, domainList, force=False, no_checks=False, email=Fals
# If no domains given, consider all yunohost domains with Let's Encrypt # If no domains given, consider all yunohost domains with Let's Encrypt
# certificates # certificates
if (domainList == []) : if (domainList == []):
for domain in yunohost.domain.domain_list(auth)['domains'] : for domain in yunohost.domain.domain_list(auth)['domains']:
# Does it has a Let's Encrypt cert ? # Does it has a Let's Encrypt cert ?
status = _get_status(domain) status = _get_status(domain)
if (status["CAtype"] != "Let's Encrypt") : continue if (status["CAtype"] != "Let's Encrypt"):
continue
# Does it expires soon ? # Does it expires soon ?
if (force) or (status["validity"] <= validity_limit) : if (force) or (status["validity"] <= validity_limit):
domainList.append(domain) domainList.append(domain)
if (len(domainList) == 0) : if (len(domainList) == 0):
logger.info("No certificate needs to be renewed.") logger.info("No certificate needs to be renewed.")
# Else, validate the domain list given # Else, validate the domain list given
else : else:
for domain in domainList : for domain in domainList:
# Is it in Yunohost dmomain list ? # Is it in Yunohost dmomain list ?
if domain not in yunohost.domain.domain_list(auth)['domains']: if domain not in yunohost.domain.domain_list(auth)['domains']:
@ -275,61 +278,56 @@ def certificate_renew(auth, domainList, force=False, no_checks=False, email=Fals
status = _get_status(domain) status = _get_status(domain)
# Does it expires soon ? # Does it expires soon ?
if not ((force) or (status["validity"] <= validity_limit)) : if not ((force) or (status["validity"] <= validity_limit)):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_attempt_to_renew_valid_cert', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_attempt_to_renew_valid_cert', domain=domain))
# Does it has a Let's Encrypt cert ? # Does it has a Let's Encrypt cert ?
if (status["CAtype"] != "Let's Encrypt") : if (status["CAtype"] != "Let's Encrypt"):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_attempt_to_renew_nonLE_cert', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_attempt_to_renew_nonLE_cert', domain=domain))
# Actual renew steps # Actual renew steps
for domain in domainList : for domain in domainList:
logger.info("Now attempting renewing of certificate for domain "+domain+" !") logger.info("Now attempting renewing of certificate for domain " + domain + " !")
try : try:
if not no_checks : _check_domain_is_correctly_configured(domain) if not no_checks:
_check_domain_is_correctly_configured(domain)
_backup_current_cert(domain) _backup_current_cert(domain)
_fetch_and_enable_new_certificate(domain) _fetch_and_enable_new_certificate(domain)
logger.success(m18n.n("certmanager_cert_renew_success", domain=domain)) logger.success(m18n.n("certmanager_cert_renew_success", domain=domain))
except Exception as e : except Exception as e:
logger.error("Certificate renewing for "+domain+" failed !") logger.error("Certificate renewing for " + domain + " failed !")
logger.error(str(e)) logger.error(str(e))
if (email) : if (email):
logger.error("Sending email with details to root ...") logger.error("Sending email with details to root ...")
_email_renewing_failed(domain, e) _email_renewing_failed(domain, e)
############################################################################### ###############################################################################
# Back-end stuff # # Back-end stuff #
############################################################################### ###############################################################################
def _install_cron() : def _install_cron():
cron_job_file = "/etc/cron.weekly/certificateRenewer" cron_job_file = "/etc/cron.weekly/certificateRenewer"
with open(cron_job_file, "w") as f : with open(cron_job_file, "w") as f:
f.write("#!/bin/bash\n") f.write("#!/bin/bash\n")
f.write("yunohost domain cert-renew --email\n") f.write("yunohost domain cert-renew --email\n")
_set_permissions(cron_job_file, "root", "root", 0755); _set_permissions(cron_job_file, "root", "root", 0755)
def _email_renewing_failed(domain, e) :
from_ = "certmanager@"+domain+" (Certificate Manager)" def _email_renewing_failed(domain, e):
from_ = "certmanager@" + domain + " (Certificate Manager)"
to_ = "root" to_ = "root"
subject_ = "Certificate renewing attempt for "+domain+" failed!" subject_ = "Certificate renewing attempt for " + domain + " failed!"
exceptionMessage = str(e) exceptionMessage = str(e)
logs = _tail(50, "/var/log/yunohost/yunohost-cli.log") logs = _tail(50, "/var/log/yunohost/yunohost-cli.log")
@ -357,29 +355,27 @@ Subject: %s
""" % (from_, to_, subject_, text) """ % (from_, to_, subject_, text)
smtp = smtplib.SMTP("localhost") smtp = smtplib.SMTP("localhost")
smtp.sendmail(from_, [ to_ ], message) smtp.sendmail(from_, [to_], message)
smtp.quit() smtp.quit()
def _configure_for_acme_challenge(auth, domain):
def _configure_for_acme_challenge(auth, domain) : nginx_conf_file = "/etc/nginx/conf.d/" + domain + ".d/000-acmechallenge.conf"
nginx_conf_file = "/etc/nginx/conf.d/"+domain+".d/000-acmechallenge.conf"
nginx_configuration = ''' nginx_configuration = '''
location '/.well-known/acme-challenge' location '/.well-known/acme-challenge'
{ {
default_type "text/plain"; default_type "text/plain";
alias '''+webroot_folder+'''; alias ''' + webroot_folder + ''';
} }
''' '''
# Write the conf # Write the conf
if os.path.exists(nginx_conf_file) : if os.path.exists(nginx_conf_file):
logger.info("Nginx configuration file for ACME challenge already exists for domain, skipping.") logger.info("Nginx configuration file for ACME challenge already exists for domain, skipping.")
else : else:
logger.info("Adding Nginx configuration file for Acme challenge for domain " + domain + ".") logger.info("Adding Nginx configuration file for Acme challenge for domain " + domain + ".")
with open(nginx_conf_file, "w") as f : with open(nginx_conf_file, "w") as f:
f.write(nginx_configuration) f.write(nginx_configuration)
# Assume nginx conf is okay, and reload it # Assume nginx conf is okay, and reload it
@ -389,29 +385,31 @@ location '/.well-known/acme-challenge'
app_ssowatconf(auth) app_ssowatconf(auth)
def _fetch_and_enable_new_certificate(domain) :
def _fetch_and_enable_new_certificate(domain):
# Make sure tmp folder exists # Make sure tmp folder exists
logger.debug("Making sure tmp folders exists...") logger.debug("Making sure tmp folders exists...")
if not (os.path.exists(webroot_folder)) : os.makedirs(webroot_folder) if not (os.path.exists(webroot_folder)):
if not (os.path.exists(tmp_folder)) : os.makedirs(tmp_folder) os.makedirs(webroot_folder)
_set_permissions(webroot_folder, "root", "www-data", 0650); if not (os.path.exists(tmp_folder)):
_set_permissions(tmp_folder, "root", "root", 0640); os.makedirs(tmp_folder)
_set_permissions(webroot_folder, "root", "www-data", 0650)
_set_permissions(tmp_folder, "root", "root", 0640)
# Prepare certificate signing request # Prepare certificate signing request
logger.info("Prepare key and certificate signing request (CSR) for "+domain+"...") logger.info("Prepare key and certificate signing request (CSR) for " + domain + "...")
domain_key_file = tmp_folder+"/"+domain+".pem" domain_key_file = tmp_folder + "/" + domain + ".pem"
_generate_key(domain_key_file) _generate_key(domain_key_file)
_set_permissions(domain_key_file, "root", "metronome", 0640); _set_permissions(domain_key_file, "root", "metronome", 0640)
_prepare_certificate_signing_request(domain, domain_key_file, tmp_folder) _prepare_certificate_signing_request(domain, domain_key_file, tmp_folder)
# Sign the certificate # Sign the certificate
logger.info("Now using ACME Tiny to sign the certificate...") logger.info("Now using ACME Tiny to sign the certificate...")
domain_csr_file = tmp_folder+"/"+domain+".csr" domain_csr_file = tmp_folder + "/" + domain + ".csr"
signed_certificate = sign_certificate(account_key_file, signed_certificate = sign_certificate(account_key_file,
domain_csr_file, domain_csr_file,
@ -425,30 +423,28 @@ def _fetch_and_enable_new_certificate(domain) :
# Create corresponding directory # Create corresponding directory
date_tag = datetime.now().strftime("%Y%m%d.%H%M%S") date_tag = datetime.now().strftime("%Y%m%d.%H%M%S")
new_cert_folder = cert_folder+"/" + domain + "." + date_tag new_cert_folder = cert_folder + "/" + domain + "." + date_tag
os.makedirs(new_cert_folder) os.makedirs(new_cert_folder)
_set_permissions(new_cert_folder, "root", "root", 0655); _set_permissions(new_cert_folder, "root", "root", 0655)
# Move the private key # Move the private key
shutil.move(domain_key_file, new_cert_folder+"/key.pem") shutil.move(domain_key_file, new_cert_folder + "/key.pem")
# Write the cert # Write the cert
domain_cert_file = new_cert_folder+"/crt.pem" domain_cert_file = new_cert_folder + "/crt.pem"
with open(domain_cert_file, "w") as f : with open(domain_cert_file, "w") as f:
f.write(signed_certificate) f.write(signed_certificate)
f.write(intermediate_certificate) f.write(intermediate_certificate)
_set_permissions(domain_cert_file, "root", "metronome", 0640); _set_permissions(domain_cert_file, "root", "metronome", 0640)
logger.info("Enabling the new certificate...") logger.info("Enabling the new certificate...")
# Replace (if necessary) the link or folder for live cert # Replace (if necessary) the link or folder for live cert
live_link = cert_folder+"/"+domain live_link = cert_folder + "/" + domain
if not os.path.islink(live_link) : if not os.path.islink(live_link):
shutil.rmtree(live_link) # Well, yep, hopefully that's not too dangerous (directory should have been backuped before calling this command) shutil.rmtree(live_link) # Well, yep, hopefully that's not too dangerous (directory should have been backuped before calling this command)
elif os.path.lexists(live_link) : elif os.path.lexists(live_link):
os.remove(live_link) os.remove(live_link)
os.symlink(new_cert_folder, live_link) os.symlink(new_cert_folder, live_link)
@ -456,18 +452,16 @@ def _fetch_and_enable_new_certificate(domain) :
# Check the status of the certificate is now good # Check the status of the certificate is now good
statusSummaryCode = _get_status(domain)["summaryCode"] statusSummaryCode = _get_status(domain)["summaryCode"]
if (statusSummaryCode < 20) : if (statusSummaryCode < 20):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_certificate_fetching_or_enabling_failed', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_certificate_fetching_or_enabling_failed', domain=domain))
logger.info("Restarting services...") logger.info("Restarting services...")
for s in [ "nginx", "postfix", "dovecot", "metronome" ] : for s in ["nginx", "postfix", "dovecot", "metronome"]:
_run_service_command("restart", s) _run_service_command("restart", s)
def _prepare_certificate_signing_request(domain, key_file, output_folder) : def _prepare_certificate_signing_request(domain, key_file, output_folder):
# Init a request # Init a request
csr = crypto.X509Req() csr = crypto.X509Req()
@ -475,7 +469,7 @@ def _prepare_certificate_signing_request(domain, key_file, output_folder) :
csr.get_subject().CN = domain csr.get_subject().CN = domain
# Set the key # Set the key
with open(key_file, 'rt') as f : with open(key_file, 'rt') as f:
key = crypto.load_privatekey(crypto.FILETYPE_PEM, f.read()) key = crypto.load_privatekey(crypto.FILETYPE_PEM, f.read())
csr.set_pubkey(key) csr.set_pubkey(key)
@ -483,158 +477,169 @@ def _prepare_certificate_signing_request(domain, key_file, output_folder) :
csr.sign(key, "sha256") csr.sign(key, "sha256")
# Save the request in tmp folder # Save the request in tmp folder
csr_file = output_folder+domain+".csr" csr_file = output_folder + domain + ".csr"
logger.info("Saving to "+csr_file+" .") logger.info("Saving to " + csr_file + " .")
with open(csr_file, "w") as f : with open(csr_file, "w") as f:
f.write(crypto.dump_certificate_request(crypto.FILETYPE_PEM, csr)) f.write(crypto.dump_certificate_request(crypto.FILETYPE_PEM, csr))
def _get_status(domain) : def _get_status(domain):
cert_file = cert_folder + "/" + domain + "/crt.pem"
cert_file = cert_folder+"/"+domain+"/crt.pem" if (not os.path.isfile(cert_file)):
return {}
if (not os.path.isfile(cert_file)) : return {} try:
try :
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(cert_file).read()) cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(cert_file).read())
except : except:
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_cannot_read_cert', domain=domain, file=cert_file)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_cannot_read_cert', domain=domain, file=cert_file))
certSubject = cert.get_subject().CN certSubject = cert.get_subject().CN
certIssuer = cert.get_issuer().CN certIssuer = cert.get_issuer().CN
validUpTo = datetime.strptime(cert.get_notAfter(),"%Y%m%d%H%M%SZ") validUpTo = datetime.strptime(cert.get_notAfter(), "%Y%m%d%H%M%SZ")
daysRemaining = (validUpTo - datetime.now()).days daysRemaining = (validUpTo - datetime.now()).days
CAtype = None CAtype = None
if (certIssuer == _name_selfCA()) : if (certIssuer == _name_selfCA()):
CAtype = "Self-signed" CAtype = "Self-signed"
elif (certIssuer.startswith("Let's Encrypt")) : elif (certIssuer.startswith("Let's Encrypt")):
CAtype = "Let's Encrypt" CAtype = "Let's Encrypt"
elif (certIssuer.startswith("Fake LE")) : elif (certIssuer.startswith("Fake LE")):
CAtype = "Fake Let's Encrypt" CAtype = "Fake Let's Encrypt"
else : else:
CAtype = "Other / Unknown" CAtype = "Other / Unknown"
# Unknown by default # Unknown by default
statusSummaryCode = 0 statusSummaryCode = 0
# Critical # Critical
if (daysRemaining <= 0) : statusSummaryCode = -30 if (daysRemaining <= 0):
statusSummaryCode = -30
# Warning, self-signed, browser will display a warning discouraging visitors to enter website # Warning, self-signed, browser will display a warning discouraging visitors to enter website
elif (CAtype == "Self-signed") or (CAtype == "Fake Let's Encrypt") : statusSummaryCode = -20 elif (CAtype == "Self-signed") or (CAtype == "Fake Let's Encrypt"):
statusSummaryCode = -20
# Attention, certificate will expire soon (should be renewed automatically if Let's Encrypt) # Attention, certificate will expire soon (should be renewed automatically if Let's Encrypt)
elif (daysRemaining < validity_limit) : statusSummaryCode = -10 elif (daysRemaining < validity_limit):
statusSummaryCode = -10
# CA not known, but still a valid certificate, so okay ! # CA not known, but still a valid certificate, so okay !
elif (CAtype == "Other / Unknown") : statusSummaryCode = 10 elif (CAtype == "Other / Unknown"):
statusSummaryCode = 10
# Let's Encrypt, great ! # Let's Encrypt, great !
elif (CAtype == "Let's Encrypt") : statusSummaryCode = 20 elif (CAtype == "Let's Encrypt"):
statusSummaryCode = 20
return { "domain" : domain, return {"domain": domain,
"subject" : certSubject, "subject": certSubject,
"CAname" : certIssuer, "CAname": certIssuer,
"CAtype" : CAtype, "CAtype": CAtype,
"validity" : daysRemaining, "validity": daysRemaining,
"summaryCode" : statusSummaryCode "summaryCode": statusSummaryCode
} }
############################################################################### ###############################################################################
# Misc small stuff ... # # Misc small stuff ... #
############################################################################### ###############################################################################
def _generate_account_key() :
def _generate_account_key():
logger.info("Generating account key ...") logger.info("Generating account key ...")
_generate_key(account_key_file) _generate_key(account_key_file)
_set_permissions(account_key_file, "root", "root", 0400) _set_permissions(account_key_file, "root", "root", 0400)
def _generate_key(destinationPath) :
def _generate_key(destinationPath):
k = crypto.PKey() k = crypto.PKey()
k.generate_key(crypto.TYPE_RSA, key_size) k.generate_key(crypto.TYPE_RSA, key_size)
with open(destinationPath, "w") as f : with open(destinationPath, "w") as f:
f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k)) f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, k))
def _set_permissions(path, user, group, permissions) :
def _set_permissions(path, user, group, permissions):
uid = pwd.getpwnam(user).pw_uid uid = pwd.getpwnam(user).pw_uid
gid = grp.getgrnam(group).gr_gid gid = grp.getgrnam(group).gr_gid
os.chown(path, uid, gid) os.chown(path, uid, gid)
os.chmod(path, permissions) os.chmod(path, permissions)
def _backup_current_cert(domain): def _backup_current_cert(domain):
logger.info("Backuping existing certificate for domain " + domain)
logger.info("Backuping existing certificate for domain "+domain) cert_folder_domain = cert_folder + "/" + domain
cert_folder_domain = cert_folder+"/"+domain
dateTag = datetime.now().strftime("%Y%m%d.%H%M%S") dateTag = datetime.now().strftime("%Y%m%d.%H%M%S")
backup_folder = cert_folder_domain+"-backup-"+dateTag backup_folder = cert_folder_domain + "-backup-" + dateTag
shutil.copytree(cert_folder_domain, backup_folder) shutil.copytree(cert_folder_domain, backup_folder)
def _check_domain_is_correctly_configured(domain) : def _check_domain_is_correctly_configured(domain):
public_ip = yunohost.domain.get_public_ip() public_ip = yunohost.domain.get_public_ip()
# Check if IP from DNS matches public IP # Check if IP from DNS matches public IP
if not _dns_ip_match_public_ip(public_ip, domain) : if not _dns_ip_match_public_ip(public_ip, domain):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_dns_ip_differs_from_public_ip', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_dns_ip_differs_from_public_ip', domain=domain))
# Check if domain seems to be accessible through HTTP ? # Check if domain seems to be accessible through HTTP ?
if not _domain_is_accessible_through_HTTP(public_ip, domain) : if not _domain_is_accessible_through_HTTP(public_ip, domain):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_http_not_working', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_domain_http_not_working', domain=domain))
def _dns_ip_match_public_ip(public_ip, domain) :
try : def _dns_ip_match_public_ip(public_ip, domain):
r = requests.get("http://dns-api.org/A/"+domain) try:
except : r = requests.get("http://dns-api.org/A/" + domain)
except:
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_error_contacting_dns_api', api="dns-api.org")) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_error_contacting_dns_api', api="dns-api.org"))
if (r.text == "[{\"error\":\"NXDOMAIN\"}]") : if (r.text == "[{\"error\":\"NXDOMAIN\"}]"):
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_no_A_dns_record', domain=domain)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_no_A_dns_record', domain=domain))
try : try:
dns_ip = json.loads(r.text)[0]["value"] dns_ip = json.loads(r.text)[0]["value"]
except : except:
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_error_parsing_dns', domain=domain, value=r.text)) raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_error_parsing_dns', domain=domain, value=r.text))
if (dns_ip != public_ip) : if (dns_ip != public_ip):
return False return False
else : else:
return True return True
def _domain_is_accessible_through_HTTP(ip, domain) :
try : def _domain_is_accessible_through_HTTP(ip, domain):
requests.head("http://"+ip, headers = { "Host" : domain }) try:
except Exception : requests.head("http://" + ip, headers={"Host": domain})
except Exception:
return False return False
return True return True
def _summary_code_to_string(code) :
if (code <= -30) : return "CRITICAL" def _summary_code_to_string(code):
elif (code <= -20) : return "WARNING" if (code <= -30):
elif (code <= -10) : return "Attention" return "CRITICAL"
elif (code <= 0) : return "Unknown?" elif (code <= -20):
elif (code <= 10) : return "Good" return "WARNING"
elif (code <= 20) : return "Great!" elif (code <= -10):
return "Attention"
elif (code <= 0):
return "Unknown?"
elif (code <= 10):
return "Good"
elif (code <= 20):
return "Great!"
return "Unknown?" return "Unknown?"
def _name_selfCA() :
def _name_selfCA():
cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(selfCA_file).read()) cert = crypto.load_certificate(crypto.FILETYPE_PEM, open(selfCA_file).read())
return cert.get_subject().CN return cert.get_subject().CN
def _tail(n, filePath): def _tail(n, filePath):
stdin,stdout = os.popen2("tail -n "+str(n)+" "+filePath) stdin, stdout = os.popen2("tail -n " + str(n) + " " + filePath)
stdin.close() stdin.close()
lines = stdout.readlines(); stdout.close() lines = stdout.readlines()
stdout.close()
lines = "".join(lines) lines = "".join(lines)
return lines return lines