Initial changes to redo the component comparision part of the validation

This commit is contained in:
Cyrus 2024-02-22 15:37:13 -05:00
parent a0fbb4dbbb
commit 8441639788
9 changed files with 109 additions and 96 deletions

View File

@ -1,6 +1,7 @@
package hirs.attestationca.persist;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.ComponentInfoRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.manager.DeviceRepository;
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
@ -52,6 +53,7 @@ public abstract class AttestationCertificateAuthority {
private Integer validDays = 1;
private final ComponentResultRepository componentResultRepository;
private ComponentInfoRepository componentInfoRepository;
private final CertificateRepository certificateRepository;
private final IssuedCertificateRepository issuedCertificateRepository;
private final ReferenceManifestRepository referenceManifestRepository;
@ -71,6 +73,7 @@ public abstract class AttestationCertificateAuthority {
* @param acaCertificate the ACA certificate
* @param structConverter the struct converter
* @param componentResultRepository the component result manager
* @param componentInfoRepository the component info manager
* @param certificateRepository the certificate manager
* @param referenceManifestRepository the Reference Manifest manager
* @param validDays the number of days issued certs are valid
@ -85,6 +88,7 @@ public abstract class AttestationCertificateAuthority {
final PrivateKey privateKey, final X509Certificate acaCertificate,
final StructConverter structConverter,
final ComponentResultRepository componentResultRepository,
final ComponentInfoRepository componentInfoRepository,
final CertificateRepository certificateRepository,
final IssuedCertificateRepository issuedCertificateRepository,
final ReferenceManifestRepository referenceManifestRepository,
@ -98,6 +102,7 @@ public abstract class AttestationCertificateAuthority {
this.acaCertificate = acaCertificate;
this.structConverter = structConverter;
this.componentResultRepository = componentResultRepository;
this.componentInfoRepository = componentInfoRepository;
this.certificateRepository = certificateRepository;
this.issuedCertificateRepository = issuedCertificateRepository;
this.referenceManifestRepository = referenceManifestRepository;
@ -111,8 +116,8 @@ public abstract class AttestationCertificateAuthority {
certificateRepository, deviceRepository,
privateKey, acaCertificate, validDays, tpm2ProvisionerStateRepository);
this.identityClaimHandler = new IdentityClaimProcessor(supplyChainValidationService,
certificateRepository, componentResultRepository, referenceManifestRepository,
referenceDigestValueRepository,
certificateRepository, componentResultRepository, componentInfoRepository,
referenceManifestRepository, referenceDigestValueRepository,
deviceRepository, tpm2ProvisionerStateRepository, policyRepository);
}

View File

@ -1,6 +1,7 @@
package hirs.attestationca.persist;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.ComponentInfoRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.manager.DeviceRepository;
import hirs.attestationca.persist.entity.manager.IssuedCertificateRepository;
@ -10,7 +11,6 @@ import hirs.attestationca.persist.entity.manager.ReferenceManifestRepository;
import hirs.attestationca.persist.entity.manager.TPM2ProvisionerStateRepository;
import hirs.attestationca.persist.service.SupplyChainValidationService;
import hirs.structs.converters.StructConverter;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
@ -63,6 +63,7 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
final PrivateKey privateKey, final X509Certificate acaCertificate,
final StructConverter structConverter,
final ComponentResultRepository componentResultRepository,
final ComponentInfoRepository componentInfoRepository,
final CertificateRepository certificateRepository,
final IssuedCertificateRepository issuedCertificateRepository,
final ReferenceManifestRepository referenceManifestRepository,
@ -72,7 +73,8 @@ public class RestfulAttestationCertificateAuthority extends AttestationCertifica
final PolicyRepository policyRepository,
final TPM2ProvisionerStateRepository tpm2ProvisionerStateRepository) {
super(supplyChainValidationService, privateKey, acaCertificate, structConverter,
componentResultRepository, certificateRepository, issuedCertificateRepository,
componentResultRepository, componentInfoRepository,
certificateRepository, issuedCertificateRepository,
referenceManifestRepository,
validDays, deviceRepository,
referenceDigestValueRepository, policyRepository, tpm2ProvisionerStateRepository);

View File

@ -0,0 +1,11 @@
package hirs.attestationca.persist.entity.manager;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.UUID;
public interface ComponentInfoRepository extends JpaRepository<ComponentInfo, UUID> {
List<ComponentInfo> findByDeviceName(String deviceName);
}

View File

@ -1,6 +1,5 @@
package hirs.attestationca.persist.entity.userdefined.certificate.attributes;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@ -130,7 +129,7 @@ public class ComponentIdentifier {
public ComponentIdentifier(final ASN1Sequence sequence) throws IllegalArgumentException {
// set all optional values to default in case they aren't set.
this();
//Check if it have a valid number of identifiers
//Check if it has a valid number of identifiers
if (sequence.size() < MANDATORY_ELEMENTS) {
throw new IllegalArgumentException("Component identifier do not have required values.");
}

View File

@ -1,36 +1,35 @@
package hirs.attestationca.persist.entity.userdefined.info;
import hirs.attestationca.persist.entity.ArchivableEntity;
import hirs.attestationca.persist.entity.userdefined.certificate.attributes.ComponentIdentifier;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.DiscriminatorType;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.xml.bind.annotation.XmlElement;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
/**
* ComponentInfo is a class to hold Hardware component information
* such as manufacturer, model, serial number and version.
*/
@Log4j2
@NoArgsConstructor
@Data
@Entity
@Getter
@DiscriminatorColumn(name = "componentTypeEnum", discriminatorType = DiscriminatorType.STRING)
public class ComponentInfo implements Serializable {
public class ComponentInfo extends ArchivableEntity {
@Id
@Column(name = "componentInfo_id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
// @Id
// @Column(name = "componentInfo_id")
// @GeneratedValue(strategy = GenerationType.AUTO)
// private Long id;
@Column(nullable = false)
private String deviceName;
@XmlElement
@Column(nullable = false)
private String componentManufacturer;
@ -53,12 +52,14 @@ public class ComponentInfo implements Serializable {
/**
* Constructor.
* @param deviceName the host machine associated with this component.
* @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,
public ComponentInfo(final String deviceName,
final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision) {
@ -77,50 +78,32 @@ public class ComponentInfo implements Serializable {
if (componentSerial != null) {
this.componentSerial = componentSerial.trim();
} else {
this.componentSerial = StringUtils.EMPTY;
this.componentSerial = ComponentIdentifier.EMPTY_COMPONENT;
}
if (componentRevision != null) {
this.componentRevision = componentRevision.trim();
} else {
this.componentRevision = StringUtils.EMPTY;
this.componentRevision = ComponentIdentifier.EMPTY_COMPONENT;
}
}
/**
* Constructor.
* @param deviceName the host machine associated with this component.
* @param componentManufacturer Component Manufacturer (must not be null)
* @param componentModel Component Model (must not be null)
* @param componentSerial Component Serial Number (can be null)
* @param componentRevision Component Revision or Version (can be null)
* @param componentClass Component Class (can be null)
*/
public ComponentInfo(final String componentManufacturer,
public ComponentInfo(final String deviceName,
final String componentManufacturer,
final String componentModel,
final String componentSerial,
final String componentRevision,
final String componentClass) {
if (isComplete(
componentManufacturer,
componentModel,
componentSerial,
componentRevision)) {
log.error("ComponentInfo: manufacturer and/or "
+ "model can not be null");
throw new NullPointerException("ComponentInfo: manufacturer and/or "
+ "model can not be null");
}
this.componentManufacturer = componentManufacturer.trim();
this.componentModel = componentModel.trim();
if (componentSerial != null) {
this.componentSerial = componentSerial.trim();
} else {
this.componentSerial = StringUtils.EMPTY;
}
if (componentRevision != null) {
this.componentRevision = componentRevision.trim();
} else {
this.componentRevision = StringUtils.EMPTY;
}
this(deviceName, componentManufacturer, componentModel,
componentSerial, componentRevision);
if (componentClass != null) {
this.componentClass = componentClass;

View File

@ -3,6 +3,7 @@ package hirs.attestationca.persist.provision;
import com.google.protobuf.ByteString;
import hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2;
import hirs.attestationca.persist.entity.manager.CertificateRepository;
import hirs.attestationca.persist.entity.manager.ComponentInfoRepository;
import hirs.attestationca.persist.entity.manager.ComponentResultRepository;
import hirs.attestationca.persist.entity.manager.DeviceRepository;
import hirs.attestationca.persist.entity.manager.PolicyRepository;
@ -19,6 +20,7 @@ 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.certificate.attributes.ComponentIdentifier;
import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import hirs.attestationca.persist.entity.userdefined.info.FirmwareInfo;
import hirs.attestationca.persist.entity.userdefined.info.HardwareInfo;
import hirs.attestationca.persist.entity.userdefined.info.NetworkInfo;
@ -33,6 +35,7 @@ import hirs.attestationca.persist.enums.AppraisalStatus;
import hirs.attestationca.persist.exceptions.IdentityProcessingException;
import hirs.attestationca.persist.provision.helper.ProvisionUtils;
import hirs.attestationca.persist.service.SupplyChainValidationService;
import hirs.attestationca.persist.validation.SupplyChainCredentialValidator;
import hirs.utils.HexUtils;
import hirs.utils.SwidResource;
import hirs.utils.enums.DeviceInfoEnums;
@ -75,6 +78,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
private SupplyChainValidationService supplyChainValidationService;
private CertificateRepository certificateRepository;
private ComponentResultRepository componentResultRepository;
private ComponentInfoRepository componentInfoRepository;
private ReferenceManifestRepository referenceManifestRepository;
private ReferenceDigestValueRepository referenceDigestValueRepository;
private DeviceRepository deviceRepository;
@ -87,6 +91,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
final SupplyChainValidationService supplyChainValidationService,
final CertificateRepository certificateRepository,
final ComponentResultRepository componentResultRepository,
final ComponentInfoRepository componentInfoRepository,
final ReferenceManifestRepository referenceManifestRepository,
final ReferenceDigestValueRepository referenceDigestValueRepository,
final DeviceRepository deviceRepository,
@ -95,6 +100,7 @@ public class IdentityClaimProcessor extends AbstractProcessor {
this.supplyChainValidationService = supplyChainValidationService;
this.certificateRepository = certificateRepository;
this.componentResultRepository = componentResultRepository;
this.componentInfoRepository = componentInfoRepository;
this.referenceManifestRepository = referenceManifestRepository;
this.referenceDigestValueRepository = referenceDigestValueRepository;
this.deviceRepository = deviceRepository;
@ -194,7 +200,9 @@ public class IdentityClaimProcessor extends AbstractProcessor {
// Parse and save device info
Device device = processDeviceInfo(claim);
device.getDeviceInfo().setPaccorOutputString(claim.getPaccorOutput());
// device.getDeviceInfo().setPaccorOutputString(claim.getPaccorOutput());
handleDeviceComponents(device.getName(),
claim.getPaccorOutput());
// There are situations in which the claim is sent with no PCs
// or a PC from the tpm which will be deprecated
// this is to check what is in the platform object and pull
@ -633,4 +641,20 @@ public class IdentityClaimProcessor extends AbstractProcessor {
}
return componentResults;
}
private int handleDeviceComponents(final String hostName, final String paccorString) {
int deviceComponents = 0 ;
try {
List<ComponentInfo> componentInfos = SupplyChainCredentialValidator
.getComponentInfoFromPaccorOutput(hostName, paccorString);
for (ComponentInfo componentInfo : componentInfos) {
this.componentInfoRepository.save(componentInfo);
}
} catch (IOException e) {
log.warn("Error parsing paccor string");
}
return deviceComponents;
}
}

View File

@ -34,7 +34,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import static hirs.attestationca.persist.enums.AppraisalStatus.Status.ERROR;
@ -88,7 +87,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
List<ComponentIdentifier> origPcComponents
= new LinkedList<>(basePlatformCredential.getComponentIdentifiers());
return validateDeltaAttributesChainV2p0(deltaPlatformCredential.getId(),
return validateDeltaAttributesChainV2p0(
deviceInfoReport, deltaMapping, origPcComponents);
}
@ -287,11 +286,20 @@ 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(paccorOutputString);
= getComponentInfoFromPaccorOutput(deviceInfoReport.getNetworkInfo().getHostname(),
paccorOutputString);
unmatchedComponents = validateV2p0PlatformCredentialComponentsExpectingExactMatch(
validPcComponents, componentInfoList);
fieldValidation &= unmatchedComponents.isEmpty();
@ -342,7 +350,6 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
*/
@SuppressWarnings("methodlength")
static AppraisalStatus validateDeltaAttributesChainV2p0(
final UUID certificateId,
final DeviceInfoReport deviceInfoReport,
final Map<PlatformCredential, SupplyChainValidation> deltaMapping,
final List<ComponentIdentifier> origPcComponents) {
@ -457,7 +464,9 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
String unmatchedComponents;
try {
// compare based on component class
List<ComponentInfo> componentInfoList = getV2PaccorOutput(paccorOutputString);
List<ComponentInfo> componentInfoList = getComponentInfoFromPaccorOutput(
deviceInfoReport.getNetworkInfo().getHostname(),
paccorOutputString);
// this is what I want to rewrite
unmatchedComponents = validateV2PlatformCredentialAttributes(
baseCompList,
@ -740,6 +749,7 @@ public class CertificateAttributeScvValidator extends SupplyChainCredentialValid
log.info("Validating the following Platform Cert components...");
pcComponents.forEach(component -> log.info(component.toString()));
log.info("...against the the following DeviceInfoReport components:");
log.error(allDeviceInfoComponents.size());
allDeviceInfoComponents.forEach(component -> log.info(component.toString()));
Set<ASN1UTF8String> manufacturerSet = new HashSet<>();
pcComponents.forEach(pcComp -> manufacturerSet.add(pcComp.getComponentManufacturer()));

View File

@ -7,7 +7,6 @@ import hirs.attestationca.persist.entity.userdefined.info.ComponentInfo;
import lombok.NoArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.CertException;
import org.bouncycastle.cert.X509AttributeCertificateHolder;
@ -32,7 +31,6 @@ import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@ -275,11 +273,13 @@ public class SupplyChainCredentialValidator {
/**
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
* @param the host machine associated with the component
* @param paccorOutput the output from PACCOR's allcomoponents.sh
* @return a list of ComponentInfo objects built from paccorOutput
* @throws java.io.IOException if something goes wrong parsing the JSON
*/
public static List<ComponentInfo> getComponentInfoFromPaccorOutput(final String paccorOutput)
public static List<ComponentInfo> getComponentInfoFromPaccorOutput(final String hostName,
final String paccorOutput)
throws IOException {
List<ComponentInfo> componentInfoList = new ArrayList<>();
@ -290,54 +290,34 @@ public class SupplyChainCredentialValidator {
= rootNode.findValue("COMPONENTS").elements();
while (jsonComponentNodes.hasNext()) {
JsonNode next = jsonComponentNodes.next();
componentInfoList.add(new ComponentInfo(
getJSONNodeValueAsText(next, "MANUFACTURER"),
getJSONNodeValueAsText(next, "MODEL"),
getJSONNodeValueAsText(next, "SERIAL"),
getJSONNodeValueAsText(next, "REVISION")));
List<JsonNode> compClassNodes = next.findValues("COMPONENTCLASS");
if (compClassNodes.isEmpty()) {
componentInfoList.add(new ComponentInfo(hostName,
getJSONNodeValueAsText(next, "MANUFACTURER"),
getJSONNodeValueAsText(next, "MODEL"),
getJSONNodeValueAsText(next, "SERIAL"),
getJSONNodeValueAsText(next, "REVISION")));
} else {
// version 2
String componentClass = StringUtils.EMPTY;
for (JsonNode subNode : compClassNodes) {
componentClass = getJSONNodeValueAsText(subNode,
"COMPONENTCLASSVALUE");
}
componentInfoList.add(new ComponentInfo(hostName,
getJSONNodeValueAsText(next, "MANUFACTURER"),
getJSONNodeValueAsText(next, "MODEL"),
getJSONNodeValueAsText(next, "SERIAL"),
getJSONNodeValueAsText(next, "REVISION"),
componentClass));
}
}
}
return componentInfoList;
}
/**
* Parses the output from PACCOR's allcomponents.sh script into ComponentInfo objects.
* @param paccorOutput the output from PACCOR's allcomoponents.sh
* @return a list of ComponentInfo objects built from paccorOutput
* @throws IOException if something goes wrong parsing the JSON
*/
public static List<ComponentInfo> getV2PaccorOutput(
final String paccorOutput) throws IOException {
List<ComponentInfo> ciList = new LinkedList<>();
String manufacturer, model, serial, revision;
String componentClass = Strings.EMPTY;
if (StringUtils.isNotEmpty(paccorOutput)) {
ObjectMapper objectMapper = new ObjectMapper(new JsonFactory());
JsonNode rootNode = objectMapper.readTree(paccorOutput);
Iterator<JsonNode> jsonComponentNodes
= rootNode.findValue("COMPONENTS").elements();
while (jsonComponentNodes.hasNext()) {
JsonNode next = jsonComponentNodes.next();
manufacturer = getJSONNodeValueAsText(next, "MANUFACTURER");
model = getJSONNodeValueAsText(next, "MODEL");
serial = getJSONNodeValueAsText(next, "SERIAL");
revision = getJSONNodeValueAsText(next, "REVISION");
List<JsonNode> compClassNodes = next.findValues("COMPONENTCLASS");
for (JsonNode subNode : compClassNodes) {
componentClass = getJSONNodeValueAsText(subNode,
"COMPONENTCLASSVALUE");
}
ciList.add(new ComponentInfo(manufacturer, model,
serial, revision, componentClass));
}
}
return ciList;
}
private static String getJSONNodeValueAsText(final JsonNode node, final String fieldName) {
if (node.hasNonNull(fieldName)) {
return node.findValue(fieldName).textValue();

View File

@ -366,7 +366,6 @@ public final class CertificateStringMapBuilder {
data.put("componentResults", PciIds.translateResults(componentResultRepository
.findByBoardSerialNumber(certificate.getPlatformSerial())));
//Get platform Configuration values and set map with it
PlatformConfiguration platformConfiguration = certificate.getPlatformConfiguration();
if (platformConfiguration != null) {