From c922474f0968d71ec903873ced8e4dc6799a6a22 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Tue, 29 Sep 2015 11:17:21 -0400 Subject: [PATCH 49/49] Lightweight CAs: implement deletion API and CLI Fixes: https://fedorahosted.org/pki/ticket/1324 --- base/ca/shared/conf/acl.ldif | 2 +- base/ca/shared/conf/acl.properties | 1 + .../src/com/netscape/ca/CertificateAuthority.java | 59 ++++++++++++++++++++++ .../dogtagpki/server/ca/rest/AuthorityService.java | 32 ++++++++++-- .../certsrv/authority/AuthorityClient.java | 5 ++ .../certsrv/authority/AuthorityResource.java | 8 +++ .../netscape/certsrv/ca/ICertificateAuthority.java | 6 +++ .../netscape/cmstools/authority/AuthorityCLI.java | 1 + .../cmstools/authority/AuthorityRemoveCLI.java | 59 ++++++++++++++++++++++ 9 files changed, 168 insertions(+), 5 deletions(-) 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..97c122b2f4575df14e61013a34ddd25adfca30b7 100644 --- a/base/ca/shared/conf/acl.ldif +++ b/base/ca/shared/conf/acl.ldif @@ -58,4 +58,4 @@ resourceACLS: certServer.ca.groups:execute:allow (execute) group="Administrators resourceACLS: certServer.ca.selftests:read,execute:allow (read,execute) group="Administrators":Only admins can access selftests. 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:create,modify,delete:allow (create,modify,delete) group="Administrators":Administrators may create, modify and 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 b3663ed1d497d03651ad1fa753b4e23ae4aea6b0..525b9bd8c0dc45a1ad0419ab35f702c57a9e8bfc 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; @@ -2624,4 +2626,61 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori } } + public void deleteAuthority() throws EBaseException { + if (isHostAuthority()) + throw new CATypeException("Cannot delete the host CA"); + + 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("deleteCA: cert is not on token: " + e); + // if the cert isn't there, never mind + } catch (TokenException e) { + CMS.debug("deleteCA: 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("deleteCA: private key is not on token: " + e); + // if the key isn't there, never mind + } catch (TokenException e) { + CMS.debug("deleteCA: 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 820f8ab6499eed9fdb8e3d8d782df64c71ad1fc3..1449a1e6a58946f1ce1fd6a2d5b5cb7b6b15f7dd 100644 --- a/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java +++ b/base/ca/src/org/dogtagpki/server/ca/rest/AuthorityService.java @@ -99,7 +99,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); @@ -116,7 +116,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); @@ -143,7 +143,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); @@ -198,7 +198,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); @@ -232,6 +232,30 @@ 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 (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/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..8cfb2f84067b63652687feb2c51d29e91baf861f --- /dev/null +++ b/base/java-tools/src/com/netscape/cmstools/authority/AuthorityRemoveCLI.java @@ -0,0 +1,59 @@ +package com.netscape.cmstools.authority; + +import java.util.Arrays; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.ParseException; + +import com.netscape.certsrv.authority.AuthorityData; +import com.netscape.certsrv.ca.AuthorityID; +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; + } + + public void printHelp() { + formatter.printHelp(getFullName() + " ", 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); + } + + String aidString = cmdArgs[0]; + authorityCLI.authorityClient.deleteCA(aidString); + MainCLI.printMessage("Deleted authority \"" + aidString + "\""); + } + +} -- 2.4.3