#!/usr/bin/env python3 # # Copyright (C) 2019-2020 VyOS maintainers and contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 or later as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. import sys import os import vyos.defaults from vyos.config import Config from vyos import ConfigError from vyos.util import cmd from vyos.util import call from vyos.util import is_systemd_service_running from vyos import airbag airbag.enable() vyos_conf_scripts_dir = vyos.defaults.directories['conf_mode'] vyos_certbot_dir = vyos.defaults.directories['certbot'] dependencies = [ 'https.py', ] def request_certbot(cert): email = cert.get('email') if email is not None: email_flag = '-m {0}'.format(email) else: email_flag = '' domains = cert.get('domains') if domains is not None: domain_flag = '-d ' + ' -d '.join(domains) else: domain_flag = '' certbot_cmd = f'certbot certonly --config-dir {vyos_certbot_dir} -n --nginx --agree-tos --no-eff-email --expand {email_flag} {domain_flag}' cmd(certbot_cmd, raising=ConfigError, message="The certbot request failed for the specified domains.") def get_config(): conf = Config() if not conf.exists('service https certificates certbot'): return None else: conf.set_level('service https certificates certbot') cert = {} if conf.exists('domain-name'): cert['domains'] = conf.return_values('domain-name') if conf.exists('email'): cert['email'] = conf.return_value('email') return cert def verify(cert): if cert is None: return None if 'domains' not in cert: raise ConfigError("At least one domain name is required to" " request a letsencrypt certificate.") if 'email' not in cert: raise ConfigError("An email address is required to request" " a letsencrypt certificate.") def generate(cert): if cert is None: return None # certbot will attempt to reload nginx, even with 'certonly'; # start nginx if not active if not is_systemd_service_running('nginx.service'): call('systemctl start nginx.service') request_certbot(cert) def apply(cert): if cert is not None: call('systemctl restart certbot.timer') else: call('systemctl stop certbot.timer') return None for dep in dependencies: cmd(f'{vyos_conf_scripts_dir}/{dep}', raising=ConfigError) if __name__ == '__main__': try: c = get_config() verify(c) generate(c) apply(c) except ConfigError as e: print(e) sys.exit(1)