diff --git a/.github/workflows/ca-renewal-system-certs-test.yml b/.github/workflows/ca-renewal-system-certs-test.yml index c19dcae2772..ac8222e093d 100644 --- a/.github/workflows/ca-renewal-system-certs-test.yml +++ b/.github/workflows/ca-renewal-system-certs-test.yml @@ -395,8 +395,7 @@ jobs: docker exec pki pki ca-cert-export $CERT_ID --output-file caadmin.crt # delete current cert - # TODO: add pki nss-cert-del command - docker exec pki certutil -D -d /root/.dogtag/nssdb -n caadmin + docker exec pki pki nss-cert-del caadmin # install new cert docker exec pki pki nss-cert-import caadmin --cert caadmin.crt diff --git a/.github/workflows/pki-nss-ecc-test.yml b/.github/workflows/pki-nss-ecc-test.yml index 80b6f8b78bb..d9ad9f2a3a2 100644 --- a/.github/workflows/pki-nss-ecc-test.yml +++ b/.github/workflows/pki-nss-ecc-test.yml @@ -142,11 +142,24 @@ jobs: sed -n 's/\s*Type:\s*\(\S\+\)\s*$/\L\1/p' output > actual diff actual expected - - name: Delete SSL server cert + - name: Delete SSL server cert but keep the key run: | - docker exec pki certutil -D -d /root/.dogtag/nssdb -n sslserver - docker exec pki certutil -L -d /root/.dogtag/nssdb - docker exec pki certutil -K -d /root/.dogtag/nssdb + docker exec pki pki nss-cert-del sslserver + + docker exec pki certutil -L -d /root/.dogtag/nssdb | tee output + + # SSL server cert should not exist + echo "ca_signing CTu,Cu,Cu" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K -d /root/.dogtag/nssdb | tee output + + # SSL server key should exist but orphaned + echo "(orphan)" > expected + echo "NSS Certificate DB:ca_signing" >> expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual - name: Create new SSL server cert request with existing EC key run: | @@ -201,3 +214,21 @@ jobs: docker exec pki certutil -K -d /root/.dogtag/nssdb | tee output sed -n 's/^<.*>\s\+\S\+\s\+\(\S\+\)\s\+NSS Certificate DB:new_sslserver$/\1/p' output > new_sslserver_key_id diff sslserver_key_id new_sslserver_key_id + + - name: Delete SSL server cert and key + run: | + docker exec pki pki nss-cert-del new_sslserver --remove-key + + docker exec pki certutil -L -d /root/.dogtag/nssdb | tee output + + # SSL server cert should not exist + echo "ca_signing CTu,Cu,Cu" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K -d /root/.dogtag/nssdb | tee output + + # SSL server key should not exist + echo "NSS Certificate DB:ca_signing" > expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual diff --git a/.github/workflows/pki-nss-hsm-test.yml b/.github/workflows/pki-nss-hsm-test.yml index efa8b3bc4f8..ac5c7019804 100644 --- a/.github/workflows/pki-nss-hsm-test.yml +++ b/.github/workflows/pki-nss-hsm-test.yml @@ -254,5 +254,209 @@ jobs: sed -n 's/\s*Type:\s*\(\S\+\)\s*$/\L\1/p' output > actual diff actual expected + # get key ID + sed -n 's/\s*Key ID:\s*\(\S\+\)\s*$/\L\1/p' output > sslserver_key_id + + - name: Delete SSL server cert but keep the key + run: | + # delete cert from internal token + docker exec pki pki \ + nss-cert-del \ + sslserver + + # delete cert from HSM + docker exec pki pki \ + -f $SHARED/password.conf \ + nss-cert-del \ + HSM:sslserver + + - name: Verify SSL server cert in internal token + run: | + docker exec pki certutil -L -d /root/.dogtag/nssdb | tee output + + # SSL server cert should not exist + echo "ca_signing CT,C,C" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K -d /root/.dogtag/nssdb | tee output + + # SSL server key should not exist + echo -n > expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual + + - name: Verify SSL server cert in HSM + run: | + docker exec pki certutil -L \ + -d /root/.dogtag/nssdb \ + -h HSM \ + -f $SHARED/password.txt | tee output + + # SSL server cert should not exist + echo "HSM:ca_signing CTu,Cu,Cu" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K \ + -d /root/.dogtag/nssdb \ + -h HSM \ + -f $SHARED/password.txt | tee output + + # SSL server key should exist but orphaned + echo "(orphan)" > expected + echo "HSM:ca_signing" >> expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual + + - name: Create new SSL server cert request with existing key in HSM + run: | + docker exec pki pki \ + --token HSM \ + -f $SHARED/password.conf \ + nss-cert-request \ + --key-id $(cat sslserver_key_id) \ + --subject "CN=pki.example.com" \ + --ext /usr/share/pki/server/certs/sslserver.conf \ + --csr new_sslserver.csr + docker exec pki openssl req -text -noout -in new_sslserver.csr + + docker exec pki certutil -K -d /root/.dogtag/nssdb || true + + docker exec pki certutil -K \ + -d /root/.dogtag/nssdb \ + -f $SHARED/password.txt \ + -h HSM + + - name: Issue new SSL server cert + run: | + docker exec pki pki \ + --token HSM \ + -f $SHARED/password.conf \ + nss-cert-issue \ + --issuer HSM:ca_signing \ + --csr new_sslserver.csr \ + --ext /usr/share/pki/server/certs/sslserver.conf \ + --cert new_sslserver.crt + docker exec pki openssl x509 -text -noout -in new_sslserver.crt + + - name: Import new SSL server cert into internal token and HSM + run: | + docker exec pki pki \ + --token HSM \ + -f $SHARED/password.conf \ + nss-cert-import \ + --cert new_sslserver.crt \ + new_sslserver + + - name: Verify SSL server cert in internal token + run: | + # verify trust flags + echo ",," > expected + + docker exec pki certutil -L -d /root/.dogtag/nssdb | tee output + sed -n 's/^new_sslserver\s*\(\S\+\)\s*$/\1/p' output > actual + diff actual expected + + docker exec pki pki nss-cert-show new_sslserver | tee output + sed -n 's/\s*Trust Flags:\s*\(\S\+\)\s*$/\1/p' output > actual + diff actual expected + + # verify key not in internal token + docker exec pki pki \ + -f $SHARED/password.conf \ + nss-key-find \ + --nickname new_sslserver | tee actual + echo -n > expected + diff actual expected + + - name: Verify SSL server cert in HSM + run: | + # verify trust flags + echo "u,u,u" > expected + + docker exec pki certutil -L \ + -d /root/.dogtag/nssdb \ + -h HSM \ + -f $SHARED/password.txt | tee output + sed -n 's/^HSM:new_sslserver\s*\(\S\+\)\s*$/\1/p' output > actual + diff actual expected + + docker exec pki pki \ + --token HSM \ + -f $SHARED/password.conf \ + nss-cert-show \ + HSM:new_sslserver | tee output + sed -n 's/\s*Trust Flags:\s*\(\S\+\)\s*$/\1/p' output > actual + diff actual expected + + # verify key type + echo rsa > expected + + docker exec pki pki \ + --token HSM \ + -f $SHARED/password.conf \ + nss-key-find \ + --nickname HSM:new_sslserver | tee output + sed -n 's/\s*Type:\s*\(\S\+\)\s*$/\L\1/p' output > actual + diff actual expected + + # get key ID + sed -n 's/\s*Key ID:\s*\(\S\+\)\s*$/\L\1/p' output > new_sslserver_key_id + diff sslserver_key_id new_sslserver_key_id + + - name: Delete SSL server cert and key from internal token and HSM + run: | + # delete cert from internal token + docker exec pki pki \ + nss-cert-del \ + new_sslserver \ + --remove-key + + # delete cert from HSM + docker exec pki pki \ + -f $SHARED/password.conf \ + nss-cert-del \ + HSM:new_sslserver \ + --remove-key + + - name: Verify SSL server cert in internal token + run: | + docker exec pki certutil -L -d /root/.dogtag/nssdb | tee output + + # SSL server cert should not exist + echo "ca_signing CT,C,C" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K -d /root/.dogtag/nssdb | tee output + + # SSL server key should not exist + echo -n > expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual + + - name: Verify SSL server cert in HSM + run: | + docker exec pki certutil -L \ + -d /root/.dogtag/nssdb \ + -h HSM \ + -f $SHARED/password.txt | tee output + + # SSL server cert should not exist + echo "HSM:ca_signing CTu,Cu,Cu" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K \ + -d /root/.dogtag/nssdb \ + -h HSM \ + -f $SHARED/password.txt | tee output + + # SSL server key should not exist + echo "HSM:ca_signing" > expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual + - name: Remove HSM token run: docker exec pki softhsm2-util --delete-token --token HSM diff --git a/.github/workflows/pki-nss-rsa-test.yml b/.github/workflows/pki-nss-rsa-test.yml index 8b3cf7e303a..a31c23eaaad 100644 --- a/.github/workflows/pki-nss-rsa-test.yml +++ b/.github/workflows/pki-nss-rsa-test.yml @@ -142,11 +142,24 @@ jobs: sed -n 's/\s*Type:\s*\(\S\+\)\s*$/\L\1/p' output > actual diff actual expected - - name: Delete SSL server cert + - name: Delete SSL server cert but keep the key run: | - docker exec pki certutil -D -d /root/.dogtag/nssdb -n sslserver - docker exec pki certutil -L -d /root/.dogtag/nssdb - docker exec pki certutil -K -d /root/.dogtag/nssdb + docker exec pki pki nss-cert-del sslserver + + docker exec pki certutil -L -d /root/.dogtag/nssdb | tee output + + # SSL server cert should not exist + echo "ca_signing CTu,Cu,Cu" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K -d /root/.dogtag/nssdb | tee output + + # SSL server key should exist but orphaned + echo "(orphan)" > expected + echo "NSS Certificate DB:ca_signing" >> expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual - name: Create new SSL server cert request with existing RSA key run: | @@ -200,3 +213,21 @@ jobs: docker exec pki pki nss-key-find --nickname new_sslserver | tee output sed -n 's/\s*Type:\s*\(\S\+\)\s*$/\L\1/p' output > actual diff actual expected + + - name: Delete SSL server cert and key + run: | + docker exec pki pki nss-cert-del new_sslserver --remove-key + + docker exec pki certutil -L -d /root/.dogtag/nssdb | tee output + + # SSL server cert should not exist + echo "ca_signing CTu,Cu,Cu" > expected + sed -n -e '1,4d' -e 's/^\(.*\S\)\s\+\(\S\+\)\s*$/\1 \2/p' output > actual + diff expected actual + + docker exec pki certutil -K -d /root/.dogtag/nssdb | tee output + + # SSL server key should not exist + echo "NSS Certificate DB:ca_signing" > expected + sed -n 's/^<.*>\s\+\S\+\s\+\S\+\s\+\(.*\)$/\1/p' output | sort > actual + diff expected actual diff --git a/.github/workflows/pki-pkcs7-test.yml b/.github/workflows/pki-pkcs7-test.yml index 1d909168622..fed0347a7a2 100644 --- a/.github/workflows/pki-pkcs7-test.yml +++ b/.github/workflows/pki-pkcs7-test.yml @@ -98,8 +98,8 @@ jobs: - name: Remove certs from NSS database run: | - docker exec pki certutil -D -d /root/.dogtag/nssdb -n sslserver - docker exec pki certutil -D -d /root/.dogtag/nssdb -n ca_signing + docker exec pki pki nss-cert-del sslserver + docker exec pki pki nss-cert-del ca_signing docker exec pki certutil -L -d /root/.dogtag/nssdb - name: "Import PKCS #7 chain into NSS database" @@ -130,8 +130,8 @@ jobs: - name: Remove certs from NSS database run: | - docker exec pki certutil -D -d /root/.dogtag/nssdb -n sslserver - docker exec pki certutil -D -d /root/.dogtag/nssdb -n "Certificate Authority" + docker exec pki pki nss-cert-del sslserver + docker exec pki pki nss-cert-del "Certificate Authority" docker exec pki certutil -L -d /root/.dogtag/nssdb - name: Import PEM certificates into NSS database diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py index 0c3e93fb6c4..5ff8f22a23b 100644 --- a/base/common/python/pki/nssdb.py +++ b/base/common/python/pki/nssdb.py @@ -2163,24 +2163,52 @@ def remove_cert( token = self.get_effective_token(token) password_file = self.get_password_file(tmpdir, token) - cmd = ['certutil'] + # remove cert from internal token + + cmd = [ + 'pki', + '-d', self.directory + ] + + if self.password_conf: + cmd.extend(['-f', self.password_conf]) + + elif password_file: + cmd.extend(['-C', password_file]) + + cmd.extend([ + 'nss-cert-del', + nickname + ]) if remove_key: - cmd.extend(['-F']) - else: - cmd.extend(['-D']) + cmd.append('--remove-key') - cmd.extend(['-d', self.directory]) + self.run(cmd, check=True, runas=True) if token: - cmd.extend(['-h', token]) + # remove cert from HSM - if password_file: - cmd.extend(['-f', password_file]) + cmd = [ + 'pki', + '-d', self.directory + ] - cmd.extend(['-n', nickname]) + if self.password_conf: + cmd.extend(['-f', self.password_conf]) - self.run(cmd, check=True, runas=True) + elif password_file: + cmd.extend(['-C', password_file]) + + cmd.extend([ + 'nss-cert-del', + token + ':' + nickname + ]) + + if remove_key: + cmd.append('--remove-key') + + self.run(cmd, check=True, runas=True) finally: shutil.rmtree(tmpdir) diff --git a/base/common/src/main/java/com/netscape/cmsutil/crypto/CryptoUtil.java b/base/common/src/main/java/com/netscape/cmsutil/crypto/CryptoUtil.java index 2a3d50e37be..5f3aa3df556 100644 --- a/base/common/src/main/java/com/netscape/cmsutil/crypto/CryptoUtil.java +++ b/base/common/src/main/java/com/netscape/cmsutil/crypto/CryptoUtil.java @@ -1898,7 +1898,16 @@ public static void deleteCertificates(String nickname) throws TokenException, ObjectNotFoundException, NoSuchItemOnTokenException, NotInitializedException { + deleteCertificates(nickname, true); + } + + public static void deleteCertificates(String nickname, boolean removeKey) + throws TokenException, ObjectNotFoundException, + NoSuchItemOnTokenException, NotInitializedException { + CryptoManager manager = CryptoManager.getInstance(); + + logger.info("Finding cert " + nickname); X509Certificate[] certs = manager.findCertsByNickname(nickname); if (certs == null || certs.length == 0) { @@ -1917,7 +1926,15 @@ public static void deleteCertificates(String nickname) } CryptoStore store = token.getCryptoStore(); - store.deleteCert(cert); + + if (removeKey) { + logger.info("Removing cert " + nickname + " and the key"); + store.deleteCert(cert); + + } else { + logger.info("Removing cert " + nickname); + store.deleteCertOnly(cert); + } } } diff --git a/base/tools/src/main/java/com/netscape/cmstools/nss/NSSCertCLI.java b/base/tools/src/main/java/com/netscape/cmstools/nss/NSSCertCLI.java index af8a1f77617..8aa5bd6dc5f 100644 --- a/base/tools/src/main/java/com/netscape/cmstools/nss/NSSCertCLI.java +++ b/base/tools/src/main/java/com/netscape/cmstools/nss/NSSCertCLI.java @@ -22,6 +22,7 @@ public NSSCertCLI(NSSCLI nssCLI) { addModule(new NSSCertIssueCLI(this)); addModule(new NSSCertRequestCLI(this)); addModule(new NSSCertShowCLI(this)); + addModule(new NSSCertRemoveCLI(this)); } public static NSSCertInfo createCertInfo(X509Certificate cert) throws Exception { diff --git a/base/tools/src/main/java/com/netscape/cmstools/nss/NSSCertRemoveCLI.java b/base/tools/src/main/java/com/netscape/cmstools/nss/NSSCertRemoveCLI.java new file mode 100644 index 00000000000..46f3e0fe420 --- /dev/null +++ b/base/tools/src/main/java/com/netscape/cmstools/nss/NSSCertRemoveCLI.java @@ -0,0 +1,51 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package com.netscape.cmstools.nss; + +import org.apache.commons.cli.CommandLine; +import org.dogtagpki.cli.CLIException; +import org.dogtagpki.cli.CommandCLI; + +import com.netscape.cmstools.cli.MainCLI; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class NSSCertRemoveCLI extends CommandCLI { + + public static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(NSSCertRemoveCLI.class); + + public NSSCertRemoveCLI(NSSCertCLI nssCertCLI) { + super("del", "Remove certificate", nssCertCLI); + } + + @Override + public void printHelp() { + formatter.printHelp(getFullName() + " [OPTIONS...] ", options); + } + + @Override + public void createOptions() { + options.addOption(null, "remove-key", false, "Remove key"); + } + + @Override + public void execute(CommandLine cmd) throws Exception { + + String[] cmdArgs = cmd.getArgs(); + + if (cmdArgs.length < 1) { + throw new CLIException("Missing certificate nickname"); + } + + String nickname = cmdArgs[0]; + + boolean removeKey = cmd.hasOption("remove-key"); + + MainCLI mainCLI = (MainCLI) getRoot(); + mainCLI.init(); + + CryptoUtil.deleteCertificates(nickname, removeKey); + } +} diff --git a/docs/changes/v11.5.0/Tools-Changes.adoc b/docs/changes/v11.5.0/Tools-Changes.adoc index 899b05119ca..16fccec8249 100644 --- a/docs/changes/v11.5.0/Tools-Changes.adoc +++ b/docs/changes/v11.5.0/Tools-Changes.adoc @@ -28,3 +28,7 @@ The `pki nss-cert-issue` command has been modified to provide the certificate validity. The default is 3 months. The `--months-valid` option has been deprecated. + +== New pki nss-cert-del CLI == + +The `pki nss-cert-del` command has been added to delete a certificate from NSS database.