These updates include a lot of changes that involve using the Component

Result class as the means to comparison for the Platform and Device
components.  Other changes are for checkstyles.
This commit is contained in:
Cyrus 2024-02-23 21:14:33 -05:00
parent e8f6064d60
commit 3f72fc5d15
18 changed files with 267 additions and 89 deletions

View File

@ -79,8 +79,8 @@ public abstract class AttestationCertificateAuthority {
* @param validDays the number of days issued certs are valid
* @param deviceRepository the device manager
* @param referenceDigestValueRepository the reference event manager
* @param policyRepository
* @param tpm2ProvisionerStateRepository
* @param policyRepository policy setting repository
* @param tpm2ProvisionerStateRepository tpm2 provisioner state repository
*/
@SuppressWarnings("checkstyle:parameternumber")
public AttestationCertificateAuthority(

View File

@ -8,4 +8,5 @@ import java.util.UUID;
public interface ComponentInfoRepository extends JpaRepository<ComponentInfo, UUID> {
List<ComponentInfo> findByDeviceName(String deviceName);
List<ComponentInfo> findByDeviceNameAndComponentSerial(String deviceName, String componentSerial);
}

View File

@ -14,14 +14,16 @@ import lombok.Setter;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
/**
* A component result is a DO to hold the status of a component validation status. This will
* also be used to display this common information on the certificate details page.
*/
@EqualsAndHashCode(callSuper=false)
@Getter
@Entity
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ComponentResult extends ArchivableEntity {
@ -34,10 +36,13 @@ public class ComponentResult extends ArchivableEntity {
private String revisionNumber;
private boolean fieldReplaceable;
// this is a string because component class doesn't inherit serializable.
private String componentClass;
@Setter
private String componentClassValue;
private String componentClassType;
private AttributeStatus attributeStatus;
private String componentAddress;
private boolean version2 = false;
@Setter
private boolean mismatched;
private String certificateType;
@ -78,13 +83,12 @@ public class ComponentResult extends ArchivableEntity {
// this is a downside of findbugs, the code is set up to indicate if a CI is V2 or not
// but find bugs is throwing a flag because instanceof isn't being used.
ComponentIdentifierV2 ciV2 = (ComponentIdentifierV2) componentIdentifier;
this.componentClass = ciV2.getComponentClass().toString();
this.componentClassValue = ciV2.getComponentClass().getComponentIdentifier();
this.componentClassType = ciV2.getComponentClass().getRegistryType();
this.attributeStatus = ciV2.getAttributeStatus();
this.version2 = true;
if (ciV2.getCertificateIdentifier() != null) {
this.issuerDN = ciV2.getCertificateIdentifier().getIssuerDN().toString();
// this.certificateSerialNumber = ciV2.getCertificateIdentifier()
// .getCertificateSerialNumber().toString();
if (ciV2.getComponentPlatformUri() != null) {
this.uniformResourceIdentifier = ciV2.getComponentPlatformUri()
.getUniformResourceIdentifier().toString();
@ -113,6 +117,15 @@ public class ComponentResult extends ArchivableEntity {
return addresses;
}
/**
* Returns a hash code that is associated with common fields for components.
* @return int value of the elements
*/
public int hashCommonElements() {
return Objects.hash(manufacturer,
model, serialNumber, revisionNumber, componentClassValue);
}
/**
* The string method for log entries.
* @return a string for the component result
@ -120,6 +133,6 @@ public class ComponentResult extends ArchivableEntity {
public String toString() {
return String.format("ComponentResult: certificateSerialNumber=[%s] "
+ "manufacturer=[%s] model=[%s] componentClass=[%s]",
boardSerialNumber, manufacturer, model, componentClass);
boardSerialNumber, manufacturer, model, componentClassValue);
}
}

View File

@ -14,10 +14,10 @@ import java.util.UUID;
* of that component mismatched.
*/
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ComponentAttributeResult extends ArchivableEntity {
@Getter
private UUID componentId;
private String expectedValue;
private String actualValue;

View File

@ -52,6 +52,7 @@ public class ComponentClass {
private String category, categoryStr;
@Getter
private String component, componentStr;
@Getter
private String registryType;
@Getter
private String componentIdentifier;

View File

@ -2,6 +2,7 @@ package hirs.attestationca.persist.entity.userdefined.info;
import hirs.attestationca.persist.entity.ArchivableEntity;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.utils.enums.DeviceInfoEnums;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.DiscriminatorType;
@ -13,6 +14,8 @@ import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
/**
* ComponentInfo is a class to hold Hardware component information
* such as manufacturer, model, serial number and version.
@ -53,21 +56,21 @@ public class ComponentInfo extends ArchivableEntity {
/**
* Base constructor for children.
* @param componentManufacturer
* @param componentModel
* @param componentSerial
* @param componentRevision
* @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)
*/
public ComponentInfo(final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
this(StringUtils.EMPTY, componentManufacturer, componentModel,
this(DeviceInfoEnums.NOT_SPECIFIED, componentManufacturer, componentModel,
componentSerial, componentRevision);
}
/**
* Constructor.
* @param deviceName the host machine associated with this component.
* @param deviceName the host machine associated with this component. (must not be null)
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
* @param componentSerial Component Serial Number (can be null)
@ -88,6 +91,7 @@ public class ComponentInfo extends ArchivableEntity {
throw new NullPointerException("ComponentInfo: manufacturer and/or "
+ "model can not be null");
}
this.deviceName = deviceName;
this.componentManufacturer = componentManufacturer.trim();
this.componentModel = componentModel.trim();
if (componentSerial != null) {
@ -120,11 +124,7 @@ public class ComponentInfo extends ArchivableEntity {
this(deviceName, componentManufacturer, componentModel,
componentSerial, componentRevision);
if (componentClass != null) {
this.componentClass = componentClass;
} else {
this.componentClass = StringUtils.EMPTY;
}
this.componentClass = Objects.requireNonNullElse(componentClass, StringUtils.EMPTY);
}
/**
@ -146,4 +146,44 @@ public class ComponentInfo extends ArchivableEntity {
return (StringUtils.isEmpty(componentManufacturer)
|| StringUtils.isEmpty(componentModel));
}
/**
* Equals for the component info that just uses this classes attributes.
* @param object the object to compare
* @return the boolean result
*/
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
ComponentInfo that = (ComponentInfo) object;
return Objects.equals(deviceName, that.deviceName)
&& Objects.equals(componentManufacturer,
that.componentManufacturer)
&& Objects.equals(componentModel, that.componentModel)
&& Objects.equals(componentSerial, that.componentSerial)
&& Objects.equals(componentRevision, that.componentRevision)
&& Objects.equals(componentClass, that.componentClass);
}
/**
* Returns a hash code that is associated with common fields for components.
* @return int value of the elements
*/
public int hashCommonElements() {
return Objects.hash(componentManufacturer, componentModel,
componentSerial, componentRevision, componentClass);
}
/**
* Hash method for the attributes of this class.
* @return int value that represents this class
*/
@Override
public int hashCode() {
return Objects.hash(deviceName, componentManufacturer,
componentModel, componentSerial, componentRevision,
componentClass);
}
}

View File

@ -14,7 +14,6 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Transient;
import jakarta.xml.bind.annotation.XmlElement;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
@ -29,7 +28,6 @@ import java.util.Objects;
*/
@Log4j2
@Getter
@NoArgsConstructor
@Entity
public class DeviceInfoReport extends AbstractEntity implements Serializable {
@ -62,6 +60,14 @@ public class DeviceInfoReport extends AbstractEntity implements Serializable {
@Transient
private String paccorOutputString;
/**
* This constructor is used to populate the inner variables with blank entries so that
* a request on a blank object isn't null.
*/
public DeviceInfoReport() {
this(null, null, null, null, null);
}
/**
* Constructor used to create a <code>DeviceInfoReport</code>. The
* information cannot be changed after the <code>DeviceInfoReport</code> is

View File

@ -51,6 +51,11 @@ public class AbstractProcessor {
@Getter
private PolicyRepository policyRepository;
/**
* Default constructor that sets main class fields.
* @param privateKey private key used for communication authentication
* @param validDays property value to set for issued certificates
*/
public AbstractProcessor(final PrivateKey privateKey,
final int validDays) {
this.privateKey = privateKey;
@ -64,6 +69,7 @@ public class AbstractProcessor {
* @param endorsementCredential the endorsement credential
* @param platformCredentials the set of platform credentials
* @param deviceName The host name used in the subject alternative name
* @param acaCertificate object used to create credential
* @return identity credential
*/
protected X509Certificate generateCredential(final PublicKey publicKey,
@ -187,10 +193,12 @@ public class AbstractProcessor {
/**
* Gets the Endorsement Credential from the DB given the EK public key.
* @param ekPublicKey the EK public key
* @param certificateRepository db store manager for certificates
* @return the Endorsement credential, if found, otherwise null
*/
private EndorsementCredential getEndorsementCredential(final PublicKey ekPublicKey,
final CertificateRepository certificateRepository) {
private EndorsementCredential getEndorsementCredential(
final PublicKey ekPublicKey,
final CertificateRepository certificateRepository) {
log.debug("Searching for endorsement credential based on public key: " + ekPublicKey);
if (ekPublicKey == null) {
@ -220,6 +228,7 @@ public class AbstractProcessor {
* Helper method to create an {@link IssuedAttestationCertificate} object, set its
* corresponding device and persist it.
*
* @param certificateRepository db store manager for certificates
* @param derEncodedAttestationCertificate the byte array representing the Attestation
* certificate
* @param endorsementCredential the endorsement credential used to generate the AC

View File

@ -37,8 +37,11 @@ public class CertificateRequestProcessor extends AbstractProcessor {
/**
* Constructor.
* @param supplyChainValidationService object that is used to run provisioning
* @param certificateRepository db connector for all certificates.
* @param deviceRepository database connector for Devices.
* @param privateKey private key used for communication authentication
* @param acaCertificate object used to create credential
* @param validDays int for the time in which a certificate is valid.
* @param tpm2ProvisionerStateRepository db connector for provisioner state.
*/
@ -97,7 +100,8 @@ public class CertificateRequestProcessor extends AbstractProcessor {
RSAPublicKey akPub = ProvisionUtils.parsePublicKey(claim.getAkPublicArea().toByteArray());
// Get Endorsement Credential if it exists or was uploaded
EndorsementCredential endorsementCredential = parseEcFromIdentityClaim(claim, ekPub, certificateRepository);
EndorsementCredential endorsementCredential = parseEcFromIdentityClaim(claim,
ekPub, certificateRepository);
// Get Platform Credentials if they exist or were uploaded
List<PlatformCredential> platformCredentials = parsePcsFromIdentityClaim(claim,

View File

@ -85,7 +85,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
private TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository;
/**
* Constructor
* Constructor.
*/
public IdentityClaimProcessor(
final SupplyChainValidationService supplyChainValidationService,
@ -201,7 +201,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
Device device = processDeviceInfo(claim);
// device.getDeviceInfo().setPaccorOutputString(claim.getPaccorOutput());
handleDeviceComponents(device.getName(),
handleDeviceComponents(device.getDeviceInfo().getNetworkInfo().getHostname(),
claim.getPaccorOutput());
// There are situations in which the claim is sent with no PCs
// or a PC from the tpm which will be deprecated
@ -231,7 +231,8 @@ public class IdentityClaimProcessor extends AbstractProcessor {
// perform supply chain validation
SupplyChainValidationSummary summary = supplyChainValidationService.validateSupplyChain(
endorsementCredential, platformCredentials, device);
endorsementCredential, platformCredentials, device,
componentInfoRepository.findByDeviceName(device.getName()));
device.setSummaryId(summary.getId().toString());
// update the validation result in the device
AppraisalStatus.Status validationResult = summary.getOverallValidationResult();
@ -644,14 +645,27 @@ public class IdentityClaimProcessor extends AbstractProcessor {
private int handleDeviceComponents(final String hostName, final String paccorString) {
int deviceComponents = 0 ;
Map<Integer, ComponentInfo> componentInfoMap = new HashMap<>();
try {
List<ComponentInfo> componentInfos = SupplyChainCredentialValidator
.getComponentInfoFromPaccorOutput(hostName, paccorString);
// check the DB for like component infos
List<ComponentInfo> dbComponentInfos = this.componentInfoRepository.findByDeviceName(hostName);
dbComponentInfos.stream().forEach((infos) -> {
componentInfoMap.put(infos.hashCode(), infos);
});
for (ComponentInfo componentInfo : dbComponentInfos) {
if (componentInfoMap.containsKey(componentInfo.hashCode())) {
componentInfos.remove(componentInfo);
}
}
for (ComponentInfo componentInfo : componentInfos) {
this.componentInfoRepository.save(componentInfo);
}
} catch (IOException e) {
} catch (IOException ioEx) {
log.warn("Error parsing paccor string");
}

View File

@ -5,11 +5,8 @@ import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import lombok.extern.log4j.Log4j2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
import java.util.stream.Collectors;
/**

View File

@ -4,8 +4,6 @@ import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCred
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.DEROctetString;
@ -42,13 +40,13 @@ public final class IssuedCertificateAttributeHelper {
/**
* Object Identifier TCPA at TPM ID Label.
*/
public final static ASN1ObjectIdentifier TCPA_AT_TPM_ID_LABEL =
public static final ASN1ObjectIdentifier TCPA_AT_TPM_ID_LABEL =
new ASN1ObjectIdentifier(TPM_ID_LABEL_OID);
/**
* The extended key usage extension.
*/
public final static Extension EXTENDED_KEY_USAGE_EXTENSION;
private final static ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
public static final Extension EXTENDED_KEY_USAGE_EXTENSION;
private static final ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
new ASN1ObjectIdentifier("2.23.133.8.3");
static {

View File

@ -17,6 +17,7 @@ import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidationSummary;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.attestationca.persist.entity.userdefined.rim.EventLogMeasurements;
import hirs.attestationca.persist.entity.userdefined.rim.SupportReferenceManifest;
import hirs.attestationca.persist.enums.AppraisalStatus;
@ -95,12 +96,14 @@ public class SupplyChainValidationService {
* @param ec The endorsement credential from the identity request.
* @param pcs The platform credentials from the identity request.
* @param device The device to be validated.
* @param componentInfos list of components from the device
* @return A summary of the validation results.
*/
@SuppressWarnings("methodlength")
public SupplyChainValidationSummary validateSupplyChain(final EndorsementCredential ec,
final List<PlatformCredential> pcs,
final Device device) {
final Device device,
final List<ComponentInfo> componentInfos) {
boolean acceptExpiredCerts = getPolicySettings().isExpiredCertificateValidationEnabled();
PlatformCredential baseCredential = null;
SupplyChainValidation platformScv = null;
@ -208,6 +211,8 @@ public class SupplyChainValidationService {
null, Level.ERROR));
} else {
if (chkDeltas) {
// There are delta certificates, so the code need to build a new list of
// certificate components to then compare against the device component list
aes.addAll(basePlatformScv.getCertificatesUsed());
Iterator<PlatformCredential> it = pcs.iterator();
while (it.hasNext()) {
@ -223,13 +228,14 @@ public class SupplyChainValidationService {
}
}
} else {
// validate attributes for a single base platform certificate
aes.add(baseCredential);
validations.remove(platformScv);
// if there are no deltas, just check base credential
platformScv = ValidationService.evaluatePCAttributesStatus(
baseCredential, device.getDeviceInfo(), ec,
certificateRepository, componentResultRepository,
componentAttributeRepository);
componentAttributeRepository, componentInfos);
validations.add(new SupplyChainValidation(
SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL,
platformScv.getValidationResult(), aes, platformScv.getMessage()));

View File

@ -13,9 +13,9 @@ import hirs.attestationca.persist.entity.userdefined.PolicySettings;
import hirs.attestationca.persist.entity.userdefined.ReferenceManifest;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.certificate.CertificateAuthorityCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.validation.CertificateAttributeScvValidator;
@ -106,7 +106,8 @@ public class ValidationService {
final EndorsementCredential ec,
final CertificateRepository certificateRepository,
final ComponentResultRepository componentResultRepository,
final ComponentAttributeRepository componentAttributeRepository) {
final ComponentAttributeRepository componentAttributeRepository,
final List<ComponentInfo> componentInfos) {
final SupplyChainValidation.ValidationType validationType
= SupplyChainValidation.ValidationType.PLATFORM_CREDENTIAL_ATTRIBUTES;
@ -117,12 +118,12 @@ public class ValidationService {
null, Level.ERROR);
}
log.info("Validating platform credential attributes");
List<ComponentResult> componentResults = componentResultRepository
.findByCertificateSerialNumberAndBoardSerialNumber(
pc.getSerialNumber().toString(), pc.getPlatformSerial());
// List<ComponentResult> componentResults = componentResultRepository
// .findByCertificateSerialNumberAndBoardSerialNumber(
// pc.getSerialNumber().toString(), pc.getPlatformSerial());
AppraisalStatus result = CredentialValidator.
validatePlatformCredentialAttributes(pc, deviceInfoReport, ec,
componentResultRepository, componentAttributeRepository);
componentResultRepository, componentAttributeRepository, componentInfos);
switch (result.getAppStatus()) {
case PASS:
return buildValidationRecord(validationType, AppraisalStatus.Status.PASS,

View File

@ -5,6 +5,7 @@ import com.github.marandus.pciid.model.Vendor;
import com.github.marandus.pciid.service.PciIdsDatabase;
import com.google.common.base.Strings;
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentClass;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import lombok.AccessLevel;
@ -178,9 +179,11 @@ public final class PciIds {
*/
public static ComponentResult translateResult(final ComponentResult componentResult) {
ComponentResult newComponent = null;
ComponentClass updateComponentClass;
if (componentResult != null) {
newComponent = componentResult;
updateComponentClass = new ComponentClass(componentResult.getComponentClassType(), componentResult.getComponentClassValue());
newComponent.setComponentClassValue(updateComponentClass.toString());
newComponent.setManufacturer(translateVendor(componentResult.getManufacturer()));
newComponent.setModel(translateDevice(componentResult.getManufacturer(),
componentResult.getModel()));

View File

@ -4,7 +4,9 @@ import hirs.attestationca.persist.entity.ArchivableEntity;
import hirs.attestationca.persist.entity.manager.ComponentAttributeRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.userdefined.SupplyChainValidation;
import hirs.attestationca.persist.entity.userdefined.certificate.ComponentResult;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentAttributeResult;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.V2.ComponentIdentifierV2;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
@ -191,13 +193,17 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
* Validates device info report against the new platform credential.
* @param platformCredential the Platform Credential
* @param deviceInfoReport the Device Info Report
* @param componentResultRepository db access to component result of mismatching
* @param componentAttributeRepository db access to component attribute match status
* @param componentInfos list of device components
* @return either PASS or FAIL
*/
public static AppraisalStatus validatePlatformCredentialAttributesV2p0(
final PlatformCredential platformCredential,
final DeviceInfoReport deviceInfoReport,
final ComponentResultRepository componentResultRepository,
final ComponentAttributeRepository componentAttributeRepository) {
final ComponentAttributeRepository componentAttributeRepository,
final List<ComponentInfo> componentInfos) {
boolean passesValidation = true;
StringBuilder resultMessage = new StringBuilder();
@ -286,46 +292,92 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
&& identifier.getComponentModel() != null)
.collect(Collectors.toList());
/**
* 1. create a mapping for the CI and the Cinfo to the component class (all trimming should happen in the object class)
* 2. Run a look based on the component class and compare the items.
* 3. if something doesn't match create a componentattributestatus
* 4. pull all relevant information on the mapping side
* Note: have to considered component class pulls of more than one. like memory
*
*/
String paccorOutputString = deviceInfoReport.getPaccorOutputString();
String unmatchedComponents;
try {
List<ComponentInfo> componentInfoList
= getComponentInfoFromPaccorOutput(deviceInfoReport.getNetworkInfo().getHostname(),
paccorOutputString);
unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
validPcComponents, componentInfoList);
fieldValidation &= unmatchedComponents.isEmpty();
} catch (IOException ioEx) {
final String baseErrorMessage = "Error parsing JSON output from PACCOR: ";
log.error(baseErrorMessage + ioEx);
log.error("PACCOR output string:\n" + paccorOutputString);
return new AppraisalStatus(ERROR, baseErrorMessage + ioEx.getMessage());
// START A NEW
// populate componentResults list
List<ComponentResult> componentResults = componentResultRepository
.findByCertificateSerialNumberAndBoardSerialNumber(
platformCredential.getSerialNumber().toString(),
platformCredential.getPlatformSerial());
// first create hash map based on hashCode
Map<Integer, List<ComponentInfo>> deviceHashMap = new HashMap<>();
componentInfos.stream().forEach((componentInfo) -> {
List<ComponentInfo> innerList;
Integer compInfoHash = componentInfo.hashCommonElements();
if (deviceHashMap.containsKey(compInfoHash)) {
innerList = deviceHashMap.get(compInfoHash);
innerList.add(componentInfo);
} else {
innerList = new ArrayList<>(0);
innerList.add(componentInfo);
}
deviceHashMap.put(compInfoHash, innerList);
});
// Look for hash code in device mapping
// if it exists, don't save the component
List<ComponentResult> remainingComponentResults = new ArrayList<>();
for (ComponentResult componentResult : componentResults) {
if (!deviceHashMap.containsKey(componentResult.hashCommonElements())) {
// didn't find the component result in the hashed mapping
remainingComponentResults.add(componentResult);
}
}
if (!remainingComponentResults.isEmpty()) {
// continue down the options, move to a different method.
// create component class mapping to component info
Map<String, List<ComponentInfo>> componentDeviceMap = new HashMap<>();
componentInfos.stream().forEach((componentInfo) -> {
List<ComponentInfo> innerList;
String componentClass = componentInfo.getComponentClass();
if (componentDeviceMap.containsKey(componentClass)) {
innerList = componentDeviceMap.get(componentClass);
innerList.add(componentInfo);
} else {
innerList = new ArrayList<>(0);
innerList.add(componentInfo);
}
componentDeviceMap.put(componentClass, innerList);
});
List<ComponentInfo> componentClassInfo;
for (ComponentResult componentResult : remainingComponentResults) {
componentClassInfo = componentDeviceMap.get(componentResult.getComponentClassValue());
if (componentClassInfo.size() > 1) {
componentResult.setMismatched(!matchBasedOnClass(
componentClassInfo, componentResult, componentAttributeRepository));
}
}
for (ComponentResult componentResult : remainingComponentResults) {
fieldValidation &= !componentResult.isMismatched();
}
}
// WIP clean this up
// END
// try {
// List<ComponentInfo> componentInfoList
// = getComponentInfoFromPaccorOutput(deviceInfoReport.getNetworkInfo().getHostname(),
// paccorOutputString);
// unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
// validPcComponents, componentInfoList);
// fieldValidation &= unmatchedComponents.isEmpty();
// } catch (IOException ioEx) {
// final String baseErrorMessage = "Error parsing JSON output from PACCOR: ";
// log.error(baseErrorMessage + ioEx);
// return new AppraisalStatus(ERROR, baseErrorMessage + ioEx.getMessage());
// }
//
// // WIP clean this up
StringBuilder additionalInfo = new StringBuilder();
if (!fieldValidation) {
resultMessage.append("There are unmatched components:\n");
resultMessage.append(unmatchedComponents);
// pass information of which ones failed in additionInfo
int counter = 0;
for (ComponentIdentifier ci : validPcComponents) {
counter++;
additionalInfo.append(String.format("%d;", ci.hashCode()));
}
if (counter > 0) {
additionalInfo.insert(0, "COMPID=");
additionalInfo.append(counter);
}
resultMessage.append("There are unmatched components...\n");
}
passesValidation &= fieldValidation;
@ -337,6 +389,29 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
}
}
private static boolean matchBasedOnClass(final List<ComponentInfo> componentInfos,
final ComponentResult componentResult,
final ComponentAttributeRepository componentAttributeRepository) {
// there are instances of components with the same class (ie hard disks, memory)
int listSize = componentInfos.size();
List<ComponentAttributeResult> attributeResults = new ArrayList<>();
boolean matched = true;
for (ComponentInfo componentInfo : componentInfos) {
// just do a single pass and save the values
attributeResults.add(new ComponentAttributeResult(componentResult.getId(), componentResult.getManufacturer(), componentInfo.getComponentManufacturer()));
attributeResults.add(new ComponentAttributeResult(componentResult.getId(), componentResult.getModel(), componentInfo.getComponentModel()));
attributeResults.add(new ComponentAttributeResult(componentResult.getId(), componentResult.getSerialNumber(), componentInfo.getComponentSerial()));
attributeResults.add(new ComponentAttributeResult(componentResult.getId(), componentResult.getRevisionNumber(), componentInfo.getComponentRevision()));
}
for (ComponentAttributeResult componentAttributeResult : attributeResults) {
componentAttributeRepository.save(componentAttributeResult);
matched &= componentAttributeResult.checkMatchedStatus();
}
return matched;
}
/**
* The main purpose of this method, the in process of validation, is to
* pick out the changes that lead to the delta cert and make sure the changes

View File

@ -4,6 +4,7 @@ import hirs.attestationca.persist.entity.manager.ComponentAttributeRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.userdefined.certificate.EndorsementCredential;
import hirs.attestationca.persist.entity.userdefined.certificate.PlatformCredential;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.attestationca.persist.entity.userdefined.report.DeviceInfoReport;
import hirs.attestationca.persist.enums.AppraisalStatus;
import lombok.extern.log4j.Log4j2;
@ -16,6 +17,7 @@ import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.ERROR;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.FAIL;
@ -162,6 +164,9 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
* serial number of the platform to be validated.
* @param endorsementCredential The endorsement credential supplied from the same
* identity request as the platform credential.
* @param componentResultRepository db access to component result of mismatching
* @param componentAttributeRepository db access to component attribute match status
* @param componentInfos list of device components
* @return The result of the validation.
*/
public static AppraisalStatus validatePlatformCredentialAttributes(
@ -169,7 +174,8 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
final DeviceInfoReport deviceInfoReport,
final EndorsementCredential endorsementCredential,
final ComponentResultRepository componentResultRepository,
final ComponentAttributeRepository componentAttributeRepository) {
final ComponentAttributeRepository componentAttributeRepository,
final List<ComponentInfo> componentInfos) {
final String baseErrorMessage = "Can't validate platform credential attributes without ";
String message;
if (platformCredential == null) {
@ -184,6 +190,10 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
message = baseErrorMessage + "an endorsement credential";
return new AppraisalStatus(FAIL, message);
}
if (componentInfos.isEmpty()) {
message = baseErrorMessage + "a list of device components";
return new AppraisalStatus(FAIL, message);
}
// Quick, early check if the platform credential references the endorsement credential
if (!endorsementCredential.getSerialNumber()
@ -197,7 +207,7 @@ public class CredentialValidator extends SupplyChainCredentialValidator {
if (PlatformCredential.CERTIFICATE_TYPE_2_0.equals(credentialType)) {
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV2p0(
platformCredential, deviceInfoReport, componentResultRepository,
componentAttributeRepository);
componentAttributeRepository, componentInfos);
}
return CertificateAttributeScvValidator.validatePlatformCredentialAttributesV1p2(
platformCredential, deviceInfoReport);

View File

@ -71,11 +71,11 @@ start_mysqlsd () {
echo "mariadb not running , attempting to restart"
systemctl start mariadb >> "$LOG_FILE";
fi
fi # non contanier mysql start
fi # non container mysql start
fi
}
# Basic check for marai db status, attempts restart if not running
# Basic check for maria db status, attempts restart if not running
check_mysql () {
PROCESS="mysqld"
source /etc/os-release
@ -90,7 +90,7 @@ check_mysql () {
chown mysql:mysql /var/log/mariadb/mariadb.log >> "$LOG_FILE";
/usr/bin/mysqld_safe --skip-syslog >> "$LOG_FILE" &
fi
else # not in a contianer
else # not in a container
DB_STATUS=$(systemctl status mysql |grep 'running' | wc -l )
if [ $DB_STATUS -eq 0 ]; then
echo "mariadb not running , attempting to restart"
@ -118,7 +118,7 @@ check_mysql () {
fi
}
# Check for mysql root password , abort if not available
# Check for mysql root password, abort if not available
check_mysql_root () {
if [ -z $HIRS_MYSQL_ROOT_PWD ]; then
if [ ! -f /etc/hirs/aca/aca.properties ]; then
@ -131,7 +131,7 @@ check_mysql_root () {
DB_ADMIN_PWD=$HIRS_MYSQL_ROOT_PWD
fi
# Allow user to enter password if not using env variabel or file
# Allow user to enter password if not using env variable or file
if [ -z $DB_ADMIN_PWD ]; then
read -p "Enter mysql root password" DB_ADMIN_PWD
else
@ -172,7 +172,7 @@ check_db_cleared () {
fi
}
# restart maraidb
# restart mariadb
mysqld_reboot () {
# reboot mysql server
mysql -u root --password=$DB_ADMIN_PWD -e "SHUTDOWN"