[Pki-devel] [PATCH] 0048-0049 Lightweight CAs: implement deletion

Fraser Tweedale ftweedal at redhat.com
Thu Oct 1 12:50:20 UTC 2015


On Wed, Sep 30, 2015 at 03:59:55PM -0400, Ade Lee wrote:
> On Wed, 2015-09-30 at 11:26 -0700, Christina Fu wrote:
> See other comments below, but the gist of Christina's comments are:
> 1.  We need to look up the parent and revoke the subca signing cert.
> 2.  We need to restrict Delete to Leaf CAs.  So if you have Host CA ->
> sub ca1 -> sub ca2 -> subca 3,
>      you cannot delete sub CA 1 without deleting subca3 and subca2 (in
> that order).
> 3.  The mothballed state Christina refers to is what we now call the
> disabled state.  In this case,
>      we should not be able to issue new certs (including subca certs). 
>  We should however still be able to
>     revoke certs and publish CRLs.
>
Thanks Christina and Ade for the feedback.  The updated patch
(attached) addresses #1.  #3 is addressed by my patch 0050 (separate
thread).

I will tackle revocation-on-delete next.  If you are happy with
what's in the attached patched we could push it and I'll file a
ticket and implement revocation in a separate patch, but the call is
yours.

Cheers,
Fraser

> > Hi Fraser,
> > 
> > Ade caught me on irc for some feedback.  I have not had chance to
> > look at your patches, but I did get the gist of the subca delete
> > issues from him.
> > Two key suggestions I have:
> > 1. make sure the action is audited to its parent (audit log
> > preserved)
> > 2. make sure revocation is taken cared of of the subca's signing cert
> > (and therefore invalidating all its signed certs)
> >    - and make sure the root CA is never deleted, so that the crls
> > could be preserved and referenced to;
> >    - and note that ocsp will no longer work for the subca that is
> > deleted, as the signing cert is gone for good
> > 
> > Regarding keeping the root CA, we had discussion on possibly keeping
> > it in a "mothballed state"...I'll let Ade add to this.
> > 
> > thanks,
> > Christina
> > 
> > On 09/30/2015 07:00 AM, Fraser Tweedale wrote:
> > > Updated patch attached. Comments inline.
> > > 
> > > On Wed, Sep 30, 2015 at 06:35:57PM +1000, Fraser Tweedale wrote:
> > > > > 3) It would be good to have a "Are you sure?" dialog on the CLI
> > > > > (with
> > > > > relevant override option).
> > > > > 
> > > > Will do.
> > > > 
> > > Done.
> > > 
> > > > > 5) I have been thinking about ways to restrict delete.  We
> > > > > should 
> > > > >    discuss and decide on options.  Some ideas:
> > > > > 
> > > > >    a) Add CS.cfg option to disable deletes (for production
> > > > > say).
> > > > > 
> > > > Disagree; don't want more config in flat files.  Having the knob
> > > > in
> > > > the database would be better but I prefer a combination of other
> > > > options (see below).
> > > > 
> > > > >    b) Add optional field (deletable) to the CA entry.  This can
> > > > > be
> > > > >       set by the creating admin to be True for test
> > > > > environments or
> > > > >       cases where we know the environment will be short lived,
> > > > > or
> > > > >       False for long lived CAs.  Default could be configurable.
> > > > > 
> > > > >       CAs could still be deleted, but only by doing something
> > > > >       out-of-band --like modifying the db entry using pki
> > > > > -server
> > > > >       commands or similar.
> > > > > 
> > > > >    c) Requiring CAs to be disabled before deleting them.
> > > > > 
> > > > I'm in favour of this.
> > > > 
> > > > >    d) Setting a separate ACL for delete, so that it would be
> > > > > easier
> > > > >       for admins to set special permissions for delete.
> > > > > 
> > > > And in favour of this.
> > > > 
> > > > >    ... others?
> > > > > 
> > > > I like (c) plus (d) plus perhaps a pkispawn knob that controls
> > > > whether the admin-can-delete ACL gets added at the beginning.
> > > > 
> > > > Let me know what you think and thanks for your feedback!
> > > > 
> > > (c) and (d) are implemented in updated patch.  If you agree with
> > > (c)
> > > plus (d) plus pkispawn knob (I guess we'll call that (e)), I'll
> > > file
> > > a ticket for (e).
> > > 
> I'm OK with (c) and (d) and others appear to be too.  Archiving is
> difficult because it basically won't work with an HSM.
> I suppose this is just equivalent to the controls we have in revoking
> the host CA signing cert.
> I don't think (e) is needed.
>
-------------- next part --------------
From 6494270363b82683136eeda2332207412f29b906 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Tue, 29 Sep 2015 11:17:21 -0400
Subject: [PATCH] Lightweight CAs: implement deletion API and CLI

Implement lightweight authority deletion including CLI command.  To
be deleted an authority must be disabled and have no sub-CAs.

Fixes: https://fedorahosted.org/pki/ticket/1324
---
 base/ca/shared/conf/acl.ldif                       |  1 +
 base/ca/shared/conf/acl.properties                 |  1 +
 .../src/com/netscape/ca/CertificateAuthority.java  | 75 ++++++++++++++++++++++
 .../dogtagpki/server/ca/rest/AuthorityService.java | 36 +++++++++--
 .../certsrv/authority/AuthorityClient.java         |  5 ++
 .../certsrv/authority/AuthorityResource.java       |  8 +++
 .../src/com/netscape/certsrv/ca/AuthorityID.java   |  4 ++
 .../netscape/certsrv/ca/CAEnabledException.java    | 15 +++++
 .../netscape/certsrv/ca/CANotLeafException.java    | 16 +++++
 .../netscape/certsrv/ca/ICertificateAuthority.java |  6 ++
 .../netscape/cmstools/authority/AuthorityCLI.java  |  1 +
 .../cmstools/authority/AuthorityRemoveCLI.java     | 72 +++++++++++++++++++++
 12 files changed, 236 insertions(+), 4 deletions(-)
 create mode 100644 base/common/src/com/netscape/certsrv/ca/CAEnabledException.java
 create mode 100644 base/common/src/com/netscape/certsrv/ca/CANotLeafException.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/authority/AuthorityRemoveCLI.java

diff --git a/base/ca/shared/conf/acl.ldif b/base/ca/shared/conf/acl.ldif
index 54c9f1d5c64b6578de83f1b7ffdff922a69975f4..27d89a3131e9220b4c03b17aad14b364fe97ff20 100644
--- a/base/ca/shared/conf/acl.ldif
+++ b/base/ca/shared/conf/acl.ldif
@@ -59,3 +59,4 @@ resourceACLS: certServer.ca.selftests:read,execute:allow (read,execute) group="A
 resourceACLS: certServer.ca.users:execute:allow (execute) group="Administrators":Admins may execute user operations
 resourceACLS: certServer.ca.authorities:list,read:allow (list,read) user="anybody":Anybody may list and read lightweight authorities
 resourceACLS: certServer.ca.authorities:create,modify:allow (create,modify) group="Administrators":Administrators may create and modify lightweight authorities
+resourceACLS: certServer.ca.authorities:delete:allow (delete) group="Administrators":Administrators may delete lightweight authorities
diff --git a/base/ca/shared/conf/acl.properties b/base/ca/shared/conf/acl.properties
index f0b5b9f650ad2fc4bde531ade94347a7280d3089..8b3e9d0eea09e5e3ab8271888ab0532d47b69348 100644
--- a/base/ca/shared/conf/acl.properties
+++ b/base/ca/shared/conf/acl.properties
@@ -25,3 +25,4 @@ authorities.create = certServer.ca.authorities,create
 authorities.list = certServer.ca.authorities,list
 authorities.modify = certServer.ca.authorities,modify
 authorities.read = certServer.ca.authorities,read
+authorities.delete = certServer.ca.authorities,delete
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index d5523c14cc0132422c971b840324bd95bfa1fda9..5440a380ab8c5627f6305ad882159a7bcf3ef88e 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -50,9 +50,11 @@ import org.mozilla.jss.asn1.INTEGER;
 import org.mozilla.jss.asn1.InvalidBERException;
 import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
 import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.crypto.CryptoStore;
 import org.mozilla.jss.crypto.CryptoToken;
 import org.mozilla.jss.crypto.KeyPairAlgorithm;
 import org.mozilla.jss.crypto.KeyPairGenerator;
+import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
 import org.mozilla.jss.crypto.SignatureAlgorithm;
 import org.mozilla.jss.crypto.TokenException;
 import org.mozilla.jss.pkix.cert.Extension;
@@ -68,7 +70,9 @@ import com.netscape.certsrv.base.Nonces;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.ca.AuthorityID;
 import com.netscape.certsrv.ca.CADisabledException;
+import com.netscape.certsrv.ca.CAEnabledException;
 import com.netscape.certsrv.ca.CANotFoundException;
+import com.netscape.certsrv.ca.CANotLeafException;
 import com.netscape.certsrv.ca.CATypeException;
 import com.netscape.certsrv.ca.ECAException;
 import com.netscape.certsrv.ca.ICRLIssuingPoint;
@@ -2627,4 +2631,75 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
         }
     }
 
+    public void deleteAuthority() throws EBaseException {
+        if (isHostAuthority())
+            throw new CATypeException("Cannot delete the host CA");
+
+        if (authorityEnabled)
+            throw new CAEnabledException("Must disable CA before deletion");
+
+        boolean hasSubCAs = false;
+        for (ICertificateAuthority ca : getCAs()) {
+            AuthorityID parentAID = ca.getAuthorityParentID();
+            if (parentAID != null && parentAID.equals(this.authorityID)) {
+                hasSubCAs = true;
+                break;
+            }
+        }
+        if (hasSubCAs)
+            throw new CANotLeafException("CA with sub-CAs cannot be deleted (delete sub-CAs first)");
+
+        caMap.remove(authorityID);
+        shutdown();
+
+        // delete ldap entry
+        ILdapConnFactory dbFactory = CMS.getLdapBoundConnFactory("updateAuthority");
+        dbFactory.init(CMS.getConfigStore().getSubStore("internaldb"));
+        LDAPConnection conn = dbFactory.getConn();
+        String dn = "cn=" + authorityID.toString() + ",ou=authorities,ou="
+            + getId() + "," + getDBSubsystem().getBaseDN();
+        try {
+            conn.delete(dn);
+        } catch (LDAPException e) {
+            throw new ELdapException("Error deleting authority entry '" + dn + "': " + e);
+        } finally {
+            dbFactory.returnConn(conn);
+            dbFactory.reset();
+        }
+
+        CryptoManager cryptoManager;
+        try {
+            cryptoManager = CryptoManager.getInstance();
+        } catch (CryptoManager.NotInitializedException e) {
+            // can't happen
+            throw new ECAException("CryptoManager not initialized");
+        }
+
+        // delete cert
+        CryptoStore cryptoStore =
+            cryptoManager.getInternalKeyStorageToken().getCryptoStore();
+        try {
+            cryptoStore.deleteCert(mCaX509Cert);
+        } catch (NoSuchItemOnTokenException e) {
+            CMS.debug("deleteAuthority: cert is not on token: " + e);
+            // if the cert isn't there, never mind
+        } catch (TokenException e) {
+            CMS.debug("deleteAuthority: TokenExcepetion while deleting cert: " + e);
+            throw new ECAException("TokenException while deleting cert: " + e);
+        }
+
+        // delete key
+        try {
+            cryptoStore.deletePrivateKey(mSigningUnit.getPrivateKey());
+        } catch (NoSuchItemOnTokenException e) {
+            CMS.debug("deleteAuthority: private key is not on token: " + e);
+            // if the key isn't there, never mind
+        } catch (TokenException e) {
+            CMS.debug("deleteAuthority: TokenExcepetion while deleting private key: " + e);
+            // TODO don't know what causes this yet, or how to
+            // prevent it.
+            //throw new ECAException("TokenException while deleting private key: " + e);
+        }
+    }
+
 }
diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java
index 2aa0e97d966d7f879a9999966fb5942bb54dcf42..8d0cac3ef997d4daab3198be68efcb66b145f991 100644
--- a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java
+++ b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java
@@ -43,7 +43,9 @@ import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.base.ResourceNotFoundException;
 import com.netscape.certsrv.ca.AuthorityID;
 import com.netscape.certsrv.ca.CADisabledException;
+import com.netscape.certsrv.ca.CAEnabledException;
 import com.netscape.certsrv.ca.CANotFoundException;
+import com.netscape.certsrv.ca.CANotLeafException;
 import com.netscape.certsrv.ca.CATypeException;
 import com.netscape.certsrv.ca.ICertificateAuthority;
 import com.netscape.certsrv.ca.IssuerUnavailableException;
@@ -100,7 +102,7 @@ public class AuthorityService extends PKIService implements AuthorityResource {
             try {
                 aid = new AuthorityID(aidString);
             } catch (IllegalArgumentException e) {
-                throw new BadRequestException("Bad CA ID: " + aidString);
+                throw new BadRequestException("Bad AuthorityID: " + aidString);
             }
 
             ca = hostCA.getCA(aid);
@@ -117,7 +119,7 @@ public class AuthorityService extends PKIService implements AuthorityResource {
         try {
             aid = new AuthorityID(aidString);
         } catch (IllegalArgumentException e) {
-            throw new BadRequestException("Bad CA ID: " + aidString);
+            throw new BadRequestException("Bad AuthorityID: " + aidString);
         }
 
         ICertificateAuthority ca = hostCA.getCA(aid);
@@ -144,7 +146,7 @@ public class AuthorityService extends PKIService implements AuthorityResource {
         try {
             aid = new AuthorityID(aidString);
         } catch (IllegalArgumentException e) {
-            throw new BadRequestException("Bad CA ID: " + aidString);
+            throw new BadRequestException("Bad AuthorityID: " + aidString);
         }
 
         ICertificateAuthority ca = hostCA.getCA(aid);
@@ -199,7 +201,7 @@ public class AuthorityService extends PKIService implements AuthorityResource {
         try {
             aid = new AuthorityID(aidString);
         } catch (IllegalArgumentException e) {
-            throw new BadRequestException("Bad CA ID: " + aidString);
+            throw new BadRequestException("Bad AuthorityID: " + aidString);
         }
 
         ICertificateAuthority ca = hostCA.getCA(aid);
@@ -233,6 +235,32 @@ public class AuthorityService extends PKIService implements AuthorityResource {
             new AuthorityData(null, null, null, null, false, null));
     }
 
+    @Override
+    public Response deleteCA(String aidString) {
+        AuthorityID aid = null;
+        try {
+            aid = new AuthorityID(aidString);
+        } catch (IllegalArgumentException e) {
+            throw new BadRequestException("Bad AuthorityID: " + aidString);
+        }
+
+        ICertificateAuthority ca = hostCA.getCA(aid);
+        if (ca == null)
+            throw new ResourceNotFoundException("CA \"" + aidString + "\" not found");
+
+        try {
+            ca.deleteAuthority();
+            return createNoContentResponse();
+        } catch (CATypeException e) {
+            throw new ForbiddenException(e.toString());
+        } catch (CAEnabledException | CANotLeafException e) {
+            throw new ConflictingOperationException(e.toString());
+        } catch (EBaseException e) {
+            CMS.debug(e);
+            throw new PKIException("Error modifying authority: " + e.toString());
+        }
+    }
+
     private static AuthorityData readAuthorityData(ICertificateAuthority ca)
             throws PKIException {
         String dn;
diff --git a/base/common/src/com/netscape/certsrv/authority/AuthorityClient.java b/base/common/src/com/netscape/certsrv/authority/AuthorityClient.java
index 86de3352e2424211125c146edf759481448a2694..5a80877ca4479058ba88005421c46d092b2df6a6 100644
--- a/base/common/src/com/netscape/certsrv/authority/AuthorityClient.java
+++ b/base/common/src/com/netscape/certsrv/authority/AuthorityClient.java
@@ -59,4 +59,9 @@ public class AuthorityClient extends Client {
         return client.getEntity(response, AuthorityData.class);
     }
 
+    public void deleteCA(String aidString) {
+        Response response = proxy.deleteCA(aidString);
+        client.getEntity(response, Void.class);
+    }
+
 }
diff --git a/base/common/src/com/netscape/certsrv/authority/AuthorityResource.java b/base/common/src/com/netscape/certsrv/authority/AuthorityResource.java
index eaef903db444512dbea6c87b11800130d94a944d..c6dc696247122b5f07802696c38c2f3517341106 100644
--- a/base/common/src/com/netscape/certsrv/authority/AuthorityResource.java
+++ b/base/common/src/com/netscape/certsrv/authority/AuthorityResource.java
@@ -1,5 +1,6 @@
 package com.netscape.certsrv.authority;
 
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -93,4 +94,11 @@ public interface AuthorityResource {
     @ACLMapping("authorities.modify")
     public Response disableCA(@PathParam("id") String caIDString);
 
+    @DELETE
+    @Path("{id}")
+    @ClientResponseType(entityType=Void.class)
+    @AuthMethodMapping("authorities")
+    @ACLMapping("authorities.delete")
+    public Response deleteCA(@PathParam("id") String caIDString);
+
 }
diff --git a/base/common/src/com/netscape/certsrv/ca/AuthorityID.java b/base/common/src/com/netscape/certsrv/ca/AuthorityID.java
index daac587b75843f5faf75e556d4d0135c8ffc8fd7..9816f87ad02289739c7ff90be1ffc71e086a2bd9 100644
--- a/base/common/src/com/netscape/certsrv/ca/AuthorityID.java
+++ b/base/common/src/com/netscape/certsrv/ca/AuthorityID.java
@@ -29,6 +29,10 @@ public class AuthorityID implements Comparable<AuthorityID> {
         return uuid.toString();
     }
 
+    public boolean equals(AuthorityID aid) {
+        return this.compareTo(aid) == 0;
+    }
+
     public int compareTo(AuthorityID aid) {
         return uuid.compareTo(aid.uuid);
     }
diff --git a/base/common/src/com/netscape/certsrv/ca/CAEnabledException.java b/base/common/src/com/netscape/certsrv/ca/CAEnabledException.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c85276f3bf71bb640a3468f4ed4be4a6aa0180c
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/ca/CAEnabledException.java
@@ -0,0 +1,15 @@
+package com.netscape.certsrv.ca;
+
+/**
+ * Exception to throw when an operation cannot be performed because
+ * the CA to which the operation pertains is enabled.
+ */
+public class CAEnabledException extends ECAException {
+
+    private static final long serialVersionUID = 1056602856006912665L;
+
+    public CAEnabledException(String msgFormat) {
+        super(msgFormat);
+    }
+
+}
diff --git a/base/common/src/com/netscape/certsrv/ca/CANotLeafException.java b/base/common/src/com/netscape/certsrv/ca/CANotLeafException.java
new file mode 100644
index 0000000000000000000000000000000000000000..eabca73641cd0f646167fb6b436aaa736e7139b2
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/ca/CANotLeafException.java
@@ -0,0 +1,16 @@
+package com.netscape.certsrv.ca;
+
+/**
+ * Exception to throw when an operation cannot be performed because
+ * the CA to which the operation pertains is not a leaf CA (ie, has
+ * sub-CAs).
+ */
+public class CANotLeafException extends ECAException {
+
+    private static final long serialVersionUID = -2729093578678941399L;
+
+    public CANotLeafException(String msgFormat) {
+        super(msgFormat);
+    }
+
+}
diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
index 31d5c9277a63ca7c916f39651300b0c9a9061c1e..96bc392294f27d57d9795c2b1b793b8cbc001fda 100644
--- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
@@ -583,4 +583,10 @@ public interface ICertificateAuthority extends ISubsystem {
      */
     public void modifyAuthority(Boolean enabled, String desc)
         throws EBaseException;
+
+    /**
+     * Delete this lightweight CA.
+     */
+    public void deleteAuthority()
+        throws EBaseException;
 }
diff --git a/base/java-tools/src/com/netscape/cmstools/authority/AuthorityCLI.java b/base/java-tools/src/com/netscape/cmstools/authority/AuthorityCLI.java
index 99d38ad1b989e171079df78ddd8b2774817ccb33..4fbcfef760086928b2e0e75fe4fc56f1b249b5fd 100644
--- a/base/java-tools/src/com/netscape/cmstools/authority/AuthorityCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/authority/AuthorityCLI.java
@@ -17,6 +17,7 @@ public class AuthorityCLI extends CLI {
         addModule(new AuthorityCreateCLI(this));
         addModule(new AuthorityDisableCLI(this));
         addModule(new AuthorityEnableCLI(this));
+        addModule(new AuthorityRemoveCLI(this));
     }
 
     public String getFullName() {
diff --git a/base/java-tools/src/com/netscape/cmstools/authority/AuthorityRemoveCLI.java b/base/java-tools/src/com/netscape/cmstools/authority/AuthorityRemoveCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..42265b180ba85b6097ef2354e969fbd0495ac73b
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/authority/AuthorityRemoveCLI.java
@@ -0,0 +1,72 @@
+package com.netscape.cmstools.authority;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.ParseException;
+
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class AuthorityRemoveCLI extends CLI {
+
+    public AuthorityCLI authorityCLI;
+
+    public AuthorityRemoveCLI(AuthorityCLI authorityCLI) {
+        super("del", "Delete Authority", authorityCLI);
+        this.authorityCLI = authorityCLI;
+
+        options.addOption(null, "force", false, "Force delete");
+    }
+
+    public void printHelp() {
+        formatter.printHelp(getFullName() + " <dn>", options);
+    }
+
+    public void execute(String[] args) throws Exception {
+        // Always check for "--help" prior to parsing
+        if (Arrays.asList(args).contains("--help")) {
+            // Display usage
+            printHelp();
+            System.exit(0);
+        }
+
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+        } catch (ParseException e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(-1);
+        }
+
+        String[] cmdArgs = cmd.getArgs();
+        if (cmdArgs.length != 1) {
+            if (cmdArgs.length < 1)
+                System.err.println("No ID specified.");
+            else
+                System.err.println("Too many arguments.");
+            printHelp();
+            System.exit(-1);
+        }
+
+        if (!cmd.hasOption("force")) {
+            System.out.print("Are you sure (Y/N)? ");
+            System.out.flush();
+
+            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+            String line = reader.readLine();
+            if (!line.equalsIgnoreCase("Y")) {
+                System.exit(-1);
+            }
+        }
+
+        String aidString = cmdArgs[0];
+        authorityCLI.authorityClient.deleteCA(aidString);
+        MainCLI.printMessage("Deleted authority \"" + aidString + "\"");
+    }
+
+}
-- 
2.4.3



More information about the Pki-devel mailing list