Repository: certbot/certbot

Issue:
Missing command line option --no-reuse-key
Using the --reuse-key command line option modifies the renewal configuration file (in a magical undocumented way) so as to make the reusing of the existing key persistent for subsequent automatic renewals. There is no (non-magical) documented way to reverse this, and to remove the change that was made to the renewal configuration file. Please add a --no-reuse-key command line option.


Discussion:
This applies to any option that results in an addition to the renewal config file [renewalparams]. For each of them, there should be an opposite option to remove the entry from [renewalparams]. Currently, the only command line interface to remove [renewalparams] is to "renew" with the certonly subcommand. That has the (not clearly documented) effect of ignoring and removing most of the [renewalparams] and replacing them with the new set of parameters. It would be better to be able to turn off an individual renewalparam, without having to resupply all the other remembered renewalparams that you don't want to remove.
Thanks for filing this.

You're right that the absence of `--no-reuse-key` is awkward. If you (or someone else) want(s) to open a PR for this, that'd be great. In the help text for `--no-reuse-key`, I'd recommend explicitly flagging that it is useful for this scenario as not reusing the key is Certbot's default.

Resolving patch:
diff --git a/certbot/certbot/_internal/cli/__init__.py b/certbot/certbot/_internal/cli/__init__.py
--- a/certbot/certbot/_internal/cli/__init__.py
+++ b/certbot/certbot/_internal/cli/__init__.py
@@ -212,6 +212,13 @@ def prepare_and_parse_args(plugins, args, detect_defaults=False):
         action="store_true", default=flag_default("reuse_key"),
         help="When renewing, use the same private key as the existing "
              "certificate.")
+    helpful.add(
+        "automation", "--no-reuse-key", dest="reuse_key",
+        action="store_false", default=flag_default("reuse_key"),
+        help="When renewing, do not use the same private key as the existing "
+             "certificate. Not reusing private keys is the default behavior of "
+             "Certbot. This option may be used to unset --reuse-key on an "
+             "existing certificate.")
 
     helpful.add(
         ["automation", "renew", "certonly"],


Test patch:
diff --git a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py
--- a/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py
+++ b/certbot-ci/certbot_integration_tests/certbot_tests/test_main.py
@@ -433,6 +433,21 @@ def test_reuse_key(context):
         privkey3 = file.read()
     assert privkey2 != privkey3
 
+    context.certbot(['--cert-name', certname, '--domains', certname,
+                     '--reuse-key','--force-renewal'])
+    context.certbot(['renew', '--cert-name', certname, '--no-reuse-key', '--force-renewal'])
+    context.certbot(['renew', '--cert-name', certname, '--force-renewal'])
+
+    with open(join(context.config_dir, 'archive/{0}/privkey4.pem').format(certname), 'r') as file:
+        privkey4 = file.read()
+    with open(join(context.config_dir, 'archive/{0}/privkey5.pem').format(certname), 'r') as file:
+        privkey5 = file.read()
+    with open(join(context.config_dir, 'archive/{0}/privkey6.pem').format(certname), 'r') as file:
+        privkey6 = file.read()
+    assert privkey3 == privkey4
+    assert privkey4 != privkey5
+    assert privkey5 != privkey6
+
     with open(join(context.config_dir, 'archive/{0}/cert1.pem').format(certname), 'r') as file:
         cert1 = file.read()
     with open(join(context.config_dir, 'archive/{0}/cert2.pem').format(certname), 'r') as file: