mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-04-29 10:10:19 +00:00
letsencrypt: Add option to let Plinth "manage" certbot's renewal hooks
- add action commands for managing and running hooks - adding template, view and url for managing and running hooks - disable Plinth hook management on domain change
This commit is contained in:
parent
1d4289068a
commit
1069f84154
@ -26,11 +26,17 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
import configobj
|
||||||
|
import shutil
|
||||||
|
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
|
from plinth.modules.config import config
|
||||||
|
|
||||||
TEST_MODE = False
|
TEST_MODE = False
|
||||||
LIVE_DIRECTORY = '/etc/letsencrypt/live/'
|
LIVE_DIRECTORY = '/etc/letsencrypt/live/'
|
||||||
|
RENEWAL_DIRECTORY = '/etc/letsencrypt/renewal/'
|
||||||
|
AUTHENTICATOR = 'webroot'
|
||||||
|
WEB_ROOT_PATH = '/var/www/html'
|
||||||
APACHE_PREFIX = '/etc/apache2/sites-available/'
|
APACHE_PREFIX = '/etc/apache2/sites-available/'
|
||||||
APACHE_CONFIGURATION = '''
|
APACHE_CONFIGURATION = '''
|
||||||
<IfModule mod_gnutls.c>
|
<IfModule mod_gnutls.c>
|
||||||
@ -91,6 +97,33 @@ def parse_arguments():
|
|||||||
delete_parser.add_argument('--domain', required=True,
|
delete_parser.add_argument('--domain', required=True,
|
||||||
help='Domain name to delete certificate of')
|
help='Domain name to delete certificate of')
|
||||||
|
|
||||||
|
help_hooks = 'Plinth management of certificates (for current domain).'
|
||||||
|
manage_hook_parser = subparsers.add_parser('manage_hooks', help=help_hooks)
|
||||||
|
manage_hook_parser.add_argument('command', help=help_hooks,
|
||||||
|
choices=('enable', 'disable', 'status'))
|
||||||
|
manage_hook_parser.add_argument('--domain',
|
||||||
|
help='Domain for hook management command.')
|
||||||
|
|
||||||
|
help_domain_arg = 'Domain name to run the hook scripts with.'
|
||||||
|
help_module_arg = 'Include hooks from the provided module names.'
|
||||||
|
help_pre_hooks = 'Maintenance tasks before a cert is obtained or renewed.'
|
||||||
|
run_pre_hooks_parser = subparsers.add_parser('run_pre_hooks',
|
||||||
|
help=help_pre_hooks)
|
||||||
|
run_pre_hooks_parser.add_argument('--domain', help=help_domain_arg)
|
||||||
|
run_pre_hooks_parser.add_argument('--modules', help=help_module_arg)
|
||||||
|
|
||||||
|
help_renew_hooks = 'Maintenance tasks after a cert is actually renewed.'
|
||||||
|
run_renew_hooks_parser = subparsers.add_parser('run_renew_hooks',
|
||||||
|
help=help_renew_hooks)
|
||||||
|
run_renew_hooks_parser.add_argument('--domain', help=help_domain_arg)
|
||||||
|
run_renew_hooks_parser.add_argument('--modules', help=help_module_arg)
|
||||||
|
|
||||||
|
help_post_hooks = 'Maintenance tasks after a cert is obtained or renewed.'
|
||||||
|
run_post_hooks_parser = subparsers.add_parser('run_post_hooks',
|
||||||
|
help=help_post_hooks)
|
||||||
|
run_post_hooks_parser.add_argument('--domain', help=help_domain_arg)
|
||||||
|
run_post_hooks_parser.add_argument('--modules', help=help_module_arg)
|
||||||
|
|
||||||
subparsers.required = True
|
subparsers.required = True
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
@ -104,7 +137,7 @@ def get_certificate_expiry(domain):
|
|||||||
|
|
||||||
|
|
||||||
def get_validity_status(domain):
|
def get_validity_status(domain):
|
||||||
"""Return validity status of a certificate, e.g. valid, revoked, expired."""
|
"""Return validity status of a certificate, e.g. valid, revoked, expired"""
|
||||||
output = subprocess.check_output(['certbot', 'certificates', '-d', domain])
|
output = subprocess.check_output(['certbot', 'certificates', '-d', domain])
|
||||||
output = output.decode(sys.stdout.encoding)
|
output = output.decode(sys.stdout.encoding)
|
||||||
|
|
||||||
@ -119,8 +152,11 @@ def get_validity_status(domain):
|
|||||||
return validity
|
return validity
|
||||||
|
|
||||||
|
|
||||||
def subcommand_get_status(_):
|
def get_status():
|
||||||
"""Return a JSON dictionary of currently configured domains."""
|
"""
|
||||||
|
Return Python dictionary of currently configured domains.
|
||||||
|
Should be run as root, otherwise might yield a wrong, empty answer.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
domains = os.listdir(LIVE_DIRECTORY)
|
domains = os.listdir(LIVE_DIRECTORY)
|
||||||
except OSError:
|
except OSError:
|
||||||
@ -138,7 +174,12 @@ def subcommand_get_status(_):
|
|||||||
action_utils.webserver_is_enabled(domain, kind='site'),
|
action_utils.webserver_is_enabled(domain, kind='site'),
|
||||||
'validity': get_validity_status(domain)
|
'validity': get_validity_status(domain)
|
||||||
}
|
}
|
||||||
|
return domain_status
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_get_status(_):
|
||||||
|
"""Print a JSON dictionary of currently configured domains."""
|
||||||
|
domain_status = get_status()
|
||||||
print(json.dumps({'domains': domain_status}))
|
print(json.dumps({'domains': domain_status}))
|
||||||
|
|
||||||
|
|
||||||
@ -168,7 +209,7 @@ def subcommand_obtain(arguments):
|
|||||||
command = [
|
command = [
|
||||||
'certbot', 'certonly', '--text', '--agree-tos',
|
'certbot', 'certonly', '--text', '--agree-tos',
|
||||||
'--register-unsafely-without-email', '--domain', arguments.domain,
|
'--register-unsafely-without-email', '--domain', arguments.domain,
|
||||||
'--authenticator', 'webroot', '--webroot-path', '/var/www/html/',
|
'--authenticator', AUTHENTICATOR, '--webroot-path', WEB_ROOT_PATH,
|
||||||
'--renew-by-default']
|
'--renew-by-default']
|
||||||
if TEST_MODE:
|
if TEST_MODE:
|
||||||
command.append('--staging')
|
command.append('--staging')
|
||||||
@ -185,6 +226,164 @@ def subcommand_obtain(arguments):
|
|||||||
action_utils.webserver_enable(domain, kind='site')
|
action_utils.webserver_enable(domain, kind='site')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_manage_hooks(arguments):
|
||||||
|
"""
|
||||||
|
Enable/disable/show status of certbot's pre-, renew-, and post-hooks.
|
||||||
|
Command enable only edits current domain, RENEWAL_DIRECTORY/DOMAIN.config,
|
||||||
|
and creates a backup beforehand that is restored if disable is called.
|
||||||
|
Commands disable and status work without error on any domain string.
|
||||||
|
"""
|
||||||
|
if arguments.command not in ('enable', 'disable', 'status'):
|
||||||
|
print('Aborted: Unknown command "%s".' % arguments.command)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
cmd_is_enable = arguments.command == 'enable'
|
||||||
|
current_domain = config.get_domainname()
|
||||||
|
if not arguments.domain:
|
||||||
|
arguments.domain = current_domain
|
||||||
|
|
||||||
|
if cmd_is_enable:
|
||||||
|
if not current_domain:
|
||||||
|
print('Aborted: No current domain set.')
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
if not arguments.domain == current_domain:
|
||||||
|
print('Aborted: Passed domain (%s) is not current domain (%s).' %
|
||||||
|
(arguments.domain, current_domain))
|
||||||
|
sys.exit(3)
|
||||||
|
|
||||||
|
domain_status = get_status()
|
||||||
|
if current_domain not in domain_status:
|
||||||
|
print('Aborted: Current domain (%s) has no LE certificate.' %
|
||||||
|
current_domain)
|
||||||
|
sys.exit(4)
|
||||||
|
|
||||||
|
config_path = RENEWAL_DIRECTORY + arguments.domain + '.conf'
|
||||||
|
if not os.path.exists(config_path):
|
||||||
|
msg, code = ('Aborted', 5) if cmd_is_enable else ('Disabled', 0)
|
||||||
|
print('%s: No certbot config file at %s.' % (msg, config_path))
|
||||||
|
sys.exit(code)
|
||||||
|
|
||||||
|
config_certbot = configobj.ConfigObj(config_path)
|
||||||
|
if 'renewalparams' not in config_certbot:
|
||||||
|
msg, code = ('Aborted', 6) if cmd_is_enable else ('Disabled', 0)
|
||||||
|
print('%s: No section [renewalparams] in config file at %s.'
|
||||||
|
% (msg, config_path))
|
||||||
|
sys.exit(code)
|
||||||
|
|
||||||
|
script_path = os.path.realpath(__file__)
|
||||||
|
config_backup_path = config_path + '_plinth_backup'
|
||||||
|
call_pre = script_path + ' run_pre_hooks --domain ' + arguments.domain
|
||||||
|
call_renew = script_path + ' run_renew_hooks --domain ' + arguments.domain
|
||||||
|
call_post = script_path + ' run_post_hooks --domain ' + arguments.domain
|
||||||
|
config_plinth = {'renewalparams':
|
||||||
|
{'authenticator': AUTHENTICATOR,
|
||||||
|
'webroot_path': [WEB_ROOT_PATH],
|
||||||
|
'webroot_map': {arguments.domain: WEB_ROOT_PATH},
|
||||||
|
'installer': 'None',
|
||||||
|
'pre_hook': call_pre,
|
||||||
|
'renew_hook': call_renew,
|
||||||
|
'post_hook': call_post}}
|
||||||
|
comment_plinth = '# This file was edited by Plinth.'
|
||||||
|
config_edited_by_plinth = any(['edited by plinth' in line.lower()
|
||||||
|
for line in config_certbot.initial_comment])
|
||||||
|
|
||||||
|
if arguments.command == 'status':
|
||||||
|
config_checks = [(entry in config_certbot['renewalparams']) and
|
||||||
|
(str(config_plinth['renewalparams'][entry]) in
|
||||||
|
str(config_certbot['renewalparams'][entry]))
|
||||||
|
for entry in config_plinth['renewalparams'].keys()]
|
||||||
|
if all(config_checks):
|
||||||
|
print('enabled')
|
||||||
|
else:
|
||||||
|
print('disabled')
|
||||||
|
|
||||||
|
elif arguments.command == 'enable':
|
||||||
|
if not config_edited_by_plinth:
|
||||||
|
shutil.copy(config_path, config_backup_path)
|
||||||
|
config_certbot.initial_comment.append(comment_plinth)
|
||||||
|
|
||||||
|
config_certbot['renewalparams'].update(config_plinth['renewalparams'])
|
||||||
|
config_certbot.write()
|
||||||
|
print('enabled successfully')
|
||||||
|
|
||||||
|
elif arguments.command == 'disable':
|
||||||
|
# if changed, restore from backup; refuse disabling if no backup exists
|
||||||
|
if not config_edited_by_plinth:
|
||||||
|
print('Disabled: Nothing to do, hook management was not enabled.')
|
||||||
|
elif os.path.exists(config_backup_path):
|
||||||
|
shutil.move(config_backup_path, config_path)
|
||||||
|
print('disabled successfully')
|
||||||
|
else:
|
||||||
|
print('Aborted: No backup config file at %s.' % config_backup_path)
|
||||||
|
sys.exit(7)
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_run_pre_hooks(arguments):
|
||||||
|
"""
|
||||||
|
Execute all needed maintenance tasks BEFORE a cert is obtained/renewed.
|
||||||
|
If registered as certbot's pre-hook, this script gets ALWAYS executed when
|
||||||
|
certbot attempts a renewal, irrespective of necessity/success (2x per day).
|
||||||
|
"""
|
||||||
|
# Require current domain, to avoid confusion (e.g. call from old cron job).
|
||||||
|
if not arguments.domain:
|
||||||
|
print('Aborted: You must specify the current domain.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
current_domain = config.get_domainname()
|
||||||
|
if not arguments.domain == current_domain:
|
||||||
|
print('Aborted: Current domain is %s, but called for %s.' %
|
||||||
|
(current_domain, arguments.domain))
|
||||||
|
sys.exit(2)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_run_renew_hooks(arguments):
|
||||||
|
"""
|
||||||
|
Execute all needed maintenance tasks when a cert is renewed.
|
||||||
|
If registered as certbot's renew-hook, this script gets ONLY executed when
|
||||||
|
certbot successfully renewed a certificate; with Debian default config,
|
||||||
|
this means it would run about once every 60 days (renewals get executed
|
||||||
|
if a cert is <30 days before expiry, and current default is 90 days).
|
||||||
|
"""
|
||||||
|
# Require current domain, to avoid confusion (e.g. call from old cron job).
|
||||||
|
if not arguments.domain:
|
||||||
|
print('Aborted: You must specify the current domain.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
current_domain = config.get_domainname()
|
||||||
|
if not arguments.domain == current_domain:
|
||||||
|
print('Aborted: Current domain is %s, but called for %s.' %
|
||||||
|
(current_domain, arguments.domain))
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
if action_utils.service_is_running('apache2'):
|
||||||
|
action_utils.service_restart('apache2')
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_run_post_hooks(arguments):
|
||||||
|
"""
|
||||||
|
Execute all needed maintenance tasks AFTER a cert is obtained/renewed.
|
||||||
|
If registered as certbot's post-hook, this script gets ALWAYS executed when
|
||||||
|
certbot attempts a renewal, irrespective of necessity/success (2x per day).
|
||||||
|
"""
|
||||||
|
# Require current domain, to avoid confusion (e.g. call from old cron job).
|
||||||
|
if not arguments.domain:
|
||||||
|
print('Aborted: You must specify the current domain.')
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
current_domain = config.get_domainname()
|
||||||
|
if not arguments.domain == current_domain:
|
||||||
|
print('Aborted: Current domain is %s, but called for %s.' %
|
||||||
|
(current_domain, arguments.domain))
|
||||||
|
sys.exit(2)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def subcommand_delete(arguments):
|
def subcommand_delete(arguments):
|
||||||
"""Disable a domain and delete the certificate."""
|
"""Disable a domain and delete the certificate."""
|
||||||
domain = arguments.domain
|
domain = arguments.domain
|
||||||
|
|||||||
@ -20,12 +20,13 @@ Plinth module for using Let's Encrypt.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from plinth import actions
|
||||||
from plinth import action_utils
|
from plinth import action_utils
|
||||||
from plinth import cfg
|
from plinth import cfg
|
||||||
from plinth.menu import main_menu
|
from plinth.menu import main_menu
|
||||||
from plinth.modules import names
|
from plinth.modules import names
|
||||||
from plinth.utils import format_lazy
|
from plinth.utils import format_lazy
|
||||||
|
from plinth.signals import domainname_change
|
||||||
|
|
||||||
|
|
||||||
version = 1
|
version = 1
|
||||||
@ -63,6 +64,7 @@ def init():
|
|||||||
menu = main_menu.get('system')
|
menu = main_menu.get('system')
|
||||||
menu.add_urlname(_('Certificates (Let\'s Encrypt)'),
|
menu.add_urlname(_('Certificates (Let\'s Encrypt)'),
|
||||||
'glyphicon-lock', 'letsencrypt:index')
|
'glyphicon-lock', 'letsencrypt:index')
|
||||||
|
domainname_change.connect(on_domainname_change)
|
||||||
|
|
||||||
|
|
||||||
def setup(helper, old_version=None):
|
def setup(helper, old_version=None):
|
||||||
@ -82,3 +84,14 @@ def diagnose():
|
|||||||
results.append(action_utils.diagnose_url('https://' + domain))
|
results.append(action_utils.diagnose_url('https://' + domain))
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def on_domainname_change(sender, old_domainname, new_domainname, **kwargs):
|
||||||
|
"""Disable renewal hook management after a domain name change."""
|
||||||
|
del sender # Unused
|
||||||
|
del new_domainname # Unused
|
||||||
|
del kwargs # Unused
|
||||||
|
|
||||||
|
actions.superuser_run('letsencrypt', ['manage_hooks', 'disable',
|
||||||
|
'--domain', old_domainname],
|
||||||
|
async=True)
|
||||||
|
|||||||
@ -49,7 +49,13 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% for domain, domain_status in status.domains.items %}
|
{% for domain, domain_status in status.domains.items %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ domain }}</td>
|
<td>
|
||||||
|
{% if domain == status.current_domain.name %}
|
||||||
|
<b>{{ domain }}</b>
|
||||||
|
{% else %}
|
||||||
|
{{ domain }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if domain_status.certificate_available and domain_status.validity == "valid" %}
|
{% if domain_status.certificate_available and domain_status.validity == "valid" %}
|
||||||
<span class="label label-success">
|
<span class="label label-success">
|
||||||
@ -128,6 +134,62 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<form class="form" method="post"
|
||||||
|
action="{% url 'letsencrypt:toggle_hooks' status.current_domain.name %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="checkbox">
|
||||||
|
<label>
|
||||||
|
{% if status.current_domain.name and status.current_domain.has_cert %}
|
||||||
|
<input type="checkbox" name="toggle_hooks" id="id_toggle_hooks"
|
||||||
|
{% if status.current_domain.manage_hooks_enabled %}checked{% endif %}
|
||||||
|
onchange="this.form.submit();">
|
||||||
|
</input>
|
||||||
|
<noscript>
|
||||||
|
<button class="btn btn-sm btn-default" type="submit">
|
||||||
|
{% trans "Update config" %}</button>
|
||||||
|
</noscript>
|
||||||
|
{% else %}
|
||||||
|
<input type="checkbox" name="toggle_hooks" id="id_toggle_hooks"
|
||||||
|
class="disabled"></input>
|
||||||
|
<noscript>
|
||||||
|
<button class="btn btn-sm btn-default disabled" type="submit">
|
||||||
|
{% trans "Update config" %}</button>
|
||||||
|
</noscript>
|
||||||
|
{% endif %}
|
||||||
|
<span>
|
||||||
|
{% if status.current_domain.name %}
|
||||||
|
{% blocktrans with current_domain=status.current_domain.name %}
|
||||||
|
Let Plinth manage certificate renewal of
|
||||||
|
<b>{{ current_domain }}</b> (recommmended)
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% else %}
|
||||||
|
{% blocktrans with current_domain=status.current_domain.name %}
|
||||||
|
Let Plinth manage certificate renewal of the current domain (recommmended)
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<p class="help-block">
|
||||||
|
{% if status.current_domain.name and status.current_domain.has_cert %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
If {{ box_name }} manages the certificate renewal for the current domain,
|
||||||
|
it will ensure that all apps that use the certificate can use it, as soon
|
||||||
|
as it gets renewed.
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% elif not status.current_domain.has_cert %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
<b>No certificate available for the current domain.</b>
|
||||||
|
First obtain a certificate to enable management of its renewal.
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% else %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
<b>No current domain is configured.</b>
|
||||||
|
First configure a domain to enable management of its certificates.
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
{% include "diagnostics_button.html" with module="letsencrypt" enabled=True %}
|
{% include "diagnostics_button.html" with module="letsencrypt" enabled=True %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% blocktrans trimmed %}
|
{% blocktrans trimmed %}
|
||||||
|
|||||||
@ -31,4 +31,6 @@ urlpatterns = [
|
|||||||
name='obtain'),
|
name='obtain'),
|
||||||
url(r'^sys/letsencrypt/delete/(?P<domain>[^/]+)/$', views.delete,
|
url(r'^sys/letsencrypt/delete/(?P<domain>[^/]+)/$', views.delete,
|
||||||
name='delete'),
|
name='delete'),
|
||||||
|
url(r'^sys/letsencrypt/toggle_hooks/(?P<domain>[^/]+)/$',
|
||||||
|
views.toggle_hooks, name='toggle_hooks'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -32,6 +32,7 @@ from plinth import actions
|
|||||||
from plinth.errors import ActionError
|
from plinth.errors import ActionError
|
||||||
from plinth.modules import letsencrypt
|
from plinth.modules import letsencrypt
|
||||||
from plinth.modules import names
|
from plinth.modules import names
|
||||||
|
from plinth.modules.config import config
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -69,14 +70,48 @@ def obtain(request, domain):
|
|||||||
"""Obtain and install a certificate for a given domain."""
|
"""Obtain and install a certificate for a given domain."""
|
||||||
try:
|
try:
|
||||||
actions.superuser_run('letsencrypt', ['obtain', '--domain', domain])
|
actions.superuser_run('letsencrypt', ['obtain', '--domain', domain])
|
||||||
|
actions.superuser_run('letsencrypt', ['manage_hooks', 'enable'])
|
||||||
messages.success(
|
messages.success(
|
||||||
request, _('Certificate successfully obtained for domain {domain}')
|
request, _('Certificate successfully obtained for domain {domain}')
|
||||||
.format(domain=domain))
|
.format(domain=domain))
|
||||||
|
successful_obtain = True
|
||||||
except ActionError as exception:
|
except ActionError as exception:
|
||||||
messages.error(
|
messages.error(
|
||||||
request,
|
request,
|
||||||
_('Failed to obtain certificate for domain {domain}: {error}')
|
_('Failed to obtain certificate for domain {domain}: {error}')
|
||||||
.format(domain=domain, error=exception.args[2]))
|
.format(domain=domain, error=exception.args[2]))
|
||||||
|
successful_obtain = False
|
||||||
|
|
||||||
|
if domain == config.get_domainname() and successful_obtain:
|
||||||
|
try:
|
||||||
|
actions.superuser_run('letsencrypt', ['manage_hooks', 'enable'])
|
||||||
|
messages.success(
|
||||||
|
request, _('Certificate management enabled for {domain}.')
|
||||||
|
.format(domain=domain))
|
||||||
|
except ActionError as exception:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_('Failed to enable certificate management for {domain}: '
|
||||||
|
'{error}')
|
||||||
|
.format(domain=domain, error=exception.args[2]))
|
||||||
|
|
||||||
|
return redirect(reverse_lazy('letsencrypt:index'))
|
||||||
|
|
||||||
|
|
||||||
|
@require_POST
|
||||||
|
def toggle_hooks(request, domain):
|
||||||
|
"""Toggle pointing of certbot's hooks to Plinth, for the current domain."""
|
||||||
|
subcommand = 'disable' if _hooks_manage_enabled() else 'enable'
|
||||||
|
try:
|
||||||
|
actions.superuser_run('letsencrypt', ['manage_hooks', subcommand])
|
||||||
|
messages.success(
|
||||||
|
request, _('Certificate management changed for domain {domain}')
|
||||||
|
.format(domain=domain))
|
||||||
|
except ActionError as exception:
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
_('Failed to switch certificate management for {domain}: {error}')
|
||||||
|
.format(domain=domain, error=exception.args[2]))
|
||||||
|
|
||||||
return redirect(reverse_lazy('letsencrypt:index'))
|
return redirect(reverse_lazy('letsencrypt:index'))
|
||||||
|
|
||||||
@ -102,6 +137,12 @@ def get_status():
|
|||||||
"""Get the current settings."""
|
"""Get the current settings."""
|
||||||
status = actions.superuser_run('letsencrypt', ['get-status'])
|
status = actions.superuser_run('letsencrypt', ['get-status'])
|
||||||
status = json.loads(status)
|
status = json.loads(status)
|
||||||
|
curr_dom = config.get_domainname()
|
||||||
|
current_domain = {'name': curr_dom,
|
||||||
|
'has_cert': curr_dom in status['domains'] and
|
||||||
|
status['domains'][curr_dom]['certificate_available'],
|
||||||
|
'manage_hooks_enabled': _hooks_manage_enabled()}
|
||||||
|
status['current_domain'] = current_domain
|
||||||
|
|
||||||
for domain_type, domains in names.domains.items():
|
for domain_type, domains in names.domains.items():
|
||||||
# XXX: Remove when Let's Encrypt supports .onion addresses
|
# XXX: Remove when Let's Encrypt supports .onion addresses
|
||||||
@ -112,3 +153,13 @@ def get_status():
|
|||||||
status['domains'].setdefault(domain, {})
|
status['domains'].setdefault(domain, {})
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|
||||||
|
def _hooks_manage_enabled():
|
||||||
|
"""Return status of hook management for current domain."""
|
||||||
|
try:
|
||||||
|
output = actions.superuser_run('letsencrypt',
|
||||||
|
['manage_hooks', 'status'])
|
||||||
|
except ActionError:
|
||||||
|
return False
|
||||||
|
return output.strip() == 'enabled'
|
||||||
|
|||||||
@ -6,3 +6,4 @@ psutil
|
|||||||
python-apt
|
python-apt
|
||||||
python-augeas
|
python-augeas
|
||||||
ruamel.yaml
|
ruamel.yaml
|
||||||
|
configobj
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user