diff options
author | Fraser Tweedale <ftweedal@redhat.com> | 2015-01-28 02:41:10 -0500 |
---|---|---|
committer | Fraser Tweedale <ftweedal@redhat.com> | 2015-09-26 14:11:51 +1000 |
commit | 2a9f56d02b4a284cda6f8b61b250e1494f19a83e (patch) | |
tree | 9b12125932ed41a5dbe06f8dafb66656e78c7ad8 /base/common | |
parent | a5a50e95a691587e22335018538b4f578dfee6d1 (diff) | |
download | pki-2a9f56d02b4a284cda6f8b61b250e1494f19a83e.tar.gz pki-2a9f56d02b4a284cda6f8b61b250e1494f19a83e.tar.xz pki-2a9f56d02b4a284cda6f8b61b250e1494f19a83e.zip |
Lightweight CAs: initial support
This commit adds initial support for "lightweight CAs" - CAs that
inhabit an existing CA instance and share the request queue and
certificate database of the "top-level CA".
We initially support only sub-CAs under the top-level CA - either
direct sub-CAs or nested. The general design will support hosting
unrelated CAs but creation or import of unrelated CAs is not yet
implemented.
Part of: https://fedorahosted.org/pki/ticket/1213
Diffstat (limited to 'base/common')
11 files changed, 403 insertions, 4 deletions
diff --git a/base/common/src/com/netscape/certsrv/authority/AuthorityData.java b/base/common/src/com/netscape/certsrv/authority/AuthorityData.java new file mode 100644 index 000000000..2312c3989 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/authority/AuthorityData.java @@ -0,0 +1,123 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2015 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +/** + * @author ftweedal + */ +package com.netscape.certsrv.authority; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; +import org.jboss.resteasy.plugins.providers.atom.Link; + +@XmlRootElement(name = "authority") +@XmlAccessorType(XmlAccessType.FIELD) +public class AuthorityData { + + public static Marshaller marshaller; + public static Unmarshaller unmarshaller; + + static { + try { + marshaller = JAXBContext.newInstance(AuthorityData.class).createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); + unmarshaller = JAXBContext.newInstance(AuthorityData.class).createUnmarshaller(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @XmlAttribute + protected Boolean isHostAuthority; + + public Boolean getIsHostAuthority() { + return isHostAuthority; + } + + + @XmlAttribute + protected String id; + + public String getID() { + return id; + } + + + @XmlAttribute + protected String parentID; + + public String getParentID() { + return parentID; + } + + + @XmlAttribute + protected String dn; + + public String getDN() { + return dn; + } + + + @XmlAttribute + protected Boolean enabled; + + public Boolean getEnabled() { + return enabled; + } + + + @XmlAttribute + protected String description; + + public String getDescription() { + return description; + } + + + protected Link link; + + public Link getLink() { + return link; + } + + public void setLink(Link link) { + this.link = link; + } + + protected AuthorityData() { + } + + public AuthorityData( + Boolean isHostAuthority, + String dn, String id, String parentID, + Boolean enabled, String description) { + this.isHostAuthority = isHostAuthority; + this.dn = dn; + this.id = id; + this.parentID = parentID; + this.enabled = enabled; + this.description = description; + } + +} diff --git a/base/common/src/com/netscape/certsrv/authority/AuthorityResource.java b/base/common/src/com/netscape/certsrv/authority/AuthorityResource.java new file mode 100644 index 000000000..eaef903db --- /dev/null +++ b/base/common/src/com/netscape/certsrv/authority/AuthorityResource.java @@ -0,0 +1,96 @@ +package com.netscape.certsrv.authority; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +import org.jboss.resteasy.annotations.ClientResponseType; + +import com.netscape.certsrv.acls.ACLMapping; +import com.netscape.certsrv.authentication.AuthMethodMapping; + +@Path("authorities") +public interface AuthorityResource { + + public static final String HOST_AUTHORITY = "host-authority"; + + @GET + public Response listCAs(); + /* + @QueryParam("start") Integer start, + @QueryParam("size") Integer size); + */ + + @GET + @Path("{id}") + @ClientResponseType(entityType=AuthorityData.class) + public Response getCA(@PathParam("id") String caIDString); + + @GET + @Path("{id}/cert") + @Produces("application/pkix-cert") + @ClientResponseType(entityType=byte[].class) + public Response getCert(@PathParam("id") String caIDString); + + @GET + @Path("{id}/cert") + @Produces("application/x-pem-file") + @ClientResponseType(entityType=String.class) + public Response getCertPEM(@PathParam("id") String caIDString); + + @GET + @Path("{id}/chain") + @Produces("application/pkcs7-mime") + @ClientResponseType(entityType=byte[].class) + public Response getChain(@PathParam("id") String caIDString); + + @GET + @Path("{id}/chain") + @Produces("application/x-pem-file") + @ClientResponseType(entityType=String.class) + public Response getChainPEM(@PathParam("id") String caIDString); + + @POST + @ClientResponseType(entityType=AuthorityData.class) + @AuthMethodMapping("authorities") + @ACLMapping("authorities.create") + public Response createCA(AuthorityData data); + + /** + * Modify a CA (supports partial updates). + * + * isHostEnabled, authorityID, authorityParentID and DN are + * immutable; differences in these values are ignored. + * + * Other values, if null, are ignored, otherwise they are + * set to the new value. To remove the description, use an + * empty string. + */ + @PUT + @Path("{id}") + @ClientResponseType(entityType=AuthorityData.class) + @AuthMethodMapping("authorities") + @ACLMapping("authorities.modify") + public Response modifyCA( + @PathParam("id") String caIDString, + AuthorityData data); + + @POST + @Path("{id}/enable") + @ClientResponseType(entityType=AuthorityData.class) + @AuthMethodMapping("authorities") + @ACLMapping("authorities.modify") + public Response enableCA(@PathParam("id") String caIDString); + + @POST + @Path("{id}/disable") + @ClientResponseType(entityType=AuthorityData.class) + @AuthMethodMapping("authorities") + @ACLMapping("authorities.modify") + public Response disableCA(@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 new file mode 100644 index 000000000..daac587b7 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/ca/AuthorityID.java @@ -0,0 +1,36 @@ +package com.netscape.certsrv.ca; + +import java.util.UUID; + +/** + * Identifier for a CertificateAuthority. + */ +public class AuthorityID implements Comparable<AuthorityID> { + + protected UUID uuid; + + /** + * Parse a AuthorityID from the given string + */ + public AuthorityID(String s) { + if (s == null) + throw new IllegalArgumentException("null AuthorityID string"); + uuid = UUID.fromString(s); + } + + /** + * Construct a random AuthorityID + */ + public AuthorityID() { + uuid = UUID.randomUUID(); + } + + public String toString() { + return uuid.toString(); + } + + public int compareTo(AuthorityID aid) { + return uuid.compareTo(aid.uuid); + } + +} diff --git a/base/common/src/com/netscape/certsrv/ca/CADisabledException.java b/base/common/src/com/netscape/certsrv/ca/CADisabledException.java new file mode 100644 index 000000000..9b3f16b90 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/ca/CADisabledException.java @@ -0,0 +1,15 @@ +package com.netscape.certsrv.ca; + +/** + * Exception to throw when a (sub-)CA cannot perform an operation + * because it is disabled. + */ +public class CADisabledException extends ECAException { + + private static final long serialVersionUID = -8827509070155037699L; + + public CADisabledException(String msgFormat) { + super(msgFormat); + } + +} diff --git a/base/common/src/com/netscape/certsrv/ca/CANotFoundException.java b/base/common/src/com/netscape/certsrv/ca/CANotFoundException.java new file mode 100644 index 000000000..f292077ec --- /dev/null +++ b/base/common/src/com/netscape/certsrv/ca/CANotFoundException.java @@ -0,0 +1,14 @@ +package com.netscape.certsrv.ca; + +/** + * Exception to throw when a (sub-)CA cannot be found. + */ +public class CANotFoundException extends ECAException { + + private static final long serialVersionUID = -4618887355685066120L; + + public CANotFoundException(String msgFormat) { + super(msgFormat); + } + +} diff --git a/base/common/src/com/netscape/certsrv/ca/CATypeException.java b/base/common/src/com/netscape/certsrv/ca/CATypeException.java new file mode 100644 index 000000000..19eb680e8 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/ca/CATypeException.java @@ -0,0 +1,16 @@ +package com.netscape.certsrv.ca; + +/** + * Exception to throw when an operation cannot be completed + * because the CA is the wrong type (e.g., an operation that + * only applies to lightweight CAs). + */ +public class CATypeException extends ECAException { + + private static final long serialVersionUID = -6004456461295692150L; + + public CATypeException(String msgFormat) { + super(msgFormat); + } + +} diff --git a/base/common/src/com/netscape/certsrv/ca/ICAService.java b/base/common/src/com/netscape/certsrv/ca/ICAService.java index 1d179e076..a4b4a6303 100644 --- a/base/common/src/com/netscape/certsrv/ca/ICAService.java +++ b/base/common/src/com/netscape/certsrv/ca/ICAService.java @@ -23,6 +23,7 @@ import netscape.security.x509.X509CertInfo; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.ca.AuthorityID; import com.netscape.certsrv.connector.IConnector; import com.netscape.certsrv.request.IRequest; @@ -59,13 +60,15 @@ public interface ICAService { * Issues certificate base on enrollment information, * creates certificate record, and stores all necessary data. * + * @param caID CA ID * @param certi information obtain from revocation request + * @param profileId Name of profile used + * @param rid Request ID * @exception EBaseException failed to issue certificate or create certificate record */ - public X509CertImpl issueX509Cert(X509CertInfo certi) - throws EBaseException; - - public X509CertImpl issueX509Cert(X509CertInfo certi, String profileId, String rid) + public X509CertImpl issueX509Cert( + AuthorityID aid, X509CertInfo certi, + String profileId, String rid) throws EBaseException; /** diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java index f87f15420..31d5c9277 100644 --- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java +++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java @@ -18,6 +18,7 @@ package com.netscape.certsrv.ca; import java.util.Enumeration; +import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -515,4 +516,71 @@ public interface ICertificateAuthority extends ISubsystem { public CertificateIssuerName getIssuerObj(); public CertificateSubjectName getSubjectObj(); + + /** + * Enumerate all authorities, including host authority. + */ + public List<ICertificateAuthority> getCAs(); + + /** + * Return whether this CA is the host authority (not a + * lightweight authority). + */ + public boolean isHostAuthority(); + + /** + * Get the AuthorityID of this CA. + */ + public AuthorityID getAuthorityID(); + + /** + * Get the AuthorityID of this CA's parent CA, if available. + */ + public AuthorityID getAuthorityParentID(); + + /** + * Return CA description. May be null. + */ + public boolean getAuthorityEnabled(); + + /** + * Return CA description. May be null. + */ + public String getAuthorityDescription(); + + /** + * Get the CA by ID. Returns null if CA not found. + */ + public ICertificateAuthority getCA(AuthorityID aid); + + /** + * Get the CA by DN. Returns null if CA not found. + */ + public ICertificateAuthority getCA(X500Name dn); + + /** + * Create a new sub-CA under the specified parent CA. + */ + public ICertificateAuthority createCA( + String dn, AuthorityID parentAID, String desc) + throws EBaseException; + + /** + * Create a new sub-CA IMMEDIATELY beneath this one. + * + * This method DOES NOT add the new CA to caMap; it is the + * caller's responsibility. + */ + public ICertificateAuthority createSubCA( + String dn, String desc) + throws EBaseException; + + /** + * Update authority configurables. + * + * @param enabled Whether CA is enabled or disabled + * @param desc Description; null or empty removes it + */ + public void modifyAuthority(Boolean enabled, String desc) + throws EBaseException; } diff --git a/base/common/src/com/netscape/certsrv/ca/IssuerUnavailableException.java b/base/common/src/com/netscape/certsrv/ca/IssuerUnavailableException.java new file mode 100644 index 000000000..75bf88251 --- /dev/null +++ b/base/common/src/com/netscape/certsrv/ca/IssuerUnavailableException.java @@ -0,0 +1,15 @@ +package com.netscape.certsrv.ca; + +/** + * Exception to throw during CA creation when requested CA + * (issuer DN) already exists. + */ +public class IssuerUnavailableException extends ECAException { + + private static final long serialVersionUID = -6247493607604418446L; + + public IssuerUnavailableException(String msgFormat) { + super(msgFormat); + } + +} diff --git a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java index 69a39d7e2..12667120e 100644 --- a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java +++ b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java @@ -175,6 +175,11 @@ public interface IEnrollProfile extends IProfile { public static final String REQUEST_ALGORITHM_PARAMS = "req_algorithm_params"; /** + * ID of requested certificate authority (absense implies host authority) + */ + public static final String REQUEST_AUTHORITY_ID = "req_authority_id"; + + /** * Set Default X509CertInfo in the request. * * @param request profile-based certificate request. diff --git a/base/common/src/com/netscape/certsrv/security/ISigningUnit.java b/base/common/src/com/netscape/certsrv/security/ISigningUnit.java index 34d2a5109..a5d641e93 100644 --- a/base/common/src/com/netscape/certsrv/security/ISigningUnit.java +++ b/base/common/src/com/netscape/certsrv/security/ISigningUnit.java @@ -17,6 +17,7 @@ // --- END COPYRIGHT BLOCK --- package com.netscape.certsrv.security; +import java.security.PrivateKey; import java.security.PublicKey; import netscape.security.x509.X509CertImpl; @@ -161,4 +162,11 @@ public interface ISigningUnit { * @return public key */ public PublicKey getPublicKey(); + + /** + * Retrieves the private key associated in this unit. + * + * @return public key + */ + public PrivateKey getPrivateKey(); } |