From eb2456af59c685bb90be82340e13a613e723c4bc Mon Sep 17 00:00:00 2001 From: Marco Fargetta Date: Mon, 19 Aug 2024 20:32:08 +0200 Subject: [PATCH] Add TPS TPSCertService to v2 APIs --- .../certsrv/tps/cert/TPSCertCollection.java | 3 +- .../tps/rest/base/TPSCertProcessor.java | 194 ++++++++++++++++++ .../server/tps/rest/v2/TPSCertServlet.java | 66 ++++++ .../server/tps/rest/v2/filters/EmptyACL.java | 2 +- .../tps/rest/v2/filters/EmptyAuthMethod.java | 2 +- 5 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 base/tps/src/main/java/org/dogtagpki/server/tps/rest/base/TPSCertProcessor.java create mode 100644 base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/TPSCertServlet.java diff --git a/base/common/src/main/java/com/netscape/certsrv/tps/cert/TPSCertCollection.java b/base/common/src/main/java/com/netscape/certsrv/tps/cert/TPSCertCollection.java index c08a54f1d2c..c923bac9a58 100644 --- a/base/common/src/main/java/com/netscape/certsrv/tps/cert/TPSCertCollection.java +++ b/base/common/src/main/java/com/netscape/certsrv/tps/cert/TPSCertCollection.java @@ -24,13 +24,14 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.netscape.certsrv.base.DataCollection; +import com.netscape.certsrv.util.JSONSerializer; /** * @author Endi S. Dewata */ @JsonInclude(Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown=true) -public class TPSCertCollection extends DataCollection { +public class TPSCertCollection extends DataCollection implements JSONSerializer { @Override public Collection getEntries() { diff --git a/base/tps/src/main/java/org/dogtagpki/server/tps/rest/base/TPSCertProcessor.java b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/base/TPSCertProcessor.java new file mode 100644 index 00000000000..7fdd8417d1f --- /dev/null +++ b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/base/TPSCertProcessor.java @@ -0,0 +1,194 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.tps.rest.base; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.dogtagpki.server.rest.v2.PKIServlet; +import org.dogtagpki.server.tps.TPSEngine; +import org.dogtagpki.server.tps.TPSSubsystem; +import org.dogtagpki.server.tps.dbs.TPSCertDatabase; +import org.dogtagpki.server.tps.dbs.TPSCertRecord; +import org.dogtagpki.server.tps.dbs.TokenDatabase; +import org.dogtagpki.server.tps.dbs.TokenRecord; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.netscape.certsrv.base.BadRequestException; +import com.netscape.certsrv.base.PKIException; +import com.netscape.certsrv.tps.cert.TPSCertCollection; +import com.netscape.certsrv.tps.cert.TPSCertData; +import com.netscape.certsrv.user.UserResource; + +/** + * @author Marco Fargetta {@literal } + * @author Endi S. Dewata + */ +public class TPSCertProcessor { + private static final Logger logger = LoggerFactory.getLogger(TPSCertProcessor.class); + private TPSSubsystem subsystem; + + + public TPSCertProcessor(TPSEngine engine) { + subsystem = (TPSSubsystem) engine.getSubsystem(TPSSubsystem.ID); + } + + + public TPSCertCollection findCerts(List authorizedProfiles, String tokenID, String filter, int start, int size) { + String method = "TPSCertProcessor:findCerts: "; + String msg = ""; + logger.debug("TPSCertProcessor.findCerts({}, {}, {}, {})", filter, tokenID, start, size); + + if(tokenID == null) { + //TODO: filter should not be mandatory but it is required to overcome a UI limitation + if (filter == null || filter.length() < PKIServlet.MIN_FILTER_LENGTH) { + throw new BadRequestException("Filter is too short. Must be at least " + PKIServlet.MIN_FILTER_LENGTH + " characters."); + } + return findAllCerts(authorizedProfiles, filter, start, size); + } + + Map attributes = new HashMap<>(); + if (tokenID != null) { + attributes.put("tokenID", tokenID); + } + + try { + if (authorizedProfiles == null) { + msg = "authorizedProfiles null"; + logger.debug("{}{}", method, msg); + throw new PKIException(method + msg); + } + + TokenDatabase tokDatabase = subsystem.getTokenDatabase(); + TokenRecord tRecord = tokDatabase.getRecord(tokenID); + if (tRecord == null) { + msg = "Token record not found"; + logger.debug("{}{}", method, msg); + throw new PKIException(method + msg); + } + String type = tRecord.getType(); + if ((type != null) && !type.isEmpty() && !authorizedProfiles.contains(UserResource.ALL_PROFILES) && !authorizedProfiles.contains(type)) + throw new PKIException(method + "Token record restricted"); + + // token was from an authorized profile + TPSCertDatabase database = subsystem.getCertDatabase(); + + Iterator certRecs = database.findRecords(filter, attributes).iterator(); + TPSCertCollection response = new TPSCertCollection(); + int i = 0; + + // skip to the start of the page + for ( ; i authorizedProfiles) { + String method = "TPSCertProcessor:getCert: "; + String msg = ""; + + if (certID == null) throw new BadRequestException("Certificate ID is null."); + + logger.debug("TPSCertProcessor.getCert(\"{}\")", certID); + + try { + if (authorizedProfiles == null) { + msg = "authorizedProfiles null"; + logger.debug("{}{}", method, msg); + throw new PKIException(method + msg); + } + + TPSCertDatabase database = subsystem.getCertDatabase(); + TPSCertRecord certRec = database.getRecord(certID); + String type = certRec.getKeyType(); + if ((type != null) && !type.isEmpty() && !authorizedProfiles.contains(UserResource.ALL_PROFILES) && !authorizedProfiles.contains(type)) + throw new PKIException(method + "Cert record restricted"); + + return createCertData(database.getRecord(certID)); + + } catch (Exception e) { + throw new PKIException(e.getMessage()); + } + } + + private TPSCertData createCertData(TPSCertRecord certRecord) { + TPSCertData certData = new TPSCertData(); + certData.setID(certRecord.getId()); + certData.setSerialNumber(certRecord.getSerialNumber()); + certData.setSubject(certRecord.getSubject()); + certData.setUserID(certRecord.getUserID()); + certData.setTokenID(certRecord.getTokenID()); + certData.setOrigin(certRecord.getOrigin()); + certData.setType(certRecord.getType()); + certData.setKeyType(certRecord.getKeyType()); + certData.setStatus(certRecord.getStatus()); + certData.setCreateTime(certRecord.getCreateTime()); + certData.setModifyTime(certRecord.getModifyTime()); + return certData; + } + + private TPSCertCollection findAllCerts(List authorizedProfiles, String filter, Integer start, Integer size) { + String method = "TPSCertProcessor:findAllCerts: "; + String msg = ""; + TPSCertCollection response = new TPSCertCollection(); + + logger.debug("TPSCertProcessor.findAllCerts({}, {}, {})", filter, start, size); + + try { + TPSCertDatabase certDatabase = subsystem.getCertDatabase(); + Iterator certRecs = certDatabase.findRecords(filter).iterator(); + TokenDatabase tokenDatabase = subsystem.getTokenDatabase(); + if (authorizedProfiles == null) { + msg = "authorizedProfiles null"; + logger.debug("{}{}", method, msg); + throw new PKIException(method + msg); + } + int total = 0; + while (certRecs.hasNext()) { + TPSCertRecord certRecord = certRecs.next(); + String tokenID = certRecord.getTokenID(); + TokenRecord tokenRecord = null; + try { + tokenRecord = tokenDatabase.getRecord(tokenID); + } catch (Exception e) { + // Proceed to next token if this one doesn't exist. + } + if (tokenRecord != null) { + String type = tokenRecord.getType(); + if (type == null || type.isEmpty() || authorizedProfiles.contains(type) || authorizedProfiles.contains(UserResource.ALL_PROFILES)) { + // Return entries from the start of the page up to the page size + if (total >= start && total < start + size) { + response.addEntry(createCertData(certRecord)); + } + // Count all accessible records, on this page or otherwise. + total++; + } + } + } + response.setTotal(total); + return response; + } catch (Exception e) { + throw new PKIException(e.getMessage()); + } + } +} diff --git a/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/TPSCertServlet.java b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/TPSCertServlet.java new file mode 100644 index 00000000000..70589d97716 --- /dev/null +++ b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/TPSCertServlet.java @@ -0,0 +1,66 @@ +// +// Copyright Red Hat, Inc. +// +// SPDX-License-Identifier: GPL-2.0-or-later +// +package org.dogtagpki.server.tps.rest.v2; + +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.dogtagpki.server.tps.rest.base.TPSCertProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.netscape.certsrv.base.WebAction; +import com.netscape.certsrv.tps.cert.TPSCertCollection; +import com.netscape.certsrv.tps.cert.TPSCertData; + +/** + * @author Marco Fargetta {@literal } + */ +@WebServlet( + name = "tpsCert", + urlPatterns = "/v2/certs/*") +public class TPSCertServlet extends TPSServlet { + private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory.getLogger(TPSCertServlet.class); + + private TPSCertProcessor certProcessor; + + @Override + public void init() throws ServletException { + super.init(); + certProcessor = new TPSCertProcessor(getTPSEngine()); + } + + @WebAction(method = HttpMethod.GET, paths = {""}) + public void findCerts(HttpServletRequest request, HttpServletResponse response) throws Exception { + HttpSession session = request.getSession(); + logger.debug("TPSCertServlet.findCerts(): session: {}", session.getId()); + int size = request.getParameter("pageSize") == null ? + DEFAULT_SIZE : Integer.parseInt(request.getParameter("pageSize")); + int start = request.getParameter("start") == null ? 0 : Integer.parseInt(request.getParameter("start")); + String filter = request.getParameter("filter"); + String tokenID = request.getParameter("tokenID"); + TPSCertCollection certs = certProcessor.findCerts(getAuthorizedProfiles(request), tokenID, filter, start, size); + PrintWriter out = response.getWriter(); + out.println(certs.toJSON()); + } + + @WebAction(method = HttpMethod.GET, paths = {"{}"}) + public void getCert(HttpServletRequest request, HttpServletResponse response) throws Exception { + HttpSession session = request.getSession(); + logger.debug("TPSCertServlet.getCert(): session: {}", session.getId()); + String[] pathElement = request.getPathInfo().substring(1).split("/"); + String certID = pathElement[0]; + TPSCertData cert = certProcessor.getCert(certID, getAuthorizedProfiles(request)); + PrintWriter out = response.getWriter(); + out.println(cert.toJSON()); + } +} diff --git a/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyACL.java b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyACL.java index 557cc086b79..877eced3e8f 100644 --- a/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyACL.java +++ b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyACL.java @@ -9,7 +9,7 @@ import org.dogtagpki.server.rest.v2.filters.ACLFilter; -@WebFilter(servletNames = {"activity", "tpsJobs"}) +@WebFilter(servletNames = {"activity", "tpsJobs", "tpsCert"}) public class EmptyACL extends ACLFilter { private static final long serialVersionUID = 1L; diff --git a/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyAuthMethod.java b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyAuthMethod.java index 9416586a821..04b8230994e 100644 --- a/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyAuthMethod.java +++ b/base/tps/src/main/java/org/dogtagpki/server/tps/rest/v2/filters/EmptyAuthMethod.java @@ -9,7 +9,7 @@ import org.dogtagpki.server.rest.v2.filters.AuthMethodFilter; -@WebFilter(servletNames = {"activity", "tpsJobs"}) +@WebFilter(servletNames = {"activity", "tpsJobs", "tpsCert"}) public class EmptyAuthMethod extends AuthMethodFilter { private static final long serialVersionUID = 1L;