Improve letsencrypt
This commit is contained in:
@@ -8,11 +8,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
|
||||
### v3.9.x - [Unreleased]
|
||||
|
||||
#### Changed
|
||||
|
||||
- Improve Let's Encrypt certificate issuance logging informations
|
||||
|
||||
#### Fixed
|
||||
|
||||
- Fix cheat.sh install [PR #139](https://github.com/WordOps/WordOps/pull/139)
|
||||
- sslutils error when trying to display SSL certificate expiration
|
||||
- Fix cheat.sh symbolink link check before creation
|
||||
- Fix cheat.sh symbolic link check before creation
|
||||
|
||||
### v3.9.8.9 - 2019-09-03
|
||||
|
||||
|
||||
@@ -163,9 +163,9 @@ class WOSiteController(CementBaseController):
|
||||
if os.path.islink("{0}/conf/nginx/ssl.conf"
|
||||
.format(wo_site_webroot)):
|
||||
sslexpiry = str(
|
||||
SSL.getExpirationDate(self, wo_root_domain))
|
||||
SSL.getexpirationdays(self, wo_root_domain))
|
||||
else:
|
||||
sslexpiry = str(SSL.getExpirationDate(self, wo_domain))
|
||||
sslexpiry = str(SSL.getexpirationdays(self, wo_domain))
|
||||
else:
|
||||
sslprovider = ''
|
||||
sslexpiry = ''
|
||||
@@ -745,9 +745,9 @@ class WOSiteCreateController(CementBaseController):
|
||||
# check if a wildcard cert for the root domain exist
|
||||
Log.debug(self, "checkWildcardExist on *.{0}"
|
||||
.format(wo_root_domain))
|
||||
isWildcard = checkWildcardExist(self, wo_root_domain)
|
||||
Log.debug(self, "isWildcard = {0}".format(isWildcard))
|
||||
if isWildcard:
|
||||
iswildcard = SSL.checkwildcardexist(self, wo_root_domain)
|
||||
Log.debug(self, "iswildcard = {0}".format(iswildcard))
|
||||
if iswildcard:
|
||||
Log.info(self, "Using existing Wildcard SSL "
|
||||
"certificate from {0} to secure {1}"
|
||||
.format(wo_root_domain, wo_domain))
|
||||
@@ -769,7 +769,7 @@ class WOSiteCreateController(CementBaseController):
|
||||
if pargs.hsts:
|
||||
setupHsts(self, wo_domain)
|
||||
|
||||
site_url_https(self, wo_domain)
|
||||
SSL.siteurlhttps(self, wo_domain)
|
||||
if not WOService.reload_service(self, 'nginx'):
|
||||
Log.error(self, "service nginx reload failed. "
|
||||
"check issues with `nginx -t` command")
|
||||
@@ -1174,7 +1174,7 @@ class WOSiteUpdateController(CementBaseController):
|
||||
|
||||
# --letsencrypt=renew code goes here
|
||||
if pargs.letsencrypt == "renew" and not pargs.all:
|
||||
expiry_days = SSL.getExpirationDays(self, wo_domain)
|
||||
expiry_days = SSL.getexpirationdays(self, wo_domain)
|
||||
min_expiry_days = 45
|
||||
if check_ssl:
|
||||
if (expiry_days <= min_expiry_days):
|
||||
@@ -1196,12 +1196,12 @@ class WOSiteUpdateController(CementBaseController):
|
||||
"check issues with `nginx -t` command")
|
||||
Log.info(self, "SUCCESS: Certificate was successfully renewed For"
|
||||
" https://{0}".format(wo_domain))
|
||||
if (SSL.getExpirationDays(self, wo_domain) > 0):
|
||||
if (SSL.getexpirationdays(self, wo_domain) > 0):
|
||||
Log.info(self, "Your cert will expire within " +
|
||||
str(SSL.getExpirationDays(self, wo_domain)) +
|
||||
str(SSL.getexpirationdays(self, wo_domain)) +
|
||||
" days.")
|
||||
Log.info(self, "Expiration date: " +
|
||||
str(SSL.getExpirationDate(self, wo_domain)))
|
||||
str(SSL.getexpirationdate(self, wo_domain)))
|
||||
|
||||
else:
|
||||
Log.warn(
|
||||
@@ -1236,12 +1236,12 @@ class WOSiteUpdateController(CementBaseController):
|
||||
self, "You have more than 45 days with the current "
|
||||
"certificate - refusing to run.\n")
|
||||
|
||||
if (SSL.getExpirationDays(self, wo_domain) > 0):
|
||||
if (SSL.getexpirationdays(self, wo_domain) > 0):
|
||||
Log.info(self, "Your cert will expire within " +
|
||||
str(SSL.getExpirationDays(self, wo_domain)) +
|
||||
str(SSL.getexpirationdays(self, wo_domain)) +
|
||||
" days.")
|
||||
Log.info(self, "Expiration date: \n\n" +
|
||||
str(SSL.getExpirationDate(self, wo_domain)))
|
||||
str(SSL.getexpirationdate(self, wo_domain)))
|
||||
return 0
|
||||
# else:
|
||||
# Log.warn(self, "Your cert already EXPIRED !
|
||||
@@ -1354,11 +1354,11 @@ class WOSiteUpdateController(CementBaseController):
|
||||
# check if a wildcard cert for the root domain exist
|
||||
Log.debug(self, "checkWildcardExist on *.{0}"
|
||||
.format(wo_root_domain))
|
||||
isWildcard = checkWildcardExist(self, wo_root_domain)
|
||||
Log.debug(self, "isWildcard = {0}".format(isWildcard))
|
||||
iswildcard = SSL.checkwildcardexist(self, wo_root_domain)
|
||||
Log.debug(self, "iswildcard = {0}".format(iswildcard))
|
||||
if not os.path.isfile("{0}/conf/nginx/ssl.conf.disabled"):
|
||||
if wo_subdomain:
|
||||
if isWildcard:
|
||||
if iswildcard:
|
||||
Log.info(self, "Using existing Wildcard SSL "
|
||||
"certificate from {0} to secure {1}"
|
||||
.format(wo_root_domain, wo_domain))
|
||||
@@ -1375,9 +1375,6 @@ class WOSiteUpdateController(CementBaseController):
|
||||
else:
|
||||
setupLetsEncrypt(self, wo_domain, wo_subdomain,
|
||||
wo_wildcard, wo_dns, wo_acme_dns)
|
||||
|
||||
httpsRedirect(self, wo_domain, True, wo_wildcard)
|
||||
site_url_https(self, wo_domain)
|
||||
else:
|
||||
WOFileUtils.mvfile(self, "{0}/conf/nginx/ssl.conf.disabled"
|
||||
.format(wo_site_webroot),
|
||||
@@ -1389,8 +1386,8 @@ class WOSiteUpdateController(CementBaseController):
|
||||
'/etc/nginx/conf.d/force-ssl-{0}.conf'
|
||||
.format(wo_domain))
|
||||
|
||||
httpsRedirect(self, wo_domain, True, wo_wildcard)
|
||||
site_url_https(self, wo_domain)
|
||||
httpsRedirect(self, wo_domain, True, wo_wildcard)
|
||||
SSL.siteUrlHttps(self, wo_domain)
|
||||
|
||||
if not WOService.reload_service(self, 'nginx'):
|
||||
Log.error(self, "service nginx reload failed. "
|
||||
@@ -1398,20 +1395,20 @@ class WOSiteUpdateController(CementBaseController):
|
||||
Log.info(self, "Congratulations! Successfully "
|
||||
"Configured SSL for Site "
|
||||
" https://{0}".format(wo_domain))
|
||||
if wo_subdomain and isWildcard:
|
||||
if (SSL.getExpirationDays(self, wo_root_domain) > 0):
|
||||
if wo_subdomain and iswildcard:
|
||||
if (SSL.getexpirationdays(self, wo_root_domain) > 0):
|
||||
Log.info(
|
||||
self, "Your cert will expire within " +
|
||||
str(SSL.getExpirationDays(self, wo_root_domain)) +
|
||||
str(SSL.getexpirationdays(self, wo_root_domain)) +
|
||||
" days.")
|
||||
else:
|
||||
Log.warn(
|
||||
self, "Your cert already EXPIRED ! "
|
||||
".PLEASE renew soon . ")
|
||||
else:
|
||||
if (SSL.getExpirationDays(self, wo_domain) > 0):
|
||||
if (SSL.getexpirationdays(self, wo_domain) > 0):
|
||||
Log.info(self, "Your cert will expire within " +
|
||||
str(SSL.getExpirationDays(self, wo_domain)) +
|
||||
str(SSL.getexpirationdays(self, wo_domain)) +
|
||||
" days.")
|
||||
else:
|
||||
Log.warn(
|
||||
|
||||
@@ -6,7 +6,6 @@ import json
|
||||
import re
|
||||
import string
|
||||
import subprocess
|
||||
import csv
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
from wo.cli.plugins.sitedb import getSiteInfo
|
||||
@@ -1290,37 +1289,6 @@ def removeAcmeConf(self, domain):
|
||||
WOService.restart_service(self, "nginx")
|
||||
|
||||
|
||||
def site_url_https(self, domain):
|
||||
if os.path.isfile('/var/www/{0}/wp-config.php'.format(domain)):
|
||||
wo_site_webroot = ('/var/www/{0}'.format(domain))
|
||||
Log.info(self, "Checking if site url already "
|
||||
"use https, please wait...")
|
||||
WOFileUtils.chdir(self, '{0}/htdocs/'.format(wo_site_webroot))
|
||||
wo_siteurl = \
|
||||
WOShellExec.cmd_exec_stdout(self,
|
||||
"{0} option get siteurl "
|
||||
.format(WOVariables.wo_wpcli_path) +
|
||||
"--allow-root --quiet")
|
||||
test_url = re.split(":", wo_siteurl)
|
||||
if not (test_url[0] == 'https'):
|
||||
try:
|
||||
WOShellExec.cmd_exec(self, "{0} option update siteurl "
|
||||
"\'https://{1}\' --allow-root".format(
|
||||
WOVariables.wo_wpcli_path, domain))
|
||||
WOShellExec.cmd_exec(self, "{0} option update home "
|
||||
"\'https://{1}\' --allow-root".format(
|
||||
WOVariables.wo_wpcli_path, domain))
|
||||
except CommandExecutionError as e:
|
||||
Log.debug(self, "{0}".format(e))
|
||||
raise SiteError("migration to https failed")
|
||||
Log.info(
|
||||
self, "Site address updated "
|
||||
"successfully to https://{0}".format(domain))
|
||||
else:
|
||||
Log.info(
|
||||
self, "Site address was already using https")
|
||||
|
||||
|
||||
def doCleanupAction(self, domain='', webroot='', dbname='', dbuser='',
|
||||
dbhost=''):
|
||||
"""
|
||||
@@ -1350,7 +1318,7 @@ def doCleanupAction(self, domain='', webroot='', dbname='', dbuser='',
|
||||
|
||||
|
||||
def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False,
|
||||
wo_dns=False, wo_acme_dns='dns_cf', backend=False):
|
||||
wo_dns=False, wo_acme_dns='dns_cf'):
|
||||
|
||||
if os.path.isfile("/etc/letsencrypt/"
|
||||
"renewal/{0}_ecc/"
|
||||
@@ -1371,11 +1339,12 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False,
|
||||
self, "Validation : DNS mode with {0}".format(wo_acme_dns))
|
||||
else:
|
||||
acme_mode = "-w /var/www/html"
|
||||
validation_mode = "Subdomain Webroot challenge"
|
||||
validation_mode = "Webroot challenge"
|
||||
Log.debug(self, "Validation : Webroot mode")
|
||||
if subdomain:
|
||||
Log.info(self, "Issuing subdomain SSL cert with acme.sh")
|
||||
Log.info(self, "Certificate type: Subdomain")
|
||||
Log.info(self, "Validation mode : {0}".format(validation_mode))
|
||||
Log.wait(self, "Issuing SSL certificate with acme.sh")
|
||||
ssl = WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) +
|
||||
"--issue "
|
||||
"-d {0} {1} "
|
||||
@@ -1384,8 +1353,9 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False,
|
||||
acme_mode,
|
||||
keylenght))
|
||||
elif wildcard:
|
||||
Log.info(self, "Issuing Wildcard SSL cert with acme.sh")
|
||||
Log.info(self, "Certificate type: Wildcard")
|
||||
Log.info(self, "Validation mode : {0}".format(validation_mode))
|
||||
Log.wait(self, "Issuing SSL certificate with acme.sh")
|
||||
ssl = WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) +
|
||||
"--issue "
|
||||
"-d {0} -d '*.{0}' --dns {1} "
|
||||
@@ -1394,8 +1364,9 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False,
|
||||
wo_acme_dns,
|
||||
keylenght))
|
||||
else:
|
||||
Log.info(self, "Issuing domain SSL cert with acme.sh")
|
||||
Log.info(self, "Certificate type: Domain + www")
|
||||
Log.info(self, "Validation mode : {0}".format(validation_mode))
|
||||
Log.wait(self, "Issuing SSL certificate with acme.sh")
|
||||
ssl = WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) +
|
||||
"--issue "
|
||||
"-d {0} -d www.{0} {1} "
|
||||
@@ -1403,7 +1374,8 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False,
|
||||
.format(wo_domain_name,
|
||||
acme_mode, keylenght))
|
||||
if ssl:
|
||||
Log.info(self, "Deploying SSL cert with acme.sh")
|
||||
Log.valide(self, "Issuing SSL certificate with acme.sh")
|
||||
Log.wait(self, "Deploying SSL cert with acme.sh")
|
||||
Log.debug(self, "Cert deployment for domain: {0}"
|
||||
.format(wo_domain_name))
|
||||
try:
|
||||
@@ -1423,21 +1395,22 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False,
|
||||
"service nginx restart\" "
|
||||
.format(WOVariables.wo_ssl_live,
|
||||
wo_domain_name))
|
||||
Log.info(
|
||||
self, "Adding /var/www/{0}/conf/nginx/ssl.conf"
|
||||
.format(wo_domain_name))
|
||||
Log.valide(self, "Deploying SSL cert with acme.sh")
|
||||
if os.path.isdir('/var/www/{0}/conf/nginx'
|
||||
.format(wo_domain_name)):
|
||||
|
||||
sslconf = open("/var/www/{0}/conf/nginx/ssl.conf"
|
||||
.format(wo_domain_name),
|
||||
encoding='utf-8', mode='w')
|
||||
sslconf.write("listen 443 ssl http2;\n"
|
||||
"listen [::]:443 ssl http2;\n"
|
||||
"ssl_certificate {0}/{1}/fullchain.pem;\n"
|
||||
"ssl_certificate_key {0}/{1}/key.pem;\n"
|
||||
"ssl_trusted_certificate {0}/{1}/ca.pem;\n"
|
||||
"ssl_stapling_verify on;\n"
|
||||
.format(WOVariables.wo_ssl_live, wo_domain_name))
|
||||
sslconf.close()
|
||||
sslconf = open("/var/www/{0}/conf/nginx/ssl.conf"
|
||||
.format(wo_domain_name),
|
||||
encoding='utf-8', mode='w')
|
||||
sslconf.write(
|
||||
"listen 443 ssl http2;\n"
|
||||
"listen [::]:443 ssl http2;\n"
|
||||
"ssl_certificate {0}/{1}/fullchain.pem;\n"
|
||||
"ssl_certificate_key {0}/{1}/key.pem;\n"
|
||||
"ssl_trusted_certificate {0}/{1}/ca.pem;\n"
|
||||
"ssl_stapling_verify on;\n"
|
||||
.format(WOVariables.wo_ssl_live, wo_domain_name))
|
||||
sslconf.close()
|
||||
# updateSiteInfo(self, wo_domain_name, ssl=True)
|
||||
if not WOFileUtils.grep(self, '/var/www/22222/conf/nginx/ssl.conf',
|
||||
'/etc/letsencrypt'):
|
||||
@@ -1466,34 +1439,6 @@ def setupLetsEncrypt(self, wo_domain_name, subdomain=False, wildcard=False,
|
||||
"you are running Let\'s Encrypt Client "
|
||||
"\n to allow it to verify the site automatically.")
|
||||
|
||||
# check if a wildcard exist to secure a new subdomain
|
||||
|
||||
|
||||
def checkWildcardExist(self, wo_domain_name):
|
||||
|
||||
wo_acme_exec = ("/etc/letsencrypt/acme.sh --config-home "
|
||||
"'/etc/letsencrypt/config'")
|
||||
# export certificates list from acme.sh
|
||||
WOShellExec.cmd_exec(self, "{0} ".format(wo_acme_exec) +
|
||||
"--list --listraw > /var/lib/wo/cert.csv")
|
||||
|
||||
# define new csv dialect
|
||||
csv.register_dialect('acmeconf', delimiter='|')
|
||||
# open file
|
||||
certfile = open('/var/lib/wo/cert.csv', mode='r', encoding='utf-8')
|
||||
reader = csv.reader(certfile, 'acmeconf')
|
||||
wo_wildcard_domain = ("*.{0}".format(wo_domain_name))
|
||||
for row in reader:
|
||||
if wo_wildcard_domain in row[2]:
|
||||
isWildcard = True
|
||||
break
|
||||
else:
|
||||
isWildcard = False
|
||||
certfile.close()
|
||||
|
||||
return isWildcard
|
||||
|
||||
|
||||
# copy wildcard certificate to a subdomain
|
||||
|
||||
|
||||
@@ -1537,9 +1482,9 @@ def renewLetsEncrypt(self, wo_domain_name):
|
||||
if not ssl:
|
||||
Log.error(self, "ERROR : Let's Encrypt certificate renewal FAILED!",
|
||||
False)
|
||||
if (SSL.getExpirationDays(self, wo_domain_name) > 0):
|
||||
if (SSL.getexpirationdays(self, wo_domain_name) > 0):
|
||||
Log.error(self, "Your current certificate will expire within " +
|
||||
str(SSL.getExpirationDays(self, wo_domain_name)) +
|
||||
str(SSL.getexpirationdays(self, wo_domain_name)) +
|
||||
" days.", False)
|
||||
else:
|
||||
Log.error(self, "Your current certificate already expired!", False)
|
||||
|
||||
@@ -45,3 +45,23 @@ class Log:
|
||||
Logs debug messages into log file
|
||||
"""
|
||||
self.app.log.debug(Log.HEADER + msg + Log.ENDC)
|
||||
|
||||
def wait(self, msg, end='\r', log=True):
|
||||
"""
|
||||
Logs info messages with validation step
|
||||
"""
|
||||
print(
|
||||
Log.OKBLUE + msg +
|
||||
"[" + Log.ENDC + ".." + Log.OKBLUE + "]", end=end)
|
||||
if log:
|
||||
self.app.log.info(Log.OKBLUE + msg + Log.ENDC)
|
||||
|
||||
def valide(self, msg, end='\n', log=True):
|
||||
"""
|
||||
Logs info messages after validation step
|
||||
"""
|
||||
print(
|
||||
Log.OKBLUE + msg +
|
||||
"[" + Log.ENDC + "OK" + Log.OKBLUE + "]", end=end)
|
||||
if log:
|
||||
self.app.log.info(Log.OKBLUE + msg + Log.ENDC)
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import csv
|
||||
import os
|
||||
import re
|
||||
|
||||
from wo.core.fileutils import WOFileUtils
|
||||
from wo.core.logging import Log
|
||||
from wo.core.shellexec import WOShellExec
|
||||
from wo.core.variables import WOVariables
|
||||
|
||||
|
||||
class SSL:
|
||||
|
||||
def getExpirationDays(self, domain, returnonerror=False):
|
||||
def getexpirationdays(self, domain, returnonerror=False):
|
||||
# check if exist
|
||||
if not os.path.isfile('/etc/letsencrypt/live/{0}/cert.pem'
|
||||
.format(domain)):
|
||||
@@ -33,7 +37,7 @@ class SSL:
|
||||
# return "Certificate Already Expired ! Please Renew soon."
|
||||
return -1
|
||||
|
||||
def getExpirationDate(self, domain):
|
||||
def getexpirationdate(self, domain):
|
||||
# check if exist
|
||||
if not os.path.isfile('/etc/letsencrypt/live/{0}/cert.pem'
|
||||
.format(domain)):
|
||||
@@ -49,3 +53,61 @@ class SSL:
|
||||
"\"Not After\" | cut -c 25-)\" "
|
||||
.format(domain))
|
||||
return expiration_date
|
||||
|
||||
def siteurlhttps(self, domain):
|
||||
wo_site_webroot = ('/var/www/{0}'.format(domain))
|
||||
WOFileUtils.chdir(
|
||||
self, '{0}/htdocs/'.format(wo_site_webroot))
|
||||
if WOShellExec.cmd_exec(
|
||||
self, "{0} --allow-root core is-installed"
|
||||
.format(WOVariables.wo_wp_cli)):
|
||||
wo_siteurl = (
|
||||
WOShellExec.cmd_exec_stdout(
|
||||
self, "{0} option get siteurl "
|
||||
.format(WOVariables.wo_wpcli_path) +
|
||||
"--allow-root --quiet"))
|
||||
test_url = re.split(":", wo_siteurl)
|
||||
if not (test_url[0] == 'https'):
|
||||
WOShellExec.cmd_exec(
|
||||
self, "{0} option update siteurl "
|
||||
"\'https://{1}\' --allow-root".format(
|
||||
WOVariables.wo_wpcli_path, domain))
|
||||
WOShellExec.cmd_exec(
|
||||
self, "{0} option update home "
|
||||
"\'https://{1}\' --allow-root".format(
|
||||
WOVariables.wo_wpcli_path, domain))
|
||||
WOShellExec.cmd_exec(
|
||||
self, "{0} search-replace \'http://{0}\'"
|
||||
"\'https://{0}\' --skip-columns=guid "
|
||||
"--skip-tables=wp_users"
|
||||
.format(domain))
|
||||
Log.info(
|
||||
self, "Site address updated "
|
||||
"successfully to https://{0}".format(domain))
|
||||
|
||||
# check if a wildcard exist to secure a new subdomain
|
||||
|
||||
def checkwildcardexist(self, wo_domain_name):
|
||||
|
||||
wo_acme_exec = ("/etc/letsencrypt/acme.sh --config-home "
|
||||
"'/etc/letsencrypt/config'")
|
||||
# export certificates list from acme.sh
|
||||
WOShellExec.cmd_exec(
|
||||
self, "{0} ".format(wo_acme_exec) +
|
||||
"--list --listraw > /var/lib/wo/cert.csv")
|
||||
|
||||
# define new csv dialect
|
||||
csv.register_dialect('acmeconf', delimiter='|')
|
||||
# open file
|
||||
certfile = open('/var/lib/wo/cert.csv', mode='r', encoding='utf-8')
|
||||
reader = csv.reader(certfile, 'acmeconf')
|
||||
wo_wildcard_domain = ("*.{0}".format(wo_domain_name))
|
||||
for row in reader:
|
||||
if wo_wildcard_domain in row[2]:
|
||||
iswildcard = True
|
||||
break
|
||||
else:
|
||||
iswildcard = False
|
||||
certfile.close()
|
||||
|
||||
return iswildcard
|
||||
|
||||
Reference in New Issue
Block a user