diff --git a/HIRS_AttestationCA/build.gradle b/HIRS_AttestationCA/build.gradle index 88f24280..f07a8941 100644 --- a/HIRS_AttestationCA/build.gradle +++ b/HIRS_AttestationCA/build.gradle @@ -20,6 +20,7 @@ dependencies { implementation libs.commons.codec implementation libs.commons.io implementation libs.commons.lang3 + implementation libs.gson implementation libs.guava implementation libs.jackson.core implementation libs.jackson.databind diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/CertificateService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/CertificateService.java index f2897d30..91d20722 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/CertificateService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/CertificateService.java @@ -93,7 +93,10 @@ public class CertificateService { // Dynamically loop through columns and create LIKE conditions for each searchable column for (String columnName : searchableColumns) { - // todo + // there is a possibility that one of the column names + // that matches one of the class fields is nested (e.g. device.name) , + // and we will need to do further work to extract the + // field name if (columnName.contains(".")) { } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/DeviceService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/DeviceService.java new file mode 100644 index 00000000..ec2f0d09 --- /dev/null +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/DeviceService.java @@ -0,0 +1,256 @@ +package hirs.attestationca.persist.service; + +import hirs.attestationca.persist.FilteredRecordsList; +import hirs.attestationca.persist.entity.manager.DeviceRepository; +import hirs.attestationca.persist.entity.manager.EndorsementCredentialRepository; +import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository; +import hirs.attestationca.persist.entity.manager.PlatformCertificateRepository; +import hirs.attestationca.persist.entity.userdefined.Device; +import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential; +import hirs.attestationca.persist.entity.userdefined.certificate.IssuedAttestationCertificate; +import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential; +import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +/** + * Service layer class that handles the storage and retrieval of devices. + */ +@Service +@Log4j2 +public class DeviceService { + + private final DeviceRepository deviceRepository; + private final PlatformCertificateRepository platformCertificateRepository; + private final EndorsementCredentialRepository endorsementCredentialRepository; + private final IssuedCertificateRepository issuedCertificateRepository; + private final EntityManager entityManager; + + /** + * Constructor for Device Service. + * + * @param deviceRepository device repository + * @param platformCertificateRepository platform certificate repository + * @param endorsementCredentialRepository endorsement credential repository + * @param issuedCertificateRepository issued certificate repository + * @param entityManager entity manager + */ + @Autowired + public DeviceService(final DeviceRepository deviceRepository, + final PlatformCertificateRepository platformCertificateRepository, + final EndorsementCredentialRepository endorsementCredentialRepository, + final IssuedCertificateRepository issuedCertificateRepository, + final EntityManager entityManager) { + this.deviceRepository = deviceRepository; + this.platformCertificateRepository = platformCertificateRepository; + this.endorsementCredentialRepository = endorsementCredentialRepository; + this.issuedCertificateRepository = issuedCertificateRepository; + this.entityManager = entityManager; + } + + /** + * Takes the provided column names, the search term that the user entered and attempts to find + * devices whose field values matches the provided search term. + * + * @param searchableColumns list of the searchable column name + * @param searchText text that was input in the search textbox + * @param pageable pageable + * @return page full of devices + */ + public Page findAllDevicesBySearchableColumns( + final List searchableColumns, + final String searchText, + final Pageable pageable) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = + criteriaBuilder.createQuery(Device.class); + Root deviceRoot = + query.from(Device.class); + + List predicates = new ArrayList<>(); + + // Dynamically add search conditions for each field that should be searchable + if (!StringUtils.isBlank(searchText)) { + // Dynamically loop through columns and create LIKE conditions for each searchable column + for (String columnName : searchableColumns) { + + // there is a possibility that one of the column names + // that matches one of the class fields is nested (e.g. device.name) , + // and we will need to do further work to extract the + // field name + // todo + if (columnName.contains(".")) { + + } + + Predicate predicate = + criteriaBuilder.like( + criteriaBuilder.lower(deviceRoot.get(columnName)), + "%" + searchText.toLowerCase() + "%"); + predicates.add(predicate); + } + } + + query.where(criteriaBuilder.or(predicates.toArray(new Predicate[0]))); + + // Apply pagination + TypedQuery typedQuery = entityManager.createQuery(query); + int totalRows = typedQuery.getResultList().size(); // Get the total count for pagination + typedQuery.setFirstResult((int) pageable.getOffset()); + typedQuery.setMaxResults(pageable.getPageSize()); + + // Wrap the result in a Page object to return pagination info + List resultList = typedQuery.getResultList(); + return new PageImpl<>(resultList, pageable, totalRows); + } + + /** + * Retrieves all devices from the database. + * + * @param pageable pageable + * @return page of devices + */ + public Page findAllDevices(final Pageable pageable) { + return deviceRepository.findAll(pageable); + } + + /** + * Retrieves the total number of records in the device repository. + * + * @return total number of records in the device repository. + */ + public long findDeviceRepositoryCount() { + return this.deviceRepository.count(); + } + + /** + * Returns the list of devices combined with the certificates. + * + * @param deviceList list containing the devices + * @return a record list after the device and certificate was mapped together. + */ + public FilteredRecordsList> retrieveDevicesAndAssociatedCertificates( + final FilteredRecordsList deviceList) { + FilteredRecordsList> records = new FilteredRecordsList<>(); + // hashmap containing the device-certificate relationship + HashMap deviceCertMap = new HashMap<>(); + List deviceIdList = getDevicesId(deviceList); + List platformCredentialList = new ArrayList<>(); + List endorsementCredentialList = new ArrayList<>(); + List issuedCertificateList = new ArrayList<>(); + List certificateListFromMap = new LinkedList<>(); + + // parse if there is a Device + if (!deviceList.isEmpty()) { + // get a list of Certificates that contains the device IDs from the list + for (UUID id : deviceIdList) { + platformCredentialList.addAll(platformCertificateRepository.findByDeviceId(id)); + endorsementCredentialList.addAll(endorsementCredentialRepository.findByDeviceId(id)); + issuedCertificateList.addAll(issuedCertificateRepository.findByDeviceId(id)); + } + + HashMap> certificatePropertyMap; + // loop all the devices + for (Device device : deviceList) { + // hashmap containing the list of certificates based on the certificate type + certificatePropertyMap = new HashMap<>(); + + deviceCertMap.put("device", device); + String deviceName; + + // loop all the certificates and combined the ones that match the ID + for (PlatformCredential pc : platformCredentialList) { + deviceName = deviceRepository.findById(pc.getDeviceId()).get().getName(); + + // set the certificate if it's the same ID + if (device.getName().equals(deviceName)) { + String certificateId = PlatformCredential.class.getSimpleName(); + // create a new list for the certificate type if does not exist + // else add it to the current certificate type list + certificateListFromMap + = certificatePropertyMap.get(certificateId); + if (certificateListFromMap != null) { + certificateListFromMap.add(pc); + } else { + certificatePropertyMap.put(certificateId, + new ArrayList<>(Collections.singletonList(pc))); + } + } + } + + for (EndorsementCredential ec : endorsementCredentialList) { + deviceName = deviceRepository.findById(ec.getDeviceId()).get().getName(); + + // set the certificate if it's the same ID + if (device.getName().equals(deviceName)) { + String certificateId = EndorsementCredential.class.getSimpleName(); + // create a new list for the certificate type if does not exist + // else add it to the current certificate type list + certificateListFromMap + = certificatePropertyMap.get(certificateId); + if (certificateListFromMap != null) { + certificateListFromMap.add(ec); + } else { + certificatePropertyMap.put(certificateId, + new ArrayList<>(Collections.singletonList(ec))); + } + } + } + + for (IssuedAttestationCertificate ic : issuedCertificateList) { + deviceName = ic.getDeviceName(); + // set the certificate if it's the same ID + if (device.getName().equals(deviceName)) { + String certificateId = IssuedAttestationCertificate.class.getSimpleName(); + // create a new list for the certificate type if does not exist + // else add it to the current certificate type list + certificateListFromMap + = certificatePropertyMap.get(certificateId); + if (certificateListFromMap != null) { + certificateListFromMap.add(ic); + } else { + certificatePropertyMap.put(certificateId, + new ArrayList<>(Collections.singletonList(ic))); + } + } + } + + // add the device-certificate map to the record + deviceCertMap.putAll(certificatePropertyMap); + records.add(new HashMap<>(deviceCertMap)); + deviceCertMap.clear(); + } + } + // set pagination values + records.setRecordsTotal(deviceList.getRecordsTotal()); + records.setRecordsFiltered(deviceList.getRecordsFiltered()); + return records; + } + + /** + * Returns the list of devices IDs. + * + * @param deviceList list containing the devices + * @return a list of the devices IDs + */ + private List getDevicesId(final FilteredRecordsList deviceList) { + return deviceList.stream().map(Device::getId).toList(); + } +} diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ReferenceManifestService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ReferenceManifestService.java new file mode 100644 index 00000000..6915fb3f --- /dev/null +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ReferenceManifestService.java @@ -0,0 +1,77 @@ +package hirs.attestationca.persist.service; + +import hirs.attestationca.persist.entity.userdefined.ReferenceManifest; +import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.StringUtils; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * + */ +@Service +@Log4j2 +public class ReferenceManifestService { + + private final EntityManager entityManager; + + + public ReferenceManifestService(EntityManager entityManager) { + this.entityManager = entityManager; + } + + public Page findRIMBySearchableColumns(final List searchableColumns, + final String searchText, + final Pageable pageable) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery query = criteriaBuilder.createQuery(ReferenceManifest.class); + Root rimRoot = query.from(ReferenceManifest.class); + + List predicates = new ArrayList<>(); + + // Dynamically add search conditions for each field that should be searchable + if (!StringUtils.isBlank(searchText)) { + // Dynamically loop through columns and create LIKE conditions for each searchable column + for (String columnName : searchableColumns) { + + // there is a possibility that one of the column names + // that matches one of the class fields is nested (e.g. device.name) , + // and we will need to do further work to extract the + // field name + // todo + if (columnName.contains(".")) { + + } + + Predicate predicate = + criteriaBuilder.like( + criteriaBuilder.lower(rimRoot.get(columnName)), + "%" + searchText.toLowerCase() + "%"); + predicates.add(predicate); + } + } + + query.where(criteriaBuilder.or(predicates.toArray(new Predicate[0]))); + + // Apply pagination + TypedQuery typedQuery = entityManager.createQuery(query); + int totalRows = typedQuery.getResultList().size(); // Get the total count for pagination + typedQuery.setFirstResult((int) pageable.getOffset()); + typedQuery.setMaxResults(pageable.getPageSize()); + + // Wrap the result in a Page object to return pagination info + List resultList = typedQuery.getResultList(); + return new PageImpl<>(resultList, pageable, totalRows); + } +} diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationSummaryReportsService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationSummaryReportsService.java index 29c2280a..33988a27 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationSummaryReportsService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationSummaryReportsService.java @@ -1,13 +1,24 @@ package hirs.attestationca.persist.service; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import hirs.attestationca.persist.entity.manager.CertificateRepository; +import hirs.attestationca.persist.entity.manager.DeviceRepository; +import hirs.attestationca.persist.entity.manager.PlatformCertificateRepository; +import hirs.attestationca.persist.entity.userdefined.Device; import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary; +import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential; +import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier; +import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2; import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -16,8 +27,19 @@ import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; +import java.util.Enumeration; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Service layer class that handles the storage and retrieval of validation reports. @@ -26,19 +48,29 @@ import java.util.List; @Log4j2 public class ValidationSummaryReportsService { + private static final String DEFAULT_COMPANY = "AllDevices"; + private static final String UNDEFINED = "undefined"; + private static final String TRUE = "true"; + private static final String SYSTEM_COLUMN_HEADERS = "Verified Manufacturer," + + "Model,SN,Verification Date,Device Status"; + private static final String COMPONENT_COLUMN_HEADERS = "Component name,Component manufacturer," + + "Component model,Component SN,Issuer,Component status"; + + private final PlatformCertificateRepository platformCertificateRepository; private final EntityManager entityManager; + private final CertificateRepository certificateRepository; + private final DeviceRepository deviceRepository; @Autowired - public ValidationSummaryReportsService(EntityManager entityManager) { + public ValidationSummaryReportsService(final PlatformCertificateRepository platformCertificateRepository, + final CertificateRepository certificateRepository, + final DeviceRepository deviceRepository, + final EntityManager entityManager) { + this.platformCertificateRepository = platformCertificateRepository; + this.certificateRepository = certificateRepository; + this.deviceRepository = deviceRepository; this.entityManager = entityManager; - } - public static Path getNestedPath(Root root, CriteriaBuilder cb, String... fieldNames) { - Path path = root; - for (String fieldName : fieldNames) { - path = path.get(fieldName); - } - return path; } /** @@ -69,6 +101,10 @@ public class ValidationSummaryReportsService { // Dynamically loop through columns and create LIKE conditions for each searchable column for (String columnName : searchableColumns) { + // there is a possibility that one of the column names + // that matches one of the class fields is nested (e.g. device.name) , + // and we will need to do further work to extract the + // field name // todo if (columnName.contains(".")) { @@ -98,4 +134,326 @@ public class ValidationSummaryReportsService { List resultList = typedQuery.getResultList(); return new PageImpl<>(resultList, pageable, totalRows); } + + /** + * Downloads the validation summary reports based on the provided request parameters. + * + * @param request http request + * @param response http response + * @throws IOException if there are any issues while trying to download the summary reports + */ + public void downloadValidationReports(final HttpServletRequest request, + final HttpServletResponse response) throws IOException { + String company = ""; + String contractNumber = ""; + Pattern pattern = Pattern.compile("^\\w*$"); + DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd"); + DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss"); + LocalDate startDate = null; + LocalDate endDate = null; + ArrayList createTimes = new ArrayList<>(); + String[] deviceNames = new String[] {}; + StringBuilder columnHeaders = new StringBuilder(); + boolean systemOnly = false; + boolean componentOnly = false; + String filterManufacturer = ""; + String filterSerial = ""; + boolean jsonVersion = false; + + final Enumeration parameters = request.getParameterNames(); + + while (parameters.hasMoreElements()) { + String parameter = parameters.nextElement(); + String parameterValue = request.getParameter(parameter); + log.info("{}: {}", parameter, parameterValue); + switch (parameter) { + case "company": + Matcher companyMatcher = pattern.matcher(parameterValue); + if (companyMatcher.matches()) { + company = parameterValue; + } else { + company = DEFAULT_COMPANY; + } + break; + case "contract": + Matcher contractMatcher = pattern.matcher(parameterValue); + if (contractMatcher.matches()) { + contractNumber = parameterValue; + } else { + contractNumber = "none"; + } + break; + case "dateStart": + if (parameterValue != null && !parameterValue.isEmpty()) { + startDate = LocalDate.parse(parameterValue, dateFormat); + } else { + startDate = LocalDate.ofEpochDay(0); + } + break; + case "dateEnd": + if (parameterValue != null && !parameterValue.isEmpty()) { + endDate = LocalDate.parse(parameterValue, dateFormat); + } else { + endDate = LocalDate.now(ZoneId.of("America/New_York")); + } + break; + case "createTimes": + //todo issue #922 + if (!parameterValue.equals(UNDEFINED) + && !parameterValue.isEmpty()) { + String[] timestamps = parameterValue.split(","); + for (String timestamp : timestamps) { + createTimes.add(LocalDateTime.parse(timestamp, + dateTimeFormat).toLocalDate()); + } + } + break; + case "deviceNames": + if (!parameterValue.equals(UNDEFINED) + && !parameterValue.isEmpty()) { + deviceNames = parameterValue.split(","); + } + break; + case "system": + if (parameterValue.equals(TRUE)) { + systemOnly = true; + if (!columnHeaders.isEmpty()) { + columnHeaders.insert(0, ","); + } + columnHeaders.insert(0, SYSTEM_COLUMN_HEADERS); + } + break; + case "component": + if (parameterValue.equals(TRUE)) { + componentOnly = true; + if (!columnHeaders.isEmpty()) { + columnHeaders.append(","); + } + columnHeaders.append(COMPONENT_COLUMN_HEADERS); + } + break; + case "manufacturer": + if (parameterValue != null && !parameterValue.isEmpty()) { + filterManufacturer = parameterValue; + } + break; + case "serial": + if (parameterValue != null && !parameterValue.isEmpty()) { + filterSerial = parameterValue; + } + break; + case "json": + response.setHeader("Content-Type", "application/json"); + jsonVersion = true; + break; + default: + } + } + + if (!jsonVersion) { + response.setHeader("Content-Type", "text/csv"); + response.setHeader("Content-Disposition", + "attachment;filename=validation_report.csv"); + } + + BufferedWriter bufferedWriter = new BufferedWriter( + new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8)); + + StringBuilder reportData = new StringBuilder(); + JsonArray jsonReportData = new JsonArray(); + for (int i = 0; i < deviceNames.length; i++) { + if ((createTimes.get(i).isAfter(startDate) || createTimes.get(i).isEqual(startDate)) + && (createTimes.get(i).isBefore(endDate) + || createTimes.get(i).isEqual(endDate))) { + Device device = deviceRepository.findByName(deviceNames[i]); + PlatformCredential pc = platformCertificateRepository.findByDeviceId(device.getId()).get(0); + if (jsonVersion) { + jsonReportData.add(assembleJsonContent(pc, parseComponents(pc), + company, contractNumber)); + } else { + if (i == 0) { + bufferedWriter.append("Company: ").append(company).append("\n"); + bufferedWriter.append("Contract number: ").append(contractNumber).append("\n"); + } + + if (systemOnly && componentOnly) { + systemOnly = false; + componentOnly = false; + } + + if ((filterManufacturer.isEmpty() || filterManufacturer.equals( + pc.getManufacturer())) + && (filterSerial.isEmpty() || filterSerial.equals( + pc.getPlatformSerial()))) { + if (!componentOnly) { + reportData.append(pc.getManufacturer()) + .append(",") + .append(pc.getModel()) + .append(",") + .append(pc.getPlatformSerial()) + .append(",") + .append(LocalDateTime.now()) + .append(",") + .append(device.getSupplyChainValidationStatus()) + .append(","); + } + + if (!systemOnly) { + ArrayList> parsedComponents = parseComponents(pc); + for (ArrayList component : parsedComponents) { + for (String data : component) { + reportData.append(data).append(","); + } + reportData.deleteCharAt(reportData.length() - 1); + reportData.append(System.lineSeparator()); + if (!componentOnly) { + reportData.append(",,,,,"); + } + } + reportData = reportData.delete( + reportData.lastIndexOf(System.lineSeparator()) + 1, + reportData.length()); + } + } + } + } + } + + if (!jsonVersion) { + if (columnHeaders.isEmpty()) { + columnHeaders = new StringBuilder(SYSTEM_COLUMN_HEADERS + "," + COMPONENT_COLUMN_HEADERS); + } + bufferedWriter.append(columnHeaders.toString()).append(System.lineSeparator()); + bufferedWriter.append(reportData.toString()); + } else { + bufferedWriter.append(jsonReportData.toString()); + } + bufferedWriter.flush(); + } + + + /** + * This method builds a JSON object from the system and component data in a + * validation report. + * + * @param pc the platform credential used to validate. + * @param parsedComponents component data parsed from the platform credential. + * @param company company name. + * @param contractNumber contract number. + * @return the JSON object in String format. + */ + private JsonObject assembleJsonContent(final PlatformCredential pc, + final ArrayList> parsedComponents, + final String company, + final String contractNumber) { + JsonObject systemData = new JsonObject(); + String deviceName = deviceRepository.findById((pc) + .getDeviceId()).get().getName(); + + systemData.addProperty("Company", company); + systemData.addProperty("Contract number", contractNumber); + systemData.addProperty("Verified Manufacturer", pc.getManufacturer()); + systemData.addProperty("Model", pc.getModel()); + systemData.addProperty("SN", pc.getPlatformSerial()); + systemData.addProperty("Verification Date", LocalDateTime.now().toString()); + systemData.addProperty("Device Status", deviceRepository.findByName(deviceName) + .getSupplyChainValidationStatus().toString()); + + JsonArray components = new JsonArray(); + final int componentDataPosition4 = 3; + final int componentDataPosition5 = 4; + final int componentDataPosition6 = 5; + for (ArrayList componentData : parsedComponents) { + JsonObject component = new JsonObject(); + component.addProperty("Component name", componentData.get(0)); + component.addProperty("Component manufacturer", componentData.get(1)); + component.addProperty("Component model", componentData.get(2)); + component.addProperty("Component SN", componentData.get(componentDataPosition4)); + component.addProperty("Issuer", componentData.get(componentDataPosition5)); + component.addProperty("Component status", componentData.get(componentDataPosition6)); + components.add(component); + } + systemData.add("Components", components); + + return systemData; + } + + /** + * This method parses the following ComponentIdentifier fields into an ArrayList of ArrayLists. + * - ComponentClass + * - Manufacturer + * - Model + * - Serial number + * - Pass/fail status (based on componentFailures string) + * + * @param pc the platform credential. + * @return the ArrayList of ArrayLists containing the parsed component data. + */ + private ArrayList> parseComponents(final PlatformCredential pc) { + ArrayList> parsedComponents = new ArrayList<>(); + ArrayList> chainComponents = new ArrayList<>(); + + StringBuilder componentFailureString = new StringBuilder(); + if (pc.getComponentIdentifiers() != null + && !pc.getComponentIdentifiers().isEmpty()) { + componentFailureString.append(pc.getComponentFailures()); + // get all the certificates associated with the platform serial + List chainCertificates = + certificateRepository.byBoardSerialNumber(pc.getPlatformSerial()); + // combine all components in each certificate + for (ComponentIdentifier ci : pc.getComponentIdentifiers()) { + ArrayList issuerAndComponent = new ArrayList<>(); + issuerAndComponent.add(pc.getHolderIssuer()); + issuerAndComponent.add(ci); + chainComponents.add(issuerAndComponent); + } + + for (PlatformCredential cert : chainCertificates) { + componentFailureString.append(cert.getComponentFailures()); + if (!cert.isPlatformBase()) { + for (ComponentIdentifier ci : cert.getComponentIdentifiers()) { + ArrayList issuerAndComponent = new ArrayList<>(); + issuerAndComponent.add(cert.getHolderIssuer()); + issuerAndComponent.add(ci); + chainComponents.add(issuerAndComponent); + } + } + } + log.info("Component failures: {}", componentFailureString); + for (ArrayList issuerAndComponent : chainComponents) { + ArrayList componentData = new ArrayList<>(); + String issuer = (String) issuerAndComponent.get(0); + issuer = issuer.replaceAll(",", " "); + ComponentIdentifier ci = (ComponentIdentifier) issuerAndComponent.get(1); + if (ci instanceof ComponentIdentifierV2) { + String componentClass = + ((ComponentIdentifierV2) ci).getComponentClass().toString(); + String[] splitStrings = componentClass.split("\r\n|\n|\r"); + StringBuilder sb = new StringBuilder(); + for (String s : splitStrings) { + sb.append(s); + sb.append(" "); + } + sb = sb.deleteCharAt(sb.length() - 1); + componentData.add(sb.toString()); + } else { + componentData.add("Platform Component"); + } + componentData.add(ci.getComponentManufacturer().getString()); + componentData.add(ci.getComponentModel().getString()); + componentData.add(ci.getComponentSerial().getString()); + componentData.add(issuer); + //Failing components are identified by hashcode + if (componentFailureString.toString().contains(String.valueOf(ci.hashCode()))) { + componentData.add("Fail"); + } else { + componentData.add("Pass"); + } + parsedComponents.add(componentData); + log.info(String.join(",", componentData)); + } + } + + return parsedComponents; + } } diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/CertificateDetailsPageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/CertificateDetailsPageController.java index 7e29388d..4cbe6952 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/CertificateDetailsPageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/CertificateDetailsPageController.java @@ -3,7 +3,6 @@ package hirs.attestationca.portal.page.controllers; import hirs.attestationca.persist.entity.manager.CACredentialRepository; import hirs.attestationca.persist.entity.manager.CertificateRepository; import hirs.attestationca.persist.entity.manager.ComponentResultRepository; -import hirs.attestationca.persist.entity.manager.IDevIDCertificateRepository; import hirs.attestationca.portal.page.Page; import hirs.attestationca.portal.page.PageController; import hirs.attestationca.portal.page.PageMessages; @@ -35,26 +34,22 @@ public class CertificateDetailsPageController extends PageController { - private final DeviceRepository deviceRepository; - private final CertificateRepository certificateRepository; - private final PlatformCertificateRepository platformCertificateRepository; - private final EndorsementCredentialRepository endorsementCredentialRepository; - private final IssuedCertificateRepository issuedCertificateRepository; + private final DeviceService deviceService; /** * Device Page Controller constructor. - * - * @param deviceRepository device repository. - * @param certificateRepository certificate repository. - * @param platformCertificateRepository platform certificate repository. - * @param endorsementCredentialRepository endorsement credential repository. - * @param issuedCertificateRepository issued certificate repository. */ @Autowired - public DevicePageController(final DeviceRepository deviceRepository, - final CertificateRepository certificateRepository, - final PlatformCertificateRepository platformCertificateRepository, - final EndorsementCredentialRepository endorsementCredentialRepository, - final IssuedCertificateRepository issuedCertificateRepository) { + public DevicePageController( + DeviceService deviceService) { super(Page.DEVICES); - this.deviceRepository = deviceRepository; - this.certificateRepository = certificateRepository; - this.platformCertificateRepository = platformCertificateRepository; - this.endorsementCredentialRepository = endorsementCredentialRepository; - this.issuedCertificateRepository = issuedCertificateRepository; + this.deviceService = deviceService; } /** @@ -87,7 +62,8 @@ public class DevicePageController extends PageController { } /** - * GET request that retrieves table data using the provided data table input. + * Processes request to retrieve the collection of devices and device related + * information that will be displayed on the devices page. * * @param input data table input. * @return a data table response @@ -95,18 +71,31 @@ public class DevicePageController extends PageController { @ResponseBody @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) - public DataTableResponse> getTableData( + public DataTableResponse> getDevicesTableData( final DataTableInput input) { - log.debug("Received request to for device list"); + log.info("Received request to display list of devices"); + log.debug("Request received a datatable input object for the device page: {}", + input); + String orderColumnName = input.getOrderColumnName(); log.debug("Ordering on column: {}", orderColumnName); + final String searchText = input.getSearch().getValue(); + final List searchableColumns = findSearchableColumnsNames(input.getColumns()); + // get all the devices FilteredRecordsList deviceList = new FilteredRecordsList<>(); int currentPage = input.getStart() / input.getLength(); - Pageable paging = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName)); - org.springframework.data.domain.Page pagedResult = deviceRepository.findAll(paging); + Pageable pageable = PageRequest.of(currentPage, input.getLength(), Sort.by(orderColumnName)); + org.springframework.data.domain.Page pagedResult; + + if (StringUtils.isBlank(searchText)) { + pagedResult = this.deviceService.findAllDevices(pageable); + } else { + pagedResult = this.deviceService.findAllDevicesBySearchableColumns(searchableColumns, searchText, + pageable); + } if (pagedResult.hasContent()) { deviceList.addAll(pagedResult.getContent()); @@ -114,134 +103,24 @@ public class DevicePageController extends PageController { } else { deviceList.setRecordsTotal(input.getLength()); } - deviceList.setRecordsFiltered(deviceRepository.count()); + + deviceList.setRecordsFiltered(this.deviceService.findDeviceRepositoryCount()); FilteredRecordsList> records - = retrieveDevicesAndAssociatedCertificates(deviceList); + = this.deviceService.retrieveDevicesAndAssociatedCertificates(deviceList); return new DataTableResponse<>(records, input); } /** - * Returns the list of devices combined with the certificates. + * Helper method that returns a list of column names that are searchable. * - * @param deviceList list containing the devices - * @return a record list after the device and certificate was mapped together. + * @param columns columns + * @return searchable column names */ - private FilteredRecordsList> retrieveDevicesAndAssociatedCertificates( - final FilteredRecordsList deviceList) { - FilteredRecordsList> records = new FilteredRecordsList<>(); - // hashmap containing the device-certificate relationship - HashMap deviceCertMap = new HashMap<>(); - PlatformCredential certificate; - List deviceIdList = getDevicesId(deviceList); - List platformCredentialList = new ArrayList<>(); - List endorsementCredentialList = new ArrayList<>(); - List issuedCertificateList = new ArrayList<>(); - List certificateListFromMap = new LinkedList<>(); - - // parse if there is a Device - if (!deviceList.isEmpty()) { - // get a list of Certificates that contains the device IDs from the list - for (UUID id : deviceIdList) { - platformCredentialList.addAll(platformCertificateRepository.findByDeviceId(id)); - endorsementCredentialList.addAll(endorsementCredentialRepository.findByDeviceId(id)); - issuedCertificateList.addAll(issuedCertificateRepository.findByDeviceId(id)); - } - - HashMap> certificatePropertyMap; - // loop all the devices - for (Device device : deviceList) { - // hashmap containing the list of certificates based on the certificate type - certificatePropertyMap = new HashMap<>(); - - deviceCertMap.put("device", device); - String deviceName; - - // loop all the certificates and combined the ones that match the ID - for (PlatformCredential pc : platformCredentialList) { - deviceName = deviceRepository.findById(pc.getDeviceId()).get().getName(); - - // set the certificate if it's the same ID - if (device.getName().equals(deviceName)) { - String certificateId = PlatformCredential.class.getSimpleName(); - // create a new list for the certificate type if does not exist - // else add it to the current certificate type list - certificateListFromMap - = certificatePropertyMap.get(certificateId); - if (certificateListFromMap != null) { - certificateListFromMap.add(pc); - } else { - certificatePropertyMap.put(certificateId, - new ArrayList<>(Collections.singletonList(pc))); - } - } - } - - for (EndorsementCredential ec : endorsementCredentialList) { - deviceName = deviceRepository.findById(ec.getDeviceId()).get().getName(); - - // set the certificate if it's the same ID - if (device.getName().equals(deviceName)) { - String certificateId = EndorsementCredential.class.getSimpleName(); - // create a new list for the certificate type if does not exist - // else add it to the current certificate type list - certificateListFromMap - = certificatePropertyMap.get(certificateId); - if (certificateListFromMap != null) { - certificateListFromMap.add(ec); - } else { - certificatePropertyMap.put(certificateId, - new ArrayList<>(Collections.singletonList(ec))); - } - } - } - - for (IssuedAttestationCertificate ic : issuedCertificateList) { - deviceName = ic.getDeviceName(); - // set the certificate if it's the same ID - if (device.getName().equals(deviceName)) { - String certificateId = IssuedAttestationCertificate.class.getSimpleName(); - // create a new list for the certificate type if does not exist - // else add it to the current certificate type list - certificateListFromMap - = certificatePropertyMap.get(certificateId); - if (certificateListFromMap != null) { - certificateListFromMap.add(ic); - } else { - certificatePropertyMap.put(certificateId, - new ArrayList<>(Collections.singletonList(ic))); - } - } - } - - // add the device-certificate map to the record - deviceCertMap.putAll(certificatePropertyMap); - records.add(new HashMap<>(deviceCertMap)); - deviceCertMap.clear(); - } - } - // set pagination values - records.setRecordsTotal(deviceList.getRecordsTotal()); - records.setRecordsFiltered(deviceList.getRecordsFiltered()); - return records; + private List findSearchableColumnsNames(final List columns) { + // Retrieve all searchable columns and collect their names into a list of strings. + return columns.stream().filter(Column::isSearchable).map(Column::getName) + .collect(Collectors.toList()); } - - /** - * Returns the list of devices IDs. - * - * @param deviceList list containing the devices - * @return a list of the devices IDs - */ - private List getDevicesId(final FilteredRecordsList deviceList) { - List deviceIds = new ArrayList<>(); - - // loop all the devices - for (Device device : deviceList) { - deviceIds.add(device.getId()); - } - - return deviceIds; - } - } diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/EndorsementCredentialPageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/EndorsementCredentialPageController.java index ade27368..53d153d2 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/EndorsementCredentialPageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/EndorsementCredentialPageController.java @@ -67,7 +67,7 @@ public class EndorsementCredentialPageController extends PageController findSearchableColumnsNames(final List columns) { - // Retrieve all searchable columns and collect their names into a list of strings. return columns.stream().filter(Column::isSearchable).map(Column::getName) .collect(Collectors.toList()); } - /** * Attempts to parse the provided file in order to create an Endorsement Credential. * diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IDevIdCertificatePageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IDevIdCertificatePageController.java index 26a20a0b..ee8b2167 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IDevIdCertificatePageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/IDevIdCertificatePageController.java @@ -66,7 +66,7 @@ public class IDevIdCertificatePageController extends PageController getTableData( @Valid final DataTableInput input) { - log.debug("Handling request for summary list: {}", input); + log.info("Received request to display list of reference manifests"); + log.debug("Request received a datatable input object for the reference manifest page " + + " page: {}", input); String orderColumnName = input.getOrderColumnName(); - log.info("Ordering on column: {}", orderColumnName); - log.info("Querying with the following dataTableInput: {}", input); + log.debug("Ordering on column: {}", orderColumnName); + + final String searchText = input.getSearch().getValue(); + final List searchableColumns = findSearchableColumnsNames(input.getColumns()); FilteredRecordsList records = new FilteredRecordsList<>(); int currentPage = input.getStart() / input.getLength(); @@ -436,6 +443,19 @@ public class ReferenceManifestPageController extends PageController findSearchableColumnsNames(final List columns) { + // Retrieve all searchable columns and collect their names into a list of strings. + return columns.stream().filter(Column::isSearchable).map(Column::getName) + .collect(Collectors.toList()); + } + + private Map updateSupportRimInfo( final List dbSupportRims) { SupportReferenceManifest supportRim; diff --git a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java index 238e213c..2aa5cf3a 100644 --- a/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java +++ b/HIRS_AttestationCAPortal/src/main/java/hirs/attestationca/portal/page/controllers/ValidationReportsPageController.java @@ -1,17 +1,8 @@ package hirs.attestationca.portal.page.controllers; -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import hirs.attestationca.persist.FilteredRecordsList; -import hirs.attestationca.persist.entity.manager.CertificateRepository; -import hirs.attestationca.persist.entity.manager.DeviceRepository; -import hirs.attestationca.persist.entity.manager.PlatformCertificateRepository; import hirs.attestationca.persist.entity.manager.SupplyChainValidationSummaryRepository; -import hirs.attestationca.persist.entity.userdefined.Device; import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary; -import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential; -import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier; -import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2; import hirs.attestationca.persist.service.ValidationSummaryReportsService; import hirs.attestationca.portal.datatables.Column; import hirs.attestationca.portal.datatables.DataTableInput; @@ -36,19 +27,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; -import java.io.BufferedWriter; import java.io.IOException; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Enumeration; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; /** @@ -59,41 +39,21 @@ import java.util.stream.Collectors; @RequestMapping("/HIRS_AttestationCAPortal/portal/validation-reports") public class ValidationReportsPageController extends PageController { - private static final String DEFAULT_COMPANY = "AllDevices"; - private static final String UNDEFINED = "undefined"; - private static final String TRUE = "true"; - private static final String SYSTEM_COLUMN_HEADERS = "Verified Manufacturer," - + "Model,SN,Verification Date,Device Status"; - private static final String COMPONENT_COLUMN_HEADERS = "Component name,Component manufacturer," - + "Component model,Component SN,Issuer,Component status"; - private final SupplyChainValidationSummaryRepository supplyChainValidatorSummaryRepository; - private final CertificateRepository certificateRepository; - private final DeviceRepository deviceRepository; - private final PlatformCertificateRepository platformCertificateRepository; private final ValidationSummaryReportsService validationSummaryReportsService; /** * Constructor providing the Page's display and routing specification. * * @param supplyChainValidatorSummaryRepository the manager - * @param certificateRepository the certificate manager - * @param deviceRepository the device manager - * @param platformCertificateRepository the platform certificate manager * @param validationSummaryReportsService the validation summary reports service */ @Autowired public ValidationReportsPageController( final SupplyChainValidationSummaryRepository supplyChainValidatorSummaryRepository, - final CertificateRepository certificateRepository, - final DeviceRepository deviceRepository, - final PlatformCertificateRepository platformCertificateRepository, final ValidationSummaryReportsService validationSummaryReportsService) { super(Page.VALIDATION_REPORTS); this.supplyChainValidatorSummaryRepository = supplyChainValidatorSummaryRepository; - this.certificateRepository = certificateRepository; - this.deviceRepository = deviceRepository; - this.platformCertificateRepository = platformCertificateRepository; this.validationSummaryReportsService = validationSummaryReportsService; } @@ -166,189 +126,17 @@ public class ValidationReportsPageController extends PageController createTimes = new ArrayList<>(); - String[] deviceNames = new String[] {}; - String columnHeaders = ""; - boolean systemOnly = false; - boolean componentOnly = false; - String filterManufacturer = ""; - String filterSerial = ""; - boolean jsonVersion = false; - Enumeration parameters = request.getParameterNames(); - while (parameters.hasMoreElements()) { - String parameter = (String) parameters.nextElement(); - String parameterValue = request.getParameter(parameter); - log.info("{}: {}", parameter, parameterValue); - switch (parameter) { - case "company": - Matcher companyMatcher = pattern.matcher(parameterValue); - if (companyMatcher.matches()) { - company = parameterValue; - } else { - company = DEFAULT_COMPANY; - } - break; - case "contract": - Matcher contractMatcher = pattern.matcher(parameterValue); - if (contractMatcher.matches()) { - contractNumber = parameterValue; - } else { - contractNumber = "none"; - } - break; - case "dateStart": - if (parameterValue != null && !parameterValue.isEmpty()) { - startDate = LocalDate.parse(parameterValue, dateFormat); - } else { - startDate = LocalDate.ofEpochDay(0); - } - break; - case "dateEnd": - if (parameterValue != null && !parameterValue.isEmpty()) { - endDate = LocalDate.parse(parameterValue, dateFormat); - } else { - endDate = LocalDate.now(ZoneId.of("America/New_York")); - } - break; - case "createTimes": - if (!parameterValue.equals(UNDEFINED) - && !parameterValue.isEmpty()) { - String[] timestamps = parameterValue.split(","); - for (String timestamp : timestamps) { - createTimes.add(LocalDateTime.parse(timestamp, - dateTimeFormat).toLocalDate()); - } - } - break; - case "deviceNames": - if (!parameterValue.equals(UNDEFINED) - && !parameterValue.isEmpty()) { - deviceNames = parameterValue.split(","); - } - break; - case "system": - if (parameterValue.equals(TRUE)) { - systemOnly = true; - if (!columnHeaders.isEmpty()) { - columnHeaders = "," + columnHeaders; - } - columnHeaders = SYSTEM_COLUMN_HEADERS + columnHeaders; - } - break; - case "component": - if (parameterValue.equals(TRUE)) { - componentOnly = true; - if (!columnHeaders.isEmpty()) { - columnHeaders += ","; - } - columnHeaders += COMPONENT_COLUMN_HEADERS; - } - break; - case "manufacturer": - if (parameterValue != null && !parameterValue.isEmpty()) { - filterManufacturer = parameterValue; - } - break; - case "serial": - if (parameterValue != null && !parameterValue.isEmpty()) { - filterSerial = parameterValue; - } - break; - case "json": - response.setHeader("Content-Type", "application/json"); - jsonVersion = true; - break; - default: - } - } - - if (!jsonVersion) { - response.setHeader("Content-Type", "text/csv"); - response.setHeader("Content-Disposition", - "attachment;filename=validation_report.csv"); - } - BufferedWriter bufferedWriter = new BufferedWriter( - new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8)); - StringBuilder reportData = new StringBuilder(); - JsonArray jsonReportData = new JsonArray(); - for (int i = 0; i < deviceNames.length; i++) { - if ((createTimes.get(i).isAfter(startDate) || createTimes.get(i).isEqual(startDate)) - && (createTimes.get(i).isBefore(endDate) - || createTimes.get(i).isEqual(endDate))) { - Device device = deviceRepository.findByName(deviceNames[i]); - PlatformCredential pc = platformCertificateRepository.findByDeviceId(device.getId()).get(0); - if (jsonVersion) { - jsonReportData.add(assembleJsonContent(pc, parseComponents(pc), - company, contractNumber)); - } else { - if (i == 0) { - bufferedWriter.append("Company: " + company + "\n"); - bufferedWriter.append("Contract number: " + contractNumber + "\n"); - } - if (systemOnly && componentOnly) { - systemOnly = false; - componentOnly = false; - } - if ((filterManufacturer.isEmpty() || filterManufacturer.equals( - pc.getManufacturer())) - && (filterSerial.isEmpty() || filterSerial.equals( - pc.getPlatformSerial()))) { - if (!componentOnly) { - reportData.append(pc.getManufacturer() + "," - + pc.getModel() + "," - + pc.getPlatformSerial() + "," - + LocalDateTime.now() + "," - + device.getSupplyChainValidationStatus() + ","); - } - if (!systemOnly) { - ArrayList> parsedComponents = parseComponents(pc); - for (ArrayList component : parsedComponents) { - for (String data : component) { - reportData.append(data + ","); - } - reportData.deleteCharAt(reportData.length() - 1); - reportData.append(System.lineSeparator()); - if (!componentOnly) { - reportData.append(",,,,,"); - } - } - reportData = reportData.delete( - reportData.lastIndexOf(System.lineSeparator()) + 1, - reportData.length()); - } - } - } - } - } - if (!jsonVersion) { - if (columnHeaders.isEmpty()) { - columnHeaders = SYSTEM_COLUMN_HEADERS + "," + COMPONENT_COLUMN_HEADERS; - } - bufferedWriter.append(columnHeaders + System.lineSeparator()); - bufferedWriter.append(reportData.toString()); - } else { - bufferedWriter.append(jsonReportData.toString()); - } - bufferedWriter.flush(); + this.validationSummaryReportsService.downloadValidationReports(request, response); } /** @@ -362,129 +150,4 @@ public class ValidationReportsPageController extends PageController> parsedComponents, - final String company, - final String contractNumber) { - JsonObject systemData = new JsonObject(); - String deviceName = deviceRepository.findById((pc) - .getDeviceId()).get().getName(); - - systemData.addProperty("Company", company); - systemData.addProperty("Contract number", contractNumber); - systemData.addProperty("Verified Manufacturer", pc.getManufacturer()); - systemData.addProperty("Model", pc.getModel()); - systemData.addProperty("SN", pc.getPlatformSerial()); - systemData.addProperty("Verification Date", LocalDateTime.now().toString()); - systemData.addProperty("Device Status", deviceRepository.findByName(deviceName) - .getSupplyChainValidationStatus().toString()); - - JsonArray components = new JsonArray(); - final int componentDataPosition4 = 3; - final int componentDataPosition5 = 4; - final int componentDataPosition6 = 5; - for (ArrayList componentData : parsedComponents) { - JsonObject component = new JsonObject(); - component.addProperty("Component name", componentData.get(0)); - component.addProperty("Component manufacturer", componentData.get(1)); - component.addProperty("Component model", componentData.get(2)); - component.addProperty("Component SN", componentData.get(componentDataPosition4)); - component.addProperty("Issuer", componentData.get(componentDataPosition5)); - component.addProperty("Component status", componentData.get(componentDataPosition6)); - components.add(component); - } - systemData.add("Components", components); - - return systemData; - } - - /** - * This method parses the following ComponentIdentifier fields into an ArrayList of ArrayLists. - * - ComponentClass - * - Manufacturer - * - Model - * - Serial number - * - Pass/fail status (based on componentFailures string) - * - * @param pc the platform credential. - * @return the ArrayList of ArrayLists containing the parsed component data. - */ - private ArrayList> parseComponents(final PlatformCredential pc) { - ArrayList> parsedComponents = new ArrayList<>(); - ArrayList> chainComponents = new ArrayList<>(); - - StringBuilder componentFailureString = new StringBuilder(); - if (pc.getComponentIdentifiers() != null - && !pc.getComponentIdentifiers().isEmpty()) { - componentFailureString.append(pc.getComponentFailures()); - // get all the certificates associated with the platform serial - List chainCertificates = - certificateRepository.byBoardSerialNumber(pc.getPlatformSerial()); - // combine all components in each certificate - for (ComponentIdentifier ci : pc.getComponentIdentifiers()) { - ArrayList issuerAndComponent = new ArrayList<>(); - issuerAndComponent.add(pc.getHolderIssuer()); - issuerAndComponent.add(ci); - chainComponents.add(issuerAndComponent); - } - - for (PlatformCredential cert : chainCertificates) { - componentFailureString.append(cert.getComponentFailures()); - if (!cert.isPlatformBase()) { - for (ComponentIdentifier ci : cert.getComponentIdentifiers()) { - ArrayList issuerAndComponent = new ArrayList<>(); - issuerAndComponent.add(cert.getHolderIssuer()); - issuerAndComponent.add(ci); - chainComponents.add(issuerAndComponent); - } - } - } - log.info("Component failures: {}", componentFailureString); - for (ArrayList issuerAndComponent : chainComponents) { - ArrayList componentData = new ArrayList<>(); - String issuer = (String) issuerAndComponent.get(0); - issuer = issuer.replaceAll(",", " "); - ComponentIdentifier ci = (ComponentIdentifier) issuerAndComponent.get(1); - if (ci instanceof ComponentIdentifierV2) { - String componentClass = - ((ComponentIdentifierV2) ci).getComponentClass().toString(); - String[] splitStrings = componentClass.split("\r\n|\n|\r"); - StringBuilder sb = new StringBuilder(); - for (String s : splitStrings) { - sb.append(s); - sb.append(" "); - } - sb = sb.deleteCharAt(sb.length() - 1); - componentData.add(sb.toString()); - } else { - componentData.add("Platform Component"); - } - componentData.add(ci.getComponentManufacturer().getString()); - componentData.add(ci.getComponentModel().getString()); - componentData.add(ci.getComponentSerial().getString()); - componentData.add(issuer); - //Failing components are identified by hashcode - if (componentFailureString.toString().contains(String.valueOf(ci.hashCode()))) { - componentData.add("Fail"); - } else { - componentData.add("Pass"); - } - parsedComponents.add(componentData); - log.info(String.join(",", componentData)); - } - } - - return parsedComponents; - } } diff --git a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/devices.jsp b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/devices.jsp index 4e6206b0..4a58bc0c 100644 --- a/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/devices.jsp +++ b/HIRS_AttestationCAPortal/src/main/webapp/WEB-INF/jsp/devices.jsp @@ -78,6 +78,8 @@ { name: "name", data: "name", + searchable: true, + orderable: true, render: function (data, type, full, meta) { return full.device.name; },