-
Notifications
You must be signed in to change notification settings - Fork 139
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement GET verb for /ca/v2/certs/<id> REST end-point
This replicate the current behaviour imeplemented in /ca/rest/certs/<id>.
- Loading branch information
Showing
4 changed files
with
291 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,13 +13,19 @@ | |
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
/** | ||
* @author Marco Fargetta <[email protected]> | ||
*/ | ||
public class CAServlet extends HttpServlet { | ||
public static final long serialVersionUID = 1L; | ||
|
||
|
||
public void get(HttpServletRequest request, HttpServletResponse response) throws Exception { | ||
} | ||
|
||
public void post(HttpServletRequest request, HttpServletResponse response) throws Exception { | ||
} | ||
|
||
@Override | ||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
try { | ||
|
@@ -33,6 +39,19 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro | |
} | ||
} | ||
|
||
@Override | ||
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | ||
try { | ||
post(request, response); | ||
|
||
} catch (ServletException | IOException e) { | ||
throw e; | ||
|
||
} catch (Exception e) { | ||
throw new ServletException(e); | ||
} | ||
} | ||
|
||
public CAEngine getCAEngine() { | ||
ServletContext servletContext = getServletContext(); | ||
return (CAEngine) servletContext.getAttribute("engine"); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
// | ||
// Copyright Red Hat, Inc. | ||
// | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
// | ||
package org.dogtagpki.server.ca.v2; | ||
|
||
import java.io.PrintWriter; | ||
|
@@ -13,11 +18,15 @@ | |
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* @author Marco Fargetta <[email protected]> | ||
*/ | ||
@WebServlet("/v2/info") | ||
public class CAInfoServlet extends CAServlet { | ||
private static final long serialVersionUID = 1L; | ||
private static Logger logger = LoggerFactory.getLogger(CAInfoServlet.class); | ||
|
||
@Override | ||
public void get(HttpServletRequest request, HttpServletResponse response) throws Exception { | ||
HttpSession session = request.getSession(); | ||
logger.debug("CAInfoServlet.get(): session: " + session.getId()); | ||
|
261 changes: 261 additions & 0 deletions
261
base/ca/src/main/java/org/dogtagpki/server/ca/v2/CertServlet.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,261 @@ | ||
// | ||
// Copyright Red Hat, Inc. | ||
// | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
// | ||
package org.dogtagpki.server.ca.v2; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.PrintWriter; | ||
import java.security.InvalidKeyException; | ||
import java.security.Principal; | ||
import java.security.PublicKey; | ||
import java.security.cert.X509Certificate; | ||
import java.util.ArrayList; | ||
import java.util.Date; | ||
import java.util.Enumeration; | ||
import java.util.List; | ||
import java.util.Locale; | ||
|
||
import javax.servlet.annotation.WebServlet; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import javax.servlet.http.HttpSession; | ||
|
||
import org.dogtagpki.server.ca.CAEngine; | ||
import org.dogtagpki.server.ca.CAServlet; | ||
import org.dogtagpki.util.cert.CertUtil; | ||
import org.mozilla.jss.netscape.security.pkcs.ContentInfo; | ||
import org.mozilla.jss.netscape.security.pkcs.PKCS7; | ||
import org.mozilla.jss.netscape.security.pkcs.SignerInfo; | ||
import org.mozilla.jss.netscape.security.provider.RSAPublicKey; | ||
import org.mozilla.jss.netscape.security.util.CertPrettyPrint; | ||
import org.mozilla.jss.netscape.security.util.Utils; | ||
import org.mozilla.jss.netscape.security.x509.AlgorithmId; | ||
import org.mozilla.jss.netscape.security.x509.CRLExtensions; | ||
import org.mozilla.jss.netscape.security.x509.CRLReasonExtension; | ||
import org.mozilla.jss.netscape.security.x509.X509CertImpl; | ||
import org.mozilla.jss.netscape.security.x509.X509ExtensionException; | ||
import org.mozilla.jss.netscape.security.x509.X509Key; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.netscape.certsrv.base.EBaseException; | ||
import com.netscape.certsrv.base.PKIException; | ||
import com.netscape.certsrv.cert.CertData; | ||
import com.netscape.certsrv.cert.CertDataInfo; | ||
import com.netscape.certsrv.cert.CertDataInfos; | ||
import com.netscape.certsrv.dbs.certdb.CertId; | ||
import com.netscape.cmscore.dbs.CertRecord; | ||
import com.netscape.cmscore.dbs.CertificateRepository; | ||
import com.netscape.cmscore.dbs.RevocationInfo; | ||
import com.netscape.cmsutil.ldap.LDAPUtil; | ||
|
||
/** | ||
* @author Marco Fargetta <[email protected]> | ||
*/ | ||
@WebServlet("/v2/certs/*") | ||
public class CertServlet extends CAServlet { | ||
public static final int DEFAULT_MAXTIME = 0; | ||
public static final int DEFAULT_MAXRESULTS = 20; | ||
public final static int DEFAULT_SIZE = 20; | ||
|
||
private static final long serialVersionUID = 1L; | ||
private static Logger logger = LoggerFactory.getLogger(CertServlet.class); | ||
|
||
@Override | ||
public void get(HttpServletRequest request, HttpServletResponse response) throws Exception { | ||
HttpSession session = request.getSession(); | ||
logger.debug("CertServlet.get(): session: {}", session.getId()); | ||
|
||
response.setContentType("application/json"); | ||
PrintWriter out = response.getWriter(); | ||
if(request.getPathInfo() != null) { | ||
CertId id = new CertId(request.getPathInfo().substring(1)); | ||
CertData cert; | ||
try { | ||
cert = getCertData(id, request.getLocale()); | ||
out.println(cert.toJSON()); | ||
} catch (Exception e) { | ||
response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI()); | ||
} | ||
return; | ||
} | ||
|
||
int maxResults = request.getParameter("maxResults") == null ? | ||
DEFAULT_MAXRESULTS : Integer.parseInt(request.getParameter("maxResults")); | ||
int maxTime = request.getParameter("maxTime") == null ? | ||
DEFAULT_MAXTIME : Integer.parseInt(request.getParameter("maxTime")); | ||
int size = request.getParameter("size") == null ? | ||
DEFAULT_SIZE : Integer.parseInt(request.getParameter("size")); | ||
int start = request.getParameter("start") == null ? 0 : Integer.parseInt(request.getParameter("start")); | ||
|
||
CertDataInfos infos = listCerts(request.getParameter("status"), maxResults, maxTime, start, size); | ||
out.println(infos.toJSON()); | ||
} | ||
|
||
@Override | ||
public void post(HttpServletRequest request, HttpServletResponse response) throws Exception { | ||
HttpSession session = request.getSession(); | ||
logger.debug("CertServlet.post(): session: {}", session.getId()); | ||
|
||
response.setContentType("application/json"); | ||
PrintWriter out = response.getWriter(); | ||
|
||
if(request.getPathInfo() == null || !request.getPathInfo().equals("/search")) { | ||
response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI()); | ||
return; | ||
} | ||
|
||
CertDataInfos infos = new CertDataInfos(); | ||
out.println(infos.toString()); | ||
} | ||
|
||
private CertData getCertData(CertId id, Locale loc) throws Exception { | ||
CAEngine engine = getCAEngine(); | ||
CertificateRepository repo = engine.getCertificateRepository(); | ||
|
||
//find the cert in question | ||
CertRecord record = repo.readCertificateRecord(id.toBigInteger()); | ||
X509CertImpl cert = record.getCertificate(); | ||
|
||
CertData certData = new CertData(); | ||
certData.setSerialNumber(id); | ||
|
||
Principal issuerDN = cert.getIssuerName(); | ||
if (issuerDN != null) certData.setIssuerDN(issuerDN.toString()); | ||
|
||
Principal subjectDN = cert.getSubjectName(); | ||
if (subjectDN != null) certData.setSubjectDN(subjectDN.toString()); | ||
|
||
String base64 = CertUtil.toPEM(cert); | ||
certData.setEncoded(base64); | ||
|
||
CertPrettyPrint print = new CertPrettyPrint(cert); | ||
certData.setPrettyPrint(print.toString(loc)); | ||
|
||
X509Certificate[] certChain = engine.getCertChain(cert); | ||
|
||
PKCS7 pkcs7 = new PKCS7( | ||
new AlgorithmId[0], | ||
new ContentInfo(new byte[0]), | ||
certChain, | ||
new SignerInfo[0]); | ||
|
||
ByteArrayOutputStream bos = new ByteArrayOutputStream(); | ||
pkcs7.encodeSignedData(bos, false); | ||
byte[] p7Bytes = bos.toByteArray(); | ||
|
||
String p7Str = Utils.base64encode(p7Bytes, true); | ||
certData.setPkcs7CertChain(p7Str); | ||
|
||
Date notBefore = cert.getNotBefore(); | ||
if (notBefore != null) certData.setNotBefore(notBefore.toString()); | ||
|
||
Date notAfter = cert.getNotAfter(); | ||
if (notAfter != null) certData.setNotAfter(notAfter.toString()); | ||
|
||
certData.setRevokedOn(record.getRevokedOn()); | ||
certData.setRevokedBy(record.getRevokedBy()); | ||
|
||
RevocationInfo revInfo = record.getRevocationInfo(); | ||
if (revInfo != null) { | ||
CRLExtensions revExts = revInfo.getCRLEntryExtensions(); | ||
if (revExts != null) { | ||
try { | ||
CRLReasonExtension ext = (CRLReasonExtension) | ||
revExts.get(CRLReasonExtension.NAME); | ||
certData.setRevocationReason(ext.getReason().getCode()); | ||
} catch (X509ExtensionException e) { | ||
// nothing to do | ||
} | ||
} | ||
} | ||
|
||
certData.setStatus(record.getStatus()); | ||
|
||
return certData; | ||
} | ||
|
||
private CertDataInfos listCerts(String status, int maxResults, int maxTime, int start, int size) { | ||
CAEngine engine = getCAEngine(); | ||
CertificateRepository repo = engine.getCertificateRepository(); | ||
|
||
logger.info("Listing certificates"); | ||
|
||
String filter; | ||
if (status == null) { | ||
filter = "(certstatus=*)"; | ||
|
||
} else { | ||
filter = "(certStatus=" + LDAPUtil.escapeFilter(status) + ")"; | ||
} | ||
logger.info("Search filter: " + filter); | ||
|
||
CertDataInfos infos = new CertDataInfos(); | ||
try { | ||
Enumeration<CertRecord> e = repo.searchCertificates(filter, maxResults, maxTime); | ||
if (e == null) { | ||
throw new EBaseException("search results are null"); | ||
} | ||
|
||
// store non-null results in a list | ||
List<CertDataInfo> results = new ArrayList<>(); | ||
while (e.hasMoreElements()) { | ||
CertRecord rec = e.nextElement(); | ||
if (rec == null) continue; | ||
results.add(createCertDataInfo(rec)); | ||
} | ||
|
||
int total = results.size(); | ||
logger.info("Search results: " + total); | ||
infos.setTotal(total); | ||
|
||
// return entries in the requested page | ||
for (int i = start; i < start + size && i < total ; i++) { | ||
infos.addEntry(results.get(i)); | ||
} | ||
} catch (Exception e) { | ||
logger.error("Unable to list certificates: " + e.getMessage(), e); | ||
throw new PKIException("Unable to list certificates: " + e.getMessage(), e); | ||
} | ||
|
||
return infos; | ||
} | ||
|
||
private CertDataInfo createCertDataInfo(CertRecord record) throws EBaseException, InvalidKeyException { | ||
CertDataInfo info = new CertDataInfo(); | ||
|
||
CertId id = new CertId(record.getSerialNumber()); | ||
info.setID(id); | ||
|
||
X509Certificate cert = record.getCertificate(); | ||
info.setIssuerDN(cert.getIssuerDN().toString()); | ||
info.setSubjectDN(cert.getSubjectDN().toString()); | ||
info.setStatus(record.getStatus()); | ||
info.setVersion(cert.getVersion()); | ||
info.setType(cert.getType()); | ||
|
||
PublicKey key = cert.getPublicKey(); | ||
if (key instanceof X509Key) { | ||
X509Key x509Key = (X509Key)key; | ||
info.setKeyAlgorithmOID(x509Key.getAlgorithmId().getOID().toString()); | ||
|
||
if (x509Key.getAlgorithmId().toString().equalsIgnoreCase("RSA")) { | ||
RSAPublicKey rsaKey = new RSAPublicKey(x509Key.getEncoded()); | ||
info.setKeyLength(rsaKey.getKeySize()); | ||
} | ||
} | ||
|
||
info.setNotValidBefore(cert.getNotBefore()); | ||
info.setNotValidAfter(cert.getNotAfter()); | ||
|
||
info.setIssuedOn(record.getCreateTime()); | ||
info.setIssuedBy(record.getIssuedBy()); | ||
|
||
info.setRevokedOn(record.getRevokedOn()); | ||
info.setRevokedBy(record.getRevokedBy()); | ||
|
||
return info; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters