Support for -j|--json option to output validation report data in JSON format. Add shorthand options for script parameters and update help menu.

This commit is contained in:
chubtub 2021-05-19 17:48:10 -04:00
parent 88d2de5eed
commit 59dff64af4
2 changed files with 129 additions and 54 deletions

View File

@ -1,18 +1,23 @@
package hirs.attestationca.portal.page.controllers; package hirs.attestationca.portal.page.controllers;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import hirs.FilteredRecordsList;
import hirs.attestationca.portal.datatables.DataTableInput; import hirs.attestationca.portal.datatables.DataTableInput;
import hirs.attestationca.portal.datatables.DataTableResponse; import hirs.attestationca.portal.datatables.DataTableResponse;
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter; import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
import hirs.attestationca.portal.page.PageController; import hirs.attestationca.portal.page.PageController;
import hirs.attestationca.portal.page.params.NoPageParams; import hirs.attestationca.portal.page.params.NoPageParams;
import hirs.data.persist.SupplyChainValidationSummary;
import hirs.data.persist.certificate.Certificate; import hirs.data.persist.certificate.Certificate;
import hirs.data.persist.certificate.PlatformCredential; import hirs.data.persist.certificate.PlatformCredential;
import hirs.data.persist.certificate.attributes.ComponentIdentifier; import hirs.data.persist.certificate.attributes.ComponentIdentifier;
import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2; import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.persist.CertificateManager; import hirs.persist.CertificateManager;
import hirs.persist.CriteriaModifier;
import hirs.persist.CrudManager;
import hirs.persist.DeviceManager; import hirs.persist.DeviceManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import static org.apache.logging.log4j.LogManager.getLogger;
import org.hibernate.Criteria; import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions; import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -24,12 +29,6 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
import static hirs.attestationca.portal.page.Page.VALIDATION_REPORTS;
import hirs.FilteredRecordsList;
import hirs.data.persist.SupplyChainValidationSummary;
import hirs.persist.CriteriaModifier;
import hirs.persist.CrudManager;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -47,6 +46,9 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static hirs.attestationca.portal.page.Page.VALIDATION_REPORTS;
import static org.apache.logging.log4j.LogManager.getLogger;
/** /**
* Controller for the Validation Reports page. * Controller for the Validation Reports page.
*/ */
@ -141,7 +143,7 @@ public class ValidationReportsPageController extends PageController<NoPageParams
* @param response object * @param response object
* @throws IOException thrown by BufferedWriter object * @throws IOException thrown by BufferedWriter object
*/ */
@SuppressWarnings("checkstyle:magicnumber") @SuppressWarnings({"checkstyle:magicnumber", "checkstyle:methodlength" })
@RequestMapping(value = "download", method = RequestMethod.POST) @RequestMapping(value = "download", method = RequestMethod.POST)
public void download(final HttpServletRequest request, public void download(final HttpServletRequest request,
final HttpServletResponse response) throws IOException { final HttpServletResponse response) throws IOException {
@ -161,6 +163,7 @@ public class ValidationReportsPageController extends PageController<NoPageParams
boolean componentOnly = false; boolean componentOnly = false;
String filterManufacturer = ""; String filterManufacturer = "";
String filterSerial = ""; String filterSerial = "";
boolean jsonVersion = false;
Enumeration parameters = request.getParameterNames(); Enumeration parameters = request.getParameterNames();
while (parameters.hasMoreElements()) { while (parameters.hasMoreElements()) {
@ -236,23 +239,23 @@ public class ValidationReportsPageController extends PageController<NoPageParams
filterSerial = parameterValue; filterSerial = parameterValue;
} }
break; break;
case "json":
response.setHeader("Content-Type", "application/json");
jsonVersion = true;
break;
default: default:
} }
} }
response.setHeader("Content-Type", "text/csv"); if (!jsonVersion) {
response.setHeader("Content-Disposition", response.setHeader("Content-Type", "text/csv");
"attachment;filename=validation_report.csv"); response.setHeader("Content-Disposition",
"attachment;filename=validation_report.csv");
}
BufferedWriter bufferedWriter = new BufferedWriter( BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8)); new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));
StringBuilder reportData = new StringBuilder(); StringBuilder reportData = new StringBuilder();
bufferedWriter.append("Company: " + company + "\n"); JsonArray jsonReportData = new JsonArray();
bufferedWriter.append("Contract number: " + contractNumber + "\n");
if (systemOnly && componentOnly) {
systemOnly = false;
componentOnly = false;
}
for (int i = 0; i < deviceNames.length; i++) { for (int i = 0; i < deviceNames.length; i++) {
if ((createTimes.get(i).isAfter(startDate) || createTimes.get(i).isEqual(startDate)) if ((createTimes.get(i).isAfter(startDate) || createTimes.get(i).isEqual(startDate))
&& (createTimes.get(i).isBefore(endDate) && (createTimes.get(i).isBefore(endDate)
@ -260,38 +263,99 @@ public class ValidationReportsPageController extends PageController<NoPageParams
UUID deviceId = deviceManager.getDevice(deviceNames[i]).getId(); UUID deviceId = deviceManager.getDevice(deviceNames[i]).getId();
PlatformCredential pc = PlatformCredential.select(certificateManager) PlatformCredential pc = PlatformCredential.select(certificateManager)
.byDeviceId(deviceId).getCertificate(); .byDeviceId(deviceId).getCertificate();
if ((filterManufacturer.isEmpty() || filterManufacturer.equals( if (jsonVersion) {
pc.getManufacturer())) jsonReportData.add(assembleJsonContent(pc, parseComponents(pc),
&& (filterSerial.isEmpty() || filterSerial.equals( company, contractNumber));
pc.getPlatformSerial()))) { } else {
if (!componentOnly) { if (i == 0) {
reportData.append(pc.getManufacturer() + "," bufferedWriter.append("Company: " + company + "\n");
+ pc.getModel() + "," bufferedWriter.append("Contract number: " + contractNumber + "\n");
+ pc.getPlatformSerial() + ","
+ LocalDateTime.now().toString() + ","
+ pc.getDevice().getSupplyChainStatus() + ",");
} }
if (!systemOnly) { if (systemOnly && componentOnly) {
ArrayList<ArrayList<String>> parsedComponents = parseComponents(pc); systemOnly = false;
for (ArrayList<String> component : parsedComponents) { componentOnly = false;
for (String data : component) { }
reportData.append(data + ","); 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().toString() + ","
+ pc.getDevice().getSupplyChainStatus() + ",");
}
if (!systemOnly) {
ArrayList<ArrayList<String>> parsedComponents = parseComponents(pc);
for (ArrayList<String> component : parsedComponents) {
for (String data : component) {
reportData.append(data + ",");
}
reportData.deleteCharAt(reportData.length() - 1);
reportData.append("\n");
if (!componentOnly) {
reportData.append(",,,,,");
}
} }
reportData.deleteCharAt(reportData.length() - 1);
reportData.append("\n,,,,,");
} }
} }
reportData.append("\n");
} }
} }
} }
if (columnHeaders.isEmpty()) { if (!jsonVersion) {
columnHeaders = systemColumnHeaders + componentColumnHeaders; if (columnHeaders.isEmpty()) {
columnHeaders = systemColumnHeaders + componentColumnHeaders;
}
bufferedWriter.append(columnHeaders + "\n");
bufferedWriter.append(reportData.toString());
} else {
bufferedWriter.append(jsonReportData.toString());
} }
bufferedWriter.append(columnHeaders + "\n");
bufferedWriter.append(reportData.toString() + "\n");
bufferedWriter.flush(); 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.
*/
@SuppressWarnings({"checkstyle:magicnumber" })
private JsonObject assembleJsonContent(final PlatformCredential pc,
final ArrayList<ArrayList<String>> parsedComponents,
final String company,
final String contractNumber) {
JsonObject systemData = new JsonObject();
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", pc.getDevice().getSupplyChainStatus().toString());
JsonArray components = new JsonArray();
for (ArrayList<String> 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(3));
component.addProperty("Issuer", componentData.get(4));
component.addProperty("Component status", componentData.get(5));
components.add(component);
}
systemData.add("Components", components);
return systemData;
}
/** /**
* This method parses the following ComponentIdentifier fields into an ArrayList of ArrayLists. * This method parses the following ComponentIdentifier fields into an ArrayList of ArrayLists.
* - ComponentClass * - ComponentClass

View File

@ -15,8 +15,8 @@ else
fi fi
#set parameter names and call getopts on inputsi, then parse/assign arguments #set parameter names and call getopts on inputsi, then parse/assign arguments
SHORTOPTS=m:s:h SHORTOPTS=d:e:i:ypm:s:jh
LONGOPTS=start-date:,end-date:,ip:,system-only,component-only,manufacturer:,serial:,help LONGOPTS=start-date:,end-date:,ip:,system-only,component-only,manufacturer:,serial:,json,help
PARSED=$(getopt --options=$SHORTOPTS --longoptions=$LONGOPTS --name "$0" -- "$@") PARSED=$(getopt --options=$SHORTOPTS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]] if [[ ${PIPESTATUS[0]} -ne 0 ]]
then then
@ -30,35 +30,37 @@ system=
component= component=
manufacturer= manufacturer=
serial= serial=
json=
helpText="\n\n\nHELP MENU\n\nThe following options are available:\n--start-date\t\t<yyyy-mm-dd>\tDefault: 1970-01-01\tThe earliest date to return validation reports from.\n" helpText="\n\n\nHELP MENU\n\nThe following options are available:\n-d|--start-date\t\t<yyyy-mm-dd>\tDefault: 1970-01-01\tThe earliest date to return validation reports from.\n"
helpText+="--end-date\t\t<yyyy-mm-dd>\tDefault: current time\tThe latest date to return validation reports from.\n" helpText+="-e|--end-date\t\t<yyyy-mm-dd>\tDefault: current time\tThe latest date to return validation reports from.\n"
helpText+="--ip\t\t\t<ACA address>\tDefault: localhost\tThe IP address where the ACA is located.\n" helpText+="-i|--ip\t\t\t<ACA address>\tDefault: localhost\tThe IP address where the ACA is located.\n"
helpText+="--system-only\t\t\t\t\t\t\tReturn only system information from validation reports.\n" helpText+="-y|--system-only\t\t\t\t\t\tReturn only system information from validation reports.\n"
helpText+="--component-only\t\t\t\t\t\tReturn only component information from validation reports.\n" helpText+="-p|--component-only\t\t\t\t\t\tReturn only component information from validation reports.\n"
helpText+="-m|--manufacturer\t<manufacturer's name>\t\t\tReturn only the validation report of the device from this manufacturer.\n" helpText+="-m|--manufacturer\t<manufacturer's name>\t\t\tReturn only the validation report of the device from this manufacturer.\n"
helpText+="-s|--serial\t\t<serial number>\t\t\t\tReturn only the validation report of the device with this serial number.\n" helpText+="-s|--serial\t\t<serial number>\t\t\t\tReturn only the validation report of the device with this serial number.\n"
helpText+="-j|--json\t\t\t\t\t\t\tReturn output in JSON format. Only --start-date, --end-date,\n\t\t\t\t\t\t\t\tand --ip parameters are read with this option, all others are ignored.\n"
while true while true
do do
case "$1" in case "$1" in
--start-date) -d|--start-date)
startDate="$2" startDate="$2"
shift 2 shift 2
;; ;;
--end-date) -e|--end-date)
endDate="$2" endDate="$2"
shift 2 shift 2
;; ;;
--ip) -i|--ip)
ip="$2" ip="$2"
shift 2 shift 2
;; ;;
--system-only) -y|--system-only)
system=true system=true
shift shift
;; ;;
--component-only) -p|--component-only)
component=true component=true
shift shift
;; ;;
@ -70,6 +72,10 @@ do
serial="$2" serial="$2"
shift 2 shift 2
;; ;;
-j|--json)
json=true
shift
;;
-h|--help) -h|--help)
printf "$helpText" printf "$helpText"
exit 0 exit 0
@ -85,8 +91,6 @@ do
esac esac
done done
#echo "start date: $startDate, end date: $endDate, ip: $ip, system: $system, component: $component, manufacturer: $manufacturer, serial: $serial"
#call ACA for validation report #call ACA for validation report
endpoint="https://$ip:8443/HIRS_AttestationCAPortal/portal/validation-reports" endpoint="https://$ip:8443/HIRS_AttestationCAPortal/portal/validation-reports"
echo "$endpoint" echo "$endpoint"
@ -103,4 +107,11 @@ deviceNames=$(jq -r '.data | map(.device.name) | join(",")' <<< "$content")
echo "Create times: $createTimes" echo "Create times: $createTimes"
echo "Device names: $deviceNames" echo "Device names: $deviceNames"
curl --data "dateStart=$startDate&dateEnd=$endDate&createTimes=$createTimes&deviceNames=$deviceNames&system=$system&component=$component&manufacturer=$manufacturer&serial=$serial" --insecure $endpoint/download curlData="dateStart=$startDate&dateEnd=$endDate&createTimes=$createTimes&deviceNames=$deviceNames"
if [[ "$json" = true ]]
then
curlData+="&json=true"
else
curlData+="&system=$system&component=$component&manufacturer=$manufacturer&serial=$serial"
fi
curl --data "$curlData" --insecure $endpoint/download