mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-02-20 09:46:14 +00:00
Add changes for device deletion.
Changes data structures to facilitate deletion of devices from the DB and all other entries with foreign key relationships.
This commit is contained in:
parent
3c5a657c17
commit
02cb30ad6d
@ -1,6 +1,12 @@
|
||||
package hirs.data.persist;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.persist.CrudManager;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.hibernate.criterion.Conjunction;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
@ -11,10 +17,14 @@ import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A container class to group multiple related {@link SupplyChainValidation} instances
|
||||
@ -26,6 +36,8 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
||||
@JoinColumn(name = "device_id")
|
||||
private final Device device;
|
||||
|
||||
private static final String DEVICE_ID_FIELD = "device.id";
|
||||
|
||||
@Column
|
||||
@Enumerated(EnumType.STRING)
|
||||
private final AppraisalStatus.Status overallValidationResult;
|
||||
@ -43,6 +55,113 @@ public class SupplyChainValidationSummary extends ArchivableEntity {
|
||||
validations = Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* This class enables the retrieval of SupplyChainValidationSummaries by their attributes.
|
||||
*/
|
||||
public static class Selector {
|
||||
private final CrudManager<SupplyChainValidationSummary>
|
||||
supplyChainValidationSummaryCrudManager;
|
||||
|
||||
private final Map<String, Object> fieldValueSelections;
|
||||
|
||||
/**
|
||||
* Construct a new Selector that will use the given {@link CrudManager} to
|
||||
* retrieve SupplyChainValidationSummaries.
|
||||
*
|
||||
* @param supplyChainValidationSummaryCrudManager the summary manager to be used to retrieve
|
||||
* supply chain validation summaries
|
||||
*/
|
||||
public Selector(
|
||||
final CrudManager<SupplyChainValidationSummary>
|
||||
supplyChainValidationSummaryCrudManager) {
|
||||
Preconditions.checkArgument(
|
||||
supplyChainValidationSummaryCrudManager != null,
|
||||
"supply chain validation summary manager cannot be null"
|
||||
);
|
||||
|
||||
this.supplyChainValidationSummaryCrudManager = supplyChainValidationSummaryCrudManager;
|
||||
this.fieldValueSelections = new HashMap<>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct the criterion that can be used to query for supply chain validation summaries
|
||||
* matching the configuration of this Selector.
|
||||
*
|
||||
* @return a Criterion that can be used to query for supply chain validation summaries
|
||||
* matching the configuration of this instance
|
||||
*/
|
||||
public Criterion getCriterion() {
|
||||
Conjunction conj = new Conjunction();
|
||||
|
||||
for (Map.Entry<String, Object> fieldValueEntry : fieldValueSelections.entrySet()) {
|
||||
conj.add(Restrictions.eq(fieldValueEntry.getKey(), fieldValueEntry.getValue()));
|
||||
}
|
||||
|
||||
return conj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a field name and value to match.
|
||||
*
|
||||
* @param name the field name to query
|
||||
* @param value the value to query
|
||||
*/
|
||||
protected void setFieldValue(final String name, final Object value) {
|
||||
Object valueToAssign = value;
|
||||
|
||||
Preconditions.checkArgument(
|
||||
value != null,
|
||||
"field value cannot be null."
|
||||
);
|
||||
|
||||
if (value instanceof String) {
|
||||
Preconditions.checkArgument(
|
||||
StringUtils.isNotEmpty((String) value),
|
||||
"field value cannot be empty."
|
||||
);
|
||||
}
|
||||
|
||||
if (value instanceof byte[]) {
|
||||
byte[] valueBytes = (byte[]) value;
|
||||
|
||||
Preconditions.checkArgument(
|
||||
ArrayUtils.isNotEmpty(valueBytes),
|
||||
"field value cannot be empty."
|
||||
);
|
||||
|
||||
valueToAssign = Arrays.copyOf(valueBytes, valueBytes.length);
|
||||
}
|
||||
|
||||
fieldValueSelections.put(name, valueToAssign);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specify a device id that supply chain validation summaries must have to be considered
|
||||
* as matching.
|
||||
*
|
||||
* @param device the device id to query
|
||||
* @return this instance (for chaining further calls)
|
||||
*/
|
||||
public Selector byDeviceId(final UUID device) {
|
||||
setFieldValue(DEVICE_ID_FIELD, device);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Selector for use in retrieving SupplyChainValidationSummary.
|
||||
*
|
||||
* @param certMan the CrudManager to be used to retrieve persisted supply chain validation
|
||||
* summaries
|
||||
* @return a SupplyChainValidationSummary.Selector instance to use for retrieving certificates
|
||||
*/
|
||||
public static SupplyChainValidationSummary.Selector select(
|
||||
final CrudManager<SupplyChainValidationSummary> certMan) {
|
||||
return new SupplyChainValidationSummary.Selector(certMan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new SupplyChainValidationSummary.
|
||||
*
|
||||
|
@ -21,6 +21,12 @@ public abstract class DeviceAssociatedCertificate extends Certificate {
|
||||
@JoinColumn(name = "device_id")
|
||||
private Device device;
|
||||
|
||||
/**
|
||||
* Holds the name of the entity 'DEVICE_ID' field.
|
||||
*/
|
||||
protected static final String DEVICE_ID_FIELD = "device.id";
|
||||
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
|
@ -7,6 +7,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
@ -40,6 +41,18 @@ public class IssuedAttestationCertificate extends DeviceAssociatedCertificate {
|
||||
public Selector(final CertificateManager certificateManager) {
|
||||
super(certificateManager, IssuedAttestationCertificate.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a device id that certificates must have to be considered
|
||||
* as matching.
|
||||
*
|
||||
* @param device the device id to query
|
||||
* @return this instance (for chaining further calls)
|
||||
*/
|
||||
public Selector byDeviceId(final UUID device) {
|
||||
setFieldValue(DEVICE_ID_FIELD, device);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -274,4 +274,26 @@ public class DBDeviceManager extends DBManager<Device> implements
|
||||
return devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>Device</code> from the database. This removes all
|
||||
* of the database entries that stored information with regards to the
|
||||
* <code>Device</code> with a foreign key relationship.
|
||||
*
|
||||
* @param name of the device to be deleted
|
||||
* @return true if successfully found and deleted, false if otherwise
|
||||
* @throws DeviceGroupManagerException
|
||||
* if unable to find the device group or delete it from the
|
||||
* database
|
||||
*/
|
||||
@Override
|
||||
public final boolean deleteDevice(final String name)
|
||||
throws DeviceManagerException {
|
||||
LOGGER.debug("deleting device: {}", name);
|
||||
try {
|
||||
return super.delete(name);
|
||||
} catch (DBManagerException e) {
|
||||
throw new DeviceManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if an error is encountered while performing the query or creating
|
||||
* the result objects
|
||||
*/
|
||||
protected final List<T> getWithCriteria(final Collection<Criterion> criteriaCollection)
|
||||
public final List<T> getWithCriteria(final Collection<Criterion> criteriaCollection)
|
||||
throws DBManagerException {
|
||||
return retryTemplate.execute(
|
||||
new RetryCallback<List<T>, DBManagerException>() {
|
||||
|
@ -118,4 +118,15 @@ public interface DeviceManager extends OrderedListQuerier<Device> {
|
||||
*/
|
||||
List<Device> getDefaultDevices() throws DeviceManagerException;
|
||||
|
||||
/**
|
||||
* Delete the <code>Device</code> identified by <code>name</code>. If
|
||||
* the deletion is successful, true is returned. Otherwise, false is
|
||||
* returned.
|
||||
*
|
||||
* @param name of the <code>Device</code> to delete
|
||||
* @return boolean indicating outcome of the deletion
|
||||
* @throws DeviceManagerException if unable to delete the device group
|
||||
*/
|
||||
boolean deleteDevice(String name) throws DeviceManagerException;
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,17 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.SpringPersistenceTest;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.data.persist.certificate.CertificateAuthorityCredential;
|
||||
import hirs.data.persist.certificate.CertificateTest;
|
||||
import hirs.data.persist.certificate.ConformanceCredential;
|
||||
import hirs.data.persist.certificate.DeviceAssociatedCertificate;
|
||||
import hirs.data.persist.certificate.EndorsementCredential;
|
||||
import hirs.data.persist.certificate.IssuedAttestationCertificate;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
import hirs.data.persist.certificate.PlatformCredentialTest;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -17,8 +22,6 @@ import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
import hirs.data.persist.certificate.CertificateTest;
|
||||
import hirs.data.persist.certificate.PlatformCredentialTest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
@ -34,6 +37,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static hirs.data.persist.certificate.CertificateTest.ISSUED_CLIENT_CERT;
|
||||
|
||||
/**
|
||||
* This class tests the storage, retrieval, and deletion of {@link Certificate}s.
|
||||
*/
|
||||
@ -75,7 +80,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
*/
|
||||
@BeforeMethod
|
||||
public void setupTestObjects() throws IOException {
|
||||
// create indivdual test certificates
|
||||
// create individual test certificates
|
||||
rootCert = CertificateTest.getTestCertificate(CertificateTest.FAKE_ROOT_CA_FILE);
|
||||
intelIntermediateCert = CertificateTest.getTestCertificate(
|
||||
CertificateTest.FAKE_INTEL_INT_CA_FILE
|
||||
@ -91,6 +96,9 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
CertificateTest.ANOTHER_SELF_SIGNED_FILE
|
||||
);
|
||||
|
||||
hirsClientCert = CertificateTest.getTestCertificate(IssuedAttestationCertificate.class,
|
||||
ISSUED_CLIENT_CERT);
|
||||
|
||||
stmEkCert = CertificateTest.getTestCertificate(EndorsementCredential.class,
|
||||
CertificateTest.STM_NUC1_EC);
|
||||
|
||||
@ -137,7 +145,7 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
IssuedAttestationCertificate issuedCert =
|
||||
(IssuedAttestationCertificate)
|
||||
CertificateTest.getTestCertificate(IssuedAttestationCertificate.class,
|
||||
CertificateTest.ISSUED_CLIENT_CERT, endorsementCredential, platformCredentials);
|
||||
ISSUED_CLIENT_CERT, endorsementCredential, platformCredentials);
|
||||
|
||||
testCertificates.put(IssuedAttestationCertificate.class, issuedCert);
|
||||
}
|
||||
@ -381,6 +389,34 @@ public class DBCertificateManagerTest extends SpringPersistenceTest {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a Certificate can be retrieved by its deviceId.
|
||||
* @throws IOException if there is a problem creating the certificate
|
||||
* @throws CertificateException if there is a problem deserializing the original X509Certificate
|
||||
*/
|
||||
@Test
|
||||
public void testGetByDeviceId() throws IOException, CertificateException {
|
||||
CertificateManager certMan = new DBCertificateManager(sessionFactory);
|
||||
DeviceManager deviceManager = new DBDeviceManager(sessionFactory);
|
||||
DeviceGroupManager deviceGroupManager = new DBDeviceGroupManager(sessionFactory);
|
||||
|
||||
Device device = new Device("test_device");
|
||||
DeviceGroup dg = new DeviceGroup("Default");
|
||||
DeviceGroup savedDg = deviceGroupManager.saveDeviceGroup(dg);
|
||||
device.setDeviceGroup(savedDg);
|
||||
Device savedDevice = deviceManager.saveDevice(device);
|
||||
((DeviceAssociatedCertificate) hirsClientCert).setDevice(savedDevice);
|
||||
Certificate savedCert = certMan.save(hirsClientCert);
|
||||
|
||||
Set<IssuedAttestationCertificate> retrievedCerts =
|
||||
IssuedAttestationCertificate.select(certMan).byDeviceId(savedDevice.getId()).
|
||||
getCertificates();
|
||||
Assert.assertEquals(retrievedCerts.size(), 1);
|
||||
for (IssuedAttestationCertificate cert: retrievedCerts) {
|
||||
Assert.assertEquals(savedCert.getId(), cert.getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that a single Certificate can be retrieved amongst many stored Certificates according
|
||||
* to its type and subject.
|
||||
|
@ -149,6 +149,35 @@ public final class DBDeviceManagerTest extends SpringPersistenceTest {
|
||||
Assert.fail("save did not fail");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when a <code>Device</code> is deleted, the
|
||||
* <code>Device</code> is removed from the DB.
|
||||
*
|
||||
* @throws Exception if error occurs while creating test device
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteDevice() throws Exception {
|
||||
LOGGER.debug("testDeleteDevice");
|
||||
Assert.assertEquals(DBUtility.getCount(sessionFactory, Device.class), 0);
|
||||
|
||||
final Device device = new Device(deviceName);
|
||||
final DeviceManager mgr = new DBDeviceManager(sessionFactory);
|
||||
final DeviceGroup group = createGroup(DeviceGroup.DEFAULT_GROUP);
|
||||
device.setDeviceGroup(group);
|
||||
final Device savedDevice = mgr.saveDevice(device);
|
||||
|
||||
Assert.assertEquals(DBUtility.getCount(sessionFactory, Device.class), 1);
|
||||
Assert.assertTrue(DBUtility.isInDatabase(sessionFactory, Device.class, deviceName));
|
||||
|
||||
final UUID deviceID = savedDevice.getId();
|
||||
Assert.assertNotNull(deviceID);
|
||||
boolean deleteSuccessful = mgr.deleteDevice(deviceName);
|
||||
Assert.assertTrue(deleteSuccessful);
|
||||
Assert.assertFalse(
|
||||
DBUtility.isInDatabase(sessionFactory, DeviceGroup.class, deviceName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the <code>DBDeviceManager</code> can update a
|
||||
* <code>Device</code>.
|
||||
|
Loading…
x
Reference in New Issue
Block a user