mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-01-30 08:04:05 +00:00
Continued refactoring to update the failed components part of the attribute validation. The delta mapping needs to be reworked to not use serials.
This commit is contained in:
parent
d99bb1039c
commit
fbdcf83840
@ -132,7 +132,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
supplyChainAppraiser);
|
||||
boolean acceptExpiredCerts = policy.isExpiredCertificateValidationEnabled();
|
||||
PlatformCredential baseCredential = null;
|
||||
String componentFailures = "";
|
||||
List<SupplyChainValidation> validations = new LinkedList<>();
|
||||
Map<PlatformCredential, SupplyChainValidation> deltaMapping = new HashMap<>();
|
||||
SupplyChainValidation platformScv = null;
|
||||
@ -199,15 +198,22 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
Iterator<PlatformCredential> it = pcs.iterator();
|
||||
while (it.hasNext()) {
|
||||
PlatformCredential pc = it.next();
|
||||
SupplyChainValidation attributeScv;
|
||||
SupplyChainValidation attributeScv = null;
|
||||
|
||||
if (pc != null) {
|
||||
if (pc.isDeltaChain()) {
|
||||
// this check validates the delta changes and recompares
|
||||
// this check validates the delta changes and re-compares
|
||||
// the modified list to the original.
|
||||
attributeScv = validateDeltaPlatformCredentialAttributes(
|
||||
pc, device.getDeviceInfo(),
|
||||
baseCredential, deltaMapping);
|
||||
try {
|
||||
attributeScv = validateDeltaPlatformCredentialAttributes(
|
||||
pc, device.getDeviceInfo(),
|
||||
baseCredential, deltaMapping);
|
||||
} catch (Exception ex) {
|
||||
for (StackTraceElement element : ex.getStackTrace()) {
|
||||
LOGGER.error(element.toString());
|
||||
}
|
||||
LOGGER.error(ex.getMessage());
|
||||
}
|
||||
} else {
|
||||
attributeScv = validatePlatformCredentialAttributes(
|
||||
pc, device.getDeviceInfo(), ec);
|
||||
@ -239,8 +245,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
String.format("%s%n%s", platformScv.getMessage(),
|
||||
attributeScv.getMessage())));
|
||||
}
|
||||
componentFailures = updateUnmatchedComponents(
|
||||
attributeScv.getMessage());
|
||||
}
|
||||
|
||||
pc.setDevice(device);
|
||||
@ -259,10 +263,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
// Generate validation summary, save it, and return it.
|
||||
SupplyChainValidationSummary summary
|
||||
= new SupplyChainValidationSummary(device, validations);
|
||||
if (baseCredential != null) {
|
||||
baseCredential.setComponentFailures(componentFailures);
|
||||
this.certificateManager.update(baseCredential);
|
||||
}
|
||||
try {
|
||||
supplyChainValidatorSummaryManager.save(summary);
|
||||
} catch (DBManagerException ex) {
|
||||
@ -272,29 +272,6 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
return summary;
|
||||
}
|
||||
|
||||
private String updateUnmatchedComponents(final String unmatchedString) {
|
||||
StringBuilder updatedFailures = new StringBuilder();
|
||||
String manufacturer = "";
|
||||
String model = "";
|
||||
for (String rows : unmatchedString.split(";")) {
|
||||
for (String str : rows.split(",")) {
|
||||
String[] manufacturerSplit;
|
||||
String[] modelSplit;
|
||||
if (str.contains("Manufacturer")) {
|
||||
manufacturerSplit = str.split("=");
|
||||
manufacturer = manufacturerSplit[VALUE_INDEX];
|
||||
}
|
||||
if (str.contains("Model")) {
|
||||
modelSplit = str.split("=");
|
||||
model = modelSplit[VALUE_INDEX];
|
||||
}
|
||||
}
|
||||
updatedFailures.append(String.format("%s%s;", manufacturer, model));
|
||||
}
|
||||
|
||||
return updatedFailures.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is a sub set of the validate supply chain method and focuses
|
||||
* on the specific multibase validation check for a delta chain. This method
|
||||
@ -724,6 +701,11 @@ public class SupplyChainValidationServiceImpl implements SupplyChainValidationSe
|
||||
return buildValidationRecord(validationType, PASS,
|
||||
result.getMessage(), delta, Level.INFO);
|
||||
case FAIL:
|
||||
if (!result.getAdditionalInfo().isEmpty()) {
|
||||
LOGGER.error(result.getAdditionalInfo());
|
||||
base.setComponentFailures(result.getAdditionalInfo());
|
||||
this.certificateManager.update(base);
|
||||
}
|
||||
return buildValidationRecord(validationType, AppraisalStatus.Status.FAIL,
|
||||
result.getMessage(), delta, Level.WARN);
|
||||
case ERROR:
|
||||
|
@ -153,17 +153,6 @@ public class CertificateRequestPageController extends PageController<NoPageParam
|
||||
|
||||
return mav;
|
||||
}
|
||||
/**
|
||||
* TODO
|
||||
* 1. add flag for rim validation dependent on pc attribute flag DONE
|
||||
* 2. create tpmbaseline on upload of rimel file (DONE?)
|
||||
* a. add device id? though one won't exist yet
|
||||
* 3. validation
|
||||
* a. looks for baseline
|
||||
* b. if it doesn't find one, looks for rim
|
||||
* a. creates baseline if it exists
|
||||
* c. validates after reading rimel, if it finds one.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Queries for the list of Certificates and returns a data table response
|
||||
|
@ -340,7 +340,11 @@ public final class CertificateStringMapBuilder {
|
||||
//CPSuri
|
||||
data.put("CPSuri", certificate.getCPSuri());
|
||||
//component failure
|
||||
data.put("failures", certificate.getComponentFailures());
|
||||
if (certificate.getComponentFailures().isEmpty()) {
|
||||
data.put("failures", certificate.getComponentFailures());
|
||||
} else {
|
||||
LOGGER.error(certificate.getComponentFailures());
|
||||
}
|
||||
|
||||
//Get platform Configuration values and set map with it
|
||||
PlatformConfiguration platformConfiguration = certificate.getPlatformConfiguration();
|
||||
|
@ -32,6 +32,7 @@ public class AppraisalStatus {
|
||||
private Status appStatus;
|
||||
|
||||
private String message;
|
||||
private String additionalInfo;
|
||||
|
||||
/**
|
||||
* Default constructor. Set appraisal status and description.
|
||||
@ -43,6 +44,20 @@ public class AppraisalStatus {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor. Set appraisal status and description.
|
||||
* @param appStatus status of appraisal
|
||||
* @param message description of result
|
||||
* @param additionalInfo any additional information needed to
|
||||
* be passed on
|
||||
*/
|
||||
public AppraisalStatus(final Status appStatus, final String message,
|
||||
final String additionalInfo) {
|
||||
this.appStatus = appStatus;
|
||||
this.message = message;
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get appraisal status.
|
||||
* @return appraisal status
|
||||
@ -74,4 +89,20 @@ public class AppraisalStatus {
|
||||
public void setMessage(final String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for additional information during validation.
|
||||
* @return string of additional information
|
||||
*/
|
||||
public String getAdditionalInfo() {
|
||||
return additionalInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for any additional information.
|
||||
* @param additionalInfo the string of additional information
|
||||
*/
|
||||
public void setAdditionalInfo(final String additionalInfo) {
|
||||
this.additionalInfo = additionalInfo;
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ public class ComponentClass {
|
||||
private String category;
|
||||
private String component;
|
||||
private int componentIdentifier;
|
||||
private String classValueString;
|
||||
|
||||
/**
|
||||
* Default class constructor.
|
||||
@ -83,6 +84,7 @@ public class ComponentClass {
|
||||
*/
|
||||
public ComponentClass(final Path componentClassPath, final String componentIdentifier) {
|
||||
this(componentClassPath, getComponentIntValue(componentIdentifier));
|
||||
this.classValueString = componentIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,6 +144,14 @@ public class ComponentClass {
|
||||
return componentIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the Component Class Value as a string.
|
||||
* @return String representation of the class.
|
||||
*/
|
||||
public final String getClassValueString() {
|
||||
return classValueString;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main way this class will be referenced and how it
|
||||
* will be displayed on the portal.
|
||||
|
@ -46,6 +46,10 @@ public class ComponentInfo implements Serializable {
|
||||
@Column
|
||||
private String componentRevision;
|
||||
|
||||
@XmlElement
|
||||
@Column
|
||||
private String componentClass;
|
||||
|
||||
/**
|
||||
* Get the Component's Manufacturer.
|
||||
* @return the Component's Manufacturer
|
||||
@ -78,6 +82,14 @@ public class ComponentInfo implements Serializable {
|
||||
return componentRevision;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Component's Class Registry.
|
||||
* @return the Component's Class
|
||||
*/
|
||||
public String getComponentClass() {
|
||||
return componentClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor required by Hibernate.
|
||||
*/
|
||||
@ -115,6 +127,45 @@ public class ComponentInfo implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param componentManufacturer Component Manufacturer (must not be null)
|
||||
* @param componentModel Component Model (must not be null)
|
||||
* @param componentSerial Component Serial Number (can be null)
|
||||
* @param componentRevision Component Revision or Version (can be null)
|
||||
* @param componentClass Component Class (can be null)
|
||||
*/
|
||||
public ComponentInfo(final String componentManufacturer,
|
||||
final String componentModel,
|
||||
final String componentSerial,
|
||||
final String componentRevision,
|
||||
final String componentClass) {
|
||||
Assert.state(isComplete(
|
||||
componentManufacturer,
|
||||
componentModel,
|
||||
componentSerial,
|
||||
componentRevision
|
||||
));
|
||||
this.componentManufacturer = componentManufacturer.trim();
|
||||
this.componentModel = componentModel.trim();
|
||||
if (componentSerial != null) {
|
||||
this.componentSerial = componentSerial.trim();
|
||||
} else {
|
||||
this.componentSerial = StringUtils.EMPTY;
|
||||
}
|
||||
if (componentRevision != null) {
|
||||
this.componentRevision = componentRevision.trim();
|
||||
} else {
|
||||
this.componentRevision = StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
if (componentClass != null) {
|
||||
this.componentClass = componentClass;
|
||||
} else {
|
||||
this.componentClass = StringUtils.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given properties represent a
|
||||
* ComponentInfo that will be useful in validation.
|
||||
@ -131,9 +182,8 @@ public class ComponentInfo implements Serializable {
|
||||
final String componentModel,
|
||||
final String componentSerial,
|
||||
final String componentRevision) {
|
||||
return !(
|
||||
StringUtils.isEmpty(componentManufacturer) || StringUtils.isEmpty(componentModel)
|
||||
);
|
||||
return !(StringUtils.isEmpty(componentManufacturer)
|
||||
|| StringUtils.isEmpty(componentModel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -149,22 +199,26 @@ public class ComponentInfo implements Serializable {
|
||||
&& Objects.equals(componentManufacturer, that.componentManufacturer)
|
||||
&& Objects.equals(componentModel, that.componentModel)
|
||||
&& Objects.equals(componentSerial, that.componentSerial)
|
||||
&& Objects.equals(componentRevision, that.componentRevision);
|
||||
&& Objects.equals(componentRevision, that.componentRevision)
|
||||
&& Objects.equals(componentClass, that.componentClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, componentManufacturer, componentModel,
|
||||
componentSerial, componentRevision);
|
||||
componentSerial, componentRevision, componentClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ComponentInfo{"
|
||||
+ "componentManufacturer='" + componentManufacturer + '\''
|
||||
+ ", componentModel='" + componentModel + '\''
|
||||
+ ", componentSerial='" + componentSerial + '\''
|
||||
+ ", componentRevision='" + componentRevision + '\''
|
||||
+ '}';
|
||||
return String.format("ComponentInfo{"
|
||||
+ "componentManufacturer='%s'"
|
||||
+ ", componentModel='%s'"
|
||||
+ ", componentSerial='%s'"
|
||||
+ ", componentRevision='%s'"
|
||||
+ ", componentClass='%s'}",
|
||||
componentManufacturer,
|
||||
componentModel, componentSerial,
|
||||
componentRevision, componentClass);
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,43 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
return componentInfoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
|
||||
* @param paccorOutput the output from PACCOR's allcomoponents.sh
|
||||
* @return a list of ComponentInfo objects built from paccorOutput
|
||||
* @throws IOException if something goes wrong parsing the JSON
|
||||
*/
|
||||
public static List<ComponentInfo> getV2PaccorOutput(
|
||||
final String paccorOutput) throws IOException {
|
||||
List<ComponentInfo> ciList = new LinkedList<>();
|
||||
String manufacturer, model, serial, revision;
|
||||
String componentClass = Strings.EMPTY;
|
||||
|
||||
if (StringUtils.isNotEmpty(paccorOutput)) {
|
||||
ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
|
||||
JsonNode rootNode = objectMapper.readTree(paccorOutput);
|
||||
Iterator<JsonNode> jsonComponentNodes
|
||||
= rootNode.findValue("COMPONENTS").elements();
|
||||
while (jsonComponentNodes.hasNext()) {
|
||||
JsonNode next = jsonComponentNodes.next();
|
||||
manufacturer = getJSONNodeValueAsText(next, "MANUFACTURER");
|
||||
model = getJSONNodeValueAsText(next, "MODEL");
|
||||
serial = getJSONNodeValueAsText(next, "SERIAL");
|
||||
revision = getJSONNodeValueAsText(next, "REVISION");
|
||||
List<JsonNode> compClassNodes = next.findValues("COMPONENTCLASS");
|
||||
|
||||
for (JsonNode subNode : compClassNodes) {
|
||||
componentClass = getJSONNodeValueAsText(subNode,
|
||||
"COMPONENTCLASSVALUE");
|
||||
}
|
||||
ciList.add(new ComponentInfo(manufacturer, model,
|
||||
serial, revision, componentClass));
|
||||
}
|
||||
}
|
||||
|
||||
return ciList;
|
||||
}
|
||||
|
||||
private static String getJSONNodeValueAsText(final JsonNode node, final String fieldName) {
|
||||
if (node.hasNonNull(fieldName)) {
|
||||
return node.findValue(fieldName).asText();
|
||||
@ -555,6 +592,7 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
* base cert for this specific chain
|
||||
* @return Appraisal Status of delta being validated.
|
||||
*/
|
||||
@SuppressWarnings("methodlength")
|
||||
static AppraisalStatus validateDeltaAttributesChainV2p0(
|
||||
final DeviceInfoReport deviceInfoReport,
|
||||
final Map<PlatformCredential, SupplyChainValidation> deltaMapping,
|
||||
@ -602,7 +640,10 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
certificateList = new ArrayList<>();
|
||||
certificateList.add(delta);
|
||||
|
||||
/**
|
||||
* This chainnn maipping may have to change because
|
||||
* the serial number isn't required
|
||||
*/
|
||||
for (ComponentIdentifier ci : delta.getComponentIdentifiers()) {
|
||||
if (ci.isVersion2()) {
|
||||
ciSerial = ci.getComponentSerial().toString();
|
||||
@ -681,10 +722,18 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
String paccorOutputString = deviceInfoReport.getPaccorOutputString();
|
||||
String unmatchedComponents;
|
||||
try {
|
||||
List<ComponentInfo> componentInfoList
|
||||
= getComponentInfoFromPaccorOutput(paccorOutputString);
|
||||
unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
|
||||
new LinkedList<>(chainCiMapping.values()), componentInfoList);
|
||||
// List<ComponentInfo> componentInfoList
|
||||
// = getComponentInfoFromPaccorOutput(paccorOutputString);
|
||||
// compare based on component class
|
||||
List<ComponentInfo> componentInfoList = getV2PaccorOutput(paccorOutputString);
|
||||
// testComponentMatching(compMapping, chainCiMapping.values());
|
||||
// this is what I want to rewrite
|
||||
// unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
|
||||
// new LinkedList<>(chainCiMapping.values()),
|
||||
// compMapping.keySet().stream().collect(Collectors.toList()));
|
||||
unmatchedComponents = validateV2PlatformCredentialAttributes(
|
||||
new LinkedList<>(chainCiMapping.values()),
|
||||
componentInfoList);
|
||||
fieldValidation &= unmatchedComponents.isEmpty();
|
||||
} catch (IOException e) {
|
||||
final String baseErrorMessage = "Error parsing JSON output from PACCOR: ";
|
||||
@ -692,16 +741,82 @@ public final class SupplyChainCredentialValidator implements CredentialValidator
|
||||
LOGGER.error("PACCOR output string:\n" + paccorOutputString);
|
||||
return new AppraisalStatus(ERROR, baseErrorMessage + e.getMessage());
|
||||
}
|
||||
|
||||
if (!fieldValidation) {
|
||||
// instead of listing all unmatched, just print the #. The failure
|
||||
// will link to the platform certificate that'll display them.
|
||||
LOGGER.error(unmatchedComponents);
|
||||
String failureResults = unmatchedComponents.substring(0,
|
||||
unmatchedComponents.length() - 1);
|
||||
String size = unmatchedComponents.substring(unmatchedComponents.length() - 1);
|
||||
resultMessage = new StringBuilder();
|
||||
resultMessage.append("There are unmatched components:\n");
|
||||
resultMessage.append(unmatchedComponents);
|
||||
resultMessage.append(String.format("There are %s unmatched components",
|
||||
size));
|
||||
return new AppraisalStatus(FAIL, resultMessage.toString(), failureResults);
|
||||
}
|
||||
return new AppraisalStatus(PASS, PLATFORM_ATTRIBUTES_VALID);
|
||||
}
|
||||
|
||||
return new AppraisalStatus(FAIL, resultMessage.toString());
|
||||
private static String validateV2PlatformCredentialAttributes(
|
||||
final List<ComponentIdentifier> fullDeltaChainComponents,
|
||||
final List<ComponentInfo> allDeviceInfoComponents) {
|
||||
ComponentIdentifierV2 ciV2;
|
||||
StringBuilder invalidDeviceInfo = new StringBuilder();
|
||||
StringBuilder invalidPcIds = new StringBuilder();
|
||||
List<ComponentIdentifier> subCompIdList = fullDeltaChainComponents
|
||||
.stream().collect(Collectors.toList());
|
||||
List<ComponentInfo> subCompInfoList = allDeviceInfoComponents
|
||||
.stream().collect(Collectors.toList());
|
||||
LOGGER.error(String.format("fullDeltaChainComponents - %d", fullDeltaChainComponents.size()));
|
||||
LOGGER.error(String.format("subCompIdList - %d", subCompIdList.size()));
|
||||
LOGGER.error(String.format("allDeviceInfoComponents - %d", allDeviceInfoComponents.size()));
|
||||
LOGGER.error(String.format("subCompInfoList - %d", subCompInfoList.size()));
|
||||
// Delta is the baseline
|
||||
for (ComponentInfo cInfo : allDeviceInfoComponents) {
|
||||
for (ComponentIdentifier cId : fullDeltaChainComponents) {
|
||||
ciV2 = (ComponentIdentifierV2) cId;
|
||||
if (cInfo.getComponentClass().equals(
|
||||
ciV2.getComponentClass().getClassValueString())) {
|
||||
LOGGER.error(String.format("Testing %s -> %s%n%n", cInfo, ciV2));
|
||||
if (!isMatch(cId, cInfo)) {
|
||||
invalidDeviceInfo.append(String.format("%s:%s;",
|
||||
cInfo.getComponentClass(), cInfo.toString()));
|
||||
invalidPcIds.append(String.format("%s:%s;",
|
||||
ciV2.getComponentClass().getClassValueString(),
|
||||
ciV2.toString()));
|
||||
} else {
|
||||
LOGGER.error("TDM - Removed items");
|
||||
subCompIdList.remove(cId);
|
||||
subCompInfoList.remove(cInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new AppraisalStatus(PASS, PLATFORM_ATTRIBUTES_VALID);
|
||||
if (subCompIdList.isEmpty() && subCompInfoList.isEmpty()) {
|
||||
return Strings.EMPTY;
|
||||
}
|
||||
|
||||
// now we return everything that was unmatched
|
||||
// what is in the component info/device reported components
|
||||
// is to be displayed as the failure
|
||||
if (!subCompIdList.isEmpty()) {
|
||||
for (ComponentIdentifier ci : subCompIdList) {
|
||||
ciV2 = (ComponentIdentifierV2) ci;
|
||||
invalidPcIds.append(String.format("%s:%s;",
|
||||
ciV2.getComponentClass().getClassValueString(),
|
||||
ciV2.getComponentModel()));
|
||||
}
|
||||
}
|
||||
|
||||
if (!subCompInfoList.isEmpty()) {
|
||||
for (ComponentInfo ci : subCompInfoList) {
|
||||
invalidDeviceInfo.append(String.format("%s:%s;",
|
||||
ci.getComponentClass(), ci.getComponentModel()));
|
||||
}
|
||||
}
|
||||
|
||||
return String.format("DEVICEINFO=%s?COMPID=%s%d",
|
||||
invalidDeviceInfo.toString(), invalidPcIds.toString(), subCompInfoList.size());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user