Repository: certbot/certbot

Issue:
Don't delete entire lineage when revoking a cert that isn't the live one
## My operating system is (include version):
Debian 9

## I installed Certbot with (certbot-auto, OS package manager, pip, etc):
Using git

## I ran this command and it produced this output:
./certbot-auto --revoke --cert-path /etc/letsencrypt/archive/domain/certN.pem
1. Certbot revoked my certificate as expected
2. Asked me if I want to delete the referenced certificate [Y (recommended)/N]
3. Answered Y
4. Certbot deleted all my certs under /etc/letsencrypt/archive/domain including the live one
## Certbot's behavior differed from what I expected because:
I wanted to revoke the old cert which differs from my new live one. Certbot completely cleaned up every cert ever associated with that domain, which was not expected, and I hardly think that's the recommended option.

## Here is a Certbot log showing the issue (if available):
Not available

###### Logs are stored in `/var/log/letsencrypt` by default. Feel free to redact domains, e-mail and IP addresses as you see fit.

## Here is the relevant nginx server block or Apache virtualhost for the domain I am configuring:
Nginx server block
 **File: /etc/nginx/sites/domain.conf**
...
    include /etc/nginx/conf/domain.ssl;
...

**File: /etc/nginx/conf/domain.ssl**
...
ssl on;
ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
...


Discussion:
Hmm this seems like a possible bug.
@bmw or @ohemorange should likely investigate
@Palethorn you mentioned that you installed certbot via git - do you know how recent your version is?
This is the expected behavior (see https://github.com/certbot/certbot/issues/4109). Our hope was to stop revoked certificates from accidentally being removed, but you're right, it's a good point that we may not want to have this behavior if the revoked cert isn't the most recent one. We plan to take another look at the behavior here, thanks for bringing it to our attention!
Hi,
last git commit is a67a917eca25b26f41c6849f45856239196ea48c, Thu Jan 18 13:03:47 2018 -0800
./certbot-auto --version prints 0.21.1.

EDIT
Just a thought, but if the certificate file is provided while revoking, certbot should only be allowed to touch that one, or a least those matching it's fingerprint.
@Palethorn that's what we used to do, but it caused bugs like https://github.com/certbot/certbot/issues/4108
Actually, soon after this issue was opened, Certbot [changed](https://github.com/certbot/certbot/commit/24ddc65cd4765e82067ab5fd963ffe81348e1f02) so that it asks if you want to delete the lineage or not. This should solve the problem.
This issue still occurs on Certbot 0.29.1 (CentOS 7).

The commit added a command line option to control whether to delete certs/keys or not.

However, when answering "Yes" (as this issued reported) or using the introduced `--delete-after-revoke` option in the revoking process, **all** keypairs in `archive` are deleted.
The `certbot revoke --cert-path /path/to/cert1` revoke and delete keypair1, **and delete** all (including those under `live` directory as this issue reported, since the cert/key are merely symlink to the files under `archive`) the other keypairs under `archive`, leaving the later ones alive but inaccessible.

Resolving patch:
diff --git a/certbot/cli.py b/certbot/cli.py
--- a/certbot/cli.py
+++ b/certbot/cli.py
@@ -1311,7 +1311,8 @@ def _create_subparsers(helpful):
     helpful.add("revoke",
                 "--delete-after-revoke", action="store_true",
                 default=flag_default("delete_after_revoke"),
-                help="Delete certificates after revoking them.")
+                help="Delete certificates after revoking them, along with all previous and later "
+                "versions of those certificates.")
     helpful.add("revoke",
                 "--no-delete-after-revoke", action="store_false",
                 dest="delete_after_revoke",
diff --git a/certbot/main.py b/certbot/main.py
--- a/certbot/main.py
+++ b/certbot/main.py
@@ -548,7 +548,8 @@ def _delete_if_appropriate(config): # pylint: disable=too-many-locals,too-many-b
 
     attempt_deletion = config.delete_after_revoke
     if attempt_deletion is None:
-        msg = ("Would you like to delete the cert(s) you just revoked?")
+        msg = ("Would you like to delete the cert(s) you just revoked, along with all earlier and "
+            "later versions of the cert?")
         attempt_deletion = display.yesno(msg, yes_label="Yes (recommended)", no_label="No",
                 force_interactive=True, default=True)
 


Test patch: