|
- # imports - standard imports
- import os
-
- # imports - third party imports
- import click
-
- # imports - module imports
- import bench
- from bench.config.nginx import make_nginx_conf
- from bench.config.production_setup import service
- from bench.config.site_config import get_domains, remove_domain, update_site_config
- from bench.bench import Bench
- from bench.utils import exec_cmd, which
- from bench.utils.bench import update_common_site_config
- from bench.exceptions import CommandFailedError
-
-
- def setup_letsencrypt(site, custom_domain, bench_path, interactive):
-
- site_path = os.path.join(bench_path, "sites", site, "site_config.json")
- if not os.path.exists(os.path.dirname(site_path)):
- print("No site named " + site)
- return
-
- if custom_domain:
- domains = get_domains(site, bench_path)
- for d in domains:
- if isinstance(d, dict) and d["domain"] == custom_domain:
- print(f"SSL for Domain {custom_domain} already exists")
- return
-
- if custom_domain not in domains:
- print(f"No custom domain named {custom_domain} set for site")
- return
-
- if interactive:
- click.confirm(
- "Running this will stop the nginx service temporarily causing your sites to go offline\n"
- "Do you want to continue?",
- abort=True,
- )
-
- if not Bench(bench_path).conf.get("dns_multitenant"):
- print("You cannot setup SSL without DNS Multitenancy")
- return
-
- create_config(site, custom_domain)
- run_certbot_and_setup_ssl(site, custom_domain, bench_path, interactive)
- setup_crontab()
-
-
- def create_config(site, custom_domain):
- config = (
- bench.config.env()
- .get_template("letsencrypt.cfg")
- .render(domain=custom_domain or site)
- )
- config_path = f"/etc/letsencrypt/configs/{custom_domain or site}.cfg"
- create_dir_if_missing(config_path)
-
- with open(config_path, "w") as f:
- f.write(config)
-
-
- def run_certbot_and_setup_ssl(site, custom_domain, bench_path, interactive=True):
- service("nginx", "stop")
-
- try:
- interactive = "" if interactive else "-n"
- exec_cmd(
- f"{get_certbot_path()} {interactive} --config /etc/letsencrypt/configs/{custom_domain or site}.cfg certonly"
- )
- except CommandFailedError:
- service("nginx", "start")
- print("There was a problem trying to setup SSL for your site")
- return
-
- ssl_path = f"/etc/letsencrypt/live/{custom_domain or site}/"
- ssl_config = {
- "ssl_certificate": os.path.join(ssl_path, "fullchain.pem"),
- "ssl_certificate_key": os.path.join(ssl_path, "privkey.pem"),
- }
-
- if custom_domain:
- remove_domain(site, custom_domain, bench_path)
- domains = get_domains(site, bench_path)
- ssl_config["domain"] = custom_domain
- domains.append(ssl_config)
- update_site_config(site, {"domains": domains}, bench_path=bench_path)
- else:
- update_site_config(site, ssl_config, bench_path=bench_path)
-
- make_nginx_conf(bench_path)
- service("nginx", "start")
-
-
- def setup_crontab():
- from crontab import CronTab
-
- job_command = (
- f'{get_certbot_path()} renew -a nginx --post-hook "systemctl reload nginx"'
- )
- job_comment = "Renew lets-encrypt every month"
- print(f"Setting Up cron job to {job_comment}")
-
- system_crontab = CronTab(user="root")
-
- for job in system_crontab.find_comment(comment=job_comment): # Removes older entries
- system_crontab.remove(job)
-
- job = system_crontab.new(command=job_command, comment=job_comment)
- job.setall("0 0 */1 * *") # Run at 00:00 every day-of-month
- system_crontab.write()
-
-
- def create_dir_if_missing(path):
- if not os.path.exists(os.path.dirname(path)):
- os.makedirs(os.path.dirname(path))
-
-
- def get_certbot_path():
- try:
- return which("certbot", raise_err=True)
- except FileNotFoundError:
- raise CommandFailedError(
- "Certbot is not installed on your system. Please visit https://certbot.eff.org/instructions for installation instructions, then try again."
- )
-
-
- def renew_certs():
- # Needs to be run with sudo
- click.confirm(
- "Running this will stop the nginx service temporarily causing your sites to go offline\n"
- "Do you want to continue?",
- abort=True,
- )
-
- setup_crontab()
-
- service("nginx", "stop")
- exec_cmd(f"{get_certbot_path()} renew")
- service("nginx", "start")
-
-
- def setup_wildcard_ssl(domain, email, bench_path, exclude_base_domain):
- def _get_domains(domain):
- domain_list = [domain]
-
- if not domain.startswith("*."):
- # add wildcard caracter to domain if missing
- domain_list.append(f"*.{domain}")
- else:
- # include base domain based on flag
- domain_list.append(domain.replace("*.", ""))
-
- if exclude_base_domain:
- domain_list.remove(domain.replace("*.", ""))
-
- return domain_list
-
- if not Bench(bench_path).conf.get("dns_multitenant"):
- print("You cannot setup SSL without DNS Multitenancy")
- return
-
- domain_list = _get_domains(domain.strip())
-
- email_param = ""
- if email:
- email_param = f"--email {email}"
-
- try:
- exec_cmd(
- f"{get_certbot_path()} certonly --manual --preferred-challenges=dns {email_param} \
- --server https://acme-v02.api.letsencrypt.org/directory \
- --agree-tos -d {' -d '.join(domain_list)}"
- )
-
- except CommandFailedError:
- print("There was a problem trying to setup SSL")
- return
-
- ssl_path = f"/etc/letsencrypt/live/{domain}/"
- ssl_config = {
- "wildcard": {
- "domain": domain,
- "ssl_certificate": os.path.join(ssl_path, "fullchain.pem"),
- "ssl_certificate_key": os.path.join(ssl_path, "privkey.pem"),
- }
- }
-
- update_common_site_config(ssl_config)
- setup_crontab()
-
- make_nginx_conf(bench_path)
- print("Restrting Nginx service")
- service("nginx", "restart")
|