mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-01-18 18:56:29 +00:00
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:
parent
e8f6064d60
commit
3f72fc5d15
@ -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(
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -52,6 +52,7 @@ public class ComponentClass {
|
||||
private String category, categoryStr;
|
||||
@Getter
|
||||
private String component, componentStr;
|
||||
@Getter
|
||||
private String registryType;
|
||||
@Getter
|
||||
private String componentIdentifier;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
@ -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()));
|
||||
|
@ -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,
|
||||
|
@ -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()));
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user