diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java index 3eb4b54d..c1b898db 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/AttestationCertificateAuthority.java @@ -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( diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/ComponentInfoRepository.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/ComponentInfoRepository.java index c4918212..375fef32 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/ComponentInfoRepository.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/manager/ComponentInfoRepository.java @@ -8,4 +8,5 @@ import java.util.UUID; public interface ComponentInfoRepository extends JpaRepository { List findByDeviceName(String deviceName); + List findByDeviceNameAndComponentSerial(String deviceName, String componentSerial); } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/ComponentResult.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/ComponentResult.java index eee59c77..f38500e8 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/ComponentResult.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/ComponentResult.java @@ -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); } } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentAttributeResult.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentAttributeResult.java index 7f369c1d..d89b7464 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentAttributeResult.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentAttributeResult.java @@ -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; diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentClass.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentClass.java index bef65e2d..a12f73c5 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentClass.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/certificate/attributes/ComponentClass.java @@ -52,6 +52,7 @@ public class ComponentClass { private String category, categoryStr; @Getter private String component, componentStr; + @Getter private String registryType; @Getter private String componentIdentifier; diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/info/ComponentInfo.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/info/ComponentInfo.java index f278aaa8..3e2617eb 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/info/ComponentInfo.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/info/ComponentInfo.java @@ -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); + } } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/report/DeviceInfoReport.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/report/DeviceInfoReport.java index a3af9efa..7088912a 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/report/DeviceInfoReport.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/entity/userdefined/report/DeviceInfoReport.java @@ -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 DeviceInfoReport. The * information cannot be changed after the DeviceInfoReport is diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java index 9bab5e1e..5a305d97 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/AbstractProcessor.java @@ -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 diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java index f3c59ad1..793187f9 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/CertificateRequestProcessor.java @@ -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 platformCredentials = parsePcsFromIdentityClaim(claim, diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/IdentityClaimProcessor.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/IdentityClaimProcessor.java index f7f6df99..3302e349 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/IdentityClaimProcessor.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/IdentityClaimProcessor.java @@ -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 componentInfoMap = new HashMap<>(); try { List componentInfos = SupplyChainCredentialValidator .getComponentInfoFromPaccorOutput(hostName, paccorString); + // check the DB for like component infos + List 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"); } diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/CredentialManagementHelper.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/CredentialManagementHelper.java index fed1411b..8bb2a7ba 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/CredentialManagementHelper.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/CredentialManagementHelper.java @@ -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; /** diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/IssuedCertificateAttributeHelper.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/IssuedCertificateAttributeHelper.java index 6a375735..f3772c9f 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/IssuedCertificateAttributeHelper.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/provision/helper/IssuedCertificateAttributeHelper.java @@ -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 { diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationService.java index fdb1b2d8..373e02d7 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/SupplyChainValidationService.java @@ -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 pcs, - final Device device) { + final Device device, + final List 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 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())); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationService.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationService.java index 94c88e58..081ff71e 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationService.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/service/ValidationService.java @@ -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 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 componentResults = componentResultRepository - .findByCertificateSerialNumberAndBoardSerialNumber( - pc.getSerialNumber().toString(), pc.getPlatformSerial()); +// List 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, diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/util/PciIds.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/util/PciIds.java index d35ff26b..22d4a79e 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/util/PciIds.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/util/PciIds.java @@ -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())); diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CertificateAttributeScvValidator.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CertificateAttributeScvValidator.java index 3d566ac6..5deba6d2 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CertificateAttributeScvValidator.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CertificateAttributeScvValidator.java @@ -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 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 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 componentResults = componentResultRepository + .findByCertificateSerialNumberAndBoardSerialNumber( + platformCredential.getSerialNumber().toString(), + platformCredential.getPlatformSerial()); + // first create hash map based on hashCode + Map> deviceHashMap = new HashMap<>(); + componentInfos.stream().forEach((componentInfo) -> { + List 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 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> componentDeviceMap = new HashMap<>(); + componentInfos.stream().forEach((componentInfo) -> { + List 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 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 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 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 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 diff --git a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CredentialValidator.java b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CredentialValidator.java index 9d6f940f..95fe8b7a 100644 --- a/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CredentialValidator.java +++ b/HIRS_AttestationCA/src/main/java/hirs/attestationca/persist/validation/CredentialValidator.java @@ -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 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); diff --git a/package/scripts/db/mysql_util.sh b/package/scripts/db/mysql_util.sh index d46dfc43..19c550b9 100755 --- a/package/scripts/db/mysql_util.sh +++ b/package/scripts/db/mysql_util.sh @@ -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"