diff --git a/actions/letsencrypt b/actions/letsencrypt index 7c592bf85..0baa1e7b9 100755 --- a/actions/letsencrypt +++ b/actions/letsencrypt @@ -79,13 +79,17 @@ def parse_arguments(): subparsers.add_parser( 'get-status', help='Return the status of configured domains.') revoke_parser = subparsers.add_parser( - 'revoke', help='Disable and domain and revoke its certificate.') - revoke_parser.add_argument( - '--domain', help='Domain name to revoke certificate for') + 'revoke', help='Revoke certificate of a domain and disable website.') + revoke_parser.add_argument('--domain', required=True, + help='Domain name to revoke certificate for') obtain_parser = subparsers.add_parser( 'obtain', help='Obtain certificate for a domain and setup website.') - obtain_parser.add_argument( - '--domain', help='Domain name to obtain certificate for') + obtain_parser.add_argument('--domain', required=True, + help='Domain name to obtain certificate for') + delete_parser = subparsers.add_parser( + 'delete', help='Delete certificate for a domain and disable website.') + delete_parser.add_argument('--domain', required=True, + help='Domain name to delete certificate of') subparsers.required = True return parser.parse_args() @@ -181,6 +185,20 @@ def subcommand_obtain(arguments): action_utils.webserver_enable(domain, kind='site') +def subcommand_delete(arguments): + """Disable a domain and delete the certificate.""" + domain = arguments.domain + command = ['certbot', 'delete', '--cert-name', domain] + process = subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = process.communicate() + if process.returncode: + print(stderr.decode(), file=sys.stderr) + sys.exit(1) + + action_utils.webserver_disable(domain, kind='site') + + def setup_webserver_config(domain): """Create SSL web server configuration for a domain. diff --git a/plinth/modules/letsencrypt/templates/letsencrypt.html b/plinth/modules/letsencrypt/templates/letsencrypt.html index 52e675b67..4ec299a6c 100644 --- a/plinth/modules/letsencrypt/templates/letsencrypt.html +++ b/plinth/modules/letsencrypt/templates/letsencrypt.html @@ -98,6 +98,12 @@ +
+ {% csrf_token %} + +
{% if "revoked" not in domain_status.validity %}
diff --git a/plinth/modules/letsencrypt/urls.py b/plinth/modules/letsencrypt/urls.py index 09d0bdb9a..00e8bed47 100644 --- a/plinth/modules/letsencrypt/urls.py +++ b/plinth/modules/letsencrypt/urls.py @@ -20,7 +20,6 @@ URLs for the Let's Encrypt module. """ from django.conf.urls import url - from . import views @@ -30,4 +29,6 @@ urlpatterns = [ name='revoke'), url(r'^sys/letsencrypt/obtain/(?P[^/]+)/$', views.obtain, name='obtain'), + url(r'^sys/letsencrypt/delete/(?P[^/]+)/$', views.delete, + name='delete'), ] diff --git a/plinth/modules/letsencrypt/views.py b/plinth/modules/letsencrypt/views.py index 4487c32ec..5b5e78ca1 100644 --- a/plinth/modules/letsencrypt/views.py +++ b/plinth/modules/letsencrypt/views.py @@ -81,6 +81,23 @@ def obtain(request, domain): return redirect(reverse_lazy('letsencrypt:index')) +@require_POST +def delete(request, domain): + """Delete a certificate for a given domain.""" + try: + actions.superuser_run('letsencrypt', ['delete', '--domain', domain]) + messages.success( + request, _('Certificate successfully deleted for domain {domain}') + .format(domain=domain)) + except ActionError as exception: + messages.error( + request, + _('Failed to delete certificate for domain {domain}: {error}') + .format(domain=domain, error=exception.args[2])) + + return redirect(reverse_lazy('letsencrypt:index')) + + def get_status(): """Get the current settings.""" status = actions.superuser_run('letsencrypt', ['get-status'])