mirror of
https://github.com/nsacyber/HIRS.git
synced 2025-03-24 21:16:01 +00:00
Removed a lot of files
This commit is contained in:
parent
cbf1b0aaa8
commit
dabd88719f
@ -34,7 +34,6 @@ import hirs.persist.DeviceManager;
|
||||
import hirs.persist.ReferenceDigestManager;
|
||||
import hirs.persist.ReferenceEventManager;
|
||||
import hirs.persist.ReferenceManifestManager;
|
||||
import hirs.persist.TPM2ProvisionerState;
|
||||
import hirs.structs.converters.SimpleStructBuilder;
|
||||
import hirs.structs.converters.StructConverter;
|
||||
import hirs.structs.elements.aca.IdentityRequestEnvelope;
|
||||
|
@ -7,6 +7,11 @@ import hirs.persist.AppraiserManager;
|
||||
import hirs.persist.DeviceGroupManager;
|
||||
import hirs.persist.PolicyManager;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import static hirs.attestationca.AbstractAttestationCertificateAuthority.LOG;
|
||||
|
||||
/**
|
||||
@ -66,4 +71,19 @@ public final class AcaDbInit {
|
||||
|
||||
LOG.info("ACA database initialization complete.");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
File file = new File("/home/tdmatth/Downloads/HP_CND12774J0_pxe.1.swidtag");
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
|
||||
BufferedInputStream bis = new BufferedInputStream(fis);
|
||||
byte[] buffer = new byte[1024];
|
||||
int length = 0;
|
||||
String output = "";
|
||||
while ((length = bis.read(buffer)) != -1) {
|
||||
output += new String(buffer, 0, length);
|
||||
}
|
||||
|
||||
System.out.println(output);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import hirs.persist.DeviceManager;
|
||||
import hirs.persist.ReferenceDigestManager;
|
||||
import hirs.persist.ReferenceEventManager;
|
||||
import hirs.persist.ReferenceManifestManager;
|
||||
import hirs.persist.TPM2ProvisionerState;
|
||||
import hirs.structs.converters.StructConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
@ -1,151 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import hirs.alert.resolve.AddToIMABaselineAlertResolver;
|
||||
import hirs.alert.resolve.AddToTPMBaselineAlertResolver;
|
||||
import hirs.alert.resolve.AlertResolver;
|
||||
import hirs.alert.resolve.IgnoreAlertResolver;
|
||||
import hirs.alert.resolve.RemoveFromIMABaselineAlertResolver;
|
||||
import hirs.alert.resolve.RemoveFromTPMBaselineAlertResolver;
|
||||
import hirs.alert.resolve.RequestNewReportAlertResolver;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.data.persist.baseline.SimpleImaBaseline;
|
||||
import hirs.data.persist.baseline.TpmWhiteListBaseline;
|
||||
|
||||
/**
|
||||
* Specifies actions that can be taken to resolve an Alert.
|
||||
*/
|
||||
public enum AlertResolutionAction {
|
||||
|
||||
/**
|
||||
* Take no action.
|
||||
*/
|
||||
NONE("No action taken"),
|
||||
/**
|
||||
* Ignore the given alert or alerts.
|
||||
*/
|
||||
IGNORE("Ignored Once", IgnoreAlertResolver.class),
|
||||
/**
|
||||
* Add the referenced IMA record to a baseline.
|
||||
*/
|
||||
ADD_TO_IMA_BASELINE("Added to IMA Baseline", AddToIMABaselineAlertResolver.class,
|
||||
SimpleImaBaseline.class),
|
||||
/**
|
||||
* Remove the referenced IMA record from any baselines it can be found in.
|
||||
*/
|
||||
REMOVE_FROM_IMA_BASELINE("Removed from IMA Baseline", RemoveFromIMABaselineAlertResolver.class,
|
||||
SimpleImaBaseline.class),
|
||||
/**
|
||||
* Add the referenced TPM record to a baseline.
|
||||
*/
|
||||
ADD_TO_TPM_BASELINE("Added to TPM baseline", AddToTPMBaselineAlertResolver.class,
|
||||
TpmWhiteListBaseline.class),
|
||||
/**
|
||||
* Remove the referenced TPM record from any baselines it can be found in.
|
||||
*/
|
||||
REMOVE_FROM_TPM_BASELINE("Removed from TPM Baseline", RemoveFromTPMBaselineAlertResolver.class,
|
||||
TpmWhiteListBaseline.class),
|
||||
/**
|
||||
* Request a new report.
|
||||
*/
|
||||
REQUEST_NEW_REPORT("Requested new report.", RequestNewReportAlertResolver.class);
|
||||
|
||||
private final String defaultReason;
|
||||
private final Class<? extends AlertResolver> alertResolver;
|
||||
private final Class<? extends Baseline> baselineType;
|
||||
|
||||
/**
|
||||
* Construct a new AlertResolutionAction with a reason the alert has been resolved, the class
|
||||
* that can perform the resolution, and the class of baseline operated on by this resolution.
|
||||
*
|
||||
* @param defaultReason the reason an alert can be considered resolved as a result of this
|
||||
* action
|
||||
* @param alertResolver the class that will perform the resolution action
|
||||
* @param baselineType the type of baseline operated on by this resolution action
|
||||
*/
|
||||
AlertResolutionAction(final String defaultReason,
|
||||
final Class<? extends AlertResolver> alertResolver,
|
||||
final Class<? extends Baseline> baselineType) {
|
||||
this.defaultReason = defaultReason;
|
||||
this.alertResolver = alertResolver;
|
||||
this.baselineType = baselineType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new AlertResolutionAction with a reason the alert has been resolved and the class
|
||||
* that can perform the resolution.
|
||||
*
|
||||
* @param defaultReason the reason an alert can be considered resolved as a result of this
|
||||
* action
|
||||
* @param alertResolver the class that will perform the resolution action
|
||||
*/
|
||||
AlertResolutionAction(final String defaultReason,
|
||||
final Class<? extends AlertResolver> alertResolver) {
|
||||
this.defaultReason = defaultReason;
|
||||
this.baselineType = null;
|
||||
this.alertResolver = alertResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new AlertResolutionAction with a reason the alert has been resolved.
|
||||
*
|
||||
* @param defaultReason the reason an alert can be considered resolved as a result of this
|
||||
* action
|
||||
*/
|
||||
AlertResolutionAction(final String defaultReason) {
|
||||
this.defaultReason = defaultReason;
|
||||
this.baselineType = null;
|
||||
this.alertResolver = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string containing a generic reason for the resolution if not provided by the user.
|
||||
*
|
||||
* @return string containing a generic reason for the resolution
|
||||
*/
|
||||
public String getDefaultReason() {
|
||||
return defaultReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the AlertResolver class for the action.
|
||||
*
|
||||
* @return the AlertResolver class for the action
|
||||
*/
|
||||
public Class<? extends AlertResolver> getAlertResolver() {
|
||||
return alertResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the appropriate {@link Baseline} class for the action or null if the action does not
|
||||
* involve a baseline.
|
||||
*
|
||||
* @return the appropriate {@link Baseline} class for the action
|
||||
*/
|
||||
public Class<? extends Baseline> getBaselineType() {
|
||||
return baselineType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the resolution modifies a Baseline.
|
||||
*
|
||||
* @return true if the resolution modifies a Baseline
|
||||
*/
|
||||
public boolean isBaselineResolution() {
|
||||
return baselineType != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the resolution can resolve the specified Baseline.
|
||||
*
|
||||
* @param baseline the Baseline to test
|
||||
* @return true if the resolution can resolve the specified Baseline.
|
||||
*/
|
||||
public boolean canResolve(final Baseline baseline) {
|
||||
if (baseline == null || baselineType == null) {
|
||||
return false;
|
||||
} else {
|
||||
return baselineType.isAssignableFrom(baseline.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A serializable response for a possible alert resolution option.
|
||||
*/
|
||||
@SuppressFBWarnings("URF_UNREAD_FIELD")
|
||||
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
|
||||
public class AlertResolutionOption {
|
||||
|
||||
// the operation that will be attempted if this option is executed
|
||||
private final AlertResolutionAction action;
|
||||
|
||||
// why the chosen option is provided
|
||||
private final String reason;
|
||||
|
||||
// the names of the baselines that can be affected by this option
|
||||
private List<String> whitelistNames;
|
||||
private List<String> requiredSetNames;
|
||||
private List<String> ignoreSetNames;
|
||||
private List<String> tpmBaselineNames;
|
||||
|
||||
/**
|
||||
* Create a new <code>AlertResolutionOption</code>.
|
||||
*
|
||||
* @param action to take if this option is chosen
|
||||
* @param reason why the chosen option is provided
|
||||
*/
|
||||
public AlertResolutionOption(final AlertResolutionAction action, final String reason) {
|
||||
this.action = action;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the names of whitelists that can be edited by choosing this option.
|
||||
*
|
||||
* @param whitelistNames that can be edited
|
||||
*/
|
||||
public void setWhitelistNames(final List<String> whitelistNames) {
|
||||
this.whitelistNames = whitelistNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the names of required sets that can be edited by choosing this option.
|
||||
*
|
||||
* @param requiredSetNames that can be edited
|
||||
*/
|
||||
public void setRequiredSetNames(final List<String> requiredSetNames) {
|
||||
this.requiredSetNames = requiredSetNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the names of ignore sets that can be edited by choosing this option.
|
||||
*
|
||||
* @param ignoreSetNames that can be edited
|
||||
*/
|
||||
public void setIgnoreSetNames(final List<String> ignoreSetNames) {
|
||||
this.ignoreSetNames = ignoreSetNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the names of TPM baselines that can be edited by choosing this option.
|
||||
*
|
||||
* @param tpmBaselineNames that can be edited
|
||||
*/
|
||||
public void setTpmBaselineNames(final List<String> tpmBaselineNames) {
|
||||
this.tpmBaselineNames = tpmBaselineNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified action matches this option's action.
|
||||
*
|
||||
* @param action the action to check
|
||||
* @return true if the specified action matches this option's action
|
||||
*/
|
||||
public boolean hasAction(final AlertResolutionAction action) {
|
||||
return action == this.action;
|
||||
}
|
||||
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Describes a resolution for an alert as specified by a user.
|
||||
*/
|
||||
public class AlertResolutionRequest {
|
||||
|
||||
private final List<Alert> alerts;
|
||||
private final AlertResolutionAction action;
|
||||
private final String baselineName;
|
||||
private final String reason;
|
||||
|
||||
/**
|
||||
* Constructor for AlertResolutionRequest.
|
||||
* @param alerts the alerts being resolved
|
||||
* @param action the action to take for resolving the alerts
|
||||
* @param baselineName the baseline
|
||||
* @param reason the reason for taking the action
|
||||
*/
|
||||
public AlertResolutionRequest(final List<Alert> alerts, final AlertResolutionAction action,
|
||||
final String baselineName, final String reason) {
|
||||
this.alerts = alerts;
|
||||
this.action = action;
|
||||
this.baselineName = baselineName;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an unmodifiable List of the alerts.
|
||||
* @return an unmodifiable List of the alerts
|
||||
*/
|
||||
public List<Alert> getAlerts() {
|
||||
return Collections.unmodifiableList(alerts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the action being taken for the alerts.
|
||||
* @return the action being taken for the alerts
|
||||
*/
|
||||
public AlertResolutionAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the baseline.
|
||||
* @return the name of the baseline
|
||||
*/
|
||||
public String getBaselineName() {
|
||||
return baselineName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reason for taking the action.
|
||||
* @return the reason for taking the action
|
||||
*/
|
||||
public String getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
}
|
@ -1,368 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import hirs.alert.resolve.AlertResolver;
|
||||
import hirs.appraiser.Appraiser;
|
||||
import hirs.appraiser.IMAAppraiser;
|
||||
import hirs.appraiser.TPMAppraiser;
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.alert.resolve.AlertResolverFactory;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.baseline.ImaAcceptableRecordBaseline;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.baseline.ImaIgnoreSetBaseline;
|
||||
import hirs.data.persist.baseline.TPMBaseline;
|
||||
import hirs.data.persist.TPMPolicy;
|
||||
import hirs.data.persist.baseline.TpmWhiteListBaseline;
|
||||
import hirs.data.persist.enums.AlertSource;
|
||||
import hirs.data.persist.enums.AlertType;
|
||||
import hirs.persist.AppraiserManager;
|
||||
import hirs.persist.DeviceManager;
|
||||
import hirs.persist.PolicyManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import hirs.persist.AlertManager;
|
||||
import hirs.persist.BaselineManager;
|
||||
import hirs.persist.DeviceHealthManager;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
|
||||
/**
|
||||
* A service to resolve {@link Alert}s that are no longer problematic. Determines the possible
|
||||
* actions that can be taken given a specific set of alerts and takes those actions.
|
||||
*/
|
||||
@Service
|
||||
public class AlertResolutionService {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(AlertResolutionService.class);
|
||||
|
||||
@Autowired
|
||||
private DeviceManager deviceManager;
|
||||
|
||||
@Autowired
|
||||
private AppraiserManager appraiserManager;
|
||||
|
||||
@Autowired
|
||||
private PolicyManager policyManager;
|
||||
|
||||
@Autowired
|
||||
private AlertManager alertManager;
|
||||
|
||||
@Autowired
|
||||
private DeviceHealthManager deviceHealthManager;
|
||||
|
||||
@Autowired
|
||||
private BaselineManager baselineManager;
|
||||
|
||||
@Autowired
|
||||
private ImaBaselineRecordManager imaBaselineRecordManager;
|
||||
|
||||
@Autowired
|
||||
private AlertResolverFactory alertResolverFactory;
|
||||
|
||||
/**
|
||||
* This method will evaluate alerts and provide potentially useful
|
||||
* <code>AlertResolutionOption</code>s for resolution.
|
||||
*
|
||||
* @param alerts alerts to be evaluated for resolution
|
||||
* @return
|
||||
* Returns a list of <code>AlertResolutionOption</code>s based on the source,
|
||||
* type, and associated policy of the given alerts
|
||||
*/
|
||||
public List<AlertResolutionOption> getResolutionOptions(final List<Alert> alerts) {
|
||||
|
||||
// find cases where ignoring is the only option, such as nonexistent devices or groups,
|
||||
// multiple alert sources, or multiple device groups
|
||||
List<AlertResolutionOption> options = getIgnoreOnlyOptions(alerts);
|
||||
if (!options.isEmpty()) {
|
||||
return options;
|
||||
}
|
||||
|
||||
// now the alert sources and the device groups of the referenced devices should all be
|
||||
// the same, so take them from the first alert
|
||||
DeviceGroup deviceGroup = deviceManager.getDevice(alerts.get(0).getDeviceName())
|
||||
.getDeviceGroup();
|
||||
AlertSource source = alerts.get(0).getSource();
|
||||
|
||||
// build a list of resolution options specific to the alert source
|
||||
LOGGER.debug(String.format("source of alerts is %s", source.toString()));
|
||||
switch (source) {
|
||||
case IMA_APPRAISER:
|
||||
return getImaResolutionOptions(alerts, deviceGroup);
|
||||
case TPM_APPRAISER:
|
||||
return getTpmResolutionOptions(alerts, deviceGroup);
|
||||
// only the default options are supported for all other alerts
|
||||
default:
|
||||
return getDefaultOptions(alerts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given alerts support any actions besides ignoring. This will be the case if
|
||||
* one of the following is true:
|
||||
* <ul>
|
||||
* <li>Any of the alerts has a null device or nonexistent device name</li>
|
||||
* <li>Any of the alerts references a device with a null group</li>
|
||||
* <li>Any two alerts have different sources</li>
|
||||
* <li>Any two alerts have different device groups (and thus different policies)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param alerts the list of alerts to check
|
||||
* @return a list with an ignore option or an empty list if there might be more options
|
||||
*/
|
||||
private List<AlertResolutionOption> getIgnoreOnlyOptions(final List<Alert> alerts) {
|
||||
|
||||
List<AlertResolutionOption> options = new ArrayList<>();
|
||||
Device device = null;
|
||||
AlertSource sharedSource = null;
|
||||
AlertSource currentSource = null;
|
||||
DeviceGroup sharedDeviceGroup = null;
|
||||
DeviceGroup currentDeviceGroup = null;
|
||||
|
||||
for (Alert alert : alerts) {
|
||||
|
||||
// the device might be null if the report was malformed
|
||||
device = deviceManager.getDevice(alert.getDeviceName());
|
||||
if (device == null) {
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.IGNORE,
|
||||
"One or more alerts reference a nonexistent device."));
|
||||
return options;
|
||||
}
|
||||
|
||||
// the device group shouldn't be null, but we should check it
|
||||
currentDeviceGroup = device.getDeviceGroup();
|
||||
if (currentDeviceGroup == null) {
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.IGNORE,
|
||||
"One or more alerts reference a device with a nonexistent group."));
|
||||
return options;
|
||||
}
|
||||
|
||||
currentSource = alert.getSource();
|
||||
if (currentSource == null) {
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.IGNORE,
|
||||
"One or more alerts is missing an alert source."));
|
||||
return options;
|
||||
}
|
||||
|
||||
// if this is the first alert in the list
|
||||
if (sharedSource == null && sharedDeviceGroup == null) {
|
||||
sharedSource = currentSource;
|
||||
sharedDeviceGroup = currentDeviceGroup;
|
||||
|
||||
} else {
|
||||
if (!currentSource.equals(sharedSource)) {
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.IGNORE,
|
||||
"Multiple alerts reference different alert sources."));
|
||||
return options;
|
||||
}
|
||||
|
||||
if (!currentDeviceGroup.equals(sharedDeviceGroup)) {
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.IGNORE,
|
||||
"One or more alerts reference devices in different device groups."));
|
||||
return options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// an empty options list means the alert list may be actionable
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine resolution options for alerts with IMA Appraiser as the alert source.
|
||||
* @param alertList - list of alerts that share a source and device group
|
||||
* @return a list of <code>AlertResolutionOption</code>s
|
||||
*/
|
||||
private List<AlertResolutionOption> getImaResolutionOptions(
|
||||
final List<Alert> alertList, final DeviceGroup deviceGroup) {
|
||||
|
||||
boolean canAddToBaseline = true;
|
||||
|
||||
AlertType alertType;
|
||||
for (Alert alert : alertList) {
|
||||
alertType = alert.getType();
|
||||
|
||||
// addToBaseline only helps if each alert would be fixed by adding a record
|
||||
if (!alertType.equals(AlertType.WHITELIST_MISMATCH)
|
||||
&& !alertType.equals(AlertType.REQUIRED_SET_MISMATCH)
|
||||
&& !alertType.equals(AlertType.UNKNOWN_FILE)) {
|
||||
LOGGER.debug("cannot add ima record to baseline to resolve alert because alert is"
|
||||
+ " type {}", alertType);
|
||||
canAddToBaseline = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
List<AlertResolutionOption> options = getDefaultOptions(alertList);
|
||||
|
||||
if (canAddToBaseline) {
|
||||
options.add(getAddToImaBaselineOption(deviceGroup));
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an <code>AlertResolutionOption</code> to add to the IMA baselines associated with the
|
||||
* given device group.
|
||||
*
|
||||
* @param deviceGroup to get IMA baselines from
|
||||
* @return option including the possible baselines to add to
|
||||
*/
|
||||
private AlertResolutionOption getAddToImaBaselineOption(final DeviceGroup deviceGroup) {
|
||||
|
||||
AlertResolutionOption option = new AlertResolutionOption(
|
||||
AlertResolutionAction.ADD_TO_IMA_BASELINE,
|
||||
"One or more alerts could be resolved by adding a record to an IMA baseline.");
|
||||
Appraiser appraiser = appraiserManager.getAppraiser(IMAAppraiser.NAME);
|
||||
IMAPolicy imaPolicy = (IMAPolicy) policyManager.getPolicy(appraiser, deviceGroup);
|
||||
|
||||
List<ImaAcceptableRecordBaseline> whitelists = new ArrayList<>(imaPolicy.getWhitelists());
|
||||
List<ImaAcceptableRecordBaseline> requiredSets =
|
||||
new ArrayList<>(imaPolicy.getRequiredSets());
|
||||
List<ImaIgnoreSetBaseline> ignoreSets = new ArrayList<>(imaPolicy.getIgnoreSets());
|
||||
|
||||
List<String> whitelistNames = new ArrayList<>();
|
||||
for (ImaBaseline whitelist : whitelists) {
|
||||
whitelistNames.add(whitelist.getName());
|
||||
}
|
||||
option.setWhitelistNames(whitelistNames);
|
||||
|
||||
List<String> requiredSetNames = new ArrayList<>();
|
||||
for (ImaBaseline requiredSet : requiredSets) {
|
||||
requiredSetNames.add(requiredSet.getName());
|
||||
}
|
||||
option.setRequiredSetNames(requiredSetNames);
|
||||
|
||||
List<String> ignoreSetNames = new ArrayList<>();
|
||||
for (ImaIgnoreSetBaseline ignoreSet : ignoreSets) {
|
||||
ignoreSetNames.add(ignoreSet.getName());
|
||||
}
|
||||
option.setIgnoreSetNames(ignoreSetNames);
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine resolution options for alerts with TPM Appraiser as the alert source.
|
||||
* @param alertList - list of alerts that share a source and device group
|
||||
* @return a list of <code>AlertResolutionOption</code>s
|
||||
*/
|
||||
private List<AlertResolutionOption> getTpmResolutionOptions(
|
||||
final List<Alert> alertList, final DeviceGroup deviceGroup) {
|
||||
|
||||
boolean canEditBaseline = true;
|
||||
|
||||
// should only attempt to add to the baseline if all the alerts are of
|
||||
// the type WHITE_LIST_PCR_MISMATCH
|
||||
for (Alert alert : alertList) {
|
||||
if (!alert.getType().equals(AlertType.WHITE_LIST_PCR_MISMATCH)) {
|
||||
canEditBaseline = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
List<AlertResolutionOption> options = getDefaultOptions(alertList);
|
||||
|
||||
if (canEditBaseline) {
|
||||
options.add(getAddToTpmBaselineOption(deviceGroup));
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.REMOVE_FROM_TPM_BASELINE,
|
||||
"One or more alerts could be resolved by removing a record from a TPM "
|
||||
+ "baseline."));
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an <code>AlertResolutionOption</code> to add to the TPM baselines associated with the
|
||||
* given device group.
|
||||
*
|
||||
* @param deviceGroup to get TPM baselines from
|
||||
* @return option including the possible baselines to add to
|
||||
*/
|
||||
private AlertResolutionOption getAddToTpmBaselineOption(final DeviceGroup deviceGroup) {
|
||||
|
||||
AlertResolutionOption option = new AlertResolutionOption(
|
||||
AlertResolutionAction.ADD_TO_TPM_BASELINE,
|
||||
"One or more alerts could be resolved by adding a record to a TPM baseline.");
|
||||
|
||||
Appraiser appraiser = appraiserManager.getAppraiser(TPMAppraiser.NAME);
|
||||
TPMPolicy tpmPolicy = (TPMPolicy) policyManager.getPolicy(appraiser, deviceGroup);
|
||||
|
||||
List<TpmWhiteListBaseline> tpmBaselines
|
||||
= new ArrayList<>(tpmPolicy.getTpmWhiteListBaselines());
|
||||
List<String> tpmBaselineNames = new ArrayList<>();
|
||||
for (TPMBaseline baseline : tpmBaselines) {
|
||||
tpmBaselineNames.add(baseline.getName());
|
||||
}
|
||||
option.setTpmBaselineNames(tpmBaselineNames);
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the list of default options.
|
||||
* @return a list of the options available for all alerts
|
||||
*/
|
||||
private List<AlertResolutionOption> getDefaultOptions(final List<Alert> alertList) {
|
||||
List<AlertResolutionOption> options = new ArrayList<>();
|
||||
|
||||
LOGGER.debug("adding default alert resolution options for alert source {}",
|
||||
alertList.get(0).getSource());
|
||||
// ignoring the alert and requesting a new report are always options
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.IGNORE,
|
||||
"Default alert resolution option"));
|
||||
options.add(new AlertResolutionOption(
|
||||
AlertResolutionAction.REQUEST_NEW_REPORT,
|
||||
"Default alert resolution option"));
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks AlertResolutionRequest parameters, then creates and invokes the appropriate
|
||||
* AlertResolver.
|
||||
*
|
||||
* @param request the AlertResolution request defining the action to be taken
|
||||
* @return AlertResolutionResults containing the resolved alerts and errors
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:avoidinlineconditionals")
|
||||
public AlertResolver resolve(final AlertResolutionRequest request) {
|
||||
|
||||
// check alerts
|
||||
final List<Alert> alerts = request.getAlerts();
|
||||
if (alerts == null || alerts.isEmpty()) {
|
||||
return alertResolverFactory.getAnonymous("No alerts were provided.");
|
||||
}
|
||||
|
||||
// check if valid resolution
|
||||
final AlertResolutionAction action = request.getAction();
|
||||
List<AlertResolutionOption> options = getResolutionOptions(request.getAlerts());
|
||||
for (AlertResolutionOption option : options) {
|
||||
if (option.hasAction(action)) {
|
||||
LOGGER.info("Resolving " + alerts.size() + " alert(s) by " + action + "...");
|
||||
return alertResolverFactory.get(request).resolve();
|
||||
}
|
||||
}
|
||||
|
||||
// return error
|
||||
String msg = action + " is not a valid resolution for the specified alert";
|
||||
msg += request.getAlerts().size() == 1 ? "." : "s.";
|
||||
return alertResolverFactory.getAnonymous(msg);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
|
||||
/**
|
||||
* Alert service for sending out alerts. This class is an interface for
|
||||
* components to use to send out <code>Alert</code>s. <code>Appraiser</code>
|
||||
* should use this interface when sending out <code>Alert</code>s when
|
||||
* an appraisal fail.
|
||||
*/
|
||||
public interface AlertService {
|
||||
|
||||
/**
|
||||
* Send out an <code>Alert</code>. This will notify all interested parties
|
||||
* of a new alert.
|
||||
*
|
||||
* @param alert alert
|
||||
*/
|
||||
void alert(Alert alert);
|
||||
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.ReportSummary;
|
||||
import hirs.persist.AlertManager;
|
||||
import hirs.persist.AlertServiceConfigManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The <code> CompositeAlertService</code> enables the forwarding of alerts. Supports alert
|
||||
* forwarding to multiple alert monitoring applications. The CompositeAlertService interacts with
|
||||
* the <code>AlertMonitorManager</code> to support Portal based management of the HIRS alert service
|
||||
* and subscribers (alert Monitors) of the service. Supports managed and 1 unmanaged alert services.
|
||||
* Currently the <code>HibernateAlertService</code> (the database) is the only unmanaged alert
|
||||
* service.
|
||||
*/
|
||||
@Service
|
||||
public class CompositeAlertService implements AlertService {
|
||||
|
||||
private static final Logger LOGGER = getLogger(CompositeAlertService.class);
|
||||
|
||||
@Autowired
|
||||
private AlertServiceConfigManager alertServiceManager;
|
||||
|
||||
@Autowired
|
||||
private List<ManagedAlertService> alertServices;
|
||||
|
||||
@Autowired
|
||||
private AlertManager alertManager;
|
||||
|
||||
/**
|
||||
* Forwarding service for alerts. Forwards the alert to all enabled Alert Service (Managed and
|
||||
* unmanaged).
|
||||
*
|
||||
* @param alert alert to forward
|
||||
*/
|
||||
public final void alert(final Alert alert) {
|
||||
LOGGER.debug("Sending alerts to all Managed Alert Services");
|
||||
|
||||
// persist the alert, must be done prior to using monitors.
|
||||
alertManager.saveAlert(alert);
|
||||
|
||||
// iterate through the managed alert services and alert on each that is enabled
|
||||
for (ManagedAlertService currentService : alertServices) {
|
||||
if (currentService.isEnabled()) {
|
||||
currentService.alert(alert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends out an <code>Alert</code> when at least one alert is found after report processing is
|
||||
* completed. The alert service configuration will determine if the service will send
|
||||
* notification on every alert. This will notify all interested parties of a new alert. This is
|
||||
* intended to be called at the end of the Integrity Report Processing when at least one or more
|
||||
* alerts have been encountered
|
||||
*
|
||||
* @param summary the Summary created for the report
|
||||
*/
|
||||
public final void alertSummary(final ReportSummary summary) {
|
||||
LOGGER.debug("Sending alert summaries to all Managed Alert Services");
|
||||
for (ManagedAlertService currentService : alertServices) {
|
||||
if (currentService.isEnabled()) {
|
||||
currentService.alertSummary(summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.ReportSummary;
|
||||
import hirs.data.persist.alert.AlertMonitor;
|
||||
import hirs.data.persist.alert.AlertServiceConfig;
|
||||
import hirs.data.persist.alert.JsonAlertMonitor;
|
||||
import hirs.persist.AlertServiceConfigManager;
|
||||
import hirs.persist.BaselineManager;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import hirs.persist.PolicyManager;
|
||||
import hirs.persist.PortalInfoManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import hirs.data.persist.enums.AlertSeverity;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Implementation of a JavaScript Object Notation (JSON) Alert Service.
|
||||
* Upon receiving an Alert, the JSON service will wrap the alert data into a JSON object
|
||||
* and forward the object to all JSON alert monitors configured for the service.
|
||||
*/
|
||||
@Service
|
||||
public class JsonAlertService extends ManagedAlertService {
|
||||
/**
|
||||
* Name of the JSON alert service.
|
||||
*/
|
||||
public static final String NAME = "JSON";
|
||||
|
||||
private static final Logger LOGGER = getLogger(JsonAlertService.class);
|
||||
|
||||
/**
|
||||
* DB Manager for Portal information.
|
||||
*/
|
||||
@Autowired
|
||||
private PortalInfoManager portalInfoManager;
|
||||
|
||||
/**
|
||||
* DB Manager for policy information.
|
||||
*/
|
||||
@Autowired
|
||||
private PolicyManager policyManager;
|
||||
|
||||
/**
|
||||
* DB Manager for baseline information.
|
||||
*/
|
||||
@Autowired
|
||||
private BaselineManager baselineManager;
|
||||
|
||||
/**
|
||||
* Creates a new <code>JsonAlertService</code> for testing. The optional config
|
||||
* parameter is a file path to a Hibernate configuration file.
|
||||
*/
|
||||
public JsonAlertService() {
|
||||
super(NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a test alert to the configured JSON Alert Monitor.
|
||||
* Used to ensure the target can receive forwarded alerts.
|
||||
* @param jsonMonitor configured JSON Alert Monitor
|
||||
* @return True if the test alert was sent. Otherwise false.
|
||||
* @throws IOException If there was a problem.
|
||||
*/
|
||||
public boolean sendTest(final JsonAlertMonitor jsonMonitor) throws IOException {
|
||||
HashMap<String, String> items = new HashMap<>();
|
||||
|
||||
String url = portalInfoManager.getPortalUrlBase() + "jsp/alertmonitors.jsp";
|
||||
items.put("url", url);
|
||||
Date datetime = new Date();
|
||||
items.put("timestamp", formatDate(datetime));
|
||||
items.put("hostname", InetAddress.getLocalHost().getHostName());
|
||||
items.put("source", "PORTAL");
|
||||
items.put("type", "Test JSON");
|
||||
items.put("severity", AlertSeverity.INFO.toString());
|
||||
items.put("details", "This is a test alert sent by the HIRS portal.");
|
||||
|
||||
return send(jsonMonitor, buildJson(items));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persist(final AlertServiceConfigManager alertServiceConfigManager) {
|
||||
alertServiceConfigManager.saveAlertServiceConfig(new AlertServiceConfig(NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a JSON alert.
|
||||
*
|
||||
* @param monitor an alert monitor configuration.
|
||||
* @param alert the individual alert to send to the remote monitor
|
||||
*/
|
||||
@Override
|
||||
protected final void sendAlert(final AlertMonitor monitor, final Alert alert) {
|
||||
if (isEnabled()) {
|
||||
try {
|
||||
if (!send((JsonAlertMonitor) monitor, convertAlert(alert))) {
|
||||
LOGGER.error("Alert was not sent to JSON monitor '" + monitor.getName() + ".");
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
LOGGER.error("Could not use properties file: " + ioe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a JSON summary.
|
||||
*
|
||||
* @param monitor an alert monitor configuration.
|
||||
* @param summary a summary of the report with the alert
|
||||
*/
|
||||
@Override
|
||||
protected void sendAlertSummary(final AlertMonitor monitor, final ReportSummary summary) {
|
||||
throw new UnsupportedOperationException("Alert summary functionality not yet implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the alert data into a JSON object.
|
||||
* @param alert Alert to wrap into JSON.
|
||||
* @return String of JSON data.
|
||||
* @throws IOException If there is a problem.
|
||||
*/
|
||||
private String convertAlert(final Alert alert) throws IOException {
|
||||
LOGGER.info("Sending JSON Alert Type = " + alert.getType().toString());
|
||||
HashMap<String, String> items = new HashMap<>();
|
||||
Optional<UUID> firstUUID = alert.getBaselineIds().stream().findFirst();
|
||||
|
||||
// Retrieve the url to the main page of the Portal
|
||||
String url = portalInfoManager.getPortalUrlBase()
|
||||
+ "jsp/alertdetails.jsp?alertID=" + alert.getId();
|
||||
items.put("url", url);
|
||||
items.put("id", alert.getId().toString());
|
||||
items.put("timestamp", formatDate(alert.getCreateTime()));
|
||||
items.put("hostname", alert.getDeviceName());
|
||||
if (alert.getPolicyId() != null) {
|
||||
items.put("policy", policyManager.getPolicy(alert.getPolicyId()).getName());
|
||||
}
|
||||
if (firstUUID.isPresent()) {
|
||||
items.put("baseline",
|
||||
baselineManager.getBaseline(firstUUID.get()).getName());
|
||||
}
|
||||
items.put("source", alert.getSource().toString());
|
||||
items.put("type", alert.getType().toString());
|
||||
items.put("severity", alert.getSeverity().toString());
|
||||
items.put("details", alert.getDetails());
|
||||
|
||||
return buildJson(items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a String of JSON data from the elements provided.
|
||||
* @param items Map<String,String> of elements to convert into a string of JSON data.
|
||||
* The keys of the map will be used as field names, and the values will be the field values.
|
||||
* @return String of JSON data.
|
||||
*/
|
||||
private String buildJson(final Map<String, String> items) throws IOException {
|
||||
return new ObjectMapper().writeValueAsString(items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the transmission of data.
|
||||
* @param jsonMonitor configured JSON Alert Monitor.
|
||||
* @param json String of JSON data.
|
||||
* @return True if the data was sent. Otherwise false.
|
||||
* @throws IOException If there is a problem.
|
||||
*/
|
||||
private boolean send(final JsonAlertMonitor jsonMonitor, final String json) throws IOException {
|
||||
|
||||
// Open the appropriate socket type
|
||||
// Each protocol has a different delivery process
|
||||
if (jsonMonitor.isTCP()) {
|
||||
try (Socket tcp = new Socket(jsonMonitor.getIpAddress(), jsonMonitor.getPort())) {
|
||||
DataOutputStream out = new DataOutputStream(tcp.getOutputStream());
|
||||
out.writeBytes(json);
|
||||
out.flush();
|
||||
return true;
|
||||
}
|
||||
} else if (jsonMonitor.isUDP()) {
|
||||
try (DatagramSocket udp = new DatagramSocket()) {
|
||||
DatagramPacket packet = new DatagramPacket(
|
||||
json.getBytes(StandardCharsets.UTF_8), json.length(),
|
||||
jsonMonitor.getIpAddress(), jsonMonitor.getPort());
|
||||
udp.send(packet);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Date object into a String using the format used on the Portal.
|
||||
* @param datetime Date object
|
||||
* @return date formatted String
|
||||
*/
|
||||
private String formatDate(final Date datetime) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
return sdf.format(datetime);
|
||||
}
|
||||
}
|
@ -1,257 +0,0 @@
|
||||
package hirs.alert;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.ReportSummary;
|
||||
import hirs.data.persist.alert.AlertMonitor;
|
||||
import hirs.data.persist.alert.AlertServiceConfig;
|
||||
import hirs.persist.AlertMonitorManager;
|
||||
import hirs.persist.AlertServiceConfigManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* The ManagedAlertService is an abstract class that enables optional HIRS alert notifications. The
|
||||
* <code>CompositeAlertService</code> will receive the alert notification from a HIRS component
|
||||
* (e.g. IMAAppraiser)and forward the alert to all enabled alert services. Managed Alert Services
|
||||
* enable portal configuration settings to create,delete, and configure settings for remote
|
||||
* consumers of HIRS alerts.
|
||||
*/
|
||||
public abstract class ManagedAlertService implements AlertService {
|
||||
|
||||
private static final Logger LOGGER = getLogger(ManagedAlertService.class);
|
||||
|
||||
/**
|
||||
* DB Manager for Alert Monitors.
|
||||
*/
|
||||
@Autowired
|
||||
private AlertMonitorManager alertMonitorManager;
|
||||
|
||||
/**
|
||||
* DB Manager for Alert Service Configs.
|
||||
*/
|
||||
@Autowired
|
||||
private AlertServiceConfigManager alertServiceManager;
|
||||
|
||||
/**
|
||||
* Alert Service Configuration for this Alert Service.
|
||||
*/
|
||||
private AlertServiceConfig config;
|
||||
|
||||
/**
|
||||
* Alert Monitor List for this Alert Service.
|
||||
*/
|
||||
private List<AlertMonitor> monitors = new ArrayList<>();
|
||||
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Construct a new ManagedAlertService.
|
||||
*
|
||||
* @param name the name of the alert service
|
||||
*/
|
||||
public ManagedAlertService(final String name) {
|
||||
Preconditions.checkNotNull(name, "Name argument cannot be null.");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a new alert service manager.
|
||||
*
|
||||
* @param alertServiceConfigManager the manager to use to persist objects
|
||||
*/
|
||||
public abstract void persist(AlertServiceConfigManager alertServiceConfigManager);
|
||||
|
||||
/**
|
||||
* Returns the type of the Managed Alert Service. type is used by DBManager to retrieve an
|
||||
* object. name should be set by the class that extends ManagedAlertService within its
|
||||
* constructor.
|
||||
*
|
||||
* @return Type of the Managed Alert Service
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single configuration for the alert service.
|
||||
*
|
||||
* @return AlertServiceConfig object
|
||||
*/
|
||||
public AlertServiceConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the configuration of a Managed Alert Service.
|
||||
*
|
||||
* @param newConfig Alert Service Configuration
|
||||
*/
|
||||
public final void updateConfig(final AlertServiceConfig newConfig) {
|
||||
LOGGER.info("Updating Configuration for Alert Service of type {}", newConfig.getType());
|
||||
alertServiceManager.updateAlertServiceConfig(newConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of alert monitors for this AlertService. Only monitors with the
|
||||
* AlertServiceName matching this service will be returned.
|
||||
*
|
||||
* @return A list of ManagedAlertMonitors
|
||||
*/
|
||||
public final List<AlertMonitor> getMonitors() {
|
||||
return Collections.unmodifiableList(monitors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns an Alert monitor.
|
||||
*
|
||||
* @param monitorName name of the Alert Monitor
|
||||
* @return a AlertMonitor or null if not found
|
||||
*/
|
||||
public final AlertMonitor getMonitor(final String monitorName) {
|
||||
LOGGER.debug("Getting Alert Monitor named {}", monitorName);
|
||||
return alertMonitorManager.getAlertMonitor(monitorName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a monitor to the service monitor list. Inserts the name of this alert service to the
|
||||
* monitor object
|
||||
*
|
||||
* @param newMonitor add a monitor to the Alert Services monitor list
|
||||
*/
|
||||
public final void addMonitor(final AlertMonitor newMonitor) {
|
||||
LOGGER.info("Adding Alert Monitor named {}", newMonitor.getName());
|
||||
newMonitor.setAlertServiceType(name);
|
||||
alertMonitorManager.saveAlertMonitor(newMonitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the specified monitor from the alert services monitor list.
|
||||
*
|
||||
* @param monitorToDelete Alert Monitor to remove
|
||||
*/
|
||||
public final void deleteMonitor(final AlertMonitor monitorToDelete) {
|
||||
LOGGER.info("Deleting Alert Monitor named {}", monitorToDelete.getName());
|
||||
alertMonitorManager.deleteAlertMonitor(monitorToDelete.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards an alert to a managed alert service.
|
||||
*
|
||||
* @param alert alert to forward
|
||||
*/
|
||||
@Override
|
||||
public void alert(final Alert alert) {
|
||||
//check if portal updated properties since last time
|
||||
reloadProperties();
|
||||
// Only process alert if this alert service is enabled.
|
||||
if (isEnabled()) {
|
||||
for (AlertMonitor currentMonitor : monitors) {
|
||||
if (currentMonitor.isMonitorEnabled()
|
||||
&& currentMonitor.isIndividualAlertEnabled()) {
|
||||
sendAlert(currentMonitor, alert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the configuration is not null and is enabled; false otherwise.
|
||||
*
|
||||
* @return true if the configuration is not null and is enabled; false otherwise
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return config != null && config.isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends out an <code>Alert</code> when at least one alert is found after report processing is
|
||||
* completed. The alert service configuration will determine if the service will send
|
||||
* notification on every alert. This will notify all interested parties of a new alert.
|
||||
*
|
||||
* @param summary summary ReportSummary
|
||||
*/
|
||||
public void alertSummary(final ReportSummary summary) {
|
||||
List<AlertMonitor> monitorList = alertMonitorManager
|
||||
.getAlertMonitorList(AlertMonitor.class);
|
||||
for (AlertMonitor currentMonitor : monitorList) {
|
||||
if (currentMonitor.isMonitorEnabled()
|
||||
&& currentMonitor.isAlertOnSummaryEnabled()) {
|
||||
sendAlertSummary(currentMonitor, summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an alert to a single alert monitor.
|
||||
*
|
||||
* @param monitor an individual alert monitor to send the alert to
|
||||
* @param alert the individual alert to send to the remote monitor
|
||||
*/
|
||||
protected abstract void sendAlert(AlertMonitor monitor, Alert alert);
|
||||
|
||||
/**
|
||||
* Sends an alert summary to a single alert monitor.
|
||||
*
|
||||
* @param monitor an individual alert monitor to send the alert to
|
||||
* @param summary a summary for for the report
|
||||
*/
|
||||
protected abstract void sendAlertSummary(AlertMonitor monitor, ReportSummary summary);
|
||||
|
||||
/**
|
||||
* Reloads <code>AlertService</code> configuration properties. This is intended to be called
|
||||
* after the HIRS Portal updates a configuration file. This will force the service to update its
|
||||
* properties.
|
||||
*/
|
||||
@PostConstruct
|
||||
public final void reloadProperties() {
|
||||
config = loadConfig();
|
||||
monitors = loadMonitors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of alert monitors for this AlertService. Only monitors with the
|
||||
* AlertServiceName matching this service will be returned.
|
||||
*
|
||||
* @return A list of ManagedAlertMonitors
|
||||
*/
|
||||
private List<AlertMonitor> loadMonitors() {
|
||||
LOGGER.debug("Getting Alert Monitor list");
|
||||
List<AlertMonitor> alertMonitors =
|
||||
alertMonitorManager.getAlertMonitorList(AlertMonitor.class);
|
||||
List<AlertMonitor> filteredMonitors = new ArrayList<>();
|
||||
|
||||
// screen all monitors and make sure they were intended for this alert service
|
||||
for (AlertMonitor monitor : alertMonitors) {
|
||||
if (monitor.getAlertServiceType().equals(getName())) {
|
||||
filteredMonitors.add(monitor);
|
||||
}
|
||||
}
|
||||
return filteredMonitors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a single configuration for the alert service.
|
||||
*
|
||||
* @return AlertServiceConfig object
|
||||
*/
|
||||
private AlertServiceConfig loadConfig() {
|
||||
List<AlertServiceConfig> configurations =
|
||||
alertServiceManager.getAlertServiceConfigList(AlertServiceConfig.class);
|
||||
|
||||
AlertServiceConfig configuration = null;
|
||||
for (AlertServiceConfig conf : configurations) {
|
||||
if (conf.getType().equals(getName())) {
|
||||
configuration = conf;
|
||||
}
|
||||
}
|
||||
return configuration;
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Classes for the alert service.
|
||||
*/
|
||||
package hirs.alert;
|
@ -1,25 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Resolves alerts by adding a record to an IMA Baseline.
|
||||
*/
|
||||
@Component
|
||||
public class AddToIMABaselineAlertResolver extends IMABaselineAlertResolver {
|
||||
|
||||
@Override
|
||||
public boolean resolve(final Alert alert) {
|
||||
IMABaselineRecord record = parseImaRecord(alert, alert.getReceived());
|
||||
if (record == null) {
|
||||
return false;
|
||||
} else {
|
||||
record.setBaselineForRecordManager(imaBaseline);
|
||||
imaBaselineRecordManager.saveRecord(record);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.TPMMeasurementRecord;
|
||||
import java.util.Set;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Resolves alerts by adding a record to a TPM Baseline.
|
||||
*/
|
||||
@Component
|
||||
public class AddToTPMBaselineAlertResolver extends TPMBaselineAlertResolver {
|
||||
|
||||
@Override
|
||||
public boolean resolve(final Alert alert) {
|
||||
Set<TPMMeasurementRecord> records = parseTpmRecords(alert, alert.getReceived());
|
||||
if (records == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (TPMMeasurementRecord record : records) {
|
||||
tpmBaseline.addToBaseline(record);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,261 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.alert.AlertResolutionAction;
|
||||
import hirs.alert.AlertResolutionRequest;
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.persist.AlertManager;
|
||||
import hirs.persist.DeviceHealthManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Abstract class providing common functionality for resolving alerts including parameter checking,
|
||||
* retrieving Alerts, Alert iteration, recording lists of resolved Alerts and error messages
|
||||
* encountered during the Alert resolution process, and ultimately marking Alerts as being
|
||||
* successfully resolved.
|
||||
*/
|
||||
public abstract class AlertResolver {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(BaselineAlertResolver.class);
|
||||
|
||||
/**
|
||||
* Returns an exception's message or its class name if message is null.
|
||||
*
|
||||
* @param ex the exception from which to get the message
|
||||
* @return the exception's message or its class name if message is null
|
||||
*/
|
||||
protected static String getMessage(final Exception ex) {
|
||||
if (StringUtils.isBlank(ex.getMessage())) {
|
||||
return ex.getClass().getSimpleName();
|
||||
} else {
|
||||
return ex.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private AlertManager alertManager;
|
||||
|
||||
@Autowired
|
||||
private DeviceHealthManager deviceHealthManager;
|
||||
|
||||
private AlertResolutionRequest request;
|
||||
private boolean hasExecuted = false;
|
||||
private final List<Alert> resolved = new ArrayList<>();
|
||||
private final List<String> errors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The default or user-specified explanation for the action taken.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:visibilitymodifier")
|
||||
protected String reason;
|
||||
|
||||
/**
|
||||
* Initializes the resolver by setting the resolution request and resetting results, errors, and
|
||||
* state.
|
||||
*
|
||||
* @param request the request specifying the alerts to be resolved and action to be taken.
|
||||
* @return this resolver
|
||||
*/
|
||||
final AlertResolver init(final AlertResolutionRequest request) {
|
||||
this.request = request;
|
||||
hasExecuted = false;
|
||||
resolved.clear();
|
||||
errors.clear();
|
||||
reason = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this resolver's alert resolution request.
|
||||
*
|
||||
* @return this resolver's alert resolution request.
|
||||
*/
|
||||
protected AlertResolutionRequest getRequest() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified alert to the list of resolved alerts.
|
||||
*
|
||||
* @param alert the alert that has been resolved successfully
|
||||
* @return this resolver
|
||||
*/
|
||||
protected final AlertResolver addResolved(final Alert alert) {
|
||||
resolved.add(alert);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of resolved alerts.
|
||||
*
|
||||
* @return the list of resolved alerts.
|
||||
*/
|
||||
public final List<Alert> getResolved() {
|
||||
return Collections.unmodifiableList(resolved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the message to the list of error messages.
|
||||
*
|
||||
* @param error the message to add
|
||||
* @return this resolver
|
||||
*/
|
||||
public final AlertResolver addError(final String error) {
|
||||
errors.add(error);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the exception's message to the list of error messages.
|
||||
*
|
||||
* @param ex the exception to add
|
||||
* @return this resolver
|
||||
*/
|
||||
public final AlertResolver addError(final Exception ex) {
|
||||
errors.add(getMessage(ex));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the error messages in the collection to the list of error messages.
|
||||
*
|
||||
* @param errors the error messages to add
|
||||
* @return this resolver
|
||||
*/
|
||||
public final AlertResolver addErrors(final Collection<String> errors) {
|
||||
this.errors.addAll(errors);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if error messages have been recorded.
|
||||
*
|
||||
* @return true if error messages have been recorded.
|
||||
*/
|
||||
public final boolean hasErrors() {
|
||||
return !errors.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of error messages.
|
||||
*
|
||||
* @return the list of error messages.
|
||||
*/
|
||||
public final List<String> getErrors() {
|
||||
return Collections.unmodifiableList(errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this resolver can perform the specified action.
|
||||
*
|
||||
* @param action the action to check
|
||||
* @return true if this resolver can perform the specified action.
|
||||
*/
|
||||
public final boolean canResolve(final AlertResolutionAction action) {
|
||||
if (action == null || action.getAlertResolver() == null) {
|
||||
return false;
|
||||
} else {
|
||||
return action.getAlertResolver().isAssignableFrom(getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the resolution for the specified alerts. Checks if the resolver's current state is
|
||||
* valid, does nothing if errors have already been encountered, sets the default reason if not
|
||||
* specified by the user, iterates over the specified alerts calling the subclass's
|
||||
* resolve(Alert) method, records the successfully resolved alerts, and updates the health
|
||||
* status for associated devices
|
||||
*
|
||||
* @return this resolver
|
||||
*/
|
||||
public final AlertResolver resolve() {
|
||||
|
||||
// don't execute if errors have already been recorded.
|
||||
if (!hasErrors()) {
|
||||
|
||||
// only run if initialized
|
||||
if (request == null) {
|
||||
throw new IllegalStateException("Resolver has not been initialized.");
|
||||
}
|
||||
|
||||
// only allow to run once
|
||||
if (hasExecuted) {
|
||||
throw new IllegalStateException("Resolver has already been executed.");
|
||||
}
|
||||
hasExecuted = true;
|
||||
|
||||
final AlertResolutionAction action = request.getAction();
|
||||
|
||||
// get reason
|
||||
reason = StringUtils.defaultIfBlank(request.getReason(), action.getDefaultReason());
|
||||
|
||||
// catch unexpected errors
|
||||
try {
|
||||
|
||||
// allow subclasses to execute code before loop
|
||||
if (beforeLoop()) {
|
||||
|
||||
// process each alert
|
||||
if (action != AlertResolutionAction.NONE) {
|
||||
for (final Alert alert : request.getAlerts()) {
|
||||
if (resolve(alert)) {
|
||||
addResolved(alert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allow subclasses to execute code after loop
|
||||
if (afterLoop()) {
|
||||
|
||||
// mark the alerts as resolved
|
||||
alertManager.resolveAlerts(getResolved(), reason);
|
||||
deviceHealthManager.updateHealth(getResolved());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("Error resolving alerts:", ex);
|
||||
addError(ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called for each alert by resolve. Must be implemented by subclasses.
|
||||
*
|
||||
* @param alert the alert to resolve
|
||||
* @return true if the resolution was successful
|
||||
*/
|
||||
public abstract boolean resolve(Alert alert);
|
||||
|
||||
/**
|
||||
* Optional hook to allow subclasses to execute code before the alerts are iterated.
|
||||
*
|
||||
* @return true if successful
|
||||
*/
|
||||
protected boolean beforeLoop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional hook to allow subclasses to execute code after the alerts are iterated.
|
||||
*
|
||||
* @return true if successful
|
||||
*/
|
||||
protected boolean afterLoop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.alert.AlertResolutionAction;
|
||||
import hirs.alert.AlertResolutionRequest;
|
||||
import hirs.data.persist.Alert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Creates the appropriate AlertResolver bean for the specified AlertResolutionRequest.
|
||||
*/
|
||||
@Component
|
||||
public class AlertResolverFactory {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext ac;
|
||||
|
||||
/**
|
||||
* Returns an anonymous AlertResolver that can be used to record and return error messages in
|
||||
* cases where a specific AlertResolver cannot or has not been created.
|
||||
*
|
||||
* @param error the initial error message to record
|
||||
* @return an anonymous AlertResolver
|
||||
*/
|
||||
public final AlertResolver getAnonymous(final String error) {
|
||||
AlertResolver resolver = new AlertResolver() {
|
||||
@Override
|
||||
public boolean resolve(final Alert alert) {
|
||||
throw new UnsupportedOperationException(
|
||||
"This class is used only to report errors.");
|
||||
}
|
||||
};
|
||||
return resolver.addError(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the appropriate AlertResolver bean for the specified AlertResolutionRequest.
|
||||
*
|
||||
* @param request the user-specified AlertResolutionRequest
|
||||
* @return the appropriate AlertResolver bean
|
||||
*/
|
||||
public final AlertResolver get(final AlertResolutionRequest request) {
|
||||
final AlertResolutionAction action = request.getAction();
|
||||
if (action == null) {
|
||||
return getAnonymous("No action was provided.");
|
||||
} else {
|
||||
Class<? extends AlertResolver> resolverClass = action.getAlertResolver();
|
||||
if (resolverClass == null) {
|
||||
return getAnonymous("Action " + action + " does not resolve alerts.");
|
||||
} else {
|
||||
final AlertResolver resolver = ac.getBean(resolverClass);
|
||||
return resolver.init(request);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.alert.AlertResolutionAction;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.persist.BaselineManager;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Abstract class for resolutions that involve the modification of baselines.
|
||||
*/
|
||||
public abstract class BaselineAlertResolver extends AlertResolver {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(AlertResolver.class);
|
||||
|
||||
/**
|
||||
* The baseline manager used to load and save baselines.
|
||||
*/
|
||||
@Autowired
|
||||
@SuppressWarnings("checkstyle:visibilitymodifier")
|
||||
protected BaselineManager baselineManager;
|
||||
|
||||
/**
|
||||
* The baseline to be modified by this resolver.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:visibilitymodifier")
|
||||
protected Baseline baseline;
|
||||
|
||||
/**
|
||||
* Checks the baseline name and loads and checks the baseline or creates a new baseline.
|
||||
*
|
||||
* @return true if successful
|
||||
*/
|
||||
@Override
|
||||
protected boolean beforeLoop() {
|
||||
|
||||
final AlertResolutionAction action = getRequest().getAction();
|
||||
|
||||
// get baseline name
|
||||
final String name = getRequest().getBaselineName();
|
||||
if (StringUtils.isBlank(name)) {
|
||||
addError("No baseline name was specified.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// add baseline name to default reason
|
||||
if (reason != null && reason.equals(action.getDefaultReason())) {
|
||||
reason += " '" + name + "'";
|
||||
}
|
||||
|
||||
// get baseline type
|
||||
final Class<? extends Baseline> type = action.getBaselineType();
|
||||
|
||||
// get or create baseline
|
||||
baseline = baselineManager.getBaseline(name);
|
||||
if (baseline != null) {
|
||||
|
||||
// check type
|
||||
if (!action.canResolve(baseline)) {
|
||||
addError("Baseline '" + name + "' is a "
|
||||
+ baseline.getClass().getSimpleName() + ", but was expected to be a "
|
||||
+ type.getSimpleName() + ".");
|
||||
return false;
|
||||
}
|
||||
|
||||
} else if (action.name().startsWith("ADD_TO")) {
|
||||
|
||||
// create new baseline
|
||||
try {
|
||||
baseline = type.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException ex) {
|
||||
String msg = "Error creating new baseline named '" + name + "'.";
|
||||
LOGGER.error(msg, ex);
|
||||
addError(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
baseline.setName(name);
|
||||
baselineManager.saveBaseline(baseline);
|
||||
|
||||
} else {
|
||||
addError("Could not find baseline named '" + name + "'.");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.baseline.SimpleImaBaseline;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
/**
|
||||
* Abstract class providing common functionality for IMA Baseline alert resolvers.
|
||||
*/
|
||||
public abstract class IMABaselineAlertResolver extends BaselineAlertResolver {
|
||||
|
||||
/**
|
||||
* The IMA baseline record manager used to load and save IMA baseline records.
|
||||
*/
|
||||
@Autowired
|
||||
@SuppressWarnings("checkstyle:visibilitymodifier")
|
||||
protected ImaBaselineRecordManager imaBaselineRecordManager;
|
||||
|
||||
/**
|
||||
* The IMA baseline to be modified by this resolver.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:visibilitymodifier")
|
||||
protected SimpleImaBaseline imaBaseline = null;
|
||||
|
||||
/**
|
||||
* Casts BaselineAlertResolver's baseline to a SimpleImaBaseline.
|
||||
*
|
||||
* @return true to indicate success
|
||||
*/
|
||||
@Override
|
||||
protected boolean beforeLoop() {
|
||||
if (super.beforeLoop()) {
|
||||
imaBaseline = (SimpleImaBaseline) baseline;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the received/expected value of an {@link Alert} into an {@link IMABaselineRecord}.
|
||||
*
|
||||
* @param alert the Alert the record is from
|
||||
* @param record - received/expected record from Alert
|
||||
* @return IMABaselineRecord created from parsing the record String
|
||||
*/
|
||||
protected IMABaselineRecord parseImaRecord(final Alert alert, final String record) {
|
||||
try {
|
||||
return IMABaselineRecord.fromString(record);
|
||||
} catch (Exception ex) {
|
||||
String error = "Error parsing IMA record '" + record + "' for alert ["
|
||||
+ alert.getId() + "]: " + getMessage(ex);
|
||||
addError(error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Ignores alerts by always indicating them as successfully resolved.
|
||||
*/
|
||||
@Component
|
||||
public class IgnoreAlertResolver extends AlertResolver {
|
||||
|
||||
/**
|
||||
* Returns true to indicate that AlertResolver should mark the alert as resolved.
|
||||
*
|
||||
* @param alert the alert to ignore
|
||||
* @return true
|
||||
*/
|
||||
@Override
|
||||
public boolean resolve(final Alert alert) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Resolves alerts by adding a record to an IMA baseline.
|
||||
*/
|
||||
@Component
|
||||
public class RemoveFromIMABaselineAlertResolver extends IMABaselineAlertResolver {
|
||||
|
||||
/**
|
||||
* Resolves alerts by adding a record to an IMA baseline.
|
||||
*
|
||||
* @param alert the alert to resolve
|
||||
* @return true if the alert is successfully resolved
|
||||
*/
|
||||
@Override
|
||||
public boolean resolve(final Alert alert) {
|
||||
|
||||
IMABaselineRecord find = parseImaRecord(alert, alert.getExpected());
|
||||
find.setBaselineForRecordManager(imaBaseline);
|
||||
IMABaselineRecord found = imaBaselineRecordManager.getRecord(
|
||||
find.getPath(), find.getHash(), imaBaseline);
|
||||
|
||||
if (found == null) {
|
||||
addError("Could not find IMA Baseline Record for alert " + "[" + alert.getId() + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!imaBaselineRecordManager.deleteRecord(found)) {
|
||||
addError("Could not delete IMA Baseline Record for alert "
|
||||
+ "[" + alert.getId() + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.TPMMeasurementRecord;
|
||||
import java.util.Set;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Resolves alerts by removing a record from a TPM Baseline.
|
||||
*/
|
||||
@Component
|
||||
public class RemoveFromTPMBaselineAlertResolver extends TPMBaselineAlertResolver {
|
||||
|
||||
/**
|
||||
* Resolves alerts by removing a record from a TPM Baseline.
|
||||
* @param alert the alert to resolve
|
||||
* @return true if the alert was successfully resolved
|
||||
*/
|
||||
@Override
|
||||
public boolean resolve(final Alert alert) {
|
||||
Set<TPMMeasurementRecord> records = parseTpmRecords(alert, alert.getExpected());
|
||||
if (records == null) {
|
||||
return false;
|
||||
} else {
|
||||
for (TPMMeasurementRecord record : records) {
|
||||
tpmBaseline.removeFromBaseline(record);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.IntegrityReport;
|
||||
import hirs.persist.DeviceManager;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Aggregates and deduplicates the devices associated with alerts so that new reports can be
|
||||
* requested for them.
|
||||
*/
|
||||
@Component
|
||||
public class RequestNewReportAlertResolver extends AlertResolver {
|
||||
|
||||
private final Map<String, Device> devices = new HashMap<>();
|
||||
|
||||
@Autowired
|
||||
private DeviceManager deviceManager;
|
||||
|
||||
/**
|
||||
* Aggregates the devices associated with alerts so that new reports can be requested for them.
|
||||
*
|
||||
* @param alert the alert to be resolved
|
||||
* @return true if the device was successfully loaded
|
||||
*/
|
||||
@Override
|
||||
public boolean resolve(final Alert alert) {
|
||||
|
||||
String name = alert.getDeviceName();
|
||||
if (StringUtils.isBlank(name)) {
|
||||
name = ((IntegrityReport) alert.getReport()).getDeviceName();
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
addError("Could not get device name for alert [" + alert.getId() + "]");
|
||||
return false;
|
||||
} else if (!devices.containsKey(name)) {
|
||||
Device device = deviceManager.getDevice(name);
|
||||
if (device == null) {
|
||||
addError("Device '" + name + "' for alert id [" + alert.getId()
|
||||
+ "] was not found");
|
||||
return false;
|
||||
}
|
||||
devices.put(name, device);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of the loaded devices indexed by name.
|
||||
*
|
||||
* @return a map of the loaded devices indexed by name.
|
||||
*/
|
||||
public Map<String, Device> getDevices() {
|
||||
return Collections.unmodifiableMap(devices);
|
||||
}
|
||||
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package hirs.alert.resolve;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.enums.DigestAlgorithm;
|
||||
import hirs.data.persist.baseline.TPMBaseline;
|
||||
import hirs.data.persist.TPMMeasurementRecord;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Abstract class providing common functionality for TPM Baseline alert resolvers.
|
||||
*/
|
||||
public abstract class TPMBaselineAlertResolver extends BaselineAlertResolver {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(TPMBaselineAlertResolver.class);
|
||||
|
||||
/**
|
||||
* The TPM baseline to be modified by this resolver.
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:visibilitymodifier")
|
||||
protected TPMBaseline tpmBaseline = null;
|
||||
|
||||
/**
|
||||
* Casts BaselineAlertResolver's baseline to a TPMBaseline.
|
||||
*
|
||||
* @return true to indicate success
|
||||
*/
|
||||
@Override
|
||||
protected boolean beforeLoop() {
|
||||
if (super.beforeLoop()) {
|
||||
tpmBaseline = (TPMBaseline) baseline;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the baseline.
|
||||
*
|
||||
* @return true if successful
|
||||
*/
|
||||
@Override
|
||||
protected boolean afterLoop() {
|
||||
if (super.afterLoop()) {
|
||||
baselineManager.updateBaseline(baseline);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Regex patterns used to parse expected/received Strings in Alerts into records
|
||||
private static final Pattern TPM_PCR_PATTERN = Pattern.compile(".*#([0-9]{1,2})");
|
||||
private static final Pattern TPM_DIGEST_PATTERN = Pattern.compile("(.*:|or).(([a-f]|[0-9])*)");
|
||||
|
||||
/**
|
||||
* Parses the record of an Alert into a TPMMeasurementRecord.
|
||||
*
|
||||
* @param alert - Alert to be resolved
|
||||
* @param record - record chosen to be parsed
|
||||
* @return TPMMeasurementRecord based on the TPM record and alert information
|
||||
*/
|
||||
protected Set<TPMMeasurementRecord> parseTpmRecords(final Alert alert, final String record) {
|
||||
|
||||
// parse the PCR values out of the Alert details String
|
||||
Integer pcr = null;
|
||||
final Matcher pcrMatcher = TPM_PCR_PATTERN.matcher(alert.getDetails());
|
||||
if (pcrMatcher.find()) {
|
||||
pcr = Integer.parseInt(pcrMatcher.group(1));
|
||||
}
|
||||
|
||||
// creates digest from String
|
||||
Set<Digest> digests = new HashSet<>();
|
||||
final Matcher digestMatcher = TPM_DIGEST_PATTERN.matcher(record);
|
||||
boolean digestError = false;
|
||||
while (digestMatcher.find()) {
|
||||
final String match = digestMatcher.group(2);
|
||||
if (StringUtils.isBlank(match)) {
|
||||
addError("Invalid syntax or digest value in record '" + record + "' for alert ["
|
||||
+ alert.getId() + "].");
|
||||
digestError = true;
|
||||
} else {
|
||||
try {
|
||||
final byte[] digestBytes = Hex.decodeHex(match.toCharArray());
|
||||
final Digest digest = new Digest(DigestAlgorithm.SHA1, digestBytes);
|
||||
digests.add(digest);
|
||||
} catch (DecoderException ex) {
|
||||
final String msg = "Error decoding TPM record digest '" + match + "' in alert ["
|
||||
+ alert.getId() + "]: " + getMessage(ex);
|
||||
addError(msg);
|
||||
digestError = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check for errors
|
||||
if (pcr == null || digests.isEmpty()) {
|
||||
if (pcr == null) {
|
||||
addError("Could not parse PCR from details '" + alert.getDetails() + "' in alert ["
|
||||
+ alert.getId() + "].");
|
||||
}
|
||||
if (digests.isEmpty() && !digestError) {
|
||||
addError("Could not parse digest from record '" + record + "' in alert ["
|
||||
+ alert.getId() + "].");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// create records
|
||||
final Set<TPMMeasurementRecord> measurementRecords = new HashSet<>();
|
||||
for (Digest digest : digests) {
|
||||
measurementRecords.add(new TPMMeasurementRecord(pcr, digest));
|
||||
}
|
||||
return measurementRecords;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Classes for alert resolvers.
|
||||
*/
|
||||
package hirs.alert.resolve;
|
@ -1,489 +0,0 @@
|
||||
package hirs.data.persist;
|
||||
|
||||
import hirs.data.persist.baseline.ImaIgnoreSetBaseline;
|
||||
import hirs.data.persist.baseline.ImaBlacklistBaseline;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.baseline.ImaAcceptableRecordBaseline;
|
||||
import hirs.data.persist.baseline.HasBaselines;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* Represents the criteria by which an <code>IMAAppraiser</code> appraises a
|
||||
* <code>Report</code>. This includes the following:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>A list of <code>ImaBlacklistBaseline</code>s to use a blacklists</li>
|
||||
* <li>A list of <code>ImaIgnoreSetBaseline</code>'s to use as ignore sets</li>
|
||||
* <li>A list of <code>ImaAcceptableRecordBaseline</code>s to use as whitelists</li>
|
||||
* <li>A list of <code>ImaAcceptableRecordBaseline</code>s to use as required sets</li>
|
||||
* <li>A flag to determine determine whether appraisal should fail on unknowns </li>
|
||||
* <li>A flag to determine whether PCR 10 should be used to validate the hash of
|
||||
* the <code>IMAReport</code></li>
|
||||
* <li>A flag to determine whether delta reports should be requested</li>
|
||||
* <li>A flag to determine whether partial path appraisal should be supported</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Entity
|
||||
public class IMAPolicy extends Policy implements HasBaselines {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(IMAPolicy.class);
|
||||
private static final boolean DEFAULT_UNKNOWN_POLICY = false;
|
||||
private static final boolean DEFAULT_PCR_VALIDATION = false;
|
||||
private static final boolean DEFAULT_DELTA_REPORT_POLICY = true;
|
||||
private static final boolean DEFAULT_PARTIAL_PATH_POLICY = true;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "Whitelists",
|
||||
joinColumns = {@JoinColumn(
|
||||
name = "PolicyID", nullable = false) })
|
||||
@OrderColumn(name = "WhitelistsIndex")
|
||||
private final List<ImaAcceptableRecordBaseline> whitelists = new LinkedList<>();
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "RequiredSets",
|
||||
joinColumns = {@JoinColumn(
|
||||
name = "PolicyID", nullable = false) })
|
||||
@OrderColumn(name = "RequiredSetsIndex")
|
||||
private final List<ImaAcceptableRecordBaseline> requiredSets = new LinkedList<>();
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "IgnoreSets",
|
||||
joinColumns = {@JoinColumn(
|
||||
name = "PolicyID", nullable = false) })
|
||||
@OrderColumn(name = "IgnoreSetsIndex")
|
||||
private final List<ImaIgnoreSetBaseline> ignoreSets = new LinkedList<>();
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "ImaBlacklists",
|
||||
joinColumns = {@JoinColumn(
|
||||
name = "PolicyID", nullable = false) })
|
||||
@OrderColumn(name = "ImaBlacklistsIndex")
|
||||
private final List<ImaBlacklistBaseline> blacklists = new LinkedList<>();
|
||||
|
||||
@Column(nullable = false)
|
||||
private boolean failOnUnknowns = DEFAULT_UNKNOWN_POLICY;
|
||||
@Column(nullable = false)
|
||||
private boolean validatePcr = DEFAULT_PCR_VALIDATION;
|
||||
@Column(nullable = false)
|
||||
private boolean deltaReportEnable = DEFAULT_DELTA_REPORT_POLICY;
|
||||
@Column(nullable = false)
|
||||
private boolean partialPathEnable = DEFAULT_PARTIAL_PATH_POLICY;
|
||||
|
||||
@Transient
|
||||
private Multimap<String, String> pathEquivalences = null;
|
||||
|
||||
/**
|
||||
* Constructor used to initialize IMAPolicy object.
|
||||
*
|
||||
* @param name a name used to uniquely identify and reference the IMA policy
|
||||
*/
|
||||
public IMAPolicy(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to initialize IMAPolicy object.
|
||||
*
|
||||
* @param name a name used to uniquely identify and reference the IMA policy
|
||||
* @param description optional description that may be provided by the user
|
||||
*/
|
||||
public IMAPolicy(final String name, final String description) {
|
||||
super(name, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected IMAPolicy() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to remove all whitelists currently contained in
|
||||
* <code>this.whitelists</code> and add the given whitelist. Replaced by
|
||||
* <code>setWhitelists</code>.
|
||||
*
|
||||
* @param imaBaseline baseline that represents the new white list, can be NULL
|
||||
*/
|
||||
public final void setWhitelist(final ImaAcceptableRecordBaseline imaBaseline) {
|
||||
LOGGER.debug("adding ImaBaseline {} as {} policy whitelist",
|
||||
imaBaseline, getName());
|
||||
if (imaBaseline == null) {
|
||||
this.whitelists.clear();
|
||||
} else {
|
||||
this.whitelists.clear();
|
||||
this.whitelists.add(imaBaseline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the current <code>List</code> of whitelists with a new
|
||||
* <code>List</code>. Can be empty but cannot be null. The order of the
|
||||
* <code>List</code> will be the order used for appraisal by the
|
||||
* <code>TPMAppraiser</code>.
|
||||
*
|
||||
* @param newWhitelists list of <code>ImaBaseline</code>s to use as whitelists, can be
|
||||
* empty but not null
|
||||
*/
|
||||
public final void setWhitelists(
|
||||
final List<? extends ImaAcceptableRecordBaseline> newWhitelists
|
||||
) {
|
||||
if (newWhitelists == null) {
|
||||
throw new PolicyException("cannot set whitelists to null");
|
||||
}
|
||||
LOGGER.debug("setting new whitelists for {}", getName());
|
||||
whitelists.clear();
|
||||
whitelists.addAll(newWhitelists);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to return the first whitelist in
|
||||
* <code>this.whitelists</code>. Replaced by <code>getWhitelists</code>.
|
||||
*
|
||||
* @return the baseline representing the first whitelist, can be NULL
|
||||
*/
|
||||
public final ImaAcceptableRecordBaseline getWhitelist() {
|
||||
if (this.whitelists == null || this.whitelists.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return this.whitelists.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current list of whitelists.
|
||||
*
|
||||
* @return the unmodifiable list of whitelists, cannot be null
|
||||
*/
|
||||
public final List<ImaAcceptableRecordBaseline> getWhitelists() {
|
||||
return Collections.unmodifiableList(this.whitelists);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to remove all required sets currently contained in
|
||||
* <code>this.requiredSets</code> and add the given required set. Replaced
|
||||
* by <code>setRequiredSets</code>.
|
||||
*
|
||||
* @param imaBaseline baseline that represents the new required set, can be NULL
|
||||
*/
|
||||
public final void setRequiredSet(final ImaAcceptableRecordBaseline imaBaseline) {
|
||||
LOGGER.debug("adding ImaBaseline {} as {} policy required set",
|
||||
imaBaseline, getName());
|
||||
if (imaBaseline == null) {
|
||||
this.requiredSets.clear();
|
||||
} else {
|
||||
this.requiredSets.clear();
|
||||
this.requiredSets.add(imaBaseline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the current <code>List</code> of required sets with a new
|
||||
* <code>List</code>. Can be empty but cannot be null. The order of the
|
||||
* <code>List</code> will be the order used for appraisal by the
|
||||
* <code>TPMAppraiser</code>.
|
||||
*
|
||||
* @param newRequiredSets list of <code>ImaBaseline</code>s to use as required sets, can
|
||||
* be empty but not null
|
||||
*/
|
||||
public final void setRequiredSets(
|
||||
final List<? extends ImaAcceptableRecordBaseline> newRequiredSets
|
||||
) {
|
||||
if (newRequiredSets == null) {
|
||||
throw new PolicyException("cannot set required sets to null");
|
||||
}
|
||||
LOGGER.debug("setting new required sets for {}", getName());
|
||||
this.requiredSets.clear();
|
||||
for (ImaAcceptableRecordBaseline baseline : newRequiredSets) {
|
||||
this.requiredSets.add(baseline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to return the first required set in
|
||||
* <code>this.requiredSets</code>. Replaced by <code>getrequiredSets</code>.
|
||||
*
|
||||
* @return the baseline representing the first required set, can be NULL
|
||||
*/
|
||||
public final ImaBaseline getRequiredSet() {
|
||||
if (this.requiredSets == null || this.requiredSets.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return this.requiredSets.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current list of required sets.
|
||||
*
|
||||
* @return the unmodifiable list of required sets, cannot be null
|
||||
*/
|
||||
public final List<ImaAcceptableRecordBaseline> getRequiredSets() {
|
||||
return Collections.unmodifiableList(this.requiredSets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to remove all ignore sets currently contained in
|
||||
* <code>this.ignoreSets</code> and add the given ignore set. Replaced
|
||||
* by <code>setIgnoreSets</code>.
|
||||
*
|
||||
* @param imaIgnoreSetBaseline set of optional records that represents the new ignore set,
|
||||
* can be NULL
|
||||
*/
|
||||
public final void setImaIgnoreSetBaseline(final ImaIgnoreSetBaseline
|
||||
imaIgnoreSetBaseline) {
|
||||
LOGGER.debug("adding optionalSetPolicy {} as {} policy ignore set",
|
||||
imaIgnoreSetBaseline, getName());
|
||||
if (imaIgnoreSetBaseline == null) {
|
||||
this.ignoreSets.clear();
|
||||
} else {
|
||||
this.ignoreSets.clear();
|
||||
this.ignoreSets.add(imaIgnoreSetBaseline);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the current <code>List</code> of ignore sets with a new
|
||||
* <code>List</code>. Can be empty but cannot be null. The order of the
|
||||
* <code>List</code> will be the order used for appraisal by the
|
||||
* <code>TPMAppraiser</code>.
|
||||
*
|
||||
* @param newIgnoreSets list of <code>OptionalSetPolicy</code>'s to use as required
|
||||
* sets, can be empty but not null
|
||||
*/
|
||||
public final void setIgnoreSets(final List<? extends ImaIgnoreSetBaseline> newIgnoreSets) {
|
||||
if (newIgnoreSets == null) {
|
||||
throw new PolicyException("cannot set ignore sets to null");
|
||||
}
|
||||
LOGGER.debug("setting new ignore sets for {}", getName());
|
||||
this.ignoreSets.clear();
|
||||
for (ImaIgnoreSetBaseline oSet : newIgnoreSets) {
|
||||
this.ignoreSets.add(oSet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated method to return the first ignore set in
|
||||
* <code>this.ignoreSets</code>. Replaced by <code>getIgnoreSets</code>.
|
||||
*
|
||||
* @return the optional set policy representing the first ignore set, can be
|
||||
* NULL
|
||||
*/
|
||||
public final ImaIgnoreSetBaseline getImaIgnoreSetBaseline() {
|
||||
if (this.ignoreSets == null || this.ignoreSets.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return this.ignoreSets.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current list of ignore sets.
|
||||
*
|
||||
* @return the unmodifiable list of ignore sets, which cannot be null
|
||||
*/
|
||||
public final List<ImaIgnoreSetBaseline> getIgnoreSets() {
|
||||
return Collections.unmodifiableList(this.ignoreSets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the IMA blacklists for this IMA policy.
|
||||
*
|
||||
* @param newBlacklists the blacklists to assign to this policy
|
||||
*/
|
||||
public final void setBlacklists(final List<ImaBlacklistBaseline> newBlacklists) {
|
||||
if (newBlacklists == null) {
|
||||
throw new PolicyException("Cannot set blacklists to null");
|
||||
}
|
||||
LOGGER.debug("setting new blacklists for {}: {}", getName(), newBlacklists);
|
||||
blacklists.clear();
|
||||
blacklists.addAll(newBlacklists);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve this policy's IMA blacklists.
|
||||
*
|
||||
* @return this policy's blacklists
|
||||
*/
|
||||
public final List<ImaBlacklistBaseline> getBlacklists() {
|
||||
return Collections.unmodifiableList(this.blacklists);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the policy on whether appraisal should fail if any unknown files
|
||||
* are found. During the IMA appraisal process unknown files may be
|
||||
* encountered. This boolean indicates if an appraisal should fail for any
|
||||
* unknown files that are found.
|
||||
*
|
||||
* @return appraisal failure policy if any unknowns found
|
||||
*/
|
||||
public final boolean isFailOnUnknowns() {
|
||||
return failOnUnknowns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the policy on whether appraisal should fail if any unknown files
|
||||
* are found. See {@link #isFailOnUnknowns()} for more details.
|
||||
*
|
||||
* @param failOnUnknowns appraisal failure policy if any unknowns found
|
||||
*/
|
||||
public final void setFailOnUnknowns(final boolean failOnUnknowns) {
|
||||
LOGGER.debug("setting fail on unknowns policy to {}", failOnUnknowns);
|
||||
this.failOnUnknowns = failOnUnknowns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean as to whether or not the PCR hash should be validated.
|
||||
* An IMA report that has a TPM enabled has a running hash stored in a TPM,
|
||||
* typically PCR 10. If this is set to true then the running hash of the IMA
|
||||
* report is regenerated during the appraisal process and compared to the
|
||||
* PCR.
|
||||
* <p>
|
||||
* If this is enabled a <code>TPMReport</code> must be in the
|
||||
* <code>IntegrityReport</code>.
|
||||
*
|
||||
* @return the validatePcr
|
||||
*/
|
||||
public final boolean isValidatePcr() {
|
||||
return validatePcr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the validation of PCR hash. See {@link #isValidatePcr()} for a
|
||||
* complete description of this property.
|
||||
*
|
||||
* @param validatePcr the validatePcr to set
|
||||
*/
|
||||
public final void setValidatePcr(final boolean validatePcr) {
|
||||
LOGGER.debug("setting validate pcr policy to {}", validatePcr);
|
||||
this.validatePcr = validatePcr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean as to whether IMA reports are enabled for
|
||||
* delta reports.
|
||||
*
|
||||
* @return deltaReportEnable
|
||||
*/
|
||||
public final boolean isDeltaReportEnable() {
|
||||
return deltaReportEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the indicator that determines if delta reports are enabled
|
||||
* within a <code>IntegrityReport</code>.
|
||||
*
|
||||
* @param deltaReportEnable the flag for delta reports
|
||||
*/
|
||||
public final void setDeltaReportEnable(final boolean deltaReportEnable) {
|
||||
LOGGER.debug("setting deltaReportEnable to {}", deltaReportEnable);
|
||||
this.deltaReportEnable = deltaReportEnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<Baseline> getBaselines() {
|
||||
List<Baseline> baselines = new LinkedList<>();
|
||||
baselines.addAll(getRequiredSets());
|
||||
baselines.addAll(getWhitelists());
|
||||
baselines.addAll(getBlacklists());
|
||||
baselines.addAll(getIgnoreSets());
|
||||
return baselines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether partial path support is enabled or not for the whitelists,
|
||||
* required sets, and ignore sets contained in this <code>Policy</code>.
|
||||
* When partial path support is enabled the full file path for records and
|
||||
* baselines is not used when calling
|
||||
* <code>ImaBaseline#contains(IMAMeasurementRecord)</code>.
|
||||
* Instead only the file name is used. For example, if a record has the file
|
||||
* path "gradle" then its path will match against baseline records with the
|
||||
* file paths "/usr/bin/gradle" and "/home/foo/bin/gradle."
|
||||
* <p>
|
||||
* This feature should be enabled when comparing against IMA reports from
|
||||
* kernels that do not have the latest IMA code. The earlier IMA code did
|
||||
* not always report the absolute file path for each record. This is true
|
||||
* for CentOS versions prior to CentOS 7.
|
||||
*
|
||||
* @return partialPathEnable
|
||||
*/
|
||||
public final boolean isPartialPathEnable() {
|
||||
return partialPathEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether partial path support is enabled or not for the whitelists.
|
||||
* See {@link #isPartialPathEnable()} for more details about the flag.
|
||||
*
|
||||
* @param partialPathEnable boolean determining whether partial paths are used
|
||||
*/
|
||||
public final void setPartialPathEnable(final boolean partialPathEnable) {
|
||||
LOGGER.debug("setting partialPathEnable to {}", partialPathEnable);
|
||||
this.partialPathEnable = partialPathEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Multimap representing that paths that should be considered
|
||||
* 'equivalent' while evaluating an IMA baseline contained by this policy.
|
||||
* Equivalent paths are those which could potentially hold the same files, or links
|
||||
* to those same files. For instance, on CentOS 7, /bin is symlinked to /usr/bin, so the
|
||||
* IMA log may report equivalent entries at both /bin/file and /usr/bin/file.
|
||||
* Creating a mapping between /bin/ and /usr/bin/ allows IMA appraisal to equate the
|
||||
* two paths.
|
||||
* <p>
|
||||
* The map returned will have directories as keys, and those directories' equivalent
|
||||
* directories as its collection of values. These relationships are bidirectional; that is,
|
||||
* if a is equivalent to b and c, b is equivalent to a, and c is also equivalent to a.
|
||||
*
|
||||
* @return a Multimap relating equivalent directories as described above
|
||||
*/
|
||||
public final synchronized Multimap<String, String> getPathEquivalences() {
|
||||
// if we've already set pathEquivalences, return it
|
||||
if (pathEquivalences != null) {
|
||||
return pathEquivalences;
|
||||
}
|
||||
|
||||
Multimap<String, String> equivalentPaths = HashMultimap.create();
|
||||
|
||||
// define equivalences
|
||||
equivalentPaths.put("/bin/", "/usr/bin/");
|
||||
equivalentPaths.put("/lib/", "/usr/lib/");
|
||||
equivalentPaths.put("/lib64/", "/usr/lib64/");
|
||||
equivalentPaths.put("/usr/bin/", "/usr/sbin/");
|
||||
equivalentPaths.put("/sbin/", "/usr/sbin/");
|
||||
|
||||
// populate inverse relationships
|
||||
Multimap<String, String> bidirectionalEquivalences = HashMultimap.create();
|
||||
for (Map.Entry<String, Collection<String>> equivalentPathPair
|
||||
: equivalentPaths.asMap().entrySet()) {
|
||||
String dir = equivalentPathPair.getKey();
|
||||
Collection<String> equivalentDirs = equivalentPathPair.getValue();
|
||||
|
||||
bidirectionalEquivalences.putAll(dir, equivalentDirs);
|
||||
|
||||
for (String equivalentDir : equivalentDirs) {
|
||||
bidirectionalEquivalences.put(equivalentDir, dir);
|
||||
}
|
||||
}
|
||||
|
||||
this.pathEquivalences = bidirectionalEquivalences;
|
||||
return this.pathEquivalences;
|
||||
}
|
||||
}
|
@ -1,306 +0,0 @@
|
||||
package hirs.data.persist.alert;
|
||||
|
||||
/**
|
||||
* The Alert Monitor holds configuration information about an individual remote monitor (a remote
|
||||
* "Alert Manager") that is subscribing (monitoring) the HIRS alert service.
|
||||
*/
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Table;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
|
||||
/**
|
||||
* Database Object representing the configuration of a remote Alert Monitor. The Alert Monitor
|
||||
* configuration holds information about an individual remote monitor (a remote "Alert Manager")
|
||||
* that is subscribing (monitoring) the HIRS alert service. The configuration allows for one alert
|
||||
* to be sent for every event or one alert per report processed that encountered at least one event.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "AlertMonitor")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class AlertMonitor {
|
||||
|
||||
/**
|
||||
* ID assigned to the configuration.
|
||||
*/
|
||||
@Id
|
||||
@Column
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column
|
||||
private InetAddress ipAddress;
|
||||
|
||||
@Column
|
||||
private int port = 0;
|
||||
|
||||
@Column(name = "alertOnSummary")
|
||||
private boolean alertOnSummaryEnabled = false;
|
||||
|
||||
@Column(name = "alertOnEvent")
|
||||
private boolean individualAlertEnabled = false;
|
||||
|
||||
@Column
|
||||
private String alertServiceType;
|
||||
|
||||
@Column
|
||||
private boolean monitorEnabled;
|
||||
|
||||
/**
|
||||
* Default constructor. Needed for Hibernate unit tests.
|
||||
*/
|
||||
protected AlertMonitor() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Alert Monitor.
|
||||
*
|
||||
* @param monitorName name assigned to this monitor.
|
||||
*/
|
||||
public AlertMonitor(final String monitorName) {
|
||||
|
||||
if (monitorName == null) {
|
||||
throw new NullPointerException("AlertMonitor name not set");
|
||||
}
|
||||
name = monitorName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the persisted ID of the monitor.
|
||||
*
|
||||
* @return persistence ID of the monitor
|
||||
*/
|
||||
public final Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the FQDN of of the Alert Monitor.
|
||||
*
|
||||
* @param type Type of the AlertService
|
||||
*/
|
||||
public void setAlertServiceType(final String type) {
|
||||
if (type == null) {
|
||||
throw new NullPointerException("AlertMonitor type not set");
|
||||
}
|
||||
alertServiceType = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Type of the AlertService associated with the monitor.
|
||||
*
|
||||
* @return Type of the AlertService this monitor is associated with
|
||||
*/
|
||||
public final String getAlertServiceType() {
|
||||
return alertServiceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the remote Manager.
|
||||
*
|
||||
* @param newName Name of the remote manager
|
||||
*/
|
||||
public final void setName(final String newName) {
|
||||
if (newName == null) {
|
||||
throw new NullPointerException("AlertMonitor name cannot be null");
|
||||
}
|
||||
name = newName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name assigned to the remote alert manager.
|
||||
*
|
||||
* @return Name of the remote alert manager
|
||||
*/
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the address of the remote alert manager.
|
||||
*
|
||||
* @param newip address assigned to the remote manager
|
||||
*/
|
||||
public final void setIpAddress(final InetAddress newip) {
|
||||
ipAddress = newip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves, then sets the address of the remote alert manager.
|
||||
*
|
||||
* @param host address assigned to the remote manager
|
||||
* @throws UnknownHostException For problems resolving or storing the host.
|
||||
*/
|
||||
public final void setIpAddress(final String host) throws UnknownHostException {
|
||||
ipAddress = InetAddress.getByName(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the IP assigned to the remote manager.
|
||||
*
|
||||
* @return IP of the remote manager
|
||||
*/
|
||||
public final InetAddress getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign port of the remote alert manager.
|
||||
*
|
||||
* @param newport port assigned to the remote manager
|
||||
*/
|
||||
public final void setPort(final int newport) {
|
||||
final int upperBound = 65535;
|
||||
if (0 < newport && newport <= upperBound) {
|
||||
port = newport;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Failed to set monitor port. Provided number was"
|
||||
+ " outside of valid range (1 - 65535)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets port assigned to the remote manager.
|
||||
*
|
||||
* @return the port used by the remote manager
|
||||
*/
|
||||
public final int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the summary Alert enable setting.
|
||||
* If true the Alert Manager will send one summary message per message that incurred an alert.
|
||||
*
|
||||
* @return true if Alert Monitor will send an alert upon an Alert Summary
|
||||
*/
|
||||
public final boolean isAlertOnSummaryEnabled() {
|
||||
return this.alertOnSummaryEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the Remote Alert Manager to send a summary of alerts per report.
|
||||
* This does not effect the enableIndividualAlert method.
|
||||
*/
|
||||
public final void enableAlertOnSummary() {
|
||||
alertOnSummaryEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the Remote Alert Manager to send a summary of alerts per report.
|
||||
* This does not effect the disableIndividualAlert method.
|
||||
*/
|
||||
public final void disableAlertOnSummary() {
|
||||
alertOnSummaryEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the individual Alert enable setting.
|
||||
* If true the Alert Manager will send the remote alert manager one message per alert.
|
||||
*
|
||||
* @return Enable setting for the Remote Alert monitor
|
||||
*/
|
||||
public final boolean isIndividualAlertEnabled() {
|
||||
return individualAlertEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the Remote Alert Manager to send individual alerts.
|
||||
* This could lead to hundreds of alerts per issued per report.
|
||||
*/
|
||||
public final void enableIndividualAlert() {
|
||||
individualAlertEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the Remote Alert Manager to send individual alerts.
|
||||
*/
|
||||
public final void disableIndividualAlert() {
|
||||
individualAlertEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables AlertMonitor. This needs to be called in order for an Alert to be sent to the
|
||||
* provided monitor.
|
||||
*/
|
||||
public final void enable() {
|
||||
monitorEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables AlertMonitor. This will prevent Alerts from being forwarded to the supplied
|
||||
* monitor.
|
||||
*/
|
||||
public final void disable() {
|
||||
monitorEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the enabled/disabled status of the monitor.
|
||||
*
|
||||
* @return the status of the monitor. True if enabled, false if disabled.
|
||||
*/
|
||||
public final boolean isMonitorEnabled() {
|
||||
return monitorEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean if other is equal to this. <code>AlertMonitor</code>s are identified
|
||||
* by their name, so this returns true if <code>other</code> is an instance of
|
||||
* <code>AlertMonitor</code> and its name is the same as this <code>AlertMonitor</code>.
|
||||
* Otherwise this returns false.
|
||||
*
|
||||
* @param other other object to test for equals
|
||||
* @return true if other is <code>AlertMonitor</code> and has same name
|
||||
*/
|
||||
@Override
|
||||
public final boolean equals(final Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (!(other instanceof AlertMonitor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final AlertMonitor config = (AlertMonitor) other;
|
||||
return this.getName().equals(config.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code for this <code>AlertMonitor</code>. <code>AlertMonitor</code>
|
||||
* are identified by their name, so the returned hash is the hash of the name.
|
||||
*
|
||||
* @return hash
|
||||
*/
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representation of this class. This returns the
|
||||
* <code>AlertMonitor</code> name.
|
||||
*
|
||||
* @return <code>AlertMonitor</code> name
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
package hirs.data.persist.alert;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* The AlertServiceConfig holds persistent configuration data for the
|
||||
* ManagedAlertService.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "AlertServiceConfig")
|
||||
public class AlertServiceConfig {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", unique = true)
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "enabled")
|
||||
private boolean enabled = false;
|
||||
|
||||
@Column
|
||||
private String serviceIdentifier;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* Needed for Hibernate unit tests.
|
||||
*/
|
||||
protected AlertServiceConfig() {
|
||||
// Do Nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertServiceConfig</code> that uses the default
|
||||
* database. The default database is used to store all of the objects.
|
||||
*
|
||||
* @param serviceType type assigned to this alert service.
|
||||
*/
|
||||
public AlertServiceConfig(final String serviceType) {
|
||||
if (serviceType == null) {
|
||||
throw new NullPointerException("AlertServiceConfig name not set");
|
||||
}
|
||||
type = serviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the alert service.
|
||||
*/
|
||||
public final void enable() {
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the alert service.
|
||||
*/
|
||||
public final void disable() {
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets enabled status (Alert Service state).
|
||||
*
|
||||
* @return True if the service is enabled, false if disabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the AlertService.
|
||||
*
|
||||
* @return Type of the service
|
||||
*/
|
||||
public final String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the Alert Service.
|
||||
*
|
||||
* @return ID of the service
|
||||
*/
|
||||
public final String getServiceIdentifier() {
|
||||
return serviceIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Identifier of the service.
|
||||
*
|
||||
* @param id
|
||||
* Identifier to assign
|
||||
*/
|
||||
public final void setServiceIdentifier(final String id) {
|
||||
serviceIdentifier = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code for this <code>Device</code>. The hash code is
|
||||
* determined from the name of the <code>Device</code>.
|
||||
*
|
||||
* @return hash code
|
||||
*/
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + type.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether <code>this</code> is equal to <code>obj</code>. This
|
||||
* returns true if and only if the class of obj is equal to this class and
|
||||
* the names are equal.
|
||||
*
|
||||
* @param obj other object to compare against
|
||||
* @return equality
|
||||
*/
|
||||
@Override
|
||||
public final boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof AlertServiceConfig)) {
|
||||
return false;
|
||||
}
|
||||
AlertServiceConfig other = (AlertServiceConfig) obj;
|
||||
return this.type.equals(other.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>String</code> representation of this class. This returns
|
||||
* the <code>AlertMonitor</code> name.
|
||||
*
|
||||
* @return <code>Policy</code> name
|
||||
*/
|
||||
@Override
|
||||
public final String toString() {
|
||||
return type.toString();
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
package hirs.data.persist.alert;
|
||||
|
||||
import hirs.alert.JsonAlertService;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* This configuration extends the generic AlertMonitor for JSON.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "JsonAlertMonitor")
|
||||
@Access(AccessType.FIELD)
|
||||
public class JsonAlertMonitor extends AlertMonitor {
|
||||
/**
|
||||
* The protocol used to send the JSON Alerts.
|
||||
*/
|
||||
public enum JsonAlertMode {
|
||||
/**
|
||||
* via TCP.
|
||||
*/
|
||||
TCP,
|
||||
/**
|
||||
* via UDP.
|
||||
*/
|
||||
UDP;
|
||||
}
|
||||
|
||||
@Column
|
||||
private JsonAlertMode mode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public JsonAlertMonitor() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param name - name of the monitor
|
||||
*/
|
||||
public JsonAlertMonitor(final String name) {
|
||||
super(name);
|
||||
setAlertServiceType(JsonAlertService.NAME);
|
||||
setTCP();
|
||||
disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>JsonAlertMode</code> of this <code>JsonAlertMonitor</code>.
|
||||
* @return JsonAlertMode
|
||||
*/
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
public JsonAlertMode getJsonAlertMode() {
|
||||
return this.mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this <code>JsonAlertMonitor</code> is configured to forward alerts via TCP.
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isTCP() {
|
||||
return this.mode == JsonAlertMode.TCP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode to TCP.
|
||||
*/
|
||||
public void setTCP() {
|
||||
this.mode = JsonAlertMode.TCP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this <code>JsonAlertMonitor</code> is configured to forward alerts via UDP.
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isUDP() {
|
||||
return this.mode == JsonAlertMode.UDP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode to UDP.
|
||||
*/
|
||||
public void setUDP() {
|
||||
this.mode = JsonAlertMode.UDP;
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package contains a set of classes for accessing alert service data.
|
||||
*/
|
||||
package hirs.data.persist.alert;
|
@ -1,200 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.enums.DigestAlgorithm;
|
||||
import hirs.data.persist.OptionalDigest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Transient;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An <code>AbstractImaBaselineRecord</code> represents an entry in a baseline used
|
||||
* during appraisal of a machine's IMA log. These records indicate paths
|
||||
* and/or hashes that may be acceptable, ignored, or blacklisted, according
|
||||
* to their uses.
|
||||
* <p>
|
||||
* Known extending classes include:
|
||||
* - {@link IMABaselineRecord}
|
||||
* - {@link ImaIgnoreSetRecord}
|
||||
* - {@link ImaBlacklistRecord}
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractImaBaselineRecord {
|
||||
private static final Logger LOGGER = LogManager.getLogger(AbstractImaBaselineRecord.class);
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private final Long id;
|
||||
|
||||
/**
|
||||
* Holds the name of the 'path' field.
|
||||
*/
|
||||
public static final String PATH_FIELD = "path";
|
||||
|
||||
@SuppressWarnings("checkstyle:magicnumber")
|
||||
@Column(name = PATH_FIELD, nullable = true, length = 2048)
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Holds the name of the 'hash' field.
|
||||
*/
|
||||
public static final String HASH_FIELD = "hash";
|
||||
|
||||
@Embedded
|
||||
private final OptionalDigest hash;
|
||||
|
||||
@SuppressWarnings("checkstyle:magicnumber")
|
||||
@Column(nullable = true, length = 255)
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ImaBaseRecord</code>. Creates a new record and
|
||||
* specifies all of the properties. All of the properties may be null
|
||||
* except for path and hash.
|
||||
*
|
||||
* @param path
|
||||
* file path
|
||||
* @param hash
|
||||
* file SHA-1 hash
|
||||
* @param description
|
||||
* a description for this baseline entry
|
||||
* @throws IllegalArgumentException
|
||||
* if digest algorithm is not SHA-1
|
||||
*/
|
||||
public AbstractImaBaselineRecord(final String path, final Digest hash, final String description)
|
||||
throws IllegalArgumentException {
|
||||
if (hash != null && hash.getAlgorithm() != DigestAlgorithm.SHA1) {
|
||||
throw new IllegalArgumentException("Hash algorithm is not SHA-1");
|
||||
}
|
||||
this.id = null;
|
||||
this.path = path;
|
||||
if (path != null && StringUtils.isBlank(path)) {
|
||||
throw new IllegalArgumentException("Path is blank");
|
||||
}
|
||||
if (hash != null) {
|
||||
this.hash = hash.asOptionalDigest();
|
||||
} else {
|
||||
this.hash = null;
|
||||
}
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected AbstractImaBaselineRecord() {
|
||||
this.id = null;
|
||||
this.path = null;
|
||||
this.hash = null;
|
||||
this.description = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database ID associated with this record. If this record has
|
||||
* not been persisted in the database then this method will return null.
|
||||
*
|
||||
* @return ID of this record
|
||||
*/
|
||||
public final Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path (including file name) of the IMA baseline record.
|
||||
*
|
||||
* @return file path of baseline record
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SHA1 hash of the file associated with IMA baseline record.
|
||||
*
|
||||
* @return hash of file associated with baseline record
|
||||
*/
|
||||
@Transient
|
||||
public Digest getHash() {
|
||||
if (hash != null) {
|
||||
return hash.asDigest();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the partial path associated with this baseline record; may be null.
|
||||
*
|
||||
* @return the partial path associated with this baseline record; may be null.
|
||||
*/
|
||||
public String getPartialPath() {
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
return getPartialPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the partial path (file name) of the given Path, represented by a string.
|
||||
*
|
||||
* @param path the path for which to generate a partial path
|
||||
* @return file name
|
||||
*/
|
||||
public static String getPartialPath(final String path) {
|
||||
if (path == null) {
|
||||
throw new IllegalArgumentException("Cannot get partial path for null value");
|
||||
}
|
||||
Path filename = Paths.get(path).getFileName();
|
||||
//should only be triggered if path is '/' directory
|
||||
if (filename == null) {
|
||||
LOGGER.error("Invalid filename from path: " + path);
|
||||
return "";
|
||||
}
|
||||
return filename.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the description of the file associated with IMA ignore baseline record.
|
||||
*
|
||||
* @return hash of file associated with baseline record
|
||||
*/
|
||||
public final String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
AbstractImaBaselineRecord that = (AbstractImaBaselineRecord) o;
|
||||
return Objects.equals(path, that.path)
|
||||
&& Objects.equals(hash, that.hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(path, hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return String.format("(%s, %s)", path, hash);
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import hirs.data.persist.UserDefinedEntity;
|
||||
import hirs.data.persist.enums.AlertSeverity;
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* A baseline (a.k.a. whitelist) contains a set of expected values for a
|
||||
* measurement comparison. In the case of a TPM a baseline for that would
|
||||
* contain the PCR IDs along with the expected hash values. This is similar for
|
||||
* IMA.
|
||||
* <p>
|
||||
* The <code>Baseline</code> class represents a baseline. This is an abstract
|
||||
* class for referencing <code>Baseline</code>s. A <code>Baseline</code> is
|
||||
* identified by its name, so the name for a <code>Baseline</code> must be
|
||||
* unique.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "Baseline")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class Baseline extends UserDefinedEntity {
|
||||
|
||||
@Column(nullable = false, name = "severity")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private AlertSeverity severity = AlertSeverity.UNSPECIFIED;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Baseline</code> with the specified name.
|
||||
*
|
||||
* @param name name
|
||||
*/
|
||||
public Baseline(final String name) {
|
||||
super(name);
|
||||
type = getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected Baseline() {
|
||||
super();
|
||||
type = getClass().getSimpleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* When baselines are serialized to be sent to the browser, this can be used
|
||||
* to determine the type of baseline.
|
||||
*
|
||||
* @return The class name for the baseline
|
||||
*/
|
||||
public String getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the baseline severity.
|
||||
* @return the severity
|
||||
*/
|
||||
public AlertSeverity getSeverity() {
|
||||
return severity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the severity of alerts raised by this baseline.
|
||||
* @param severity The desired severity of alerts raised by this baseline
|
||||
*/
|
||||
public void setSeverity(final AlertSeverity severity) {
|
||||
this.severity = severity;
|
||||
}
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import hirs.persist.RepositoryManager;
|
||||
import hirs.repository.Repository;
|
||||
import hirs.repository.RepoPackage;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
* An IMA baseline that references a set of <code>Repository</code> instances. Appraisals are done
|
||||
* by using every package in each of the repositories as a baseline. An update() will synchronize
|
||||
* the local packages to the measured contents of the repositories.
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
public class BroadRepoImaBaseline extends QueryableRecordImaBaseline
|
||||
implements UpdatableImaBaseline {
|
||||
/**
|
||||
* The repositories used for an appraisal against this baseline.
|
||||
*/
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
private Set<Repository<?>> repositories;
|
||||
|
||||
/**
|
||||
* Name of the repoPackages field.
|
||||
*/
|
||||
public static final String REPO_PACKAGES_FIELD = "repoPackages";
|
||||
|
||||
/**
|
||||
* The packages that have been extracted from this baseline's repositories.
|
||||
*/
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
private Set<RepoPackage> repoPackages;
|
||||
|
||||
@Transient
|
||||
private final Set<IMABaselineRecord> cachedBaselineRecords = new HashSet<>();
|
||||
|
||||
@Transient
|
||||
private boolean shouldUpdateCache = true;
|
||||
|
||||
/**
|
||||
* Constructor used to initialize a <code>BroadRepoImaBaseline</code> with the given name and
|
||||
* an empty <code>Set</code> of <code>Repository</code> instances and <code>RepoPackage</code>s.
|
||||
*
|
||||
* @param name the name of the new baseline
|
||||
*/
|
||||
public BroadRepoImaBaseline(final String name) {
|
||||
super(name);
|
||||
repositories = new HashSet<>();
|
||||
repoPackages = new HashSet<>();
|
||||
}
|
||||
|
||||
/** Default constructor necessary for Hibernate. Makes an empty <code>Set</code> of
|
||||
* <code>Repository</code> instances and <code>RepoPackage</code>s.
|
||||
*/
|
||||
protected BroadRepoImaBaseline() {
|
||||
super();
|
||||
repositories = new HashSet<>();
|
||||
repoPackages = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this baseline to match repositories that may have been updated. First clear the
|
||||
* current <code>Set</code> of <code>RepoPackage</code>s, then iterate through the
|
||||
* <code>Repository</code> objects referenced in this baseline and use all of the measured
|
||||
* packages found within each of them to populate this baseline's <code>Set</code> of
|
||||
* <code>RepoPackage</code>s.
|
||||
*
|
||||
* @param repositoryManager a repository manager to use to gather data about repositories, or
|
||||
* null if object already contains all info (no lazy-loaded data)
|
||||
*/
|
||||
@Override
|
||||
public final void update(final RepositoryManager repositoryManager) {
|
||||
repoPackages.clear();
|
||||
for (Repository<?> repository : repositories) {
|
||||
Repository<?> repoWithPackages;
|
||||
if (repositoryManager != null) {
|
||||
repoWithPackages = repositoryManager.getRepository(repository.getId());
|
||||
} else {
|
||||
repoWithPackages = repository;
|
||||
}
|
||||
repoPackages.addAll(repoWithPackages.getPackages());
|
||||
}
|
||||
|
||||
synchronized (cachedBaselineRecords) {
|
||||
this.shouldUpdateCache = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<IMABaselineRecord> getBaselineRecords() {
|
||||
synchronized (cachedBaselineRecords) {
|
||||
if (!shouldUpdateCache) {
|
||||
return Collections.unmodifiableSet(cachedBaselineRecords);
|
||||
}
|
||||
|
||||
cachedBaselineRecords.clear();
|
||||
for (RepoPackage repoPackage : repoPackages) {
|
||||
cachedBaselineRecords.addAll(repoPackage.getPackageRecords());
|
||||
}
|
||||
shouldUpdateCache = false;
|
||||
|
||||
return Collections.unmodifiableSet(cachedBaselineRecords);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureCriteriaForBaselineRecords(final Criteria criteria, final int bucket) {
|
||||
criteria.add(Restrictions.eq("id", getId()))
|
||||
.setProjection(Projections.projectionList()
|
||||
.add(Projections.property(
|
||||
String.format("%s.%s",
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD,
|
||||
IMABaselineRecord.PATH_FIELD)
|
||||
), IMABaselineRecord.PATH_FIELD)
|
||||
.add(Projections.property(
|
||||
String.format("%s.%s",
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD,
|
||||
IMABaselineRecord.HASH_FIELD)
|
||||
), IMABaselineRecord.HASH_FIELD)
|
||||
);
|
||||
|
||||
criteria.add(Restrictions.eq(
|
||||
String.format("%s.%s",
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD,
|
||||
IMABaselineRecord.BUCKET_FIELD),
|
||||
bucket)
|
||||
);
|
||||
criteria.createAlias(REPO_PACKAGES_FIELD, REPO_PACKAGES_FIELD);
|
||||
criteria.createAlias(
|
||||
String.format("%s.%s", REPO_PACKAGES_FIELD, RepoPackage.PACKAGE_RECORDS_FIELD),
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>Set</code> of <code>RepoPackage</code>s associated with this baseline.
|
||||
*
|
||||
* @return the RepoPackages associated with this baseline
|
||||
*/
|
||||
public final Set<RepoPackage> getRepositoryPackages() {
|
||||
return Collections.unmodifiableSet(repoPackages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>Set</code> of <code>Repository</code> instances associated with this baseline.
|
||||
*
|
||||
* @return the Repositories tracked by this baseline
|
||||
*/
|
||||
public final Set<Repository<?>> getRepositories() {
|
||||
return Collections.unmodifiableSet(repositories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the <code>Set</code> of <code>Repository</code> instances associated with this baseline.
|
||||
* Note that the map update needed flags do not change here. They will only change during an
|
||||
* update() because that is where the <code>RepoPackage</code>s change.
|
||||
*
|
||||
* @param newRepositories the new repositories to be tracked by this baseline
|
||||
*/
|
||||
public final void setRepositories(final Set<Repository<?>> newRepositories) {
|
||||
repositories.clear();
|
||||
repositories.addAll(newRepositories);
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface HasBaselines {
|
||||
/**
|
||||
* Convenience method for accessing related Baselines.
|
||||
* @return Baselines related to this object
|
||||
*/
|
||||
List<Baseline> getBaselines();
|
||||
}
|
@ -1,176 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.Digest;
|
||||
|
||||
/**
|
||||
* An <code>IMABaselineRecord</code> represents a single entry in an
|
||||
* {@link ImaAcceptableRecordBaseline}. These contain paths and hashes of expected
|
||||
* entries in a machine's IMA log, and are used in the contexts of whitelists and required
|
||||
* sets via ImaAcceptableRecordBaselines.
|
||||
*/
|
||||
@Entity
|
||||
@Table(indexes = { @Index(columnList = "bucket") })
|
||||
public class IMABaselineRecord extends AbstractImaBaselineRecord {
|
||||
/**
|
||||
* IMABaselineRecords are randomly assigned buckets based on a hash of their path. These
|
||||
* bucket values are used to artificially segment the baseline into equal divisions for
|
||||
* simultaneous multithreaded retrieval. This defines the number of distinct bucket values that
|
||||
* will be used in this process.
|
||||
*/
|
||||
public static final int FILENAME_HASH_BUCKET_COUNT = 4;
|
||||
|
||||
/**
|
||||
* Holds the name of the 'bucket' field.
|
||||
*/
|
||||
public static final String BUCKET_FIELD = "bucket";
|
||||
|
||||
@Column(name = BUCKET_FIELD, nullable = false)
|
||||
private final int bucket;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "ima_baseline_id")
|
||||
private SimpleImaBaseline baseline;
|
||||
|
||||
@Transient
|
||||
private static final Pattern RECORD_PATTERN = Pattern.compile("\\((.*), (.*)\\)");
|
||||
|
||||
/**
|
||||
* Creates a new <code>IMABaselineRecord</code>.
|
||||
* @param path
|
||||
* file path of the record
|
||||
* @param hash
|
||||
* hash of the record
|
||||
*/
|
||||
public IMABaselineRecord(final String path, final Digest hash) {
|
||||
super(path, hash, null);
|
||||
Preconditions.checkNotNull(path, "Path cannot be null.");
|
||||
Preconditions.checkNotNull(hash, "Hash cannot be null.");
|
||||
this.bucket = getBucket(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>IMABaselineRecord</code>. Creates a new record and
|
||||
* specifies all of the properties. All of the properties may be null
|
||||
* except for path and hash.
|
||||
*
|
||||
* @param path
|
||||
* file path
|
||||
* @param hash
|
||||
* file SHA-1 hash
|
||||
* @param baseline
|
||||
* baseline assigned to the record (nullable)
|
||||
* @throws IllegalArgumentException
|
||||
* if digest algorithm is not SHA-1
|
||||
*/
|
||||
public IMABaselineRecord(final String path, final Digest hash, final SimpleImaBaseline baseline)
|
||||
throws IllegalArgumentException {
|
||||
this(path, hash);
|
||||
setBaselineForRecordManager(baseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 'bucket' of the given path (based on its hash).
|
||||
*
|
||||
* @param path the path to hash
|
||||
* @return the hash of the path
|
||||
*/
|
||||
private static int getBucket(final String path) {
|
||||
if (path == null) {
|
||||
throw new IllegalArgumentException("Cannot get bucket for null value");
|
||||
}
|
||||
return Math.abs(getPartialPath(path).hashCode()) % FILENAME_HASH_BUCKET_COUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected IMABaselineRecord() {
|
||||
super();
|
||||
this.bucket = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets the baseline.
|
||||
*
|
||||
* @return Baseline
|
||||
*/
|
||||
public final ImaBaseline getBaseline() {
|
||||
return baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given baseline.
|
||||
*
|
||||
* @param baseline baseline that matches the given baseline
|
||||
*/
|
||||
public final void setBaseline(final SimpleImaBaseline baseline) {
|
||||
setOnlyBaseline(baseline);
|
||||
if (baseline != null) {
|
||||
baseline.addOnlyToBaseline(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the baseline for this record.
|
||||
*
|
||||
* @param baseline
|
||||
* baseline or null
|
||||
*/
|
||||
final void setOnlyBaseline(final SimpleImaBaseline baseline) {
|
||||
if (this.baseline != null && baseline != null) {
|
||||
this.baseline.removeOnlyBaseline(this);
|
||||
}
|
||||
|
||||
this.baseline = baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is to be used strictly for when the record is being added or modified by the
|
||||
* <code>ImaBaselineRecordManager</code>. The methods
|
||||
* {@link #setBaseline(hirs.data.persist.SimpleImaBaseline)} and {@link
|
||||
* #setOnlyBaseline(hirs.data.persist.SimpleImaBaseline)} will still need to exist for
|
||||
* use with the <code>BaselineManager</code>
|
||||
*
|
||||
* @param baseline
|
||||
* SimpleImaBaseline that will be set and persisted by the
|
||||
* <code>ImaBaselineRecordManager</code>
|
||||
*/
|
||||
public final void setBaselineForRecordManager(final SimpleImaBaseline baseline) {
|
||||
this.baseline = baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the toString operation. Throws an IllegalArgumentException if an invalid String is
|
||||
* passed in
|
||||
*
|
||||
* @param record
|
||||
* String representation of the IMABaselineRecord
|
||||
* @return IMABaselineRecord
|
||||
*/
|
||||
public static IMABaselineRecord fromString(final String record) {
|
||||
Matcher m = RECORD_PATTERN.matcher(record);
|
||||
m.matches();
|
||||
if (m.groupCount() != 2) {
|
||||
String msg = String.format("Unexpected number of groups found with pattern \"%s\" "
|
||||
+ "on string \"%s\"", RECORD_PATTERN.toString(), record);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
String path = m.group(1);
|
||||
String digestString = m.group(2);
|
||||
Digest digest = Digest.fromString(digestString);
|
||||
return new IMABaselineRecord(path, digest);
|
||||
}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.ima.matching.BatchImaMatchStatus;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base class for all {@link ImaBaseline}s which contain data representing 'acceptable'
|
||||
* IMA baseline entries in the form of {@link IMABaselineRecord}s. Used in the roles
|
||||
* of whitelists and required sets in {@link IMAPolicy}.
|
||||
*/
|
||||
@Entity
|
||||
public abstract class ImaAcceptableRecordBaseline extends ImaBaseline<IMABaselineRecord> {
|
||||
|
||||
/**
|
||||
* Creates a new ImaAcceptableRecordBaseline with the given name.
|
||||
*
|
||||
* @param name a name used to uniquely identify and reference the IMA baseline
|
||||
*/
|
||||
public ImaAcceptableRecordBaseline(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected ImaAcceptableRecordBaseline() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to contains, but only considers the hash value and does not consider
|
||||
* the path as relevant to matching at all.
|
||||
*
|
||||
* Each type of baseline specifies its own
|
||||
* 'contains' algorithm for deciding whether the given measurements are
|
||||
* considered as matches, mismatches, or unknowns to the baseline. The 'contains' method
|
||||
* of ImaAcceptableRecordBaselines that is normally used to judge measurement records
|
||||
* against baseline records considers both paths and hashes; this method offers an
|
||||
* additional mechanism for finding matching baseline records solely based
|
||||
* on matching hash values.
|
||||
*
|
||||
* @param records
|
||||
* measurement records to find in this baseline
|
||||
* @param recordManager
|
||||
* an ImaBaselineRecordManager that can be used to retrieve persisted records
|
||||
* @param imaPolicy
|
||||
* the IMA policy to use while determining if a baseline contains the given records
|
||||
*
|
||||
* @return batch match status for the measurement records, according only to hashes
|
||||
*/
|
||||
@JsonIgnore
|
||||
public abstract BatchImaMatchStatus<IMABaselineRecord> containsHashes(
|
||||
Collection<IMAMeasurementRecord> records,
|
||||
ImaBaselineRecordManager recordManager,
|
||||
IMAPolicy imaPolicy
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable set of IMA baseline records found in the IMA
|
||||
* baseline. The returned set only contains the baseline records from this
|
||||
* baseline.
|
||||
*
|
||||
* @return list of IMA records
|
||||
*/
|
||||
@JsonIgnore
|
||||
public abstract Set<IMABaselineRecord> getBaselineRecords();
|
||||
|
||||
/**
|
||||
* Retrieve the {@link IMABaselineRecord}s from this baseline that are not contained
|
||||
* in the given set of records. In other words, the returned set is the relative complement of
|
||||
* the given records in {@link IMABaselineRecord}s.
|
||||
*
|
||||
* @param recordManager
|
||||
* an ImaBaselineRecordManager that can be used to retrieve persisted records
|
||||
* @param foundRecords
|
||||
* the records that shall not be included in the returned set
|
||||
* @return all of the baseline's records except the set of given records
|
||||
*/
|
||||
@JsonIgnore
|
||||
public abstract Collection<IMABaselineRecord> getRecordsExcept(
|
||||
ImaBaselineRecordManager recordManager,
|
||||
Set<IMABaselineRecord> foundRecords
|
||||
);
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.ima.matching.BatchImaMatchStatus;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Class represents the basic functionality of an IMA baseline: determining whether a baseline
|
||||
* 'contains' {@link IMAMeasurementRecord}s that were collected from a machine's IMA log.
|
||||
* Extending classes represent different ways to assemble and manipulate these baselines. See
|
||||
* {@link SimpleImaBaseline} for an example of a baseline with records that can be manually
|
||||
* added and removed.
|
||||
*
|
||||
* @param <T> the type of record that this baseline holds
|
||||
*/
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class ImaBaseline<T extends AbstractImaBaselineRecord> extends Baseline {
|
||||
@Column
|
||||
@Type(type = "timestamp")
|
||||
private Date date;
|
||||
|
||||
/**
|
||||
* Creates a new ImaBaseline with the given name.
|
||||
*
|
||||
* @param name a name used to uniquely identify and reference the IMA baseline
|
||||
*/
|
||||
public ImaBaseline(final String name) {
|
||||
super(name);
|
||||
date = new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected ImaBaseline() {
|
||||
super();
|
||||
date = new Date();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the record is found in the baseline. This returns a
|
||||
* <code>ReportMatchStatus</code> representing the result of the search for
|
||||
* the record. The returns conditions are as follows:
|
||||
* <ul>
|
||||
* <li>MATCH - if an <code>IMABaselineRecord</code> is found with a matching
|
||||
* path and hash</li>
|
||||
* <li>MISMATCH - if at least one <code>IMABaselineRecord</code> is found
|
||||
* with a matching path but none with a matching path and hash</li>
|
||||
* <li>UNKNOWN - if no <code>IMABaselineRecord</code>s found with a matching
|
||||
* path</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* If partial paths are enabled, records not starting with '/' are compared
|
||||
* against all baseline records not starting with '/' and the last segment
|
||||
* (the filename after the last '/') of each full path baseline record.
|
||||
* Records starting with '/' are compared against all full path baseline
|
||||
* records and the last segment of the record is compared against all
|
||||
* partial path baseline records.
|
||||
* <p>
|
||||
* If partial paths are disabled, records are only compared using the full
|
||||
* path of the baseline record and the report record.
|
||||
*
|
||||
* @param records
|
||||
* measurement records to find in this baseline
|
||||
* @param recordManager
|
||||
* an ImaBaselineRecordManager that can be used to retrieve persisted records
|
||||
* @param imaPolicy
|
||||
* the IMA policy to use while determining if a baseline contains the given records
|
||||
*
|
||||
* @return batch match status for the measurement records
|
||||
*/
|
||||
public abstract BatchImaMatchStatus<T> contains(
|
||||
Collection<IMAMeasurementRecord> records,
|
||||
ImaBaselineRecordManager recordManager,
|
||||
IMAPolicy imaPolicy
|
||||
);
|
||||
|
||||
/**
|
||||
* Set this <code>IMABaselines</code>'s <code>date</code>, which can either
|
||||
* be the date that it was added, or some other date such as the patch date
|
||||
* this baseline is associated with.
|
||||
*
|
||||
* @param newDate
|
||||
* the new date to set, can be null
|
||||
*/
|
||||
public final void setDate(final Date newDate) {
|
||||
if (newDate == null) {
|
||||
this.date = null;
|
||||
} else {
|
||||
this.date = new Date(newDate.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this <code>IMABaselines</code>'s <code>date</code>, which can either
|
||||
* be the date that it was added, or some other date such as the patch date
|
||||
* this baseline is associated with.
|
||||
*
|
||||
* @return this baseline's date, can be null
|
||||
*/
|
||||
public final Date getDate() {
|
||||
return new Date(date.getTime());
|
||||
}
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import hirs.ima.matching.BatchImaMatchStatus;
|
||||
import hirs.ima.matching.ImaBlacklistRecordMatcher;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class holds baseline records that represent known undesirable
|
||||
* facts, such as the existence of an IMA log entry with a certain
|
||||
* filename, or a certain hash, or both.
|
||||
*/
|
||||
@Entity
|
||||
public class ImaBlacklistBaseline extends ImaBaseline<ImaBlacklistRecord> {
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
|
||||
orphanRemoval = true, mappedBy = "baseline")
|
||||
@JsonIgnore
|
||||
private Set<ImaBlacklistRecord> imaBlacklistRecords;
|
||||
|
||||
/**
|
||||
* Construct a new ImaBlacklistBaseline.
|
||||
*
|
||||
* @param name the name of the new baseline
|
||||
*/
|
||||
public ImaBlacklistBaseline(final String name) {
|
||||
super(name);
|
||||
imaBlacklistRecords = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected ImaBlacklistBaseline() {
|
||||
super();
|
||||
imaBlacklistRecords = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BatchImaMatchStatus<ImaBlacklistRecord> contains(
|
||||
final Collection<IMAMeasurementRecord> records,
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final IMAPolicy imaPolicy) {
|
||||
Preconditions.checkArgument(records != null, "Records cannot be null");
|
||||
Preconditions.checkArgument(imaPolicy != null, "IMA policy cannot be null");
|
||||
return new ImaBlacklistRecordMatcher(imaBlacklistRecords, imaPolicy, this)
|
||||
.batchMatch(records);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link ImaBlacklistRecord} to this baseline.
|
||||
*
|
||||
* @param record the record to add to this baseline
|
||||
* @return true if the record was added to this baseline; false otherwise
|
||||
*/
|
||||
public final boolean addToBaseline(final ImaBlacklistRecord record) {
|
||||
record.setBaseline(this);
|
||||
return imaBlacklistRecords.add(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an {@link ImaBlacklistRecord} to this baseline.
|
||||
*
|
||||
* @param record the record to remove from this baseline
|
||||
* @return true if the record was removed from this baseline; false otherwise
|
||||
*/
|
||||
public final boolean removeFromBaseline(final ImaBlacklistRecord record) {
|
||||
record.setBaseline(null);
|
||||
return imaBlacklistRecords.remove(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the given records with this baseline.
|
||||
*
|
||||
* @param records the records that the baseline should contain
|
||||
*/
|
||||
public final void setBaselineRecords(final Set<ImaBlacklistRecord> records) {
|
||||
Preconditions.checkNotNull(records);
|
||||
imaBlacklistRecords.clear();
|
||||
imaBlacklistRecords.addAll(records);
|
||||
for (ImaBlacklistRecord record : records) {
|
||||
record.setBaseline(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of blacklist records in this baseline.
|
||||
*
|
||||
* @return the set of blacklist records contained in this baseline
|
||||
*/
|
||||
@JsonIgnore
|
||||
public final Set<ImaBlacklistRecord> getRecords() {
|
||||
return Collections.unmodifiableSet(imaBlacklistRecords);
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.ImaIgnoreSetRecord;
|
||||
import hirs.ima.matching.BatchImaMatchStatus;
|
||||
import hirs.ima.matching.ImaIgnoreSetRecordMatcher;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
import hirs.utils.RegexFilePathMatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* This class holds baseline records that indicate which measurements should
|
||||
* be ignored in an IMA measurement log, as determined by their paths.
|
||||
*/
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
public class ImaIgnoreSetBaseline extends ImaBaseline<ImaIgnoreSetRecord> {
|
||||
private static final Logger LOGGER = getLogger(ImaIgnoreSetBaseline.class);
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
|
||||
orphanRemoval = true, mappedBy = "baseline")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@JsonIgnore
|
||||
private Set<ImaIgnoreSetRecord> imaIgnoreSetRecords;
|
||||
|
||||
/**
|
||||
* Constructor used to initialize ImaIgnoreSetBaseline object. Makes an empty
|
||||
* <code>Set</code> of Strings and passes up the user provided name.
|
||||
*
|
||||
* @param name
|
||||
* a name used to uniquely identify and reference the IMA ignore set
|
||||
*/
|
||||
public ImaIgnoreSetBaseline(final String name) {
|
||||
super(name);
|
||||
imaIgnoreSetRecords = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate. Makes an empty
|
||||
* <code>Set</code> of Strings and passes up the user provided name.
|
||||
*/
|
||||
protected ImaIgnoreSetBaseline() {
|
||||
super();
|
||||
imaIgnoreSetRecords = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an IMA ignore set record to this ignore set baseline. If the record is not already in
|
||||
* the list, it is added. If the record already exists in the list, then this method will
|
||||
* quietly ignore the request because it already exists in the list.
|
||||
*
|
||||
* @param record
|
||||
* ignore set record to be added to the ignore set
|
||||
* @return
|
||||
* returns true if record was added to the baseline, false if it wasn't
|
||||
*
|
||||
* @throws IllegalArgumentException if the new record has a malformed matcher pattern
|
||||
*/
|
||||
public final boolean addToBaseline(final ImaIgnoreSetRecord record)
|
||||
throws IllegalArgumentException {
|
||||
validateMatcherPattern(record.getPath());
|
||||
record.setOnlyBaseline(this);
|
||||
return addOnlyToBaseline(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the given ignore record path can be used as a valid pattern according
|
||||
* to this ignore set's matcher.
|
||||
*
|
||||
* @throws IllegalArgumentException if an ignore set record has a path that cannot be used as a
|
||||
* valid pattern by this ignore set's matcher
|
||||
*/
|
||||
private void validateMatcherPattern(final String ignoreRecordPattern)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
// the exception will be thrown here if a pattern cannot be added to the matcher
|
||||
RegexFilePathMatcher matcher = new RegexFilePathMatcher("default pattern");
|
||||
matcher.setPatterns(ignoreRecordPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove IMA Ignore Set record from baseline.
|
||||
*
|
||||
* @param record
|
||||
* to remove from baseline
|
||||
* @return a boolean indicated whether or not the ima ignore record was
|
||||
* successfully removed from the list.
|
||||
*/
|
||||
public final boolean removeFromBaseline(final ImaIgnoreSetRecord record) {
|
||||
LOGGER.debug("removing record {} from baseline {}", record, getName());
|
||||
if (record == null) {
|
||||
LOGGER.error("null record");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean retVal = imaIgnoreSetRecords.remove(record);
|
||||
if (retVal) {
|
||||
record.setBaseline(null);
|
||||
}
|
||||
|
||||
LOGGER.debug("record removed: {}", record);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BatchImaMatchStatus indicating, for each of the given records, whether a matching
|
||||
* entry is contained in this ignore set baseline. The match status will be MATCH if one
|
||||
* of the following cases applies:
|
||||
*
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>if any of of the ignore set records contain a regex that matches the given path</li>
|
||||
* <li>if any of of the ignore set records are an exact match with the given path</li>
|
||||
* <li>if any of of the ignore set records are the initial substring of the given path</li>
|
||||
* <li>if any of of the ignore set records are partial paths and the given path is a full path
|
||||
* with the same filename</li>
|
||||
* <li>if the given path is a partial path and any of of the ignore set records are full paths
|
||||
* with the same filename</li>
|
||||
* </ul>
|
||||
*
|
||||
* Otherwise, a record's match status will be UNKNOWN.
|
||||
*
|
||||
* @param records
|
||||
* measurement records to find in this baseline
|
||||
* @param recordManager
|
||||
* an ImaBaselineRecordManager that can be used to retrieve persisted records
|
||||
* @param imaPolicy
|
||||
* the IMA policy to use while determining if a baseline contains the given records
|
||||
*
|
||||
* @return a BatchImaMatchStatus containing the match status for the given records
|
||||
*/
|
||||
public final BatchImaMatchStatus<ImaIgnoreSetRecord> contains(
|
||||
final Collection<IMAMeasurementRecord> records,
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final IMAPolicy imaPolicy
|
||||
) {
|
||||
Preconditions.checkArgument(records != null, "Records cannot be null");
|
||||
Preconditions.checkArgument(imaPolicy != null, "IMA policy cannot be null");
|
||||
return new ImaIgnoreSetRecordMatcher(imaIgnoreSetRecords, imaPolicy, this)
|
||||
.batchMatch(records);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of file paths in this IMA Ignore Set in this Baseline.
|
||||
*
|
||||
* @return list of optional measurement records representing optional list
|
||||
*/
|
||||
@JsonIgnore
|
||||
public final synchronized Set<ImaIgnoreSetRecord> getImaIgnoreRecords() {
|
||||
return Collections.unmodifiableSet(imaIgnoreSetRecords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual <code>Set</code> that contains the IMA records. Needed for
|
||||
* Hibernate due to the AccessType.FIELD configuration on the IMA baseline classes.
|
||||
*
|
||||
* @return IMA ignore set records
|
||||
*/
|
||||
private Set<ImaIgnoreSetRecord> getImaIgnoreSetRecords() {
|
||||
return imaIgnoreSetRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the IMA Ignore records. Needed for Hibernate due to the AccessType.FIELD
|
||||
* configuration on the IMA baseline classes.
|
||||
*
|
||||
* @param imaIgnoreSetRecords IMA ignore set records to set
|
||||
*/
|
||||
private void setImaIgnoreSetRecords(final Set<ImaIgnoreSetRecord> imaIgnoreSetRecords) {
|
||||
this.imaIgnoreSetRecords = imaIgnoreSetRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an IMA ignore record to this IMA ignore baseline. If the record does not exist
|
||||
* then it is added. If an equal record exists, based upon
|
||||
* {@link ImaIgnoreSetRecord#equals(Object)}, then this method quietly ignores the
|
||||
* request to add the record because one already exists in the baseline.
|
||||
*
|
||||
* @param record
|
||||
* record to add to baseline
|
||||
* @return
|
||||
* returns true is the record was added to the list, false if not
|
||||
*/
|
||||
public final synchronized boolean addOnlyToBaseline(final ImaIgnoreSetRecord record) {
|
||||
if (record == null) {
|
||||
LOGGER.error("invalid parameter (NULL value) "
|
||||
+ "passed to ImaIgnoreSetBaseline.addOnlyToBaseline");
|
||||
throw new IllegalArgumentException("null ignore set record");
|
||||
}
|
||||
if (imaIgnoreSetRecords.add(record)) {
|
||||
LOGGER.info("added file path " + record.getPath()
|
||||
+ " to ImaIgnoreSetBaseline " + getName());
|
||||
} else {
|
||||
LOGGER.info("file path" + record.getPath()
|
||||
+ " already added to ImaIgnoreSetBaseline " + getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove IMA Ignore record from the baseline.
|
||||
*
|
||||
* @param record
|
||||
* record to remove
|
||||
* @return a boolean indicating if the removal was successful
|
||||
*/
|
||||
public final boolean removeOnlyBaseline(final ImaIgnoreSetRecord record) {
|
||||
return imaIgnoreSetRecords.remove(record);
|
||||
}
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.ima.matching.BatchImaMatchStatus;
|
||||
import hirs.ima.matching.IMAMatchStatus;
|
||||
import hirs.ima.matching.ImaAcceptableHashRecordMatcher;
|
||||
import hirs.ima.matching.ImaAcceptablePathAndHashRecordMatcher;
|
||||
import hirs.ima.matching.ImaRecordMatcher;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
import hirs.utils.Callback;
|
||||
import org.hibernate.Criteria;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This class defines the basis of operation for a baseline that supports querying
|
||||
* a persistence layer for its component {@link IMABaselineRecord}s. A QueryableRecordImaBaseline
|
||||
* uses this functionality to implement its <code>contains</code> method.
|
||||
*/
|
||||
public abstract class QueryableRecordImaBaseline extends ImaAcceptableRecordBaseline {
|
||||
/**
|
||||
* Constructor used to initialize an <code>QueryableRecordImaBaseline</code> with a name.
|
||||
*
|
||||
* @param name the name of the new baseline
|
||||
*/
|
||||
public QueryableRecordImaBaseline(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected QueryableRecordImaBaseline() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check membership of the given {@link IMAMeasurementRecord}s in this baseline.
|
||||
*
|
||||
* @param records the records to attempt to match
|
||||
* @param recordManager the {@link ImaBaselineRecordManager} to query
|
||||
* @param imaPolicy the IMA policy to use while determining if a baseline contains the records
|
||||
*
|
||||
* @return a collection of {@link IMAMatchStatus}es reflecting the results
|
||||
*/
|
||||
@Override
|
||||
public final BatchImaMatchStatus<IMABaselineRecord> contains(
|
||||
final Collection<IMAMeasurementRecord> records,
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final IMAPolicy imaPolicy) {
|
||||
Preconditions.checkArgument(records != null, "records cannot be null");
|
||||
Preconditions.checkArgument(recordManager != null, "record manager cannot be null");
|
||||
|
||||
final Collection<String> pathsToFind = new HashSet<>();
|
||||
for (IMAMeasurementRecord record : records) {
|
||||
if (record != null) {
|
||||
pathsToFind.addAll(ImaRecordMatcher.getMatchingPaths(imaPolicy, record.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
Collection<IMABaselineRecord> retrievedRecords = recordManager.iterateOverBaselineRecords(
|
||||
this, new Callback<IMABaselineRecord, IMABaselineRecord>() {
|
||||
@Override
|
||||
public IMABaselineRecord call(final IMABaselineRecord baselineRecord) {
|
||||
if (pathsToFind.contains(baselineRecord.getPath())) {
|
||||
return baselineRecord;
|
||||
} else if (imaPolicy.isPartialPathEnable()
|
||||
&& pathsToFind.contains(baselineRecord.getPartialPath())) {
|
||||
return baselineRecord;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return new ImaAcceptablePathAndHashRecordMatcher(retrievedRecords, imaPolicy, this)
|
||||
.batchMatch(records);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check membership of the given {@link IMAMeasurementRecord}s in this baseline.
|
||||
*
|
||||
* @param records the records to attempt to match
|
||||
* @param recordManager the {@link ImaBaselineRecordManager} to query
|
||||
* @param imaPolicy the IMA policy to use while determining if a baseline contains the records
|
||||
*
|
||||
* @return a collection of {@link IMAMatchStatus}es reflecting the results
|
||||
*/
|
||||
@Override
|
||||
public final BatchImaMatchStatus<IMABaselineRecord> containsHashes(
|
||||
final Collection<IMAMeasurementRecord> records,
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final IMAPolicy imaPolicy) {
|
||||
Preconditions.checkArgument(records != null, "records cannot be null");
|
||||
Preconditions.checkArgument(recordManager != null, "record manager cannot be null");
|
||||
|
||||
final Set<Digest> hashesToFind = records.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(IMAMeasurementRecord::getHash)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Collection<IMABaselineRecord> retrievedRecords = recordManager.iterateOverBaselineRecords(
|
||||
this, new Callback<IMABaselineRecord, IMABaselineRecord>() {
|
||||
@Override
|
||||
public IMABaselineRecord call(final IMABaselineRecord baselineRecord) {
|
||||
if (hashesToFind.contains(baselineRecord.getHash())) {
|
||||
return baselineRecord;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return new ImaAcceptableHashRecordMatcher(retrievedRecords, imaPolicy, this)
|
||||
.batchMatch(records);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Collection<IMABaselineRecord> getRecordsExcept(
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final Set<IMABaselineRecord> foundRecords) {
|
||||
if (foundRecords == null) {
|
||||
throw new IllegalArgumentException("foundRecords cannot be null");
|
||||
}
|
||||
|
||||
if (recordManager == null) {
|
||||
throw new IllegalArgumentException("ImaBaselineRecordManager cannot be null");
|
||||
}
|
||||
|
||||
return recordManager.iterateOverBaselineRecords(
|
||||
this, new Callback<IMABaselineRecord, IMABaselineRecord>() {
|
||||
@Override
|
||||
public IMABaselineRecord call(final IMABaselineRecord param) {
|
||||
if (!foundRecords.contains(param)) {
|
||||
return param;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method configures the provided criteria to retrieve all of its component
|
||||
* {@link IMABaselineRecord}s. The given bucket should be used by the receiving code
|
||||
* to only retrieve {@link IMABaselineRecord}s that are in the given bucket.
|
||||
*
|
||||
* @param criteria the criteria to configure
|
||||
* @param bucket the bucket that should be configured on the criteria
|
||||
*/
|
||||
public abstract void configureCriteriaForBaselineRecords(Criteria criteria, int bucket);
|
||||
}
|
@ -1,308 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.ima.matching.BatchImaMatchStatus;
|
||||
import hirs.ima.matching.ImaAcceptableHashRecordMatcher;
|
||||
import hirs.ima.matching.ImaAcceptablePathAndHashRecordMatcher;
|
||||
import hirs.persist.ImaBaselineRecordManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* Class represents a simple, flexible IMA measurement baseline. A baseline contains one or more
|
||||
* IMA records. A baseline is used to define a collection of approved files that
|
||||
* may be accessed or executed on an IMA supported computing platform. Each IMA
|
||||
* record contains information pertaining to a specific file including file name
|
||||
* and path, file hash, and other file attributes.
|
||||
* <p>
|
||||
* An IMA record can be either a full path record or a partial path record. Both
|
||||
* types can always be added to a baseline, but when a baseline is checked using
|
||||
* the contains() method, a parameter is passed in to determine whether or not
|
||||
* partial path records can be considered.
|
||||
* <p>
|
||||
* NOTE: This class is not thread-safe.
|
||||
*/
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
public class SimpleImaBaseline extends ImaAcceptableRecordBaseline {
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
|
||||
orphanRemoval = true, mappedBy = "baseline")
|
||||
@Access(AccessType.PROPERTY)
|
||||
@JsonIgnore
|
||||
private Set<IMABaselineRecord> imaRecords;
|
||||
|
||||
@Column(nullable = true)
|
||||
private URL yumRepoURL;
|
||||
|
||||
private static final Logger LOGGER = getLogger(ImaBaseline.class);
|
||||
|
||||
/**
|
||||
* Constructor used to initialize ImaBaseline object. Partial path support
|
||||
* is not enabled by default. Makes an empty <code>Set</code> of
|
||||
* <code>IMABaselineRecord</code>s and initializes the date to the current
|
||||
* date.
|
||||
*
|
||||
* @param name
|
||||
* a name used to uniquely identify and reference the IMA
|
||||
* baseline
|
||||
*/
|
||||
public SimpleImaBaseline(final String name) {
|
||||
super(name);
|
||||
imaRecords = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to initialize an ImaBaseline object with a link to a Yum repository.
|
||||
*
|
||||
* @param name the name for this ImaBaseline
|
||||
* @param yumRepoURL the base URL of the repository from which to add package measurements
|
||||
*/
|
||||
public SimpleImaBaseline(final String name, final URL yumRepoURL) {
|
||||
this(name);
|
||||
this.yumRepoURL = yumRepoURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate and BaselineAlertResolver. Makes an empty
|
||||
* <code>Set</code> of <code>IMABaselineRecord</code>s.
|
||||
*/
|
||||
public SimpleImaBaseline() {
|
||||
super();
|
||||
imaRecords = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an unmodifiable set of IMA baseline records found in the IMA
|
||||
* baseline. The returned set only contains the baseline records from this
|
||||
* baseline.
|
||||
*
|
||||
* @return list of IMA records
|
||||
*/
|
||||
public final synchronized Set<IMABaselineRecord> getBaselineRecords() {
|
||||
return Collections.unmodifiableSet(imaRecords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a record to this baseline. If the record is not already part of the baseline,
|
||||
* then it is added. If an equal record is already part of the baseline, then the
|
||||
* request to add the record will be quietly ignored. This method also sets
|
||||
* <code>Baseline</code> field on the <code>IMABaselineRecord</code>.
|
||||
*
|
||||
* @param record
|
||||
* record to add to the baseline
|
||||
* @return
|
||||
* returns true if record was added to the baseline, false if it wasn't
|
||||
*/
|
||||
public final boolean addToBaseline(final IMABaselineRecord record) {
|
||||
record.setOnlyBaseline(this);
|
||||
return addOnlyToBaseline(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove IMA record from baseline.
|
||||
*
|
||||
* @param record
|
||||
* to remove from baseline
|
||||
* @return a boolean indicated whether or not the ima record was
|
||||
* successfully removed from the list.
|
||||
*/
|
||||
public final boolean removeFromBaseline(final IMABaselineRecord record) {
|
||||
LOGGER.debug("removing record {} from baseline {}", record, getName());
|
||||
if (record == null) {
|
||||
LOGGER.error("null record");
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean retVal = imaRecords.remove(record);
|
||||
if (retVal) {
|
||||
record.setBaseline(null);
|
||||
}
|
||||
LOGGER.debug("record removed: {}", record);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a collection of records are found in the baseline. This returns a
|
||||
* <code>BatchImaMatchStatus</code> representing the result of the search for
|
||||
* the records, which is itself a mapping of IMAMeasurementRecords to IMAMatchStatuses.
|
||||
* IMAMatchStatus conditions are as follows:
|
||||
* <ul>
|
||||
* <li>MATCH - if an <code>IMABaselineRecord</code> is found with a matching
|
||||
* path and hash</li>
|
||||
* <li>MISMATCH - if at least one <code>IMABaselineRecord</code> is found
|
||||
* with a matching path but none with a matching path and hash</li>
|
||||
* <li>UNKNOWN - if no <code>IMABaselineRecord</code>s found with a matching
|
||||
* path</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* If partial paths are enabled, records not starting with '/' are compared
|
||||
* against all baseline records not starting with '/' and the last segment
|
||||
* (the filename after the last '/') of each full path baseline record.
|
||||
* Records starting with '/' are compared against all full path baseline
|
||||
* records and the last segment of the record is compared against all
|
||||
* partial path baseline records.
|
||||
* <p>
|
||||
* If partial paths are disabled, records are only compared using the full
|
||||
* path of the baseline record and the report record.
|
||||
*
|
||||
* @param records
|
||||
* measurement records
|
||||
* @param recordManager
|
||||
* an ImaBaselineRecordManager that can be used to retrieve persisted records
|
||||
* @param imaPolicy
|
||||
* the IMA policy to use while determining if a baseline contains the records
|
||||
* @return search status for the measurement record
|
||||
*/
|
||||
@Override
|
||||
public final BatchImaMatchStatus<IMABaselineRecord> contains(
|
||||
final Collection<IMAMeasurementRecord> records,
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final IMAPolicy imaPolicy) {
|
||||
Preconditions.checkArgument(records != null, "Records cannot be null");
|
||||
Preconditions.checkArgument(imaPolicy != null, "IMA policy cannot be null");
|
||||
|
||||
return new ImaAcceptablePathAndHashRecordMatcher(imaRecords, imaPolicy, this)
|
||||
.batchMatch(records);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BatchImaMatchStatus<IMABaselineRecord> containsHashes(
|
||||
final Collection<IMAMeasurementRecord> records,
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final IMAPolicy imaPolicy) {
|
||||
Preconditions.checkArgument(records != null, "Records cannot be null");
|
||||
Preconditions.checkArgument(imaPolicy != null, "IMA policy cannot be null");
|
||||
|
||||
return new ImaAcceptableHashRecordMatcher(imaRecords, imaPolicy, this)
|
||||
.batchMatch(records);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<IMABaselineRecord> getRecordsExcept(
|
||||
final ImaBaselineRecordManager recordManager,
|
||||
final Set<IMABaselineRecord> foundRecords) {
|
||||
if (foundRecords == null) {
|
||||
throw new IllegalArgumentException("foundRecords cannot be null");
|
||||
}
|
||||
|
||||
if (recordManager == null) {
|
||||
throw new IllegalArgumentException("ImaBaselineRecordManager cannot be null");
|
||||
}
|
||||
|
||||
Set<IMABaselineRecord> leftover = new HashSet<>();
|
||||
leftover.addAll(imaRecords);
|
||||
leftover.removeAll(foundRecords);
|
||||
return leftover;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Yum Repo URL.
|
||||
*
|
||||
* @param yumRepoURL a URL to the yum repository that measurements will be gathered from
|
||||
*/
|
||||
public final void setYumRepoURL(final URL yumRepoURL) {
|
||||
this.yumRepoURL = yumRepoURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Yum Repo URL.
|
||||
*
|
||||
* @return the Yum repository URL
|
||||
*/
|
||||
public final URL getYumRepoURL() {
|
||||
return yumRepoURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an IMA record to this IMA baseline. If the record does not exist
|
||||
* then it is added. If an equal record exists, based upon
|
||||
* {@link IMABaselineRecord#equals(Object)}, then this method quietly
|
||||
* ignores the request to add the record because one already exists in the
|
||||
* baseline.
|
||||
*
|
||||
* @param record
|
||||
* record to add to baseline
|
||||
* @return
|
||||
* returns true is the record was added to the list, false if not
|
||||
*/
|
||||
final synchronized boolean addOnlyToBaseline(final IMABaselineRecord record) {
|
||||
LOGGER.debug("adding record {} to baseline {}", record, getName());
|
||||
if (record == null) {
|
||||
LOGGER.error("null record");
|
||||
throw new NullPointerException("record");
|
||||
}
|
||||
|
||||
if (imaRecords.contains(record)) {
|
||||
final String msg = String.format(
|
||||
"record already exists in baseline: %s", record);
|
||||
LOGGER.debug(msg);
|
||||
|
||||
return false;
|
||||
|
||||
} else {
|
||||
imaRecords.add(record);
|
||||
LOGGER.debug("record added: {}", record);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove record from the baseline.
|
||||
*
|
||||
* @param record
|
||||
* record to remove
|
||||
* @return a boolean indicating if the removal was successful
|
||||
*/
|
||||
final boolean removeOnlyBaseline(final IMABaselineRecord record) {
|
||||
return imaRecords.remove(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual <code>Set</code> that contains the IMA records. See
|
||||
* {@link #setImaRecords(Set)} for more details on why this is needed.
|
||||
*
|
||||
* @return IMA records
|
||||
*/
|
||||
private Set<IMABaselineRecord> getImaRecords() {
|
||||
return imaRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the IMA records. This is needed for Hibernate. The issue is that
|
||||
* this class needs to be aware of when the <code>imaRecords</code>
|
||||
* <code>Set</code> is set. This allows isUpdateNeeded to be set, indicating
|
||||
* that the transient elements fullMap and partialMap should be populated
|
||||
* using the imaRecords set that comes back from the database. This method
|
||||
* should only be invoked by Hibernate.
|
||||
* <p>
|
||||
* Hibernate cannot use a public method like
|
||||
* {@link #getAllMeasurementRecords()} and a corresponding private setter
|
||||
* method. The reason is that the set pointer would be changing and confuse
|
||||
* Hibernate.
|
||||
*
|
||||
* @param imaRecords IMA records
|
||||
*/
|
||||
private void setImaRecords(final Set<IMABaselineRecord> imaRecords) {
|
||||
this.imaRecords = imaRecords;
|
||||
}
|
||||
}
|
@ -1,288 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import hirs.data.persist.DeviceInfoReport;
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.info.FirmwareInfo;
|
||||
import hirs.data.persist.info.HardwareInfo;
|
||||
import hirs.data.persist.info.OSInfo;
|
||||
import hirs.data.persist.info.TPMInfo;
|
||||
import hirs.data.persist.TPMMeasurementRecord;
|
||||
import hirs.data.persist.info.RIMInfo;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Class represents a Trusted Platform Module (TPM) measurement baseline. A TPM baseline consists of
|
||||
* a set of <code>TPMMeasurementRecord</code>s. The set of
|
||||
* <code>TPMMeasurementRecord</code>s may have multiple entries for the same PCR ID. This is useful
|
||||
* for scenarios where the PCR may have a few possible valid entries.
|
||||
*/
|
||||
@Entity
|
||||
public abstract class TPMBaseline extends Baseline {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(TPMBaseline.class);
|
||||
|
||||
@ElementCollection(fetch = FetchType.EAGER)
|
||||
@CollectionTable(name = "TPMBaselineRecords",
|
||||
joinColumns = { @JoinColumn(name = "BaselineID", nullable = false) })
|
||||
private final Set<TPMMeasurementRecord> pcrRecords = new LinkedHashSet<>();
|
||||
|
||||
@Embedded
|
||||
private FirmwareInfo firmwareInfo;
|
||||
|
||||
@Embedded
|
||||
private HardwareInfo hardwareInfo;
|
||||
|
||||
@Embedded
|
||||
private OSInfo osInfo;
|
||||
|
||||
@Embedded
|
||||
private TPMInfo tpmInfo;
|
||||
|
||||
@Embedded
|
||||
private RIMInfo rimInfo;
|
||||
|
||||
/**
|
||||
* Creates a new <code>TPMBaseline</code> with no valid PCR entries and no device-specific PCRs.
|
||||
*
|
||||
* @param name
|
||||
* a name used to uniquely identify and reference the PCR baseline
|
||||
*/
|
||||
public TPMBaseline(final String name) {
|
||||
super(name);
|
||||
initDeviceInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate and BaselineAlertResolver.
|
||||
*/
|
||||
public TPMBaseline() {
|
||||
super();
|
||||
initDeviceInfo();
|
||||
}
|
||||
|
||||
private void initDeviceInfo() {
|
||||
firmwareInfo = new FirmwareInfo();
|
||||
hardwareInfo = new HardwareInfo();
|
||||
osInfo = new OSInfo();
|
||||
tpmInfo = new TPMInfo();
|
||||
rimInfo = new RIMInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the FirmwareInfo for this <code>TPMBaseline</code>.
|
||||
* @return FirmwareInfo
|
||||
*/
|
||||
public final FirmwareInfo getFirmwareInfo() {
|
||||
return firmwareInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the HardwareInfo for this <code>TPMBaseline</code>.
|
||||
* @return HardwareInfo
|
||||
*/
|
||||
public final HardwareInfo getHardwareInfo() {
|
||||
return hardwareInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the OSInfo for this <code>TPMBaseline</code>.
|
||||
* @return OSInfo
|
||||
*/
|
||||
public final OSInfo getOSInfo() {
|
||||
return osInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the TPMInfo for this <code>TPMBaseline</code>.
|
||||
* @return TPMInfo
|
||||
*/
|
||||
public final TPMInfo getTPMInfo() {
|
||||
return tpmInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the RIMInfo for this <code>TPMBaseline</code>.
|
||||
* @return an instance of RIMInfo
|
||||
*/
|
||||
public final RIMInfo getRIMInfo() {
|
||||
return rimInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the Firmware data from another object. If null, the default
|
||||
* FirmwareInfo data will be used.
|
||||
* @param firmwareInfo FirmwareInfo object or null.
|
||||
*/
|
||||
public final void setFirmwareInfo(final FirmwareInfo firmwareInfo) {
|
||||
if (firmwareInfo == null) {
|
||||
this.firmwareInfo = new FirmwareInfo();
|
||||
} else {
|
||||
this.firmwareInfo = firmwareInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the Hardware data from another object. If null, the default
|
||||
* HardwareInfo data will be used.
|
||||
* @param hardwareInfo HardwareInfo object or null.
|
||||
*/
|
||||
public final void setHardwareInfo(final HardwareInfo hardwareInfo) {
|
||||
if (hardwareInfo == null) {
|
||||
this.hardwareInfo = new HardwareInfo();
|
||||
} else {
|
||||
this.hardwareInfo = hardwareInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the OSInfo data from another object. If null, the default
|
||||
* OSInfo data will be used.
|
||||
* @param osInfo OSInfo object or null.
|
||||
*/
|
||||
public final void setOSInfo(final OSInfo osInfo) {
|
||||
if (osInfo == null) {
|
||||
this.osInfo = new OSInfo();
|
||||
} else {
|
||||
this.osInfo = osInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the TPMInfo data from another object. If null, the default
|
||||
* TPMInfo data will be used.
|
||||
* @param tpmInfo TPMInfo object or null.
|
||||
*/
|
||||
public final void setTPMInfo(final TPMInfo tpmInfo) {
|
||||
if (tpmInfo == null) {
|
||||
this.tpmInfo = new TPMInfo();
|
||||
} else {
|
||||
this.tpmInfo = tpmInfo;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns acceptable hash values for a PCR ID. This returns a set of all the acceptable PCR
|
||||
* hash values. The set may be empty if none are found.
|
||||
*
|
||||
* @param pcrId
|
||||
* PCR index
|
||||
* @return list of acceptable hash values
|
||||
*/
|
||||
public final Set<Digest> getPCRHashes(final int pcrId) {
|
||||
TPMMeasurementRecord.checkForValidPcrId(pcrId);
|
||||
final Set<Digest> ret = new LinkedHashSet<>();
|
||||
for (TPMMeasurementRecord record : pcrRecords) {
|
||||
if (record.getPcrId() == pcrId) {
|
||||
ret.add(record.getHash());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of all PCR records associated with baseline.
|
||||
*
|
||||
* @return set of PCR records found in TPM baseline
|
||||
*/
|
||||
public final Set<TPMMeasurementRecord> getPcrRecords() {
|
||||
return Collections.unmodifiableSet(pcrRecords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches this baseline for the supplied <code>TPMMeasurementRecord</code> . This returns true
|
||||
* if a measurement record was found with a matching PCR ID and hash value. Otherwise this
|
||||
* returns false.
|
||||
*
|
||||
* @param record
|
||||
* record to find
|
||||
* @return true if measurement record is found in list, otherwise false
|
||||
*/
|
||||
public final boolean isInBaseline(final TPMMeasurementRecord record) {
|
||||
return pcrRecords.contains(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PCR measurement record to baseline. If there is already a measurement with the same
|
||||
* PCR ID and hash value then an <code>IllegalArgumentException</code> is thrown.
|
||||
*
|
||||
* @param record
|
||||
* record to add to TPM baseline
|
||||
*/
|
||||
public final void addToBaseline(final TPMMeasurementRecord record) {
|
||||
LOGGER.debug("adding record {} to baseline {}", record, getName());
|
||||
if (record == null) {
|
||||
LOGGER.error("null record");
|
||||
throw new NullPointerException("TPMMeasurementRecord");
|
||||
}
|
||||
|
||||
if (pcrRecords.contains(record)) {
|
||||
final String msg = String.format("record already exist: %s", record);
|
||||
LOGGER.info(msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
pcrRecords.add(record);
|
||||
LOGGER.debug("record added");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the <code>TPMMeasurementRecord</code> from this baseline. If the record is found and
|
||||
* successfully removed then true is returned. Otherwise false is returned.
|
||||
*
|
||||
* @param record
|
||||
* record to remove from baseline
|
||||
* @return true if found and removed, otherwise false
|
||||
*/
|
||||
public final boolean removeFromBaseline(final TPMMeasurementRecord record) {
|
||||
LOGGER.debug("removing record {} from baseline {}", record, getName());
|
||||
if (record == null) {
|
||||
LOGGER.error("null record can not be removed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return pcrRecords.remove(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the properties of FirmwareInfo, HardwareInfo, OSInfo, and TPMInfo and the contents of
|
||||
* pcrRecords to determine if this instance of TPMBaseline is empty or not.
|
||||
*
|
||||
* @return true if baseline has no data
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
LOGGER.debug("Check for empty baseline");
|
||||
return (firmwareInfo.getBiosReleaseDate().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& firmwareInfo.getBiosVendor().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& firmwareInfo.getBiosVersion().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& hardwareInfo.getBaseboardSerialNumber().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& hardwareInfo.getChassisSerialNumber().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& hardwareInfo.getManufacturer().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& hardwareInfo.getProductName().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& hardwareInfo.getSystemSerialNumber().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& hardwareInfo.getVersion().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& osInfo.getDistribution().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& osInfo.getDistributionRelease().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& osInfo.getOSArch().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& osInfo.getOSName().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& osInfo.getOSVersion().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& tpmInfo.getTPMMake().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& tpmInfo.getTPMVersionMajor() == 0
|
||||
&& tpmInfo.getTPMVersionMinor() == 0
|
||||
&& tpmInfo.getTPMVersionRevMajor() == 0
|
||||
&& tpmInfo.getTPMVersionRevMinor() == 0
|
||||
&& rimInfo.getRimManufacturer().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& rimInfo.getModel().equals(DeviceInfoReport.NOT_SPECIFIED)
|
||||
&& pcrRecords.isEmpty());
|
||||
}
|
||||
}
|
@ -1,244 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import hirs.persist.RepositoryManager;
|
||||
import hirs.repository.RepoPackage;
|
||||
import hirs.repository.Repository;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
* An IMA baseline that references a specified set of <code>RepoPackage</code>s. These packages are
|
||||
* used during appraisal to generate a set of measurement records. An update() will use the source
|
||||
* repository referenced within each package to refresh the measurements of that package.
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Access(AccessType.FIELD)
|
||||
public class TargetedRepoImaBaseline extends QueryableRecordImaBaseline
|
||||
implements UpdatableImaBaseline {
|
||||
private static final Logger LOGGER = LogManager.getLogger(TargetedRepoImaBaseline.class);
|
||||
private static final int MAX_REPO_CACHE_SIZE = 10;
|
||||
|
||||
/**
|
||||
* Name of the repoPackages field.
|
||||
*/
|
||||
public static final String REPO_PACKAGES_FIELD = "repoPackages";
|
||||
|
||||
/**
|
||||
* The packages used for an appraisal against this baseline.
|
||||
*/
|
||||
@OneToMany(fetch = FetchType.EAGER)
|
||||
private Set<RepoPackage> repoPackages;
|
||||
|
||||
@Transient
|
||||
private final Set<IMABaselineRecord> cachedBaselineRecords = new HashSet<>();
|
||||
|
||||
@Transient
|
||||
private boolean shouldUpdateCache = true;
|
||||
|
||||
/**
|
||||
* Constructor used to initialize a <code>TargetedRepoImaBaseline</code> with the given name and
|
||||
* an empty <code>Set</code> of <code>RepoPackage</code>s.
|
||||
* @param name the name of the new baseline
|
||||
*/
|
||||
public TargetedRepoImaBaseline(final String name) {
|
||||
super(name);
|
||||
repoPackages = new HashSet<>();
|
||||
}
|
||||
|
||||
/** Default constructor necessary for Hibernate. Makes an empty <code>Set</code> of
|
||||
* <code>RepoPackage</code>s.
|
||||
*/
|
||||
protected TargetedRepoImaBaseline() {
|
||||
super();
|
||||
repoPackages = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through the <code>RepoPackage</code>s referenced in this baseline and check the
|
||||
* associated repository for any updated versions or releases.
|
||||
*
|
||||
* @param repositoryManager a repository manager to use to gather data about repositories, or
|
||||
* null if object already contains all info (no lazy-loaded data)
|
||||
*/
|
||||
@Override
|
||||
public final void update(final RepositoryManager repositoryManager) {
|
||||
LoadingCache<UUID, Repository<? extends RepoPackage>> repositoryCache =
|
||||
CacheBuilder.newBuilder()
|
||||
.maximumSize(MAX_REPO_CACHE_SIZE)
|
||||
.build(
|
||||
new CacheLoader<UUID, Repository<? extends RepoPackage>>() {
|
||||
@Override
|
||||
public Repository<? extends RepoPackage> load(final UUID id)
|
||||
throws Exception {
|
||||
LOGGER.debug("Retrieving repository {}", id);
|
||||
return repositoryManager.getRepository(id);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Set<RepoPackage> newPackages = new HashSet<>();
|
||||
Repository<? extends RepoPackage> repoWithPackages;
|
||||
|
||||
for (RepoPackage baselineRepoPackage : repoPackages) {
|
||||
try {
|
||||
if (repositoryManager != null) {
|
||||
repoWithPackages = repositoryCache.get(
|
||||
baselineRepoPackage.getSourceRepository().getId()
|
||||
);
|
||||
} else {
|
||||
repoWithPackages = baselineRepoPackage.getSourceRepository();
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
throw new RuntimeException("Couldn't retrieve persisted repository via cache.");
|
||||
}
|
||||
newPackages.addAll(repoWithPackages.getUpdatedPackages(baselineRepoPackage));
|
||||
}
|
||||
|
||||
repoPackages.addAll(newPackages);
|
||||
|
||||
synchronized (cachedBaselineRecords) {
|
||||
this.shouldUpdateCache = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<IMABaselineRecord> getBaselineRecords() {
|
||||
synchronized (cachedBaselineRecords) {
|
||||
if (!shouldUpdateCache) {
|
||||
return Collections.unmodifiableSet(cachedBaselineRecords);
|
||||
}
|
||||
|
||||
cachedBaselineRecords.clear();
|
||||
for (RepoPackage repoPackage : repoPackages) {
|
||||
cachedBaselineRecords.addAll(repoPackage.getPackageRecords());
|
||||
}
|
||||
shouldUpdateCache = false;
|
||||
|
||||
return Collections.unmodifiableSet(cachedBaselineRecords);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureCriteriaForBaselineRecords(final Criteria criteria, final int bucket) {
|
||||
criteria.add(Restrictions.eq("id", getId()))
|
||||
.setProjection(Projections.projectionList()
|
||||
.add(Projections.property(
|
||||
String.format("%s.%s",
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD,
|
||||
IMABaselineRecord.PATH_FIELD)
|
||||
), IMABaselineRecord.PATH_FIELD)
|
||||
.add(Projections.property(
|
||||
String.format("%s.%s",
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD,
|
||||
IMABaselineRecord.HASH_FIELD)
|
||||
), IMABaselineRecord.HASH_FIELD)
|
||||
);
|
||||
|
||||
criteria.add(Restrictions.eq(
|
||||
String.format("%s.%s",
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD,
|
||||
IMABaselineRecord.BUCKET_FIELD),
|
||||
bucket)
|
||||
);
|
||||
criteria.createAlias(REPO_PACKAGES_FIELD, REPO_PACKAGES_FIELD);
|
||||
criteria.createAlias(
|
||||
String.format("%s.%s", REPO_PACKAGES_FIELD, RepoPackage.PACKAGE_RECORDS_FIELD),
|
||||
RepoPackage.PACKAGE_RECORDS_FIELD
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the <code>Set</code> of <code>RepoPackage</code>s associated with this baseline.
|
||||
*
|
||||
* @return the RepoPackages tracked by this baseline
|
||||
*/
|
||||
public final Set<RepoPackage> getRepositoryPackages() {
|
||||
return Collections.unmodifiableSet(repoPackages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual <code>Set</code> that contains the IMA records. This is needed for
|
||||
* Hibernate.
|
||||
*
|
||||
* @return RepoPackages
|
||||
*/
|
||||
private Set<RepoPackage> getRepoPackages() {
|
||||
return this.repoPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the <code>Set</code> of <code>RepoPackage</code>s associated with this baseline. Also
|
||||
* flips the map update needed flags so the next call to contains will require map updates.
|
||||
*
|
||||
* @param newRepoPackages the new RepoPackages to be tracked by this baseline
|
||||
*/
|
||||
public final void setRepoPackages(final Set<RepoPackage> newRepoPackages) {
|
||||
this.repoPackages = newRepoPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the <code>Set</code> of <code>RepoPackage</code>s. Also
|
||||
* flips the map update needed flags so the next call to contains will require map updates.
|
||||
*
|
||||
* @param repoPackage the new RepoPackage to be tracked by this baseline
|
||||
*/
|
||||
public final void addRepoPackage(final RepoPackage repoPackage) {
|
||||
this.repoPackages.add(repoPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes from the <code>Set</code> of <code>RepoPackage</code>s. Also
|
||||
* flips the map update needed flags so the next call to contains will require map updates.
|
||||
*
|
||||
* @param repoPackage this package should no longer be tracked by this baseline
|
||||
*/
|
||||
public final void removeRepoPackage(final RepoPackage repoPackage) {
|
||||
this.repoPackages.remove(repoPackage);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if this baseline's set of packages is associated with the specified set of
|
||||
* repositories. This is determined by checking each repo package's source repository.
|
||||
* @param repositories the set of repositories to check for association
|
||||
* @return true if any repository packages are linked to the set of specified repositories
|
||||
*/
|
||||
public boolean isAssociatedWithRepositories(final Collection<Repository> repositories) {
|
||||
|
||||
Set<RepoPackage> repositoryPackages = getRepositoryPackages();
|
||||
|
||||
if (CollectionUtils.isEmpty(repositoryPackages) || CollectionUtils.isEmpty(repositories)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (RepoPackage repoPackage : repositoryPackages) {
|
||||
if (repositories.contains(repoPackage.getSourceRepository())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* A {@link TPMBaseline} that represents TPM measurement values that are not allowed in the system.
|
||||
* If a device provides a TPM Report that includes TPM measurements matching a blacklist in its
|
||||
* TPM Policy, an alert will be generated.
|
||||
*/
|
||||
@Entity
|
||||
public class TpmBlackListBaseline extends TPMBaseline {
|
||||
|
||||
/**
|
||||
* Creates a new baseline with no PCR.
|
||||
*
|
||||
* @param name
|
||||
* a name used to uniquely identify and reference the PCR baseline
|
||||
*/
|
||||
public TpmBlackListBaseline(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate and BaselineAlertResolver.
|
||||
*/
|
||||
public TpmBlackListBaseline() {
|
||||
super();
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
/**
|
||||
* A {@link TPMBaseline} that represents expected TPM measurement values.
|
||||
* If a device provides a TPM Report that includes TPM measurements not matching the whitelist
|
||||
* in its TPM Policy, an alert will be generated.
|
||||
*/
|
||||
@Entity
|
||||
public class TpmWhiteListBaseline extends TPMBaseline {
|
||||
|
||||
/**
|
||||
* Creates a new baseline with no valid PCR entries and no device-specific PCRs.
|
||||
*
|
||||
* @param name
|
||||
* a name used to uniquely identify and reference the PCR baseline
|
||||
*/
|
||||
public TpmWhiteListBaseline(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate and BaselineAlertResolver.
|
||||
*/
|
||||
public TpmWhiteListBaseline() {
|
||||
super();
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package hirs.data.persist.baseline;
|
||||
|
||||
import hirs.persist.RepositoryManager;
|
||||
|
||||
/**
|
||||
* An IMA baseline that supports an update capability through which the associated records can be
|
||||
* managed by an external source, such as a Yum repository.
|
||||
*
|
||||
*/
|
||||
public interface UpdatableImaBaseline {
|
||||
/**
|
||||
* Update this baseline from an external source.
|
||||
*
|
||||
* @param repositoryManager a repository manager to use to gather data about repositories, or
|
||||
* null if object already contains all info (no lazy-loaded data)
|
||||
*/
|
||||
void update(RepositoryManager repositoryManager);
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package contains a set of classes for accessing baseline code.
|
||||
*/
|
||||
package hirs.data.persist.baseline;
|
@ -1,185 +0,0 @@
|
||||
package hirs.ima;
|
||||
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.info.FirmwareInfo;
|
||||
import hirs.data.persist.info.HardwareInfo;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.baseline.ImaAcceptableRecordBaseline;
|
||||
import hirs.data.persist.baseline.ImaBlacklistBaseline;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import hirs.data.persist.baseline.ImaIgnoreSetBaseline;
|
||||
import hirs.data.persist.ImaIgnoreSetRecord;
|
||||
import hirs.data.persist.info.OSInfo;
|
||||
import hirs.data.persist.baseline.TPMBaseline;
|
||||
import hirs.data.persist.info.TPMInfo;
|
||||
import hirs.data.persist.TPMMeasurementRecord;
|
||||
import hirs.tpm.TPMBaselineGenerator.TPMBaselineFields;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Class used to generate CSV from baselines and ignore sets. These utility functions are useful
|
||||
* for exporting the objects to files.
|
||||
*/
|
||||
public final class CSVGenerator {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(CSVGenerator.class);
|
||||
|
||||
/**
|
||||
* Private constructor, should never be called.
|
||||
*/
|
||||
private CSVGenerator() {
|
||||
// intentionally blank
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all IMA records stored in IMABaselineRecords for IMABaseline.
|
||||
*
|
||||
* Adds logic to remove stray commas that were appearing in large baselines.
|
||||
*
|
||||
* @param imaBaseline baseline
|
||||
* @return CSV in a String
|
||||
*/
|
||||
public static String imaRecordsToCsv(final ImaAcceptableRecordBaseline imaBaseline) {
|
||||
LOGGER.info("Retrieved and parsing all records");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (IMABaselineRecord record : imaBaseline.getBaselineRecords()) {
|
||||
String stringHashValue;
|
||||
Digest theHash = record.getHash();
|
||||
if (theHash == null) {
|
||||
stringHashValue = "";
|
||||
} else {
|
||||
final byte[] digest = theHash.getDigest();
|
||||
final char[] hash = Hex.encodeHex(digest);
|
||||
stringHashValue = String.valueOf(hash);
|
||||
}
|
||||
|
||||
sb.append("\"")
|
||||
.append(record.getPath().replace("\"", "\"\""))
|
||||
.append("\",")
|
||||
.append(stringHashValue)
|
||||
.append(System.lineSeparator());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the file paths of records that should be ignored.
|
||||
*
|
||||
* @param ignoreSetBaseline ignoreSetBaseline
|
||||
* @return CSV in a String
|
||||
*/
|
||||
public static String ignoreSetToCsv(final ImaIgnoreSetBaseline ignoreSetBaseline) {
|
||||
LOGGER.info("Retrieved and parsing all records");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (ImaIgnoreSetRecord record : ignoreSetBaseline.getImaIgnoreRecords()) {
|
||||
sb.append(record.getPath())
|
||||
.append(",")
|
||||
.append(StringUtils.defaultString(record.getDescription()))
|
||||
.append(",")
|
||||
.append(System.lineSeparator());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes an {@link ImaBlacklistBaseline} into a CSV file, whose rows represent
|
||||
* entries in the baseline.
|
||||
*
|
||||
* @param blacklistBaseline the baseline to serialize
|
||||
* @return the resulting CSV in a String
|
||||
*/
|
||||
public static String blacklistToCsv(final ImaBlacklistBaseline blacklistBaseline) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
CSVPrinter csvPrinter;
|
||||
try {
|
||||
csvPrinter = CSVFormat.DEFAULT.builder()
|
||||
.setRecordSeparator(System.lineSeparator())
|
||||
.build().print(sb);
|
||||
for (ImaBlacklistRecord record : blacklistBaseline.getRecords()) {
|
||||
String digest = "";
|
||||
Digest hash = record.getHash();
|
||||
if (hash != null) {
|
||||
digest = hash.toString();
|
||||
}
|
||||
csvPrinter.printRecord(
|
||||
nullToEmpty(record.getPath()),
|
||||
digest,
|
||||
nullToEmpty(record.getDescription())
|
||||
);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Could not instantiate CSV printer");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TPM records in the TPMBaseline.
|
||||
*
|
||||
* @param tpmBaseline tpmBaseline
|
||||
* @return CSV in a String
|
||||
*/
|
||||
public static String tpmRecordsToCsv(final TPMBaseline tpmBaseline) {
|
||||
LOGGER.info("Retrieved and parsing all records");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// Add device info records to the map
|
||||
HashMap<TPMBaselineFields, String> map = new HashMap<TPMBaselineFields, String>();
|
||||
final FirmwareInfo firmwareInfo = tpmBaseline.getFirmwareInfo();
|
||||
map.put(TPMBaselineFields.BIOS_VENDOR, firmwareInfo.getBiosVendor());
|
||||
map.put(TPMBaselineFields.BIOS_VERSION, firmwareInfo.getBiosVersion());
|
||||
map.put(TPMBaselineFields.BIOS_RELEASE_DATE, firmwareInfo.getBiosReleaseDate());
|
||||
final HardwareInfo hardwareInfo = tpmBaseline.getHardwareInfo();
|
||||
map.put(TPMBaselineFields.MANUFACTURER, hardwareInfo.getManufacturer());
|
||||
map.put(TPMBaselineFields.PRODUCT_NAME, hardwareInfo.getProductName());
|
||||
map.put(TPMBaselineFields.VERSION, hardwareInfo.getVersion());
|
||||
map.put(TPMBaselineFields.SYSTEM_SERIAL_NUMBER, hardwareInfo.getSystemSerialNumber());
|
||||
map.put(TPMBaselineFields.CHASSIS_SERIAL_NUMBER, hardwareInfo.getChassisSerialNumber());
|
||||
map.put(TPMBaselineFields.BASEBOARD_SERIAL_NUMBER, hardwareInfo.getBaseboardSerialNumber());
|
||||
final OSInfo osInfo = tpmBaseline.getOSInfo();
|
||||
map.put(TPMBaselineFields.OS_NAME, osInfo.getOSName());
|
||||
map.put(TPMBaselineFields.OS_VERSION, osInfo.getOSVersion());
|
||||
map.put(TPMBaselineFields.OS_ARCH, osInfo.getOSArch());
|
||||
map.put(TPMBaselineFields.DISTRIBUTION, osInfo.getDistribution());
|
||||
map.put(TPMBaselineFields.DISTRIBUTION_RELEASE, osInfo.getDistributionRelease());
|
||||
final TPMInfo tpmInfo = tpmBaseline.getTPMInfo();
|
||||
map.put(TPMBaselineFields.TPM_MAKE, tpmInfo.getTPMMake());
|
||||
map.put(TPMBaselineFields.TPM_VERSION_MAJOR, "" + tpmInfo.getTPMVersionMajor());
|
||||
map.put(TPMBaselineFields.TPM_VERSION_MINOR, "" + tpmInfo.getTPMVersionMinor());
|
||||
map.put(TPMBaselineFields.TPM_VERSION_REV_MAJOR, "" + tpmInfo.getTPMVersionRevMajor());
|
||||
map.put(TPMBaselineFields.TPM_VERSION_REV_MINOR, "" + tpmInfo.getTPMVersionRevMinor());
|
||||
// Add device info records to the CSV file
|
||||
sb.append(TPMBaselineFields.toCSV(map));
|
||||
|
||||
// Add measurement records to the CSV file
|
||||
for (TPMMeasurementRecord record : tpmBaseline.getPcrRecords()) {
|
||||
final byte[] digest = record.getHash().getDigest();
|
||||
final char[] hash = Hex.encodeHex(digest);
|
||||
sb.append(record.getPcrId())
|
||||
.append(",")
|
||||
.append(String.valueOf(hash))
|
||||
.append(System.lineSeparator());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convers a null String to an empty String, for serialization purposes.
|
||||
*
|
||||
* @param str the input string
|
||||
* @return the same string, or an empty String if the original was null
|
||||
*/
|
||||
public static String nullToEmpty(final String str) {
|
||||
if (str == null) {
|
||||
return "";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package hirs.ima;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>CreateIMABaseline</code>.
|
||||
*/
|
||||
public class IMABaselineGeneratorException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1704308568386321875L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateIMABaselineException</code> that has the
|
||||
* message <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
IMABaselineGeneratorException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateIMABaselineException</code> that wraps the
|
||||
* given <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
IMABaselineGeneratorException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateIMABaselineException</code> that has the
|
||||
* message <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
IMABaselineGeneratorException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package hirs.ima;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.baseline.ImaBlacklistBaseline;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* This class provides methods for generating {@link ImaBlacklistBaseline}s as serialized
|
||||
* by {@link CSVGenerator}.
|
||||
*/
|
||||
public final class ImaBlacklistBaselineGenerator {
|
||||
private static final int NUM_CSV_FIELDS = 3;
|
||||
|
||||
/**
|
||||
* This is a utility class that should not be constructed.
|
||||
*/
|
||||
private ImaBlacklistBaselineGenerator() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ImaBlacklistBaseline} instance from the provided CSV input.
|
||||
*
|
||||
* @param baselineName the name that the resultant baseline should have
|
||||
* @param inputStream input stream containing the CSV data
|
||||
* @return the resulting blacklist baseline
|
||||
* @throws IOException if there is a problem deserializing the baseline records
|
||||
*/
|
||||
public static ImaBlacklistBaseline generateBaselineFromCSV(
|
||||
final String baselineName,
|
||||
final InputStream inputStream
|
||||
) throws IOException {
|
||||
Preconditions.checkArgument(
|
||||
!StringUtils.isBlank(baselineName),
|
||||
"Cannot generate a baseline with a blank name"
|
||||
);
|
||||
|
||||
ImaBlacklistBaseline blacklistBaseline = new ImaBlacklistBaseline(baselineName);
|
||||
updateBaselineFromCSVFile(blacklistBaseline, inputStream);
|
||||
return blacklistBaseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds blacklist baseline records from the provided CSV input to the given
|
||||
* {@link ImaBlacklistBaseline} instance.
|
||||
*
|
||||
* @param baseline the baseline whose blacklist records should be updated
|
||||
* @param inputStream input stream containing the CSV data
|
||||
* @throws IOException if there is a problem deserializing the baseline records
|
||||
*/
|
||||
public static void updateBaselineFromCSVFile(
|
||||
final ImaBlacklistBaseline baseline,
|
||||
final InputStream inputStream
|
||||
) throws IOException {
|
||||
Preconditions.checkNotNull(baseline, "Cannot update null baseline");
|
||||
Preconditions.checkNotNull(inputStream, "Cannot update from null input");
|
||||
|
||||
BufferedReader buffReader = new BufferedReader(new InputStreamReader(
|
||||
inputStream, Charsets.UTF_8
|
||||
));
|
||||
CSVParser parser = CSVFormat.DEFAULT.parse(buffReader);
|
||||
|
||||
try {
|
||||
for (CSVRecord record : parser.getRecords()) {
|
||||
if (record.size() != NUM_CSV_FIELDS) {
|
||||
throw new IOException(String.format(
|
||||
"Expected %d fields for record %s", NUM_CSV_FIELDS, record.toString()
|
||||
));
|
||||
}
|
||||
|
||||
String path = StringUtils.defaultIfBlank(record.get(0), null);
|
||||
String description = StringUtils.defaultIfBlank(record.get(2), null);
|
||||
Digest digest = null;
|
||||
|
||||
if (!StringUtils.isBlank(record.get(1))) {
|
||||
digest = Digest.fromString(record.get(1));
|
||||
}
|
||||
|
||||
baseline.addToBaseline(new ImaBlacklistRecord(path, digest, description));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
} finally {
|
||||
parser.close();
|
||||
buffReader.close();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
package hirs.ima;
|
||||
|
||||
import hirs.data.persist.baseline.ImaIgnoreSetBaseline;
|
||||
import hirs.data.persist.ImaIgnoreSetRecord;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.text.ParseException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Class used to process comma separated value measurement files or HIRS
|
||||
* integrity reports to generate an IMA measurement baseline. Generating an IMA
|
||||
* measurement baseline from a HIRS integrity report is considered experimental
|
||||
* and provided as a tool to assist with creating, analyzing, and refining
|
||||
* measurement baselines.
|
||||
*/
|
||||
public class ImaIgnoreSetBaselineGenerator {
|
||||
|
||||
private static final Logger LOGGER
|
||||
= LogManager.getLogger(ImaIgnoreSetBaseline.class);
|
||||
private static final int PATH_INDEX = 0;
|
||||
private static final int DESCRIPTION_INDEX = 1;
|
||||
|
||||
/**
|
||||
* Method generates an IMA measurement baseline from a .csv file containing
|
||||
* IMA baseline records. An IMA record consists of properties associated
|
||||
* with an IMA measured file such as file hash, and path. An off-line IMA
|
||||
* measurement baseline process is used to create the .csv file. IMA
|
||||
* baseline records are expected to adhere to the following record
|
||||
* structure separated by commas:
|
||||
* <ul>
|
||||
* <li>file Path (includes file name)</li>
|
||||
* <li>Description of why path was chosen to be ignored</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param baselineName
|
||||
* name applied to baseline
|
||||
* @param in
|
||||
* is input stream containing IMA baseline records
|
||||
* @return IMAbaseline
|
||||
* @throws IOException
|
||||
* if error encountered reading data from input stream
|
||||
* @throws ParseException
|
||||
* if error encountered parsing data
|
||||
* @throws ImaIgnoreSetBaselineGeneratorException
|
||||
* if error encountered when retrieving baseline records from
|
||||
* input stream
|
||||
*/
|
||||
public final ImaIgnoreSetBaseline generateBaselineFromCSVFile(
|
||||
final String baselineName, final InputStream in)
|
||||
throws IOException, ParseException, ImaIgnoreSetBaselineGeneratorException {
|
||||
if (baselineName == null) {
|
||||
LOGGER.error("null argument: baselineName");
|
||||
throw new NullPointerException("baselineName");
|
||||
}
|
||||
ImaIgnoreSetBaseline ignoreBaseline = new ImaIgnoreSetBaseline(baselineName);
|
||||
updateBaselineFromCSVFile(ignoreBaseline, in);
|
||||
LOGGER.debug("meaurement baseline initialized: {}", ignoreBaseline.getName());
|
||||
return ignoreBaseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method parses a .csv file containing IMA ignore baseline records and adds then to
|
||||
* a IMA ignore baseline object.
|
||||
*
|
||||
* @param baseline The baseline to be updated with records from the stream
|
||||
* @param inStream
|
||||
* containing file contents to be read. inStream is closed by
|
||||
* this method.
|
||||
* @throws IOException
|
||||
* if error encountered reading data from input stream
|
||||
* @throws ParseException
|
||||
* if error encountered parsing data
|
||||
* @throws ImaIgnoreSetBaselineGeneratorException
|
||||
* if error encountered when retrieving baseline records from
|
||||
* input stream
|
||||
*/
|
||||
public final void updateBaselineFromCSVFile(final ImaIgnoreSetBaseline baseline,
|
||||
final InputStream inStream) throws IOException, ParseException,
|
||||
ImaIgnoreSetBaselineGeneratorException {
|
||||
|
||||
if (baseline == null) {
|
||||
LOGGER.error("null argument: baseline");
|
||||
throw new NullPointerException("baseline");
|
||||
}
|
||||
if (inStream == null) {
|
||||
LOGGER.error("null argument: in");
|
||||
throw new NullPointerException("in");
|
||||
}
|
||||
|
||||
// (tmmcgil) I realize this is not the most robust way to parse, but it works
|
||||
// better than what was here before and it doesn't require a lot of changes.
|
||||
String regex = "\"?(.*?)\"?,(.*)";
|
||||
Pattern p = Pattern.compile(regex);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
inStream, "UTF8"));
|
||||
String dataRow;
|
||||
|
||||
while ((dataRow = reader.readLine()) != null) {
|
||||
if (StringUtils.isBlank(dataRow)) {
|
||||
continue;
|
||||
}
|
||||
Matcher m = p.matcher(dataRow);
|
||||
if (!m.matches() || m.groupCount() != 2) {
|
||||
final String msg = "row does not match regex: " + dataRow;
|
||||
LOGGER.error(msg);
|
||||
throw new ImaIgnoreSetBaselineGeneratorException(msg);
|
||||
}
|
||||
|
||||
String path = m.group(1);
|
||||
path = path.replace("\"\"", "\"");
|
||||
|
||||
String description = m.group(2);
|
||||
if (StringUtils.defaultString(description).equalsIgnoreCase("")) {
|
||||
description = null;
|
||||
}
|
||||
final ImaIgnoreSetRecord imaRecord = new ImaIgnoreSetRecord(path,
|
||||
description);
|
||||
baseline.addToBaseline(imaRecord);
|
||||
final String msg = String.format("added record %s", imaRecord);
|
||||
LOGGER.debug(msg);
|
||||
}
|
||||
reader.close();
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package hirs.ima;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>CreateImaIgnoreSetBaseline</code>.
|
||||
*/
|
||||
public class ImaIgnoreSetBaselineGeneratorException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1704308568386321875L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateImaIgnoreSetBaselineException</code> that has the
|
||||
* message <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
ImaIgnoreSetBaselineGeneratorException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateImaIgnoreSetBaselineException</code> that wraps the
|
||||
* given <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
ImaIgnoreSetBaselineGeneratorException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>CreateImaIgnoreSetBaselineException</code> that has the
|
||||
* message <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
ImaIgnoreSetBaselineGeneratorException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
package hirs.ima;
|
||||
|
||||
import hirs.data.persist.IMAReport;
|
||||
import hirs.data.persist.baseline.SimpleImaBaseline;
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.enums.DigestAlgorithm;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IntegrityReport;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.text.ParseException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Class used to process comma separated value measurement files or HIRS
|
||||
* integrity reports to generate an IMA measurement baseline. Generating an IMA
|
||||
* measurement baseline from a HIRS integrity report is considered experimental
|
||||
* and provided as a tool to assist with creating, analyzing, and refining
|
||||
* measurement baselines.
|
||||
*/
|
||||
public class SimpleImaBaselineGenerator {
|
||||
|
||||
private static final Logger LOGGER
|
||||
= LogManager.getLogger(ImaBaseline.class);
|
||||
|
||||
/**
|
||||
* Method generates an IMA measurement baseline from a .csv file containing
|
||||
* IMA baseline records. An IMA record consists of properties associated
|
||||
* with an IMA measured file such as file hash, and path. An off-line IMA
|
||||
* measurement baseline process is used to create the .csv file. IMA
|
||||
* baseline records are expected to adhere to the following record
|
||||
* structure separated by commas:
|
||||
* <ul>
|
||||
* <li>file Path (includes file name)</li>
|
||||
* <li>SHA1 of file</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param baselineName
|
||||
* name applied to baseline
|
||||
* @param in
|
||||
* is input stream containing IMA baseline records
|
||||
* @return IMAbaseline
|
||||
* @throws IOException
|
||||
* if error encountered reading data from input stream
|
||||
* @throws ParseException
|
||||
* if error encountered parsing data
|
||||
* @throws IMABaselineGeneratorException
|
||||
* if error encountered when retrieving baseline records from
|
||||
* input stream
|
||||
*/
|
||||
public final SimpleImaBaseline generateBaselineFromCSVFile(
|
||||
final String baselineName, final InputStream in)
|
||||
throws IOException, ParseException, IMABaselineGeneratorException {
|
||||
if (baselineName == null) {
|
||||
LOGGER.error("null argument: baselineName");
|
||||
throw new NullPointerException("baselineName");
|
||||
}
|
||||
SimpleImaBaseline imaBaseline = new SimpleImaBaseline(baselineName);
|
||||
updateBaselineFromCSVFile(imaBaseline, in);
|
||||
LOGGER.debug("meaurement baseline initialized: {}", imaBaseline.getName());
|
||||
return imaBaseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces IMA baseline from IMA report. The method extracts the list of
|
||||
* IMA records from the trusted report then it uses each IMA report record
|
||||
* to construct the baseline. Note: The HIRS portal selects an IMA report
|
||||
* to use as a seed to generate IMA baseline, the IMA report should be
|
||||
* generated with sufficient (complete list of files measurements) and
|
||||
* should be in trusted state to use as basis for baseline. However, IMA
|
||||
* baselines generated from measurement reports are expected to have high
|
||||
* rate of false positives because many alerts will be generated for files
|
||||
* that change every boot cycle that need to be filtered by system
|
||||
* operators that will build expertise regarding IMA measurements in their
|
||||
* specific deployment configuration, and who will utilize the portal to
|
||||
* adjust the baseline to identify all files that should have policy set
|
||||
* to ignore hash. there are many other cases that may cause false
|
||||
* positive which will require human in the loop also to refine the
|
||||
* produced baseline.
|
||||
*
|
||||
* @param baselineName
|
||||
* name of the new baseline
|
||||
* @param report
|
||||
* IMAReport instance of IMA integrity report object. The IMA
|
||||
* Integrity report is extracted from a host integrity report.
|
||||
*
|
||||
* @return ImaBaseline
|
||||
* @throws IMABaselineGeneratorException
|
||||
* if we find no IMA records in the trusted report that method
|
||||
* should use to generate IMA baseline.
|
||||
* @throws NullPointerException
|
||||
* if baselineName or report parameters are null.
|
||||
*/
|
||||
public final SimpleImaBaseline generateBaselineFromIMAReport(
|
||||
final String baselineName, final IMAReport report)
|
||||
throws IMABaselineGeneratorException, NullPointerException {
|
||||
|
||||
IMABaselineRecord imaBaselineRecord;
|
||||
|
||||
if (baselineName == null) {
|
||||
LOGGER.error("null argument: baselineName");
|
||||
throw new NullPointerException("baselineName");
|
||||
}
|
||||
|
||||
if (report == null) {
|
||||
LOGGER.error("null argument: report");
|
||||
throw new NullPointerException("report");
|
||||
}
|
||||
|
||||
if (report.getRecords().size() < 1) {
|
||||
String msg;
|
||||
msg = "no IMA records in the report";
|
||||
LOGGER.error(msg);
|
||||
throw new IMABaselineGeneratorException(msg);
|
||||
}
|
||||
|
||||
SimpleImaBaseline newBaseline = new SimpleImaBaseline(baselineName);
|
||||
for (IMAMeasurementRecord record : report.getRecords()) {
|
||||
imaBaselineRecord = new IMABaselineRecord(record.getPath(), record.getHash());
|
||||
newBaseline.addToBaseline(imaBaselineRecord);
|
||||
}
|
||||
|
||||
return newBaseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces IMA baseline from a HIRS full integrity report that complies
|
||||
* with HIRS new XML report format. The method the IMA report from the full
|
||||
* integrity report, then it extracts the the list of IMA records from the
|
||||
* trusted report then it uses each IMA report record to construct the IMA
|
||||
* baseline.
|
||||
* @param baselineName
|
||||
* name of the new baseline
|
||||
* @param report
|
||||
* IMAReport instance of IMA integrity report object. The IMA
|
||||
* Integrity report is extracted from a host integrity report.
|
||||
*
|
||||
* @return ImaBaseline
|
||||
* @throws IMABaselineGeneratorException
|
||||
* if no IMA report, or IMA records, in the trusted integrity
|
||||
* report passed to the method to generate IMA baseline.
|
||||
* @throws NullPointerException
|
||||
* if baselineName or report parameters are null.
|
||||
*/
|
||||
public final SimpleImaBaseline generateBaselineFromIntegrityReport(
|
||||
final String baselineName, final IntegrityReport report)
|
||||
throws IMABaselineGeneratorException, NullPointerException {
|
||||
IMABaselineRecord imaBaselineRecord;
|
||||
|
||||
if (baselineName == null) {
|
||||
LOGGER.error("null argument: baselineName");
|
||||
throw new NullPointerException("baselineName");
|
||||
}
|
||||
|
||||
if (report == null) {
|
||||
LOGGER.error("null argument: report");
|
||||
throw new NullPointerException("report");
|
||||
}
|
||||
|
||||
if (!report.contains(IMAReport.class)) {
|
||||
String msg = "no IMA report in the integrity report";
|
||||
LOGGER.error(msg);
|
||||
throw new IMABaselineGeneratorException(msg);
|
||||
}
|
||||
|
||||
IMAReport imaReport = report.extractReport(IMAReport.class);
|
||||
if (imaReport.getRecords().size() < 1) {
|
||||
String msg = "no IMA records in the report";
|
||||
LOGGER.error(msg);
|
||||
throw new IMABaselineGeneratorException(msg);
|
||||
}
|
||||
SimpleImaBaseline newBaseline = new SimpleImaBaseline(baselineName);
|
||||
for (IMAMeasurementRecord imaRecord : imaReport.getRecords()) {
|
||||
imaBaselineRecord = new IMABaselineRecord(imaRecord.getPath(),
|
||||
imaRecord.getHash());
|
||||
newBaseline.addToBaseline(imaBaselineRecord);
|
||||
}
|
||||
return newBaseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method parses a .csv file containing IMA baseline records and adds then to
|
||||
* a IMA baseline object.
|
||||
*
|
||||
* @param baseline The baseline to be updated with records from the stream
|
||||
* @param inStream
|
||||
* containing file contents to be read. inStream is closed by
|
||||
* this method.
|
||||
* @throws IOException
|
||||
* if error encountered reading data from input stream
|
||||
* @throws ParseException
|
||||
* if error encountered parsing data
|
||||
* @throws IMABaselineGeneratorException
|
||||
* if error encountered when retrieving baseline records from
|
||||
* input stream
|
||||
*/
|
||||
public final void updateBaselineFromCSVFile(final SimpleImaBaseline baseline,
|
||||
final InputStream inStream) throws IOException, ParseException,
|
||||
IMABaselineGeneratorException {
|
||||
|
||||
if (baseline == null) {
|
||||
LOGGER.error("null argument: baseline");
|
||||
throw new NullPointerException("baseline");
|
||||
}
|
||||
if (inStream == null) {
|
||||
LOGGER.error("null argument: in");
|
||||
throw new NullPointerException("in");
|
||||
}
|
||||
|
||||
String regex = "\"?(.*?)\"?,([a-fA-F0-9]{40})";
|
||||
Pattern p = Pattern.compile(regex);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
inStream, "UTF8"));
|
||||
String dataRow;
|
||||
|
||||
while ((dataRow = reader.readLine()) != null) {
|
||||
if (StringUtils.isBlank(dataRow)) {
|
||||
continue;
|
||||
}
|
||||
Matcher m = p.matcher(dataRow);
|
||||
if (!m.matches() || m.groupCount() != 2) {
|
||||
final String msg = "row does not match regex: " + dataRow;
|
||||
LOGGER.error(msg);
|
||||
throw new IMABaselineGeneratorException(msg);
|
||||
}
|
||||
|
||||
String path = m.group(1);
|
||||
path = path.replace("\"\"", "\"");
|
||||
|
||||
try {
|
||||
final byte[] hash = Hex.decodeHex(m.group(2).toCharArray());
|
||||
final Digest digest = new Digest(DigestAlgorithm.SHA1, hash);
|
||||
final IMABaselineRecord imaRecord = new IMABaselineRecord(path,
|
||||
digest);
|
||||
baseline.addToBaseline(imaRecord);
|
||||
final String msg = String.format("added record %s", imaRecord);
|
||||
LOGGER.debug(msg);
|
||||
} catch (DecoderException e) {
|
||||
String msg = "File " + path + " has invalid hash sting. "
|
||||
+ "Record not added to baseline";
|
||||
LOGGER.error(msg, e);
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
}
|
||||
}
|
@ -1,317 +0,0 @@
|
||||
package hirs.ima.matching;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.baseline.AbstractImaBaselineRecord;
|
||||
import hirs.data.persist.enums.ReportMatchStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class holds the results of the appraisal of a batch of {@link IMAMeasurementRecord}s against
|
||||
* one or many {@link hirs.data.persist.baseline.ImaBaseline}s.
|
||||
*
|
||||
* @param <T> the type of IMA baseline record that an instance of this class matches against
|
||||
*/
|
||||
public class BatchImaMatchStatus<T extends AbstractImaBaselineRecord> {
|
||||
// mapping from measurement record to match statuses, one per baseline
|
||||
private Map<IMAMeasurementRecord, Set<IMAMatchStatus<T>>> matchStatuses = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create an empty instance of this class.
|
||||
*/
|
||||
public BatchImaMatchStatus() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a set of {@link IMAMatchStatus}es that result from appraising one or many measurement
|
||||
* records against a baseline.
|
||||
*
|
||||
* @param matchStatuses the results of matching measurement records against a baseline
|
||||
*/
|
||||
public BatchImaMatchStatus(final Collection<IMAMatchStatus<T>> matchStatuses) {
|
||||
if (matchStatuses == null) {
|
||||
throw new IllegalArgumentException("Cannot construct from null matches");
|
||||
}
|
||||
|
||||
for (IMAMatchStatus<T> match : matchStatuses) {
|
||||
add(match);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the result of a match to this instance.
|
||||
*
|
||||
* @param status the match status to add
|
||||
*/
|
||||
public void add(final IMAMatchStatus<T> status) {
|
||||
if (status == null) {
|
||||
throw new IllegalArgumentException("Cannot add a null match status");
|
||||
}
|
||||
|
||||
IMAMeasurementRecord measurementRecord = status.getRecordToMatch();
|
||||
|
||||
if (!matchStatuses.containsKey(measurementRecord)) {
|
||||
matchStatuses.put(measurementRecord, new HashSet<IMAMatchStatus<T>>());
|
||||
}
|
||||
|
||||
for (IMAMatchStatus<T> existingMatchStatus : matchStatuses.get(measurementRecord)) {
|
||||
if (existingMatchStatus.getBaseline().equals(status.getBaseline())) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"A conflicting match result exists: %s",
|
||||
existingMatchStatus.toString())
|
||||
);
|
||||
}
|
||||
}
|
||||
matchStatuses.get(measurementRecord).add(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the {@link IMAMatchStatus} that results from checking whether an
|
||||
* {@link IMAMeasurementRecord} was in a baseline.
|
||||
*
|
||||
* @param record the record whose match should be returned
|
||||
* @return the relevant {@link IMAMatchStatus}
|
||||
*/
|
||||
public Set<IMAMatchStatus<T>> getIMAMatchStatuses(final IMAMeasurementRecord record) {
|
||||
Set<IMAMatchStatus<T>> imaMatchStatusSet = matchStatuses.get(record);
|
||||
if (imaMatchStatusSet == null) {
|
||||
throw new IllegalArgumentException("No match status stored for this record.");
|
||||
}
|
||||
return imaMatchStatusSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the {@link IMAMatchStatus} that results from checking whether an
|
||||
* {@link IMAMeasurementRecord} was in a baseline.
|
||||
*
|
||||
* @param record the record whose match should be returned
|
||||
* @return the relevant {@link IMAMatchStatus}, or null if no match was attempted for the record
|
||||
*/
|
||||
public Set<IMAMatchStatus<T>> getMatchingIMAMatchStatuses(final IMAMeasurementRecord record) {
|
||||
Preconditions.checkArgument(contains(record), "No match status stored for this record.");
|
||||
HashSet<IMAMatchStatus<T>> matchingStatuses = new HashSet<>();
|
||||
for (IMAMatchStatus<T> matchStatus : getIMAMatchStatuses(record)) {
|
||||
if (matchStatus.getStatus().equals(ReportMatchStatus.MATCH)) {
|
||||
matchingStatuses.add(matchStatus);
|
||||
}
|
||||
}
|
||||
return matchingStatuses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this BatchImaMatchStatus indicates that the given record has an associated
|
||||
* {@link ReportMatchStatus}.
|
||||
*
|
||||
* @param record the IMAMeasurementRecord to consider
|
||||
* @param matchStatus the match status to find for the given record
|
||||
* @return true if the given matchStatus was found associated with the given record;
|
||||
* false otherwise
|
||||
*/
|
||||
private boolean foundMatchStatusForRecord(final IMAMeasurementRecord record,
|
||||
final ReportMatchStatus matchStatus) {
|
||||
Preconditions.checkArgument(contains(record), "No match status stored for this record.");
|
||||
|
||||
for (IMAMatchStatus<T> status : getIMAMatchStatuses(record)) {
|
||||
if (status.getStatus().equals(matchStatus)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this BatchImaMatchStatus indicates that an actual (path & hash) match was
|
||||
* found for the given {@link IMAMeasurementRecord}. Not mutually exclusive
|
||||
* with the other 'found' methods.
|
||||
*
|
||||
* @param record the IMAMeasurementRecord to consider
|
||||
* @return true if there an actual (path & hash) match was found, false otherwise
|
||||
*/
|
||||
public boolean foundMatch(final IMAMeasurementRecord record) {
|
||||
return foundMatchStatusForRecord(record, ReportMatchStatus.MATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this BatchImaMatchStatus indicates that a mismatch was found
|
||||
* for the given {@link IMAMeasurementRecord} (matching path, but not hash.) Not mutually
|
||||
* exclusive with the other 'found' methods.
|
||||
*
|
||||
* @param record the IMAMeasurementRecord to consider
|
||||
* @return true if there a mismatch was found, false otherwise
|
||||
*/
|
||||
public boolean foundMismatch(final IMAMeasurementRecord record) {
|
||||
return foundMatchStatusForRecord(record, ReportMatchStatus.MISMATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this BatchImaMatchStatus indicates that the given record produced only an
|
||||
* UNKNOWN match status, and no matches or mismatches.
|
||||
*
|
||||
* @param record the IMAMeasurementRecord to consider
|
||||
* @return true if relevant IMAMatchStatuses are UNKNOWN, false otherwise
|
||||
*/
|
||||
public boolean foundOnlyUnknown(final IMAMeasurementRecord record) {
|
||||
Preconditions.checkArgument(contains(record), "No match status stored for this record.");
|
||||
|
||||
for (IMAMatchStatus<T> status : getIMAMatchStatuses(record)) {
|
||||
if (!status.getStatus().equals(ReportMatchStatus.UNKNOWN)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all IMA baseline records held in this instance whose file paths match the given
|
||||
* record. If the second parameter is non-null, only matches with the given match status will
|
||||
* be returned. If the second parameter is null, all matching records will be returned.
|
||||
*
|
||||
* @param record the record whose paths should be considered when retrieving IMA baseline
|
||||
* records that have matching file paths
|
||||
* @param reportMatchStatus if non-null, only IMA baseline records that are of the given match
|
||||
* type will be returned (this is only useful for MATCH and MISMATCH.) If
|
||||
* null, both matching and mismatching baseline records will be returned.
|
||||
* @return a set of all matching IMABaselineRecords
|
||||
*/
|
||||
private Set<T> getBaselineRecords(
|
||||
final IMAMeasurementRecord record,
|
||||
final ReportMatchStatus reportMatchStatus) {
|
||||
Preconditions.checkArgument(contains(record), "No match status stored for this record.");
|
||||
HashSet<T> baselineRecords = new HashSet<>();
|
||||
|
||||
for (IMAMatchStatus<T> imaMatchStatus : getIMAMatchStatuses(record)) {
|
||||
if (reportMatchStatus == null || imaMatchStatus.getStatus().equals(reportMatchStatus)) {
|
||||
baselineRecords.addAll(imaMatchStatus.getBaselineRecords());
|
||||
}
|
||||
}
|
||||
|
||||
return baselineRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Set of the IMABaselineRecords that are an actual match (path & hash)
|
||||
* of the given {@link IMAMeasurementRecord}.
|
||||
*
|
||||
* @param record the IMAMeasurementRecord to consider
|
||||
* @return the Set of all records that have a MATCH to the given record; may be empty
|
||||
*/
|
||||
public Set<T> getMatchingBaselineRecords(final IMAMeasurementRecord record) {
|
||||
return getBaselineRecords(record, ReportMatchStatus.MATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Set of the IMABaselineRecords that are a mismatch with the given
|
||||
* {@link IMAMeasurementRecord}.
|
||||
*
|
||||
* @param record the IMAMeasurementRecord to consider
|
||||
* @return the Set of all records that have a MISMATCH to the given record; may be empty
|
||||
*/
|
||||
public Set<T> getMismatchingBaselineRecords(final IMAMeasurementRecord record) {
|
||||
return getBaselineRecords(record, ReportMatchStatus.MISMATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Set of the IMABaselineRecords matched or mismatched with the given record.
|
||||
* {@link IMAMeasurementRecord}.
|
||||
*
|
||||
* @param record the IMAMeasurementRecord to consider
|
||||
* @return the Set of all records that match or mismatch the given record
|
||||
*/
|
||||
public Set<T> getBaselineRecords(final IMAMeasurementRecord record) {
|
||||
return getBaselineRecords(record, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Set containing all {@link IMAMeasurementRecord}s that were evaluated against a
|
||||
* baseline in this instance.
|
||||
*
|
||||
* @return the set of all IMAMeasurementRecords in this instance
|
||||
*/
|
||||
public Set<IMAMeasurementRecord> getAppraisedMeasurementRecords() {
|
||||
return Collections.unmodifiableSet(matchStatuses.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a collection of all IMAMatchStatuses with a status of ReportMatchStatus.MATCH.
|
||||
*
|
||||
* @return matching IMAMatchStatuses
|
||||
*/
|
||||
public Collection<IMAMatchStatus<T>> getAllMatches() {
|
||||
List<IMAMatchStatus<T>> matches = new ArrayList<>();
|
||||
for (Map.Entry<IMAMeasurementRecord, Set<IMAMatchStatus<T>>> e : matchStatuses.entrySet()) {
|
||||
for (IMAMatchStatus<T> matchStatus : e.getValue()) {
|
||||
if (matchStatus.getStatus().equals(ReportMatchStatus.MATCH)) {
|
||||
matches.add(matchStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the given {@link IMAMeasurementRecord} has one
|
||||
* or more recorded match statuses in this instance.
|
||||
*
|
||||
* @param record the record whose presence will be determined
|
||||
* @return true if this object contains results related to the given record; false otherwise
|
||||
*/
|
||||
public boolean contains(final IMAMeasurementRecord record) {
|
||||
return matchStatuses.containsKey(record);
|
||||
}
|
||||
|
||||
private Set<IMAMatchStatus<T>> getMatchStatuses() {
|
||||
Set<IMAMatchStatus<T>> matchSet = new HashSet<>();
|
||||
for (Map.Entry<IMAMeasurementRecord, Set<IMAMatchStatus<T>>> e : matchStatuses.entrySet()) {
|
||||
matchSet.addAll(e.getValue());
|
||||
}
|
||||
return matchSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given another BatchImaMatchStatus, merge its match statuses into this instance. Useful in
|
||||
* collecting match results from multiple baselines.
|
||||
*
|
||||
* @param other the other BatchImaMatchStatus whose results should be merged into this instance
|
||||
*/
|
||||
public void merge(final BatchImaMatchStatus<T> other) {
|
||||
for (IMAMatchStatus<T> match : other.getMatchStatuses()) {
|
||||
add(match);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
BatchImaMatchStatus that = (BatchImaMatchStatus) o;
|
||||
return Objects.equals(matchStatuses, that.matchStatuses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(matchStatuses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BatchImaMatchStatus{"
|
||||
+ "matchStatuses=" + matchStatuses
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
package hirs.ima.matching;
|
||||
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.baseline.AbstractImaBaselineRecord;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.enums.ReportMatchStatus;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This represents the match status for when an <code>ImaBaseline</code> tests
|
||||
* if an <code>IMAMeasurementRecord</code> is contained in it. This contains the
|
||||
* <code>ReportMatchStatus</code> as well as a set of records.
|
||||
* <p>
|
||||
* The set of records has different meanings depending upon the return value.
|
||||
* If the match status return MATCH then the list contains all of the matching
|
||||
* entries. If partial path support is disabled then this can only return one
|
||||
* entry. If partial path is enabled then this can return multiple matches,
|
||||
* consider /usr/bin/gradle and /home/foo/bin/gradle as an example.
|
||||
* <p>
|
||||
* If the report status is a mismatch then this returns the set of baseline
|
||||
* records that have the same path but a different hash. This can happen if
|
||||
* multiple values are acceptable for a file. This can also happen if partial
|
||||
* path is enabled and different files have the same name but in different
|
||||
* directories.
|
||||
* <p>
|
||||
* If the report status is unknown then the set is empty.
|
||||
*
|
||||
* @param <T> the type of IMA baseline record that this class matches against
|
||||
*/
|
||||
public final class IMAMatchStatus<T extends AbstractImaBaselineRecord> {
|
||||
|
||||
private ReportMatchStatus status;
|
||||
private IMAMeasurementRecord recordToMatch;
|
||||
private HashSet<T> baselineRecords; // these should all be from the same baseline
|
||||
private ImaBaseline baseline;
|
||||
|
||||
/**
|
||||
* Convenience constructor for an UNKNOWN match status. This creates
|
||||
* a new <code>IMAMatchStatus</code> that must have a status of
|
||||
* UNKNOWN. If not UNKNOWN then an Exception will be thrown. The set of
|
||||
* records is initialized to an empty list.
|
||||
*
|
||||
* @param recordToMatch the record associated with this match status
|
||||
* @param status must be UNKNOWN
|
||||
* @param baseline the baseline from which this match originated
|
||||
*/
|
||||
public IMAMatchStatus(final IMAMeasurementRecord recordToMatch,
|
||||
final ReportMatchStatus status,
|
||||
final ImaBaseline baseline) {
|
||||
this(recordToMatch, status, new HashSet<T>(), baseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience constructor for creating a match status that only has one
|
||||
* record. The record can only be null if status is UNKNOWN. In that case an
|
||||
* empty set is created. Otherwise it cannot be null and the status must be
|
||||
* either MATCH or MISMATCH.
|
||||
*
|
||||
* @param recordToMatch the record associated with this match status
|
||||
* @param status status
|
||||
* @param record record (can be null if status is UNKNOWN)
|
||||
* @param baseline the baseline from which this match originated
|
||||
*/
|
||||
public IMAMatchStatus(
|
||||
final IMAMeasurementRecord recordToMatch,
|
||||
final ReportMatchStatus status,
|
||||
final T record,
|
||||
final ImaBaseline baseline) {
|
||||
this(recordToMatch, status, Collections.singleton(record), baseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>IMAMatchStatus</code>. If status is MATCH or
|
||||
* MISMATCH then the records set cannot be empty. Else the records set
|
||||
* must be empty.
|
||||
*
|
||||
* @param recordToMatch the record associated with this match status
|
||||
* @param status match status
|
||||
* @param baselineRecords records
|
||||
* @param baseline the baseline from which this match originated
|
||||
*/
|
||||
public IMAMatchStatus(
|
||||
final IMAMeasurementRecord recordToMatch,
|
||||
final ReportMatchStatus status,
|
||||
final Set<T> baselineRecords,
|
||||
final ImaBaseline baseline) {
|
||||
if (recordToMatch == null) {
|
||||
throw new IllegalArgumentException("Cannot have a null IMAMeasurementRecord.");
|
||||
}
|
||||
if (status == null) {
|
||||
throw new IllegalArgumentException("Cannot have a null match status.");
|
||||
}
|
||||
if (baselineRecords == null) {
|
||||
throw new IllegalArgumentException("Cannot have null baseline records.");
|
||||
}
|
||||
if (baseline == null) {
|
||||
throw new IllegalArgumentException("Cannot have a null baseline.");
|
||||
}
|
||||
if (status == ReportMatchStatus.UNKNOWN && baselineRecords.size() > 0) {
|
||||
throw new IllegalArgumentException("Cannot have an unknown status with associated"
|
||||
+ "baseline records.");
|
||||
}
|
||||
if (status != ReportMatchStatus.UNKNOWN && baselineRecords.size() == 0) {
|
||||
throw new IllegalArgumentException("Cannot have a match or mismatch status without"
|
||||
+ "associated baseline records.");
|
||||
}
|
||||
this.recordToMatch = recordToMatch;
|
||||
this.status = status;
|
||||
this.baselineRecords = new HashSet<>(baselineRecords);
|
||||
this.baseline = baseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the match status as to whether or not the record was found.
|
||||
*
|
||||
* @return match status
|
||||
*/
|
||||
public ReportMatchStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the records associated with the match status. See the class
|
||||
* JavaDocs for a complete description of what to expect in the set.
|
||||
*
|
||||
* @return records
|
||||
*/
|
||||
public Set<T> getBaselineRecords() {
|
||||
return Collections.unmodifiableSet(baselineRecords);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the record for which matches were either found or not found.
|
||||
*
|
||||
* @return the record that has been matched (or not)
|
||||
*/
|
||||
public IMAMeasurementRecord getRecordToMatch() {
|
||||
return recordToMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the <code>Baseline</code> used to generate this match status.
|
||||
*
|
||||
* @return baseline used to generate status
|
||||
*/
|
||||
public Baseline getBaseline() {
|
||||
return baseline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
IMAMatchStatus<?> that = (IMAMatchStatus<?>) o;
|
||||
return status == that.status
|
||||
&& Objects.equals(recordToMatch, that.recordToMatch)
|
||||
&& Objects.equals(baselineRecords, that.baselineRecords)
|
||||
&& Objects.equals(baseline, that.baseline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(status, recordToMatch, baselineRecords, baseline);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "IMAMatchStatus{"
|
||||
+ "status=" + status
|
||||
+ ", recordToMatch=" + recordToMatch
|
||||
+ ", baselineRecords=" + baselineRecords
|
||||
+ ", baseline=" + baseline
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package hirs.ima.matching;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.enums.ReportMatchStatus;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class extends the base matching functionality of {@link ImaRecordMatcher} to
|
||||
* compare {@link IMAMeasurementRecord}s against a collection of {@link IMABaselineRecord}s
|
||||
* based solely on their hashes.
|
||||
*/
|
||||
public class ImaAcceptableHashRecordMatcher extends ImaRecordMatcher<IMABaselineRecord> {
|
||||
/**
|
||||
* Construct a new ImaAcceptablePathAndHashRecordMatcher.
|
||||
*
|
||||
* @param records the baseline records to use for matching
|
||||
* @param imaPolicy the IMA policy to reference during matching; its partial path and path
|
||||
* equivalence settings influence matching behavior
|
||||
* @param imaBaseline the IMA baseline these records were sourced from; this is only used to
|
||||
*/
|
||||
public ImaAcceptableHashRecordMatcher(
|
||||
final Collection<IMABaselineRecord> records,
|
||||
final IMAPolicy imaPolicy,
|
||||
final ImaBaseline imaBaseline) {
|
||||
super(records, imaPolicy, imaBaseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an IMAMatchStatus indicating whether the given {@link IMAMeasurementRecord} is
|
||||
* contained within the originally provided {@link IMABaselineRecord}s.
|
||||
*
|
||||
* @param record the record to look up
|
||||
* @return an IMAMatchStatus indicating whether the record is a match or unknown to
|
||||
* the given baseline records
|
||||
*/
|
||||
@Override
|
||||
public IMAMatchStatus<IMABaselineRecord> contains(final IMAMeasurementRecord record) {
|
||||
Preconditions.checkArgument(record != null, "Cannot match on null record.");
|
||||
|
||||
final Set<IMABaselineRecord> matchingRecords = getRelatedBaselineRecordsByHash(record);
|
||||
|
||||
if (matchingRecords.isEmpty()) {
|
||||
return new IMAMatchStatus<>(record, ReportMatchStatus.UNKNOWN, getImaBaseline());
|
||||
}
|
||||
|
||||
return new IMAMatchStatus<>(
|
||||
record,
|
||||
ReportMatchStatus.MATCH,
|
||||
matchingRecords,
|
||||
getImaBaseline()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
package hirs.ima.matching;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import hirs.data.persist.enums.DigestComparisonResultType;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.enums.ReportMatchStatus;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* This class extends the base matching functionality of {@link ImaRecordMatcher} to
|
||||
* compare {@link IMAMeasurementRecord}s against a collection of {@link IMABaselineRecord}s
|
||||
* based on both their paths and hashes.
|
||||
*/
|
||||
public class ImaAcceptablePathAndHashRecordMatcher extends ImaRecordMatcher<IMABaselineRecord> {
|
||||
private static final Logger LOGGER = getLogger(ImaAcceptablePathAndHashRecordMatcher.class);
|
||||
|
||||
/**
|
||||
* Construct a new ImaAcceptablePathAndHashRecordMatcher.
|
||||
*
|
||||
* @param records the baseline records to use for matching
|
||||
* @param imaPolicy the IMA policy to reference during matching; its partial path and path
|
||||
* equivalence settings influence matching behavior
|
||||
* @param imaBaseline the IMA baseline these records were sourced from; this is only used to
|
||||
*/
|
||||
public ImaAcceptablePathAndHashRecordMatcher(
|
||||
final Collection<IMABaselineRecord> records,
|
||||
final IMAPolicy imaPolicy,
|
||||
final ImaBaseline imaBaseline) {
|
||||
super(records, imaPolicy, imaBaseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an IMAMatchStatus indicating whether the given {@link IMAMeasurementRecord} is
|
||||
* contained within the originally provided {@link IMABaselineRecord}s.
|
||||
*
|
||||
* @param record the record to look up
|
||||
* @return an IMAMatchStatus indicating whether the record is a match, mismatch, or unknown to
|
||||
* the given baseline records
|
||||
*/
|
||||
@Override
|
||||
public IMAMatchStatus<IMABaselineRecord> contains(final IMAMeasurementRecord record) {
|
||||
Preconditions.checkArgument(record != null, "Cannot match on null record.");
|
||||
|
||||
final Set<IMABaselineRecord> matchRecords = new HashSet<>();
|
||||
final Set<IMABaselineRecord> mismatchRecords = new HashSet<>();
|
||||
|
||||
final Collection<IMABaselineRecord> matchingRecords = getRelatedBaselineRecordsByPath(
|
||||
record
|
||||
);
|
||||
|
||||
for (IMABaselineRecord baselineRecord : matchingRecords) {
|
||||
compareDigestsAndPopulateMatchLists(
|
||||
baselineRecord, record, matchRecords, mismatchRecords
|
||||
);
|
||||
}
|
||||
|
||||
if (matchRecords.isEmpty() && mismatchRecords.isEmpty()) {
|
||||
return new IMAMatchStatus<>(record, ReportMatchStatus.UNKNOWN, getImaBaseline());
|
||||
}
|
||||
|
||||
if (matchRecords.isEmpty()) {
|
||||
return new IMAMatchStatus<>(
|
||||
record, ReportMatchStatus.MISMATCH, mismatchRecords, getImaBaseline()
|
||||
);
|
||||
}
|
||||
|
||||
return new IMAMatchStatus<>(
|
||||
record,
|
||||
ReportMatchStatus.MATCH,
|
||||
matchRecords,
|
||||
getImaBaseline()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private static void compareDigestsAndPopulateMatchLists(
|
||||
final IMABaselineRecord baselineRecord,
|
||||
final IMAMeasurementRecord measurementRecord,
|
||||
final Set<IMABaselineRecord> matchRecords,
|
||||
final Set<IMABaselineRecord> mismatchRecords) {
|
||||
DigestComparisonResultType comparison =
|
||||
measurementRecord.getHash().compare(baselineRecord.getHash());
|
||||
|
||||
switch (comparison) {
|
||||
case MATCH:
|
||||
matchRecords.add(baselineRecord);
|
||||
break;
|
||||
case MISMATCH:
|
||||
mismatchRecords.add(baselineRecord);
|
||||
break;
|
||||
default:
|
||||
LOGGER.warn("{} comparison result when comparing {} with {}.",
|
||||
comparison, baselineRecord, measurementRecord);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
package hirs.ima.matching;
|
||||
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import hirs.data.persist.enums.AlertType;
|
||||
import hirs.data.persist.enums.ReportMatchStatus;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class extends the base matching functionality of {@link ImaRecordMatcher} to
|
||||
* compare {@link IMAMeasurementRecord}s against a collection of {@link ImaBlacklistRecord}s.
|
||||
*/
|
||||
public class ImaBlacklistRecordMatcher extends ImaRecordMatcher<ImaBlacklistRecord> {
|
||||
/**
|
||||
* Construct a new ImaBlacklistRecordMatcher.
|
||||
*
|
||||
* @param records the baseline records to use for matching
|
||||
* @param imaPolicy the IMA policy to reference during matching; its partial path and path
|
||||
* equivalence settings influence matching behavior
|
||||
* @param imaBaseline the IMA baseline these records were sourced from; this is only used to
|
||||
*/
|
||||
public ImaBlacklistRecordMatcher(
|
||||
final Collection<ImaBlacklistRecord> records,
|
||||
final IMAPolicy imaPolicy,
|
||||
final ImaBaseline imaBaseline) {
|
||||
super(records, imaPolicy, imaBaseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an IMAMatchStatus indicating whether the given {@link IMAMeasurementRecord} is
|
||||
* contained within the originally provided {@link ImaBlacklistRecord}s.
|
||||
*
|
||||
* @param record the record to look up
|
||||
* @return an IMAMatchStatus indicating whether the record is a match, mismatch, or unknown to
|
||||
* the given baseline records
|
||||
*/
|
||||
public IMAMatchStatus<ImaBlacklistRecord> contains(final IMAMeasurementRecord record) {
|
||||
if (record == null) {
|
||||
throw new IllegalArgumentException("Cannot match on null record.");
|
||||
}
|
||||
|
||||
final Set<ImaBlacklistRecord> matchesByPath = getRelatedBaselineRecordsByPath(record);
|
||||
final Set<ImaBlacklistRecord> matchesByHash = getRelatedBaselineRecordsByHash(record);
|
||||
final Set<ImaBlacklistRecord> matchingRecords = new HashSet<>();
|
||||
|
||||
for (ImaBlacklistRecord blacklistRecord : matchesByPath) {
|
||||
if (blacklistRecord.getHash() == null || matchesByHash.contains(blacklistRecord)) {
|
||||
matchingRecords.add(blacklistRecord);
|
||||
}
|
||||
}
|
||||
|
||||
for (ImaBlacklistRecord blacklistRecord : matchesByHash) {
|
||||
if (blacklistRecord.getPath() == null || matchesByPath.contains(blacklistRecord)) {
|
||||
matchingRecords.add(blacklistRecord);
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingRecords.isEmpty()) {
|
||||
return new IMAMatchStatus<>(record, ReportMatchStatus.UNKNOWN, getImaBaseline());
|
||||
} else {
|
||||
return new IMAMatchStatus<>(
|
||||
record,
|
||||
ReportMatchStatus.MATCH,
|
||||
matchingRecords,
|
||||
getImaBaseline()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of IMA blacklist alert that should be generated from the given list
|
||||
* of blacklist matches. If all matches are of a single type, it will return the type of alert
|
||||
* as given by {@link ImaBlacklistRecord#getAlertMatchType()}. Otherwise, it will return
|
||||
* <code>Alert.AlertType.IMA_BLACKLIST_MIXED_MATCH</code>.
|
||||
*
|
||||
* @param blacklistMatches the list of matches
|
||||
* @return the relevant alert type
|
||||
*/
|
||||
public static AlertType getBlacklistAlertType(
|
||||
final Set<IMAMatchStatus<ImaBlacklistRecord>> blacklistMatches) {
|
||||
AlertType type = null;
|
||||
for (IMAMatchStatus<ImaBlacklistRecord> match : blacklistMatches) {
|
||||
for (ImaBlacklistRecord blacklistRecord : match.getBaselineRecords()) {
|
||||
if (type == null) {
|
||||
type = blacklistRecord.getAlertMatchType();
|
||||
} else {
|
||||
if (type != blacklistRecord.getAlertMatchType()) {
|
||||
return AlertType.IMA_BLACKLIST_MIXED_MATCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
package hirs.ima.matching;
|
||||
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
import hirs.data.persist.ImaIgnoreSetRecord;
|
||||
import hirs.data.persist.enums.ReportMatchStatus;
|
||||
import hirs.utils.RegexFilePathMatcher;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class extends the base matching functionality of {@link ImaRecordMatcher} to
|
||||
* compare {@link IMAMeasurementRecord}s against a collection of {@link ImaIgnoreSetRecord}s.
|
||||
*/
|
||||
public class ImaIgnoreSetRecordMatcher extends ImaRecordMatcher<ImaIgnoreSetRecord> {
|
||||
private Map<ImaIgnoreSetRecord, RegexFilePathMatcher> matchers = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Construct a new ImaBlacklistRecordMatcher.
|
||||
*
|
||||
* @param records the baseline records to use for matching
|
||||
* @param imaPolicy the IMA policy to reference during matching; its partial path and path
|
||||
* equivalence settings influence matching behavior
|
||||
* @param imaBaseline the IMA baseline these records were sourced from; this is only used to
|
||||
*/
|
||||
public ImaIgnoreSetRecordMatcher(
|
||||
final Collection<ImaIgnoreSetRecord> records,
|
||||
final IMAPolicy imaPolicy,
|
||||
final ImaBaseline imaBaseline) {
|
||||
super(records, imaPolicy, imaBaseline);
|
||||
|
||||
for (ImaIgnoreSetRecord ignoreRecord : records) {
|
||||
matchers.put(ignoreRecord, new RegexFilePathMatcher(ignoreRecord.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an IMAMatchStatus indicating whether the given {@link IMAMeasurementRecord} is
|
||||
* contained within the originally provided {@link ImaIgnoreSetRecord}s.
|
||||
*
|
||||
* A measurement record's path will match this ignore set in the following cases:
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>if any of of the ignore set records contain a regex that matches the given path</li>
|
||||
* <li>if any of of the ignore set records are an exact match with the given path</li>
|
||||
* <li>if any of of the ignore set records are the initial substring of the given path</li>
|
||||
* <li>if any of of the ignore set records are partial paths and the given path is a full path
|
||||
* with the same filename</li>
|
||||
* <li>if the given path is a partial path and any of of the ignore set records are full paths
|
||||
* with the same filename</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param record the record to look up
|
||||
* @return an IMAMatchStatus indicating whether the record is a match, mismatch, or unknown to
|
||||
* the given baseline records
|
||||
*/
|
||||
public IMAMatchStatus<ImaIgnoreSetRecord> contains(final IMAMeasurementRecord record) {
|
||||
if (record == null) {
|
||||
throw new IllegalArgumentException("Cannot match on null record.");
|
||||
}
|
||||
|
||||
Set<ImaIgnoreSetRecord> matchingRecords = getRelatedBaselineRecordsByPath(record);
|
||||
|
||||
for (Map.Entry<ImaIgnoreSetRecord, RegexFilePathMatcher> recordMatcher
|
||||
: matchers.entrySet()) {
|
||||
if (recordMatcher.getValue().isMatch(record.getPath())) {
|
||||
matchingRecords.add(recordMatcher.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingRecords.isEmpty()) {
|
||||
return new IMAMatchStatus<>(record, ReportMatchStatus.UNKNOWN, getImaBaseline());
|
||||
} else {
|
||||
return new IMAMatchStatus<>(
|
||||
record,
|
||||
ReportMatchStatus.MATCH,
|
||||
matchingRecords,
|
||||
getImaBaseline()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,211 +0,0 @@
|
||||
package hirs.ima.matching;
|
||||
|
||||
import com.google.common.collect.ImmutableListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.IMAMeasurementRecord;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.baseline.AbstractImaBaselineRecord;
|
||||
import hirs.data.persist.baseline.ImaBaseline;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This class contains the logic used to match IMA measurement records against
|
||||
* IMA baseline records. Given a collection of IMABaselineRecords, an IMAPolicy,
|
||||
* and an ImaBaseline, it is able to determine which measurement records should be considered
|
||||
* matches, mismatches, or unknown to the given set of baseline records.
|
||||
*
|
||||
* @param <T> the type of IMA baseline record that this class matches against
|
||||
*/
|
||||
public abstract class ImaRecordMatcher<T extends AbstractImaBaselineRecord> {
|
||||
private final IMAPolicy imaPolicy;
|
||||
private final ImaBaseline imaBaseline;
|
||||
private final Collection<T> records;
|
||||
|
||||
// lookup maps
|
||||
private Multimap<String, T> pathMap = null;
|
||||
private Multimap<String, T> hashMap = null;
|
||||
|
||||
/**
|
||||
* Construct a new IMARecordMatcher.
|
||||
*
|
||||
* @param records the baseline records to use for matching
|
||||
* @param imaPolicy the IMA policy to reference during matching; its partial path and path
|
||||
* equivalence settings influence matching behavior
|
||||
* @param imaBaseline the IMA baseline these records were sourced from; this is only used to
|
||||
* record references to mismatched records
|
||||
*/
|
||||
public ImaRecordMatcher(
|
||||
final Collection<T> records,
|
||||
final IMAPolicy imaPolicy,
|
||||
final ImaBaseline imaBaseline) {
|
||||
this.records = records;
|
||||
this.imaPolicy = imaPolicy;
|
||||
this.imaBaseline = imaBaseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the baseline associated with this record matcher.
|
||||
*
|
||||
* @return the associated IMA baseline
|
||||
*/
|
||||
protected ImaBaseline getImaBaseline() {
|
||||
return this.imaBaseline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an IMAMatchStatus indicating whether the given {@link IMAMeasurementRecord} is
|
||||
* contained within the originally provided baseline records.
|
||||
*
|
||||
* @param record the record to look up
|
||||
* @return an IMAMatchStatus indicating whether the record is a match, mismatch, or unknown to
|
||||
* the given baseline records
|
||||
*/
|
||||
public abstract IMAMatchStatus<T> contains(IMAMeasurementRecord record);
|
||||
|
||||
/**
|
||||
* Given a collection of measurement records, populate and return a BatchImaMatchStatus
|
||||
* instance containing the match results according to this ImaRecordMatcher's matching
|
||||
* behavior and the given IMA policy, baseline, and baseline records.
|
||||
*
|
||||
* @param records the measurement records to match to baseline records
|
||||
* @return a BatchImaMatchStatus containing the match status of all the given records
|
||||
*/
|
||||
public BatchImaMatchStatus<T> batchMatch(final Collection<IMAMeasurementRecord> records) {
|
||||
List<IMAMatchStatus<T>> matchStatuses = new ArrayList<>();
|
||||
for (IMAMeasurementRecord record : records) {
|
||||
matchStatuses.add(contains(record));
|
||||
}
|
||||
return new BatchImaMatchStatus<>(matchStatuses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all IMA baseline records that are related to the given IMA measurement record
|
||||
* as determined by path similarity or equivalency. This method respects the IMA policy
|
||||
* that was given at construction time with respect to partial path matching.
|
||||
*
|
||||
* @param record the record for which all matching IMA baseline records should be returned
|
||||
* @return the resulting set of IMA baseline records
|
||||
*/
|
||||
protected Set<T> getRelatedBaselineRecordsByPath(final IMAMeasurementRecord record) {
|
||||
if (record == null) {
|
||||
throw new IllegalArgumentException("Cannot match on null record.");
|
||||
}
|
||||
|
||||
if (pathMap == null) {
|
||||
pathMap = createPathMap(this.records);
|
||||
}
|
||||
|
||||
final Set<T> matchingRecords = new HashSet<>();
|
||||
matchingRecords.addAll(pathMap.get(record.getPath()));
|
||||
|
||||
if (imaPolicy.isPartialPathEnable() && isFullPath(record.getPath())) {
|
||||
for (T matchingPartialRecord
|
||||
: pathMap.get(IMABaselineRecord.getPartialPath(record.getPath()))) {
|
||||
|
||||
// ensure that we're not about to match two unequal full paths
|
||||
if (isFullPath(matchingPartialRecord.getPath())
|
||||
&& !matchingPartialRecord.getPath().equals(record.getPath())) {
|
||||
continue;
|
||||
} else {
|
||||
matchingRecords.add(matchingPartialRecord);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingRecords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all IMA baseline records that are related to the given IMA measurement record
|
||||
* as determined by their hash values.
|
||||
*
|
||||
* @param record the record for which all matching IMA baseline records should be returned
|
||||
* @return the resulting set of IMA baseline records
|
||||
*/
|
||||
protected Set<T> getRelatedBaselineRecordsByHash(final IMAMeasurementRecord record) {
|
||||
if (record == null) {
|
||||
throw new IllegalArgumentException("Cannot match on null record.");
|
||||
}
|
||||
|
||||
if (hashMap == null) {
|
||||
hashMap = createHashMap(this.records);
|
||||
}
|
||||
|
||||
return new HashSet<>(hashMap.get(record.getHash().toString()));
|
||||
}
|
||||
|
||||
private Multimap<String, T> createPathMap(
|
||||
final Collection<T> imaBaselineRecords) {
|
||||
ImmutableListMultimap.Builder<String, T> mapBuilder =
|
||||
ImmutableListMultimap.builder();
|
||||
|
||||
for (T record : imaBaselineRecords) {
|
||||
if (record.getPath() != null) {
|
||||
for (String matchingPath : getMatchingPaths(imaPolicy, record.getPath())) {
|
||||
mapBuilder.put(matchingPath, record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mapBuilder.build();
|
||||
}
|
||||
|
||||
private Multimap<String, T> createHashMap(
|
||||
final Collection<T> imaBaselineRecords) {
|
||||
ImmutableListMultimap.Builder<String, T> mapBuilder =
|
||||
ImmutableListMultimap.builder();
|
||||
|
||||
for (T record : imaBaselineRecords) {
|
||||
Digest hash = record.getHash();
|
||||
if (hash != null) {
|
||||
mapBuilder.put(hash.toString(), record);
|
||||
}
|
||||
}
|
||||
|
||||
return mapBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates all paths that should be considered as 'matching' the given path, according to
|
||||
* the given IMAPolicy, including the original path itself. For instance, if partial paths are
|
||||
* enabled, the path's filename will be included in the returned collection. Additionally, if
|
||||
* the IMA policy is configured with equivalent paths, these are evaluated against the given
|
||||
* path and any relevant permutations are returned as well.
|
||||
*
|
||||
* @param imaPolicy the IMAPolicy to use in calculating matching paths
|
||||
* @param targetPath the original path whose matching paths will calculated and returned
|
||||
* @return a collection of paths that this IMAPolicy would consider as matching the path
|
||||
*/
|
||||
public static Collection<String> getMatchingPaths(
|
||||
final IMAPolicy imaPolicy,
|
||||
final String targetPath) {
|
||||
Multimap<String, String> pathEquivalences = imaPolicy.getPathEquivalences();
|
||||
Set<String> pathsToFind = new HashSet<>();
|
||||
|
||||
pathsToFind.add(targetPath);
|
||||
for (String path : pathEquivalences.keySet()) {
|
||||
if (targetPath.startsWith(path)) {
|
||||
for (String equivalentPath : pathEquivalences.get(path)) {
|
||||
pathsToFind.add(targetPath.replaceFirst(path, equivalentPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imaPolicy.isPartialPathEnable() && isFullPath(targetPath)) {
|
||||
pathsToFind.add(IMABaselineRecord.getPartialPath(targetPath));
|
||||
}
|
||||
|
||||
return pathsToFind;
|
||||
}
|
||||
|
||||
private static boolean isFullPath(final String path) {
|
||||
return path.startsWith("/");
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Contains classes related to matching IMA measurement records against IMA baseline records.
|
||||
*/
|
||||
package hirs.ima.matching;
|
@ -1,6 +0,0 @@
|
||||
/**
|
||||
* Non-persistant classes related to IMA.
|
||||
*/
|
||||
|
||||
package hirs.ima;
|
||||
|
@ -56,14 +56,14 @@ import static org.hibernate.criterion.Restrictions.sqlRestriction;
|
||||
* This class exists primarily to reduce code in {@link DBManager} which retries these methods
|
||||
* using a RetryTemplate.
|
||||
*
|
||||
* @param <T> type of objects to manage by this manager
|
||||
* @param <AbstractEntity> type of objects to manage by this manager
|
||||
*/
|
||||
public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
public abstract class AbstractDbManager<AbstractEntity> implements CrudManager<AbstractEntity> {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(AbstractDbManager.class);
|
||||
private static final int MAX_CLASS_CACHE_ENTRIES = 500;
|
||||
|
||||
private final Class<T> clazz;
|
||||
private final AbstractEntity entity;
|
||||
|
||||
private SessionFactory factory;
|
||||
|
||||
@ -74,8 +74,8 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* unfortunately class type of T cannot be determined using only T
|
||||
* @param sessionFactory the session factory to use to interact with the database
|
||||
*/
|
||||
public AbstractDbManager(final Class<T> clazz, final SessionFactory sessionFactory) {
|
||||
if (clazz == null) {
|
||||
public AbstractDbManager(final AbstractEntity entity, final SessionFactory sessionFactory) {
|
||||
if (entity == null) {
|
||||
LOGGER.error("AbstractDbManager cannot be instantiated with a null class");
|
||||
throw new IllegalArgumentException(
|
||||
"AbstractDbManager cannot be instantiated with a null class"
|
||||
@ -87,26 +87,24 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
"AbstractDbManager cannot be instantiated with a null SessionFactory"
|
||||
);
|
||||
}
|
||||
this.clazz = clazz;
|
||||
this.entity = entity;
|
||||
this.factory = sessionFactory;
|
||||
}
|
||||
|
||||
private static final LoadingCache<Class, Set<Field>> PERSISTED_FIELDS =
|
||||
private static final LoadingCache<AbstractEntity, Set<Field>> PERSISTED_FIELDS =
|
||||
CacheBuilder.newBuilder()
|
||||
.maximumSize(MAX_CLASS_CACHE_ENTRIES)
|
||||
.build(
|
||||
new CacheLoader<Class, Set<Field>>() {
|
||||
.build(new CacheLoader<AbstractEntity, Set<Field>>() {
|
||||
@Override
|
||||
public Set<Field> load(final Class clazz) throws Exception {
|
||||
return getPersistedFields(clazz);
|
||||
public Set<Field> load(final AbstractEntity entity) throws Exception {
|
||||
return getPersistedFields(entity);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
private static Set<Field> getPersistedFields(final Class clazz) {
|
||||
private static Set<Field> getPersistedFields(final AbstractEntity entity) {
|
||||
Set<Field> fields = new HashSet<>();
|
||||
|
||||
for (Field f : clazz.getDeclaredFields()) {
|
||||
for (Field f : entity.getDeclaredFields()) {
|
||||
if (f.isAnnotationPresent(OneToMany.class)
|
||||
|| f.isAnnotationPresent(ManyToMany.class)
|
||||
|| f.isAnnotationPresent(ManyToOne.class)
|
||||
@ -116,8 +114,8 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
}
|
||||
}
|
||||
|
||||
if (clazz.getSuperclass() != Object.class) {
|
||||
fields.addAll(getPersistedFields(clazz.getSuperclass()));
|
||||
if (entity.getSuperclass() != Object.class) {
|
||||
fields.addAll(getPersistedFields(entity.getSuperclass()));
|
||||
}
|
||||
|
||||
return fields;
|
||||
@ -205,9 +203,9 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
try {
|
||||
LOGGER.debug("retrieving object from db");
|
||||
tx = session.beginTransaction();
|
||||
Object o = session.get(clazz, id);
|
||||
if (o != null && clazz.isInstance(o)) {
|
||||
T objectOfTypeT = clazz.cast(o);
|
||||
Object obj = session.get(entity, id);
|
||||
if (obj instanceof AbstractEntity) {
|
||||
AbstractEntity objectOfTypeT = (AbstractEntity) obj;
|
||||
LOGGER.debug("found object, deleting it");
|
||||
session.delete(objectOfTypeT);
|
||||
deleted = true;
|
||||
@ -250,16 +248,16 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
Transaction tx = null;
|
||||
Session session = factory.getCurrentSession();
|
||||
CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<T> criteria = builder.createQuery(clazz);
|
||||
CriteriaQuery<AbstractEntity> criteria = builder.createQuery(entity);
|
||||
try {
|
||||
LOGGER.debug("retrieving object from db");
|
||||
tx = session.beginTransaction();
|
||||
Root<T> myObjectRoot = criteria.from(clazz);
|
||||
Join<T, JoinObject> joinObject = myObjectRoot.join("joinObject");
|
||||
Root<AbstractEntity> myObjectRoot = criteria.from(clazz);
|
||||
Join<AbstractEntity, JoinObject> joinObject = myObjectRoot.join("joinObject");
|
||||
Object object = session.getSessionFactory().getCurrentSession().createCriteria(clazz)
|
||||
.add(Restrictions.eq("name", name)).uniqueResult();
|
||||
if (object != null && clazz.isInstance(object)) {
|
||||
T objectOfTypeT = clazz.cast(object);
|
||||
if (object instanceof AbstractEntity) {
|
||||
AbstractEntity objectOfTypeT = (AbstractEntity) object;
|
||||
LOGGER.debug("found object, deleting it");
|
||||
session.delete(objectOfTypeT);
|
||||
deleted = true;
|
||||
@ -289,7 +287,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if unable to find the baseline or delete it
|
||||
* from the database
|
||||
*/
|
||||
protected boolean doDelete(final T object) throws DBManagerException {
|
||||
protected boolean doDelete(final AbstractEntity object) throws DBManagerException {
|
||||
LOGGER.debug("deleting object: {}", object);
|
||||
if (object == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
@ -329,14 +327,14 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
LOGGER.debug("Deleting instances of class: {}", clazz);
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<T> criteriaQuery = builder.createQuery(clazz);
|
||||
Root<T> root = criteriaQuery.from(clazz);
|
||||
CriteriaQuery<AbstractEntity> criteriaQuery = builder.createQuery(clazz);
|
||||
Root<AbstractEntity> root = criteriaQuery.from(clazz);
|
||||
Predicate recordPredicate = builder.and(
|
||||
);
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<T> query = session.createQuery(criteriaQuery);
|
||||
List<T> results = query.getResultList();
|
||||
T ret = null;
|
||||
Query<AbstractEntity> query = session.createQuery(criteriaQuery);
|
||||
List<AbstractEntity> results = query.getResultList();
|
||||
AbstractEntity ret = null;
|
||||
if (results != null && !results.isEmpty()) {
|
||||
ret = results.get(0);
|
||||
}
|
||||
@ -344,8 +342,8 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
List instances = session.createCriteria(clazz)
|
||||
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
|
||||
for (Object instance : instances) {
|
||||
if (instance != null && clazz.isInstance(instance)) {
|
||||
session.delete(clazz.cast(instance));
|
||||
if (instance instanceof AbstractEntity) {
|
||||
session.delete((AbstractEntity) instance);
|
||||
numEntitiesDeleted++;
|
||||
}
|
||||
}
|
||||
@ -372,16 +370,16 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if an error is encountered while performing the query or creating
|
||||
* the result objects
|
||||
*/
|
||||
protected List<T> doGetWithCriteria(final Collection<Criterion> criteriaCollection)
|
||||
protected List<AbstractEntity> doGetWithCriteria(final Collection<Criterion> criteriaCollection)
|
||||
throws DBManagerException {
|
||||
return doGetWithCriteria(clazz, criteriaCollection);
|
||||
return doGetWithCriteria(entity, criteriaCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a Criteria query using the given collection of Criterion over the
|
||||
* associated class.
|
||||
*
|
||||
* @param <U> the specific type of class to retrieve
|
||||
* @param <AbstractEntity> the specific type of class to retrieve
|
||||
* (should extend this class' <T> parameter)
|
||||
* @param clazzToGet the class of object to retrieve
|
||||
* @param criteriaCollection the collection of Criterion to apply
|
||||
@ -390,8 +388,8 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if an error is encountered while performing the query or creating
|
||||
* the result objects
|
||||
*/
|
||||
protected final <U extends T> List<U> doGetWithCriteria(
|
||||
final Class<U> clazzToGet,
|
||||
protected final List<AbstractEntity> doGetWithCriteria(
|
||||
final Class<AbstractEntity> clazzToGet,
|
||||
final Collection<Criterion> criteriaCollection
|
||||
) throws DBManagerException {
|
||||
LOGGER.debug("running criteria query over: {}", clazzToGet);
|
||||
@ -399,7 +397,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("criteria or restrictions");
|
||||
}
|
||||
List<U> ret = new ArrayList<>();
|
||||
List<AbstractEntity> ret = new ArrayList<>();
|
||||
Transaction tx = null;
|
||||
Session session = factory.getCurrentSession();
|
||||
try {
|
||||
@ -439,7 +437,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if object has previously been saved or an
|
||||
* error occurs while trying to save it to the database
|
||||
*/
|
||||
protected T doSave(final T object) throws DBManagerException {
|
||||
protected AbstractEntity doSave(final AbstractEntity object) throws DBManagerException {
|
||||
LOGGER.debug("saving object: {}", object);
|
||||
if (object == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
@ -454,7 +452,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
final Serializable id = session.save(object);
|
||||
Object o = session.get(object.getClass(), id);
|
||||
session.getTransaction().commit();
|
||||
return clazz.cast(o);
|
||||
return (AbstractEntity) o;
|
||||
} catch (Exception e) {
|
||||
final String msg = "unable to save object";
|
||||
LOGGER.error(msg, e);
|
||||
@ -473,7 +471,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @param object object to update
|
||||
* @throws DBManagerException if unable to update the record
|
||||
*/
|
||||
protected void doUpdate(final T object) throws DBManagerException {
|
||||
protected void doUpdate(final AbstractEntity object) throws DBManagerException {
|
||||
LOGGER.debug("updating object");
|
||||
if (object == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
@ -508,7 +506,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
protected T doGet(final String name) throws DBManagerException {
|
||||
protected AbstractEntity doGet(final String name) throws DBManagerException {
|
||||
LOGGER.debug("getting object: {}", name);
|
||||
if (name == null) {
|
||||
LOGGER.debug("null name argument");
|
||||
@ -518,17 +516,17 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
Transaction tx = null;
|
||||
Session session = factory.getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("retrieving " + clazz.toString() + " from db");
|
||||
LOGGER.debug("retrieving " + entity.toString() + " from db");
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<T> criteriaQuery = builder.createQuery(clazz);
|
||||
Root<T> root = criteriaQuery.from(clazz);
|
||||
CriteriaQuery<AbstractEntity> criteriaQuery = builder.createQuery(entity);
|
||||
Root<AbstractEntity> root = criteriaQuery.from(entity);
|
||||
Predicate recordPredicate = builder.and(
|
||||
builder.equal(root.get("name"), name));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<T> query = session.createQuery(criteriaQuery);
|
||||
List<T> results = query.getResultList();
|
||||
T ret = null;
|
||||
Query<AbstractEntity> query = session.createQuery(criteriaQuery);
|
||||
List<AbstractEntity> results = query.getResultList();
|
||||
AbstractEntity ret = null;
|
||||
if (results != null && !results.isEmpty()) {
|
||||
ret = results.get(0);
|
||||
}
|
||||
@ -557,7 +555,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
protected T doGet(final Serializable id) throws DBManagerException {
|
||||
protected AbstractEntity doGet(final Serializable id) throws DBManagerException {
|
||||
LOGGER.debug("getting object: {}", id);
|
||||
if (id == null) {
|
||||
LOGGER.debug("null id argument");
|
||||
@ -568,7 +566,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
try {
|
||||
LOGGER.debug("retrieving object from db");
|
||||
tx = session.beginTransaction();
|
||||
T ret = clazz.cast(session.get(clazz, id));
|
||||
AbstractEntity ret = (AbstractEntity) session.get(entity, id);
|
||||
tx.commit();
|
||||
return ret;
|
||||
} catch (Exception e) {
|
||||
@ -645,7 +643,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
protected T doGetAndLoadLazyFields(final String name, final boolean recurse)
|
||||
protected AbstractEntity doGetAndLoadLazyFields(final String name, final boolean recurse)
|
||||
throws DBManagerException {
|
||||
LOGGER.debug("getting object: {}", name);
|
||||
if (name == null) {
|
||||
@ -656,17 +654,17 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
Transaction tx = null;
|
||||
Session session = factory.getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("retrieving " + clazz.toString() + " from db");
|
||||
LOGGER.debug("retrieving " + entity.toString() + " from db");
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<T> criteriaQuery = builder.createQuery(clazz);
|
||||
Root<T> root = criteriaQuery.from(clazz);
|
||||
CriteriaQuery<AbstractEntity> criteriaQuery = builder.createQuery(entity);
|
||||
Root<AbstractEntity> root = criteriaQuery.from(entity);
|
||||
Predicate recordPredicate = builder.and(
|
||||
builder.equal(root.get("name"), name));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<T> query = session.createQuery(criteriaQuery);
|
||||
List<T> results = query.getResultList();
|
||||
T ret = null;
|
||||
Query<AbstractEntity> query = session.createQuery(criteriaQuery);
|
||||
List<AbstractEntity> results = query.getResultList();
|
||||
AbstractEntity ret = null;
|
||||
if (results != null && !results.isEmpty()) {
|
||||
ret = results.get(0);
|
||||
}
|
||||
@ -702,7 +700,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
protected T doGetAndLoadLazyFields(final Serializable id, final boolean recurse)
|
||||
protected AbstractEntity doGetAndLoadLazyFields(final Serializable id, final boolean recurse)
|
||||
throws DBManagerException {
|
||||
LOGGER.debug("getting object: {}", id);
|
||||
if (id == null) {
|
||||
@ -715,7 +713,7 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
try {
|
||||
LOGGER.debug("retrieving object from db");
|
||||
tx = session.beginTransaction();
|
||||
T ret = clazz.cast(session.get(clazz, id));
|
||||
AbstractEntity ret = (AbstractEntity) session.get(entity, id);
|
||||
doLoadLazyFields(ret, recurse);
|
||||
tx.commit();
|
||||
return ret;
|
||||
@ -744,17 +742,17 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @return list of <code>T</code> names
|
||||
* @throws DBManagerException if unable to search the database
|
||||
*/
|
||||
protected List<T> doGetList(final Class<? extends T> clazz,
|
||||
protected List<AbstractEntity> doGetList(final AbstractEntity entity,
|
||||
final Criterion additionalRestriction)
|
||||
throws DBManagerException {
|
||||
LOGGER.debug("Getting object list");
|
||||
Class<? extends T> searchClass = clazz;
|
||||
if (clazz == null) {
|
||||
LOGGER.debug("clazz is null");
|
||||
searchClass = this.clazz;
|
||||
AbstractEntity searchClass = entity;
|
||||
if (entity == null) {
|
||||
LOGGER.debug("entity is null");
|
||||
searchClass = this.entity;
|
||||
}
|
||||
|
||||
List<T> objects = new ArrayList<>();
|
||||
List<AbstractEntity> objects = new ArrayList<>();
|
||||
Transaction tx = null;
|
||||
Session session = factory.getCurrentSession();
|
||||
try {
|
||||
@ -776,8 +774,8 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
}
|
||||
// List list = criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
|
||||
for (Object o : results) {
|
||||
if (searchClass.isInstance(o)) {
|
||||
objects.add(searchClass.cast(o));
|
||||
if (o instanceof AbstractEntity) {
|
||||
objects.add((AbstractEntity) o);
|
||||
}
|
||||
}
|
||||
tx.commit();
|
||||
@ -814,12 +812,12 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
* @throws DBManagerException if unable to create the list
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
protected FilteredRecordsList<T> doGetOrderedList(final Class<? extends T> clazz,
|
||||
protected FilteredRecordsList<AbstractEntity> doGetOrderedList(final AbstractEntity clazz,
|
||||
final String columnToOrder, final boolean ascending, final int firstResult,
|
||||
final int maxResults, final String search, final Map<String, Boolean> searchableColumns,
|
||||
final CriteriaModifier criteriaModifier) throws DBManagerException {
|
||||
LOGGER.debug("Getting object list");
|
||||
Class<? extends T> searchClass = clazz;
|
||||
AbstractEntity searchClass = clazz;
|
||||
if (clazz == null) {
|
||||
LOGGER.debug("clazz is null");
|
||||
searchClass = this.clazz;
|
||||
@ -832,9 +830,9 @@ public abstract class AbstractDbManager<T> implements CrudManager<T> {
|
||||
}
|
||||
|
||||
//Object that will store query values
|
||||
FilteredRecordsList<T> aqr = new FilteredRecordsList<>();
|
||||
FilteredRecordsList<AbstractEntity> aqr = new FilteredRecordsList<>();
|
||||
|
||||
List<T> objects = new ArrayList<>();
|
||||
List<AbstractEntity> objects = new ArrayList<>();
|
||||
Transaction tx = null;
|
||||
Session session = factory.getCurrentSession();
|
||||
try {
|
||||
|
@ -1,230 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.Policy;
|
||||
import hirs.data.persist.Report;
|
||||
import hirs.data.persist.enums.AlertSource;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
* An <code>AlertManager</code> manages <code>Alert</code> objects. An
|
||||
* <code>AlertManager</code> is used to store and manage alerts. It has support
|
||||
* for the basic create and read methods. Update and delete are being discussed
|
||||
* but will not be implemented at this time.
|
||||
*/
|
||||
public interface AlertManager {
|
||||
|
||||
/**
|
||||
* Enumeration identify the type of list to return when querying for the ordered alert list.
|
||||
*/
|
||||
enum AlertListType {
|
||||
/**
|
||||
* List will contain only resolved alerts.
|
||||
*/
|
||||
RESOLVED_ALERTS,
|
||||
/**
|
||||
* List will contain only unresolved alerts.
|
||||
*/
|
||||
UNRESOLVED_ALERTS
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a new <code>Alert</code>. This stores a new
|
||||
* <code>Alert</code> to be managed by the <code>AlertManager</code>.
|
||||
* If the <code>Alert</code> is successfully saved then a reference to it
|
||||
* is returned.
|
||||
*
|
||||
* @param alert
|
||||
* Alert to save
|
||||
* @return reference to saved Alert
|
||||
* @throws AlertManagerException
|
||||
* if the Alert has previously been saved or unexpected error
|
||||
* occurs
|
||||
*/
|
||||
Alert saveAlert(Alert alert) throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Updates all of the {@link Alert}s provided in the list.
|
||||
*
|
||||
* @param alerts list of alerts to be updated
|
||||
* @return list of updated Alerts
|
||||
* @throws AlertManagerException
|
||||
* if unable to update the list of Alerts
|
||||
*/
|
||||
List<Alert> updateAlerts(List<Alert> alerts) throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>Alert</code>s managed by this manager.
|
||||
*
|
||||
* @return list of all managed <code>Alert</code> objects
|
||||
* @throws AlertManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
List<Alert> getAlertList() throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Alert</code> identified by <code>name</code>. If
|
||||
* the <code>Alert</code> cannot be found then null is returned.
|
||||
*
|
||||
* @param id
|
||||
* id of the <code>Alert</code>
|
||||
* @return <code>Alert</code> whose name is <code>name</code> or null if
|
||||
* not found
|
||||
* @throws AlertManagerException
|
||||
* if unable to retrieve the Alert
|
||||
*/
|
||||
Alert getAlert(UUID id) throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>Alert</code>s that relate to the provided <code>Report</code>
|
||||
* ID. The Alerts are ordered by a column and direction (ASC, DESC) that is provided by the
|
||||
* user. The alerts can be filtered by begin and/or end date.
|
||||
* This method helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param reportId - ID of the Report to return Alerts from
|
||||
* @param columnToOrder - Column to be ordered
|
||||
* @param ascending - direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @param listType enumeration indicating if the returned list conatins resolved or
|
||||
* unresolved alerts
|
||||
* @param searchableColumns Map of String and boolean values with column
|
||||
* headers and whether they are to. Boolean is true if field provides
|
||||
* a typical String that can be searched by Hibernate without
|
||||
* transformation.
|
||||
* @param beginDate the earliest date of any alert returned from this method. Can be null.
|
||||
* @param endDate the latest date of any alert returned from this method. Can be null.
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws AlertManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
FilteredRecordsList<Alert> getOrderedAlertList(
|
||||
String reportId, String columnToOrder, boolean ascending,
|
||||
int firstResult, int maxResults, String search,
|
||||
AlertListType listType,
|
||||
Map<String, Boolean> searchableColumns, Date beginDate, Date endDate)
|
||||
throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Overloads the resolveAlerts method and provides a null description for the
|
||||
* alert resolution.
|
||||
*
|
||||
* @param alerts - list of Alert objects to be marked as resolved
|
||||
* @throws AlertManagerException
|
||||
* if unable to save the list
|
||||
*/
|
||||
void resolveAlerts(List<Alert> alerts) throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Marks all Alerts that are provided as arguments as resolved. This is used as
|
||||
* a "soft delete" method and will ensure they no longer appear in the Alert
|
||||
* table on the Portal.
|
||||
*
|
||||
* @param alerts - list of Alert objects to be marked as resolved
|
||||
* @param description - description of action taken. The description can be null
|
||||
* @throws AlertManagerException
|
||||
* if unable to save the list
|
||||
*/
|
||||
void resolveAlerts(List<Alert> alerts, String description)
|
||||
throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves unresolved {@link Alert}s associated with the provided {@link Policy}.
|
||||
*
|
||||
* @param policy policy that is being evaluated
|
||||
* @return list of unresolved alerts associated with {@link Policy}
|
||||
* @throws AlertManagerException
|
||||
* If there is a query error
|
||||
*/
|
||||
List<Alert> getAlertsForPolicy(Policy policy) throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves unresolved {@link Alert}s associated with the provided {@link Baseline}.
|
||||
*
|
||||
* @param baseline baseline that is being evaluated
|
||||
* @return list of unresolved alerts associated with {@link Baseline}
|
||||
* @throws AlertManagerException
|
||||
* If there is a query error
|
||||
*/
|
||||
List<Alert> getAlertsForBaseline(Baseline baseline) throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the total number of Unresolved {@link Alert}s associated with the provided
|
||||
* {@link Baseline}.
|
||||
*
|
||||
* @param baseline baseline that is being evaluated
|
||||
* @return number of unresolved alerts associated with Baseline
|
||||
* @throws AlertManagerException
|
||||
* If there is a query error
|
||||
*/
|
||||
long getTotalAlertsForBaseline(Baseline baseline) throws AlertManagerException;
|
||||
|
||||
/**
|
||||
* Gets the set of alerts for a device in order to determine the status of
|
||||
* the device (trusted or untrusted).
|
||||
*
|
||||
* The alerts meet one or more of these specifications:
|
||||
* <ol>
|
||||
* <li> Have no report associated (missed periodic report alerts) for this device </li>
|
||||
* <li> Are associated with the provided integrity report </li>
|
||||
* <li> Match the specified criteria. e.g. leftover alerts from
|
||||
* delta reports in the current series of delta reports). </li>
|
||||
* </ol>
|
||||
* @param device the device to query for alerts on
|
||||
* @param integrityReport the integrity report to find associated alerts with
|
||||
* @param optionalCriterion the optional additional criteria for which to query on
|
||||
* @return the set of device alerts associated with trust
|
||||
*/
|
||||
List<Alert> getTrustAlerts(Device device, Report integrityReport,
|
||||
Criterion optionalCriterion);
|
||||
|
||||
/**
|
||||
* Gets the count of trust alerts for a device. See {@link #getTrustAlerts} for more
|
||||
* information about which alerts are counted.
|
||||
*
|
||||
* @param device the device to query for alerts on
|
||||
* @param integrityReport the integrity report to find associated alerts with
|
||||
* @param optionalCriterion the optional additional criteria for which to query on
|
||||
* @return the count of alerts associated with trust
|
||||
*/
|
||||
int getTrustAlertCount(Device device, Report integrityReport,
|
||||
Criterion optionalCriterion);
|
||||
|
||||
/**
|
||||
* Return the count of unresolved alerts associated with the given device.
|
||||
*
|
||||
* @param device associated with unresolved alerts being counted
|
||||
* @return count of unresolved alerts
|
||||
*/
|
||||
int countUnresolvedAlerts(Device device);
|
||||
|
||||
/**
|
||||
* Return the count of unresolved alerts associated with the given device that originate from
|
||||
* the given AlertSource.
|
||||
*
|
||||
* @param device associated with unresolved alerts being counted
|
||||
* @param source counted alerts must originate from
|
||||
* @return count of unresolved alerts
|
||||
*/
|
||||
int countUnresolvedAlerts(Device device, AlertSource source);
|
||||
|
||||
/**
|
||||
* Count the total number of devices with at least one unresolved alert within the given group.
|
||||
*
|
||||
* @param deviceGroup to count devices from
|
||||
* @return count of devices with unresolved alerts
|
||||
*/
|
||||
int countUnresolvedDevices(DeviceGroup deviceGroup);
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>AlertManageer</code>.
|
||||
*/
|
||||
public class AlertManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 3081536085161873284L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertManagerException</code> that has the message
|
||||
* <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
AlertManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertManagerException</code> that wraps the given
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
AlertManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertManagerException</code> that has the message
|
||||
* <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
AlertManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.alert.AlertMonitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An <code>AlertMonitorManager</code> manages <code>AlertMonitor</code>. An
|
||||
* <code>AlertMonitorManager</code> is used to store and manage AlertMonitors.
|
||||
* It has support for the basic create, read, update, and delete methods.
|
||||
*/
|
||||
public interface AlertMonitorManager {
|
||||
|
||||
/**
|
||||
* Stores a new <code>AlertMonitor</code>. This stores a new
|
||||
* <code>AlertMonitor</code> to be managed by the
|
||||
* <code>AlertMonitorManager</code>. If the <code>AlertMonitor</code> is
|
||||
* successfully saved then a reference to it is returned.
|
||||
*
|
||||
* @param monitor
|
||||
* the AlertMonitor to save AlertMonitor to save
|
||||
* @return reference to saved AlertMonitor
|
||||
* @throws AlertMonitorManagerException
|
||||
* if the AlertMonitor has previously been saved or unexpected
|
||||
* error occurs
|
||||
*/
|
||||
AlertMonitor saveAlertMonitor(AlertMonitor monitor)
|
||||
throws AlertMonitorManagerException;
|
||||
|
||||
/**
|
||||
* Updates a <code>AlertMonitor</code>. This updates the
|
||||
* <code>AlertMonitor</code> that is managed so subsequent calls to get this
|
||||
* <code>AlertMonitor</code> will return the values set by the incoming
|
||||
* <code>AlertMonitor</code>.
|
||||
*
|
||||
* @param alertMonitor
|
||||
* AlertMonitor
|
||||
* @throws AlertMonitorManagerException
|
||||
* if unable to update the AlertMonitor
|
||||
*/
|
||||
void updateAlertMonitor(AlertMonitor alertMonitor)
|
||||
throws AlertMonitorManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all AlertMonitor names managed by this manager. Every
|
||||
* <code>AlertMonitor</code> must have a name that users can use to
|
||||
* reference the <code>AlertMonitor</code>. This returns a listing of all
|
||||
* the <code>AlertMonitor</code>s.
|
||||
* <p>
|
||||
* A <code>Class</code> argument may be specified to limit which types of
|
||||
* <code>AlertMonitor</code>s to return. This argument may be null to return
|
||||
* all <code>AlertMonitor</code>s.
|
||||
*
|
||||
* @param clazz class type of <code>AlertMonitor</code>s to return (may be null)
|
||||
* @return list of <code>AlertMonitor</code> names
|
||||
* @throws AlertMonitorManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
List<AlertMonitor> getAlertMonitorList(Class<? extends AlertMonitor> clazz)
|
||||
throws AlertMonitorManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>AlertMonitor</code> identified by <code>name</code>.
|
||||
* If the <code>AlertMonitor</code> cannot be found then null is returned.
|
||||
*
|
||||
* @param name
|
||||
* name of the <code>AlertMonitor</code>
|
||||
* @return <code>AlertMonitor</code> whose name is <code>name</code> or null
|
||||
* if not found
|
||||
* @throws AlertMonitorManagerException
|
||||
* if unable to retrieve the AlertMonitor
|
||||
*/
|
||||
AlertMonitor getAlertMonitor(String name)
|
||||
throws AlertMonitorManagerException;
|
||||
|
||||
/**
|
||||
* Deletes the <code>AlertMonitor</code> identified by <code>name</code>. If
|
||||
* the <code>AlertMonitor</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
*
|
||||
* @param name
|
||||
* name of the <code>AlertMonitor</code> to delete
|
||||
* @return true if successfully found and deleted from repo, otherwise false
|
||||
* @throws AlertMonitorManagerException
|
||||
* if unable to delete the AlertMonitor for any reason other
|
||||
* than not found
|
||||
*/
|
||||
boolean deleteAlertMonitor(String name) throws AlertMonitorManagerException;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* This class represents an <code>AlertMonitorManagerException</code> generated by a
|
||||
* <code>AlertMonitorConfigManager</code>.
|
||||
*/
|
||||
public class AlertMonitorManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 4732897562100987654L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertMonitorManagerException</code> that has the message
|
||||
* <code>msg</code>.
|
||||
*
|
||||
* @param msg exception message
|
||||
*/
|
||||
AlertMonitorManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertMonitorManagerException</code> that wraps the given
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @param t root cause
|
||||
*/
|
||||
AlertMonitorManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertMonitorManagerException</code> that has the message <code>msg</code>
|
||||
* and wraps the root cause.
|
||||
*
|
||||
* @param msg exception message
|
||||
* @param t root cause
|
||||
*/
|
||||
AlertMonitorManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.alert.AlertServiceConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An <code>AlertServiceManager</code> manages <code>AlertServiceConfig</code>s. An
|
||||
* <code>AlertServiceManager</code> is used to store and manage AlertServiceConfigs. It has support
|
||||
* for the basic create, read, update, and delete methods.
|
||||
*/
|
||||
public interface AlertServiceConfigManager {
|
||||
|
||||
/**
|
||||
* Stores a new <code>AlertServiceConfig</code>. This stores a new
|
||||
* <code>AlertServiceConfig</code> to be managed by the <code>AlertServiceManager</code>. If the
|
||||
* <code>AlertServiceConfig</code> is successfully saved then a reference to it is returned.
|
||||
*
|
||||
* @param service the AlertServiceConfig to save AlertServiceConfig to save
|
||||
* @return reference to saved AlertServiceConfig
|
||||
* @throws AlertServiceConfigManagerException if the AlertServiceConfig has previously been
|
||||
* saved or unexpected error occurs
|
||||
*/
|
||||
AlertServiceConfig saveAlertServiceConfig(AlertServiceConfig service)
|
||||
throws AlertServiceConfigManagerException;
|
||||
|
||||
/**
|
||||
* Updates a <code>AlertServiceConfig</code>. This updates the <code>AlertServiceConfig</code>
|
||||
* that is managed so subsequent calls to get this <code>AlertServiceConfig</code> will return
|
||||
* the values set by the incoming <code>AlertServiceConfig</code>.
|
||||
*
|
||||
* @param serviceConfig the AlertServiceConfig
|
||||
* @throws AlertServiceConfigManagerException if unable to update the AlertServiceConfig
|
||||
*/
|
||||
void updateAlertServiceConfig(AlertServiceConfig serviceConfig)
|
||||
throws AlertServiceConfigManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all AlertServiceConfig names managed by this manager. Every
|
||||
* <code>AlertServiceConfig</code> must have a name that users can use to reference the
|
||||
* <code>AlertServiceConfig</code>. This returns a listing of all the
|
||||
* <code>AlertServiceConfig</code>s.
|
||||
* <p>
|
||||
* A <code>Class</code> argument may be specified to limit which types of
|
||||
* <code>AlertServiceConfig</code>s to return. This argument may be null to return all
|
||||
* <code>AlertServiceConfig</code>s.
|
||||
*
|
||||
* @param clazz class type of <code>AlertServiceConfig</code>s to return (may be null)
|
||||
* @return list of <code>AlertServiceConfig</code> names
|
||||
* @throws AlertServiceConfigManagerException if unable to create the list
|
||||
*/
|
||||
List<AlertServiceConfig>
|
||||
getAlertServiceConfigList(Class<? extends AlertServiceConfig> clazz)
|
||||
throws AlertServiceConfigManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>AlertServiceConfig</code> identified by <code>name</code>. If the
|
||||
* <code>AlertServiceConfig</code> cannot be found then null is returned.
|
||||
*
|
||||
* @param type type of the <code>AlertServiceConfig</code>
|
||||
* @return <code>AlertServiceConfig</code> whose name is <code>name</code> or null if not found
|
||||
* @throws AlertServiceConfigManagerException if unable to retrieve the AlertServiceConfig
|
||||
*/
|
||||
AlertServiceConfig getAlertServiceConfig(String type)
|
||||
throws AlertServiceConfigManagerException;
|
||||
|
||||
/**
|
||||
* Deletes the <code>AlertServiceConfig</code> identified by <code>name</code>. If the
|
||||
* <code>AlertServiceConfig</code> is found and deleted then true is returned, otherwise false.
|
||||
*
|
||||
* @param type type of the <code>AlertServiceConfig</code> to delete
|
||||
* @return true if successfully found and deleted from repo, otherwise false
|
||||
* @throws AlertServiceConfigManagerException if unable to delete the AlertServiceConfig for any
|
||||
* reason other than not found
|
||||
*/
|
||||
boolean deleteAlertServiceConfig(String type)
|
||||
throws AlertServiceConfigManagerException;
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* This class represents an <code>AlertServiceConfigManagerException</code> generated by a
|
||||
* <code>AlertServiceConfigManager</code>.
|
||||
*/
|
||||
public class AlertServiceConfigManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 4732897562100987655L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertServiceManagerException</code> that has the message
|
||||
* <code>msg</code>.
|
||||
*
|
||||
* @param msg exception message
|
||||
*/
|
||||
AlertServiceConfigManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertServiceManagerException</code> that wraps the given
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @param t root cause
|
||||
*/
|
||||
AlertServiceConfigManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>AlertServiceManagerException</code> that has the message <code>msg</code>
|
||||
* and wraps the root cause.
|
||||
*
|
||||
* @param msg exception message
|
||||
* @param t root cause
|
||||
*/
|
||||
AlertServiceConfigManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.data.bean.SimpleBaselineBean;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import hirs.repository.RepoPackage;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A <code>BaselineManager</code> manages <code>Baseline</code>s. A <code>BaselineManager</code> can
|
||||
* read, update, and archive <code>Baseline</code>s.
|
||||
*/
|
||||
public interface BaselineManager extends OrderedListQuerier<Baseline> {
|
||||
|
||||
/**
|
||||
* Stores a new <code>Baseline</code>. This stores a new
|
||||
* <code>Baseline</code> to be managed by the <code>BaselineManager</code>.
|
||||
* If the <code>Baseline</code> is successfully saved then a reference to it
|
||||
* is returned.
|
||||
*
|
||||
* @param baseline baseline to save
|
||||
* @return reference to saved baseline
|
||||
* @throws BaselineManagerException if baseline is already saved or other error occurs
|
||||
*/
|
||||
Baseline saveBaseline(Baseline baseline) throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Updates a <code>Baseline</code>. This updates the <code>Baseline</code>
|
||||
* that is managed so subsequent calls to get this <code>Baseline</code>
|
||||
* will return the values set by the incoming <code>Baseline</code>.
|
||||
*
|
||||
* @param baseline baseline
|
||||
* @throws BaselineManagerException if unable to update the baseline
|
||||
*/
|
||||
void updateBaseline(Baseline baseline) throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all baseline names managed by this manager. Every
|
||||
* <code>Baseline</code> must have a name that users can use to reference
|
||||
* the <code>Baseline</code>. This returns a listing of all the
|
||||
* <code>Baseline</code>s.
|
||||
* <p>
|
||||
* A <code>Class</code> argument may be specified to limit which types of
|
||||
* <code>Baseline</code>s to return. This argument may be null to return all
|
||||
* <code>Baseline</code>s.
|
||||
*
|
||||
* @param clazz
|
||||
* class type of <code>Baseline</code>s to return (may be null)
|
||||
* @return list of <code>Baseline</code> names
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
List<Baseline> getBaselineList(Class<? extends Baseline> clazz)
|
||||
throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>Baseline</code>s that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables. The returned list does not
|
||||
* contain <code>Baseline</code>s that have been soft-deleted.
|
||||
*
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @param searchableColumns Map of String and boolean values with column
|
||||
* headers and whether they are to. Boolean is true if field provides
|
||||
* a typical String that can be searched by Hibernate without
|
||||
* transformation.
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
FilteredRecordsList<Baseline> getOrderedBaselineList(
|
||||
String columnToOrder, boolean ascending,
|
||||
int firstResult, int maxResults, String search,
|
||||
Map<String, Boolean> searchableColumns)
|
||||
throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all ImaBaseline Records that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param baselineId id of the baseline
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
FilteredRecordsList<IMABaselineRecord> getOrderedRecordList(
|
||||
UUID baselineId, String columnToOrder, boolean ascending,
|
||||
int firstResult, int maxResults, String search)
|
||||
throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all ImaBlacklistBaseline Records that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param baselineId id of the baseline
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
FilteredRecordsList<ImaBlacklistRecord> getOrderedBlacklistRecordList(
|
||||
UUID baselineId, String columnToOrder, boolean ascending,
|
||||
int firstResult, int maxResults, String search)
|
||||
throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all RepoPackages that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param name name of the baseline
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
FilteredRecordsList<RepoPackage> getOrderedPackageList(
|
||||
String name, String columnToOrder, boolean ascending,
|
||||
int firstResult, int maxResults, String search)
|
||||
throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all IMABaselineRecords in the specified package.
|
||||
*
|
||||
* @param id of the package
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return List the records
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
List<IMABaselineRecord> getPackageRecords(
|
||||
UUID id, String search) throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Baseline</code> identified by <code>name</code>. If
|
||||
* the <code>Baseline</code> cannot be found then null is returned.
|
||||
*
|
||||
* @param name name of the <code>Baseline</code>
|
||||
* @return <code>Baseline</code> whose name is <code>name</code> or null if not found
|
||||
* @throws BaselineManagerException if unable to retrieve the baseline
|
||||
*/
|
||||
Baseline getBaseline(String name) throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Baseline</code> identified by the given <code>id</code>. If
|
||||
* the <code>Baseline</code> cannot be found then null is returned.
|
||||
*
|
||||
* @param id the id of the desired <code>Baseline</code>
|
||||
* @return <code>Baseline</code> whose id is <code>id</code> or null if not found
|
||||
* @throws BaselineManagerException if unable to retrieve the baseline
|
||||
*/
|
||||
Baseline getBaseline(Serializable id) throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Baseline</code> identified by <code>name</code>. This method
|
||||
* fully loads a Baseline object; any lazy fields will be recursively loaded. This is
|
||||
* necessary when conducting an appraisal. If the <code>Baseline</code> cannot be found
|
||||
* then null is returned.
|
||||
*
|
||||
* @param name name of the <code>Baseline</code>
|
||||
* @return <code>Baseline</code> whose name is <code>name</code> or null if not found
|
||||
* @throws BaselineManagerException if unable to retrieve the baseline
|
||||
*/
|
||||
Baseline getCompleteBaseline(String name) throws BaselineManagerException;
|
||||
|
||||
/**
|
||||
* Archives the named {@link Baseline} and updates it in the database.
|
||||
*
|
||||
* @param name name of the {@link Baseline} to <code>archive</code>
|
||||
* @return true if the {@link Baseline} was successfully found and archived, false if the
|
||||
* {@link Baseline} was not found
|
||||
* @throws DBManagerException
|
||||
* if the {@link Baseline} is not an instance of ArchivableEntity.
|
||||
*/
|
||||
boolean archive(String name) throws DBManagerException;
|
||||
|
||||
/**
|
||||
* Deletes the named {@link Baseline} from the database.
|
||||
*
|
||||
* @param baseline {@link Baseline} to be deleted
|
||||
* @return <code>true</code> if the {@link Baseline} was successfully found and
|
||||
* deleted, <code>false</code> if the {@link Baseline} was not found
|
||||
* @throws DBManagerException
|
||||
* if the {@link Baseline} is not an instance of ArchivableEntity.
|
||||
*/
|
||||
boolean delete(Baseline baseline) throws DBManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>Baseline</code>s that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables. The returned list does not
|
||||
* contain <code>Baseline</code>s that have been soft-deleted. The records stored within each
|
||||
* baseline are not loaded.
|
||||
*
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @param searchableColumns Map of String and boolean values with column
|
||||
* headers and whether they are to. Boolean is true if field provides
|
||||
* a typical String that can be searched by Hibernate without
|
||||
* transformation.
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
FilteredRecordsList<SimpleBaselineBean> getOrderedBaselineListWithoutRecords(
|
||||
String columnToOrder, boolean ascending,
|
||||
int firstResult, int maxResults, String search,
|
||||
Map<String, Boolean> searchableColumns)
|
||||
throws BaselineManagerException;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>BaselineManageer</code>.
|
||||
*/
|
||||
public class BaselineManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 3081536085161873284L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>BaselineManagerException</code> that has the message
|
||||
* <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
BaselineManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>BaselineManagerException</code> that wraps the given
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
BaselineManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>BaselineManagerException</code> that has the message
|
||||
* <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
BaselineManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
@ -9,7 +9,7 @@ import java.util.List;
|
||||
* Interface defining database CRUD operations (Create, Read, Update, Delete).
|
||||
* @param <T> the object type, T.
|
||||
*/
|
||||
public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
public interface CrudManager<AbstractEntity> extends OrderedListQuerier<AbstractEntity> {
|
||||
|
||||
/**
|
||||
* Deletes all instances of the associated class.
|
||||
@ -27,7 +27,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @throws DBManagerException if object has previously been saved or an
|
||||
* error occurs while trying to save it to the database
|
||||
*/
|
||||
T save(T object) throws DBManagerException;
|
||||
AbstractEntity save(AbstractEntity object) throws DBManagerException;
|
||||
|
||||
/**
|
||||
* Updates an object stored in the database. This updates the database
|
||||
@ -36,7 +36,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @param object object to update
|
||||
* @throws DBManagerException if an error occurs while trying to save it to the database
|
||||
*/
|
||||
void update(T object) throws DBManagerException;
|
||||
void update(AbstractEntity object) throws DBManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Object</code> from the database. This searches the
|
||||
@ -48,7 +48,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
T get(String name) throws DBManagerException;
|
||||
AbstractEntity get(String name) throws DBManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Object</code> from the database. This searches the
|
||||
@ -65,7 +65,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
T getAndLoadLazyFields(String name, boolean recurse)
|
||||
AbstractEntity getAndLoadLazyFields(String name, boolean recurse)
|
||||
throws DBManagerException;
|
||||
|
||||
/**
|
||||
@ -78,7 +78,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
T get(Serializable id) throws DBManagerException;
|
||||
AbstractEntity get(Serializable id) throws DBManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Object</code> from the database. This searches the
|
||||
@ -95,7 +95,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
T getAndLoadLazyFields(Serializable id, boolean recurse)
|
||||
AbstractEntity getAndLoadLazyFields(Serializable id, boolean recurse)
|
||||
throws DBManagerException;
|
||||
|
||||
/**
|
||||
@ -111,7 +111,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @return list of <code>T</code> names
|
||||
* @throws DBManagerException if unable to search the database
|
||||
*/
|
||||
List<T> getList(Class<? extends T> clazz)
|
||||
List<AbstractEntity> getList(AbstractEntity entity)
|
||||
throws DBManagerException;
|
||||
|
||||
/**
|
||||
@ -128,7 +128,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @return list of <code>T</code> names
|
||||
* @throws DBManagerException if unable to search the database
|
||||
*/
|
||||
List<T> getList(Class<? extends T> clazz, Criterion additionalRestriction)
|
||||
List<AbstractEntity> getList(AbstractEntity entity, Criterion additionalRestriction)
|
||||
throws DBManagerException;
|
||||
|
||||
/**
|
||||
@ -171,7 +171,7 @@ public interface CrudManager<T> extends OrderedListQuerier<T> {
|
||||
* @return true if successfully found and deleted the object
|
||||
* @throws DBManagerException if unable to delete the object from the database
|
||||
*/
|
||||
boolean delete(T object) throws DBManagerException;
|
||||
boolean delete(AbstractEntity object) throws DBManagerException;
|
||||
|
||||
/**
|
||||
* Archives the named object and updates it in the database.
|
||||
|
@ -1,773 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.Policy;
|
||||
import hirs.data.persist.Report;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.data.persist.enums.AlertSource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* This class defines a <code>AlertManager</code> that stores policies in a
|
||||
* database.
|
||||
*/
|
||||
public class DBAlertManager extends DBManager<Alert> implements AlertManager {
|
||||
private static final Logger LOGGER = getLogger(DBAlertManager.class);
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBAlertManager</code>. The optional SessionFactory
|
||||
* parameter is used to initialize a session factory to manage all hibernate
|
||||
* sessions.
|
||||
*
|
||||
* @param factory session factory to manage connections to hibernate db
|
||||
*/
|
||||
public DBAlertManager(final SessionFactory factory) {
|
||||
super(Alert.class, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the <code>Alert</code> in the database and returns it.
|
||||
*
|
||||
* @param alert
|
||||
* alert to save
|
||||
* @return <code>Alert</code> that was saved
|
||||
* @throws AlertManagerException
|
||||
* if alert has previously been saved or an error occurs while
|
||||
* trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final Alert saveAlert(final Alert alert)
|
||||
throws AlertManagerException {
|
||||
LOGGER.debug("saving alert: {}", alert);
|
||||
try {
|
||||
return super.save(alert);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all of the {@link Alert}s provided in the list.
|
||||
*
|
||||
* @param alerts list of alerts to be updated
|
||||
* @return list of updated Alerts
|
||||
* @throws AlertManagerException
|
||||
* if unable to update the list of Alerts
|
||||
*/
|
||||
@Override
|
||||
public final List<Alert> updateAlerts(final List<Alert> alerts) throws AlertManagerException {
|
||||
LOGGER.debug("updating object");
|
||||
if (alerts == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("object");
|
||||
}
|
||||
|
||||
Transaction tx = null;
|
||||
List<Alert> updatedAlerts = new ArrayList<>();
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("updating object in db");
|
||||
tx = session.beginTransaction();
|
||||
for (Alert alert : alerts) {
|
||||
updatedAlerts.add((Alert) session.merge(alert));
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
final String msg = "unable to update alert";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw new AlertManagerException(msg, e);
|
||||
}
|
||||
|
||||
return updatedAlerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>Alert</code>s.
|
||||
* This searches through the database for this information.
|
||||
*
|
||||
* @return list of <code>Alert</code>s
|
||||
* @throws AlertManagerException
|
||||
* if unable to search the database
|
||||
*/
|
||||
@Override
|
||||
public final List<Alert> getAlertList() throws AlertManagerException {
|
||||
LOGGER.debug("getting alert list");
|
||||
try {
|
||||
return super.getList(Alert.class);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>Alert</code>s that relate to the provided <code>Report</code>
|
||||
* ID. If the given reportId is null or an empty, alerts for all reports are provided. The
|
||||
* Alerts are ordered by a column and direction (ASC, DESC) that is provided by the user.
|
||||
* This method helps support the server-side processing in the JQuery DataTables. Alerts with a
|
||||
* non-null archivedTime are not included in the returned list.
|
||||
*
|
||||
* @param reportId ID of the Report to return Alerts from, empty or null for all Alerts
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @param listType enumeration indicating if the returned list conatins resolved or
|
||||
* unresolved alerts
|
||||
* @param searchableColumns Map of String and boolean values with column
|
||||
* headers and whether they are to. Boolean is true if field provides
|
||||
* a typical String that can be searched by Hibernate without
|
||||
* transformation.
|
||||
* @param beginDate the earliest date of any alert returned from this method. Can be null.
|
||||
* @param endDate the latest date of any alert returned from this method. Can be null.
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws AlertManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
public final FilteredRecordsList<Alert> getOrderedAlertList(
|
||||
final String reportId, final String columnToOrder, final boolean ascending,
|
||||
final int firstResult, final int maxResults, final String search,
|
||||
final AlertListType listType,
|
||||
final Map<String, Boolean> searchableColumns, final Date beginDate, final Date endDate)
|
||||
throws AlertManagerException {
|
||||
|
||||
if (columnToOrder == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("object");
|
||||
}
|
||||
|
||||
// verify that the report ID is a legit UUID
|
||||
if (StringUtils.isNotEmpty(reportId)) {
|
||||
try {
|
||||
UUID.fromString(reportId);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new AlertManagerException(reportId + " is not a valid UUID", iae);
|
||||
}
|
||||
}
|
||||
|
||||
final FilteredRecordsList<Alert> alerts;
|
||||
|
||||
// check that the alert is not archived and that it is in the specified report
|
||||
CriteriaModifier modifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
if (listType == AlertListType.RESOLVED_ALERTS) {
|
||||
criteria.add(Restrictions.isNotNull("archivedTime"));
|
||||
} else {
|
||||
criteria.add(Restrictions.isNull("archivedTime"));
|
||||
}
|
||||
|
||||
// filter by date, if specified
|
||||
if (null != beginDate) {
|
||||
criteria.add(Restrictions.ge("createTime", beginDate));
|
||||
}
|
||||
|
||||
if (null != endDate) {
|
||||
criteria.add(Restrictions.le("createTime", endDate));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(reportId)) {
|
||||
// creating a separate criteria associated with the report field is necessary
|
||||
// for this to work in HSQL and MySQL to avoid column ambiguity.
|
||||
Criteria reportCriteria = criteria.createCriteria("report");
|
||||
reportCriteria.add(Restrictions.eq("id", UUID.fromString(reportId)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
LOGGER.debug("querying db for alerts");
|
||||
alerts = super.getOrderedList(Alert.class, columnToOrder, ascending, firstResult,
|
||||
maxResults, search, searchableColumns, modifier);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertManagerException(e);
|
||||
}
|
||||
return alerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Alert</code> from the database. This searches the
|
||||
* database for an entry whose name matches <code>name</code>. It then
|
||||
* reconstructs a <code>Alert</code> object from the database entry
|
||||
*
|
||||
* @param id
|
||||
* id of the <code>Alert</code>
|
||||
* @return alert if found, otherwise null.
|
||||
* @throws AlertManagerException
|
||||
* if unable to search the database or recreate the
|
||||
* <code>Alert</code>
|
||||
*/
|
||||
@Override
|
||||
public final Alert getAlert(final UUID id) throws AlertManagerException {
|
||||
LOGGER.debug("getting alert: {}", id);
|
||||
try {
|
||||
return super.get(id);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Alert}s associated with the provided {@link Policy}.
|
||||
*
|
||||
* @param policy policy that is being evaluated
|
||||
* @return list of all alerts associated with {@link Policy}
|
||||
* @throws AlertManagerException
|
||||
* If there is a query error
|
||||
*/
|
||||
@Override
|
||||
public final List<Alert> getAlertsForPolicy(final Policy policy)
|
||||
throws AlertManagerException {
|
||||
LOGGER.debug("");
|
||||
|
||||
if (policy == null) {
|
||||
throw new NullPointerException("policy was null");
|
||||
}
|
||||
|
||||
List<Alert> alerts = new ArrayList<>();
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
// query hibernate to count alerts with the given deviceName and null archivedTime
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Alert> criteriaQuery = criteriaBuilder.createQuery(Alert.class);
|
||||
Root<Alert> root = criteriaQuery.from(Alert.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.and(criteriaBuilder.equal(root.get("policyId"), policy.getId()));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<Alert> query = session.createQuery(criteriaQuery);
|
||||
List<Alert> results = query.getResultList();
|
||||
|
||||
// criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
|
||||
|
||||
for (Object o : results) {
|
||||
if (o instanceof Alert) {
|
||||
alerts.add((Alert) o);
|
||||
}
|
||||
}
|
||||
|
||||
tx.commit();
|
||||
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
return alerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Alert}s associated with the provided {@link Baseline}.
|
||||
*
|
||||
* @param baseline baseline that is being evaluated
|
||||
* @return list of all alerts associated with {@link Baseline}
|
||||
* @throws AlertManagerException
|
||||
* If there is a query error
|
||||
*/
|
||||
@Override
|
||||
public final List<Alert> getAlertsForBaseline(final Baseline baseline)
|
||||
throws AlertManagerException {
|
||||
LOGGER.debug("");
|
||||
|
||||
if (baseline == null) {
|
||||
throw new NullPointerException("baseline was null");
|
||||
}
|
||||
|
||||
List<Alert> alerts = new ArrayList<>();
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
|
||||
// query hibernate to retrieve alerts with the given baseline id
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Alert> criteriaQuery = criteriaBuilder.createQuery(Alert.class);
|
||||
Root<Alert> root = criteriaQuery.from(Alert.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.and(criteriaBuilder.equal(root.get("baselineId"), baseline.getId()));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<Alert> query = session.createQuery(criteriaQuery);
|
||||
List<Alert> results = query.getResultList();
|
||||
|
||||
// criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
|
||||
|
||||
for (Object o : results) {
|
||||
if (o instanceof Alert) {
|
||||
alerts.add((Alert) o);
|
||||
}
|
||||
}
|
||||
|
||||
tx.commit();
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
return alerts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the total number of Unresolved {@link Alert}s associated with the provided
|
||||
* {@link Baseline}.
|
||||
*
|
||||
* @param baseline baseline that is being evaluated
|
||||
* @return number of unresolved alerts associated with Baseline
|
||||
* @throws AlertManagerException
|
||||
* If there is a query error
|
||||
*/
|
||||
@Override
|
||||
public final long getTotalAlertsForBaseline(final Baseline baseline)
|
||||
throws AlertManagerException {
|
||||
LOGGER.debug("");
|
||||
|
||||
if (baseline == null) {
|
||||
throw new NullPointerException("baseline was null");
|
||||
}
|
||||
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
|
||||
// query hibernate to count alerts with the given deviceName and null archivedTime
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Alert> criteriaQuery = criteriaBuilder.createQuery(Alert.class);
|
||||
Root<Alert> root = criteriaQuery.from(Alert.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.and(criteriaBuilder.equal(root.get("baselineId"), baseline.getId()),
|
||||
criteriaBuilder.isNull(root.get("archivedTime")));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<Alert> query = session.createQuery(criteriaQuery);
|
||||
List<Alert> results = query.getResultList();
|
||||
Long result = results.stream().count();
|
||||
tx.commit();
|
||||
if (result == null) {
|
||||
throw new AlertManagerException("failed to query unresolved alert count");
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private Query<Alert> getCriteriaForTrustAlertsForDevice(final Device device,
|
||||
final Report integrityReport,
|
||||
final Criterion optionalCriterion,
|
||||
final Session session) {
|
||||
if (device == null) {
|
||||
throw new NullPointerException("device was null");
|
||||
}
|
||||
|
||||
if (integrityReport == null) {
|
||||
throw new NullPointerException("integrityReport was null");
|
||||
}
|
||||
|
||||
if (session == null) {
|
||||
throw new NullPointerException("session was null");
|
||||
}
|
||||
|
||||
// query hibernate to count alerts with the given deviceName and null archivedTime
|
||||
// alerts for this report, or alerts not associated with any report (case 1 and 2)
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Alert> criteriaQuery = criteriaBuilder.createQuery(Alert.class);
|
||||
Root<Alert> root = criteriaQuery.from(Alert.class);
|
||||
Predicate recordPredicate = criteriaBuilder.and(
|
||||
criteriaBuilder.isNull(root.get("archivedTime")),
|
||||
criteriaBuilder.equal(root.get("deviceName"), device.getName()));
|
||||
|
||||
Predicate reportEqualsDisjunction = criteriaBuilder.disjunction();
|
||||
Predicate reportNullDisjunction = criteriaBuilder.disjunction();
|
||||
// alerts for this report, or alerts not associated with any report (case 1 and 2)
|
||||
// Criterion reportEqualsCriterion = Restrictions.eq("report", integrityReport);
|
||||
// Criterion reportNullCriterion = Restrictions.isNull("report");
|
||||
reportEqualsDisjunction = criteriaBuilder.equal(root.get("report"), integrityReport);
|
||||
reportNullDisjunction = criteriaBuilder.isNull(root.get("report"));
|
||||
criteriaBuilder.or(reportEqualsDisjunction, reportNullDisjunction);
|
||||
|
||||
// only apply the optional criterion to the disjunction if there is one.
|
||||
if (optionalCriterion != null) {
|
||||
LOGGER.error("optional criterion needs to be updated");
|
||||
}
|
||||
|
||||
criteriaQuery.select(root).where(recordPredicate,
|
||||
reportEqualsDisjunction,
|
||||
reportNullDisjunction);
|
||||
return session.createQuery(criteriaQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of alerts for a device in order to determine the status of
|
||||
* the device (trusted or untrusted).
|
||||
*
|
||||
* The alerts meet one or more of these specifications:
|
||||
* <ol>
|
||||
* <li>Have no report associated (missed periodic report alerts) for this device</li>
|
||||
* <li>Are associated with the provided integrity report</li>
|
||||
* <li>Match the specified criteria. e.g. leftover alerts from
|
||||
* delta reports in the current series of delta reports).</li>
|
||||
* </ol>
|
||||
* @param device the device to query for alerts on
|
||||
* @param integrityReport the integrity report to find associated alerts with
|
||||
* @param optionalCriterion the optional additional criteria for which to query on
|
||||
* @return the set of device alerts associated with trust
|
||||
*/
|
||||
@Override
|
||||
public List<Alert> getTrustAlerts(final Device device, final Report integrityReport,
|
||||
final Criterion optionalCriterion) {
|
||||
LOGGER.debug("getting trust alerts for {}", device);
|
||||
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
|
||||
Query<Alert> criteria = getCriteriaForTrustAlertsForDevice(device, integrityReport,
|
||||
optionalCriterion, session);
|
||||
|
||||
List<Alert> alerts = new ArrayList<>();
|
||||
List list = criteria.list();
|
||||
for (Object o : list) {
|
||||
if (o instanceof Alert) {
|
||||
alerts.add((Alert) o);
|
||||
}
|
||||
}
|
||||
tx.commit();
|
||||
return alerts;
|
||||
} catch (HibernateException | NullPointerException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the count of trust alerts for a device. See {@link #getTrustAlerts} for more
|
||||
* information about which alerts are counted.
|
||||
*
|
||||
* @param device the device to query for alerts on
|
||||
* @param integrityReport the integrity report to find associated alerts with
|
||||
* @param optionalCriterion the optional additional criteria for which to query on
|
||||
* @return the count of alerts associated with trust
|
||||
*/
|
||||
@Override
|
||||
public final int getTrustAlertCount(final Device device, final Report integrityReport,
|
||||
final Criterion optionalCriterion) {
|
||||
LOGGER.debug("getting trust alert count for {}", device);
|
||||
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
|
||||
Query<Alert> criteria = getCriteriaForTrustAlertsForDevice(device, integrityReport,
|
||||
optionalCriterion, session);
|
||||
Long result = criteria.stream().count();
|
||||
|
||||
tx.commit();
|
||||
return result.intValue();
|
||||
} catch (HibernateException | NullPointerException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloads the resolveAlerts method and provides a null description for the
|
||||
* alert resolution.
|
||||
*
|
||||
* @param alerts - list of Alert objects to be marked as resolved.
|
||||
* @throws AlertManagerException
|
||||
* if unable to save the list
|
||||
*/
|
||||
@Override
|
||||
public final void resolveAlerts(final List<Alert> alerts)
|
||||
throws AlertManagerException {
|
||||
resolveAlerts(alerts, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks all Alerts that are provided as arguments as resolved. This is used as
|
||||
* a "soft delete" method and will ensure they no longer appear in the Alert
|
||||
* table on the Portal.
|
||||
*
|
||||
* @param alerts - Alert objects to be marked as resolved
|
||||
* @param description - description of action taken. The description can be null
|
||||
* @throws AlertManagerException
|
||||
* if unable to save the list
|
||||
*/
|
||||
@Override
|
||||
public final void resolveAlerts(final List<Alert> alerts, final String description)
|
||||
throws AlertManagerException {
|
||||
if (alerts == null) {
|
||||
String message = "list of alert objects was null";
|
||||
LOGGER.debug(message);
|
||||
throw new NullPointerException(message);
|
||||
}
|
||||
|
||||
LOGGER.debug("Marking " + alerts.size() + " alerts to resolved and saving.");
|
||||
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("saving object in db");
|
||||
tx = session.beginTransaction();
|
||||
for (Alert alert : alerts) {
|
||||
alert.archive(description);
|
||||
session.merge(alert);
|
||||
LOGGER.info("Alert {} is marked as resolved.", alert.getId());
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
final String msg = "unable to save alert";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw new DBManagerException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of unresolved alerts associated with the given device.
|
||||
*
|
||||
* @param device associated with unresolved alerts being counted
|
||||
* @return count of unresolved alerts
|
||||
*/
|
||||
public final int countUnresolvedAlerts(final Device device) {
|
||||
if (device == null) {
|
||||
LOGGER.warn("null device found, returning 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Long result = null;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("querying alerts table for unresolved alerts");
|
||||
tx = session.beginTransaction();
|
||||
|
||||
// query hibernate to count alerts with the given deviceName and null archivedTime
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Alert> criteriaQuery = criteriaBuilder.createQuery(Alert.class);
|
||||
Root<Alert> root = criteriaQuery.from(Alert.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.and(criteriaBuilder.equal(root.get("deviceName"), device.getName()),
|
||||
criteriaBuilder.isNull(root.get("archivedTime")));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<Alert> query = session.createQuery(criteriaQuery);
|
||||
List<Alert> results = query.getResultList();
|
||||
if (results != null && !results.isEmpty()) {
|
||||
result = results.stream().count();
|
||||
}
|
||||
|
||||
// Criteria criteria = session.createCriteria(Alert.class);
|
||||
// criteria.add(Restrictions.isNull("archivedTime"));
|
||||
// criteria.add(Restrictions.eq("deviceName", device.getName()));
|
||||
// criteria.setProjection(Projections.rowCount()).uniqueResult();
|
||||
// Long result = (Long) criteria.uniqueResult();
|
||||
tx.commit();
|
||||
if (result == null) {
|
||||
throw new AlertManagerException("failed to query unresolved alert count");
|
||||
} else {
|
||||
return result.intValue();
|
||||
}
|
||||
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of unresolved alerts associated with the given device that originate from
|
||||
* the given AlertSource.
|
||||
*
|
||||
* @param device associated with unresolved alerts being counted
|
||||
* @param source counted alerts must originate from
|
||||
* @return count of unresolved alerts
|
||||
*/
|
||||
public final int countUnresolvedAlerts(final Device device, final AlertSource source) {
|
||||
if (device == null) {
|
||||
String msg = "invalid argument - null value for device";
|
||||
LOGGER.error(msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
if (source == null) {
|
||||
String msg = "invalid argument - null value for source";
|
||||
LOGGER.error(msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
Long result = null;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("querying alerts table for unresolved alerts");
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Alert> criteriaQuery = criteriaBuilder.createQuery(Alert.class);
|
||||
Root<Alert> root = criteriaQuery.from(Alert.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.and(criteriaBuilder.equal(root.get("deviceName"), device.getName()),
|
||||
criteriaBuilder.equal(root.get("source"), source),
|
||||
criteriaBuilder.isNull(root.get("archivedTime")));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<Alert> query = session.createQuery(criteriaQuery);
|
||||
List<Alert> results = query.getResultList();
|
||||
if (results != null && !results.isEmpty()) {
|
||||
result = results.stream().count();
|
||||
}
|
||||
|
||||
// Criteria criteria = session.createCriteria(Alert.class);
|
||||
// criteria.add(Restrictions.isNull("archivedTime"));
|
||||
// criteria.add(Restrictions.eq("deviceName", device.getName()));
|
||||
// criteria.add(Restrictions.eq("source", source));
|
||||
// criteria.setProjection(Projections.rowCount()).uniqueResult();
|
||||
// result = (Long) criteria.uniqueResult();
|
||||
tx.commit();
|
||||
if (result == null) {
|
||||
throw new AlertManagerException("failed to query unresolved alert count");
|
||||
} else {
|
||||
return result.intValue();
|
||||
}
|
||||
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the total number of devices with at least one unresolved alert within the given group.
|
||||
*
|
||||
* @param deviceGroup to count devices from
|
||||
* @return count of devices with unresolved alerts
|
||||
*/
|
||||
public final int countUnresolvedDevices(final DeviceGroup deviceGroup) {
|
||||
if (deviceGroup == null) {
|
||||
String msg = "invalid argument - null value for device group";
|
||||
LOGGER.error(msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("querying alerts table for unresolved devices");
|
||||
// tx = session.beginTransaction();
|
||||
|
||||
// first use a subquery to list the devices in the given group
|
||||
// DetachedCriteria deviceQuery = DetachedCriteria.forClass(Device.class);
|
||||
// deviceQuery.createAlias("deviceGroup", "g");
|
||||
// deviceQuery.add(Restrictions.eq("g.name", deviceGroup.getName()));
|
||||
// deviceQuery.setProjection(Property.forName("name"));
|
||||
|
||||
// now query within that group for unique device names among unresolved alerts
|
||||
// Criteria criteria = session.createCriteria(Alert.class);
|
||||
// criteria.add(Restrictions.isNull("archivedTime"));
|
||||
// criteria.add(Subqueries.propertyIn("deviceName", deviceQuery));
|
||||
// criteria.setProjection(Projections.countDistinct("deviceName"));
|
||||
// Long result = (Long) criteria.uniqueResult();
|
||||
|
||||
// CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
// CriteriaQuery<Alert> criteriaQuery = criteriaBuilder.createQuery(Alert.class);
|
||||
// Root<Alert> root = criteriaQuery.from(Alert.class);
|
||||
// Predicate recordPredicate = criteriaBuilder.and(
|
||||
// criteriaBuilder.equal(criteriaBuilder.Subqueries.propertiesIn("deviceName", deviceQuery)),
|
||||
// criteriaBuilder.isNull(root.get("archivedTime"))
|
||||
//
|
||||
// );
|
||||
// criteriaQuery.select(root).where(recordPredicate);
|
||||
// Query<Alert> query = session.createQuery(criteriaQuery);
|
||||
// List<Alert> results = query.getResultList();
|
||||
// if (results != null && !results.isEmpty()) {
|
||||
// result = results.stream().count();
|
||||
// }
|
||||
// tx.commit();
|
||||
// if (result == null) {
|
||||
// throw new AlertManagerException("failed to query unresolved alert count");
|
||||
// } else {
|
||||
// return result.intValue();
|
||||
// }
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to query alerts table";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,134 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import hirs.data.persist.alert.AlertMonitor;
|
||||
|
||||
/**
|
||||
* A <code>DBAlertMonitorManager</code> is a service (extends <code>DBManager</code>) that
|
||||
* implements the <code>AlertMonitorManager</code> that stores and retrieves Alert Monitors.
|
||||
*/
|
||||
public class DBAlertMonitorManager
|
||||
extends DBManager<AlertMonitor> implements AlertMonitorManager {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(DBAlertMonitorManager.class);
|
||||
|
||||
/**
|
||||
* Creates the DBAlertMonitoringManager.
|
||||
*
|
||||
* @param sessionFactory session factory used to access database connections
|
||||
*/
|
||||
public DBAlertMonitorManager(final SessionFactory sessionFactory) {
|
||||
super(AlertMonitor.class, sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the <code>AlertMonitor</code> in the database. This creates a new database
|
||||
* session and saves the AlertMonitor. If the <code>AlertMonitor</code> had previously
|
||||
* been saved then a <code>AlertMonitorManagerException</code> is thrown.
|
||||
*
|
||||
* @param monitor AlertMonitor to save
|
||||
* @return reference to saved AlertMonitor
|
||||
* @throws AlertMonitorManagerException if AlertMonitor has previously been saved or an
|
||||
error occurs while trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final AlertMonitor saveAlertMonitor(final AlertMonitor monitor)
|
||||
throws AlertMonitorManagerException {
|
||||
LOGGER.debug("saving Alert Monitor {}", monitor);
|
||||
try {
|
||||
return super.save(monitor);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertMonitorManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an <code>AlertMonitor</code>. This updates the database entries to reflect the new
|
||||
* values that should be set.
|
||||
*
|
||||
* @param monitor AlertMonitor
|
||||
* @throws AlertMonitorManagerException if AlertMonitor has not previously been saved or
|
||||
an error occurs while trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final void updateAlertMonitor(final AlertMonitor monitor)
|
||||
throws AlertMonitorManagerException {
|
||||
LOGGER.debug("updating Alert Monitor: {}", monitor);
|
||||
try {
|
||||
super.update(monitor);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertMonitorManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>AlertMonitor</code>s of type <code>clazz</code>. This
|
||||
* searches through the database for this information.
|
||||
*
|
||||
* @param clazz class type of <code>AlertMonitor</code>s to return (may be null)
|
||||
* @return list of <code>AlertMonitor</code> names
|
||||
* @throws AlertMonitorManagerException if unable to retrieve the list
|
||||
*/
|
||||
@Override
|
||||
public final List<AlertMonitor> getAlertMonitorList(final Class<? extends AlertMonitor> clazz)
|
||||
throws AlertMonitorManagerException {
|
||||
LOGGER.debug("Getting Alert Monitor list");
|
||||
final List<AlertMonitor> monitors;
|
||||
try {
|
||||
monitors = super.getList(clazz);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertMonitorManagerException(e);
|
||||
}
|
||||
LOGGER.debug("Got {} Alert Monitors", monitors.size());
|
||||
return monitors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>AlertMonitor</code> from the database. This searches the database for an
|
||||
* entry whose name matches <code>name</code>. It then reconstructs a <code>AlertMonitor</code>
|
||||
* object from the database entry.
|
||||
*
|
||||
* @param name name of the AlertMonitor
|
||||
* @return AlertMonitor if found, otherwise null.
|
||||
* @throws AlertMonitorManagerException if unable to search the database or recreate the
|
||||
* <code>AlertMonitor</code>
|
||||
*/
|
||||
@Override
|
||||
public final AlertMonitor getAlertMonitor(final String name)
|
||||
throws AlertMonitorManagerException {
|
||||
LOGGER.debug("getting Alert Monitor: {}", name);
|
||||
try {
|
||||
return super.get(name);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertMonitorManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>AlertMonitor</code> from the database. This removes all of the database
|
||||
* entries that stored information with regards to the this <code>AlertMonitor</code>.
|
||||
* Currently, iterates over <code>Policy</code> entries and removes the selected
|
||||
* <code>AlertMonitor</code> from them if it exists. This needs to be fixed as this should not
|
||||
* be performed without user action. Update is expected soon.
|
||||
*
|
||||
* @param name name of the <code>AlertMonitor</code> to delete
|
||||
* @return true if successfully found and deleted <code>AlertMonitor</code>
|
||||
* @throws AlertMonitorManagerException if unable to find the AlertMonitor or delete it
|
||||
from the database
|
||||
*/
|
||||
@Override
|
||||
public final boolean deleteAlertMonitor(final String name)
|
||||
throws AlertMonitorManagerException {
|
||||
LOGGER.debug("deleting Alert Monitor: {}", name);
|
||||
try {
|
||||
return super.delete(name);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertMonitorManagerException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.alert.AlertServiceConfig;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A <code>DBAlertServiceManager</code> is a service (extends <code>DBManager</code>) that
|
||||
* implements the <code>AlertServiceConfigManager</code> that stores and retrieves Alert Services.
|
||||
*/
|
||||
public class DBAlertServiceManager
|
||||
extends DBManager<AlertServiceConfig> implements AlertServiceConfigManager {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(DBAlertServiceManager.class);
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBReportSummaryManager</code>. The optional SessionFactory parameter is
|
||||
* used to manage sessions with a hibernate db.
|
||||
*
|
||||
* @param factory a hibernate session factory
|
||||
*/
|
||||
public DBAlertServiceManager(final SessionFactory factory) {
|
||||
super(AlertServiceConfig.class, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the <code>AlertServiceConfig</code> in the database. This creates a new database
|
||||
* session and saves the AlertServiceConfig. If the <code>AlertServiceConfig</code> had
|
||||
* previously been saved then a <code>AlertServiceManagerException</code> is thrown.
|
||||
*
|
||||
* @param serviceConfig AlertServiceConfig to save
|
||||
* @return reference to saved AlertServiceConfig
|
||||
* @throws AlertServiceConfigManagerException if baseline has previously been saved or an error
|
||||
* occurs while trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final AlertServiceConfig saveAlertServiceConfig(final AlertServiceConfig serviceConfig)
|
||||
throws AlertServiceConfigManagerException {
|
||||
LOGGER.debug("saving Alert Monitor {}", serviceConfig);
|
||||
try {
|
||||
return super.save(serviceConfig);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertServiceConfigManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a <code>AlertServiceConfig</code>. This updates the database entries to reflect the
|
||||
* new values that should be set.
|
||||
*
|
||||
* @param serviceConfig baseline
|
||||
* @throws AlertServiceConfigManagerException if baseline has not previously been saved or an
|
||||
* error occurs while trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final void updateAlertServiceConfig(final AlertServiceConfig serviceConfig)
|
||||
throws AlertServiceConfigManagerException {
|
||||
LOGGER.debug("updating Alert Monitor: {}", serviceConfig);
|
||||
try {
|
||||
super.update(serviceConfig);
|
||||
} catch (DBManagerException e) {
|
||||
throw new AlertServiceConfigManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>AlertServiceConfig</code>s of type <code>clazz</code>. This
|
||||
* searches through the database for this information.
|
||||
*
|
||||
* @param clazz class type of <code>AlertServiceConfig</code>s to return (may be null)
|
||||
* @return list of <code>AlertServiceConfig</code> names
|
||||
* @throws AlertServiceConfigManagerException if unable to retrieve the list
|
||||
*/
|
||||
@Override
|
||||
public final List<AlertServiceConfig> getAlertServiceConfigList(
|
||||
final Class<? extends AlertServiceConfig> clazz)
|
||||
throws AlertServiceConfigManagerException {
|
||||
LOGGER.debug("Getting Alert Service Config list");
|
||||
final List<AlertServiceConfig> serviceConfigs;
|
||||
try {
|
||||
serviceConfigs = super.getList(clazz);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
LOGGER.debug("Got {} Alert Monitors", serviceConfigs.size());
|
||||
return serviceConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>AlertServiceConfig</code> from the database. This searches the database
|
||||
* for an entry whose name matches <code>name</code>. It then reconstructs a
|
||||
* <code>AlertServiceConfig</code> object from the database entry.
|
||||
*
|
||||
* @param type type of the AlertServiceConfig
|
||||
* @return baseline if found, otherwise null.
|
||||
* @throws AlertServiceConfigManagerException if unable to search the database or recreate the
|
||||
* <code>AlertServiceConfig</code>
|
||||
*/
|
||||
@Override
|
||||
public final AlertServiceConfig getAlertServiceConfig(final String type)
|
||||
throws AlertServiceConfigManagerException {
|
||||
if (type == null) {
|
||||
LOGGER.debug("null name argument");
|
||||
return null;
|
||||
}
|
||||
LOGGER.debug("getting Alert Monitor: {}", type);
|
||||
|
||||
AlertServiceConfig ret = null;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("retrieving AlertServiceConfig from db");
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<AlertServiceConfig> criteriaQuery = criteriaBuilder.createQuery(AlertServiceConfig.class);
|
||||
Root<AlertServiceConfig> root = criteriaQuery.from(AlertServiceConfig.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.and(criteriaBuilder.equal(root.get("type"), type));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<AlertServiceConfig> query = session.createQuery(criteriaQuery);
|
||||
List<AlertServiceConfig> results = query.getResultList();
|
||||
if (results != null && !results.isEmpty()) {
|
||||
ret = results.get(0);
|
||||
}
|
||||
// ret = (AlertServiceConfig) session.createCriteria(AlertServiceConfig.class)
|
||||
// .add(Restrictions.eq("type", type)).uniqueResult();
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
final String msg = "unable to retrieve object";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>AlertServiceConfig</code> from the database. This removes all of the
|
||||
* database entries that stored information with regards to the this
|
||||
* <code>AlertServiceConfig</code>. Currently, iterates over <code>Policy</code> entries and
|
||||
* removes the selected <code>AlertServiceConfig</code> from them if it exists. This needs to be
|
||||
* fixed as this should not be performed without user action. Update is expected soon.
|
||||
*
|
||||
* @param type type of the <code>AlertServiceConfig</code> to delete
|
||||
* @return true if successfully found and deleted <code>AlertServiceConfig</code>
|
||||
* @throws AlertServiceConfigManagerException if unable to find the baseline or delete it from
|
||||
* the database
|
||||
*/
|
||||
@Override
|
||||
public final boolean deleteAlertServiceConfig(final String type)
|
||||
throws AlertServiceConfigManagerException {
|
||||
if (type == null) {
|
||||
LOGGER.debug("null name argument");
|
||||
return false;
|
||||
}
|
||||
LOGGER.debug("deleting Alert Monitor: {}", type);
|
||||
|
||||
boolean deleted = false;
|
||||
AlertServiceConfig object = null;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("retrieving object from db");
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<AlertServiceConfig> criteriaQuery = criteriaBuilder.createQuery(AlertServiceConfig.class);
|
||||
Root<AlertServiceConfig> root = criteriaQuery.from(AlertServiceConfig.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.and(criteriaBuilder.equal(root.get("type"), type));
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
Query<AlertServiceConfig> query = session.createQuery(criteriaQuery);
|
||||
List<AlertServiceConfig> results = query.getResultList();
|
||||
if (results != null && !results.isEmpty()) {
|
||||
object = results.get(0);
|
||||
}
|
||||
// object = (AlertServiceConfig) session.createCriteria(AlertServiceConfig.class)
|
||||
// .add(Restrictions.eq("type", type)).uniqueResult();
|
||||
if (object != null) {
|
||||
LOGGER.debug("found object, deleting it");
|
||||
session.delete(object);
|
||||
deleted = true;
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
final String msg = "unable to retrieve object";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
}
|
@ -1,764 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.data.bean.SimpleBaselineBean;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.data.persist.baseline.BroadRepoImaBaseline;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import hirs.repository.RepoPackage;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
|
||||
import org.hibernate.criterion.Disjunction;
|
||||
import org.hibernate.criterion.MatchMode;
|
||||
import org.hibernate.criterion.Order;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
|
||||
import static org.hibernate.criterion.Restrictions.ilike;
|
||||
import static org.hibernate.criterion.Restrictions.sqlRestriction;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hibernate.criterion.Conjunction;
|
||||
import org.hibernate.criterion.DetachedCriteria;
|
||||
import org.hibernate.criterion.Property;
|
||||
import org.hibernate.criterion.Subqueries;
|
||||
import org.hibernate.exception.SQLGrammarException;
|
||||
import org.hibernate.transform.Transformers;
|
||||
|
||||
/**
|
||||
* This class defines a <code>BaselineManager</code> that stores the baselines
|
||||
* in a database.
|
||||
*/
|
||||
public class DBBaselineManager extends DBManager<Baseline> implements BaselineManager {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(DBBaselineManager.class);
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBBaselineManager</code> that uses the default
|
||||
* database. The default database is used to store all of the
|
||||
* <code>Baseline</code>s.
|
||||
*
|
||||
* @param sessionFactory session factory used to access database connections
|
||||
*/
|
||||
public DBBaselineManager(final SessionFactory sessionFactory) {
|
||||
super(Baseline.class, sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the <code>Baseline</code> in the database. This creates a new
|
||||
* database session and saves the baseline. If the <code>Baseline</code> had
|
||||
* previously been saved then a <code>BaselineManagerException</code> is
|
||||
* thrown.
|
||||
*
|
||||
* @param baseline
|
||||
* baseline to save
|
||||
* @return reference to saved baseline
|
||||
* @throws BaselineManagerException
|
||||
* if baseline has previously been saved or an error occurs
|
||||
* while trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final Baseline saveBaseline(final Baseline baseline)
|
||||
throws BaselineManagerException {
|
||||
LOGGER.debug("saving baseline: {}", baseline);
|
||||
try {
|
||||
return super.save(baseline);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a <code>Baseline</code>. This updates the database entries to
|
||||
* reflect the new values that should be set.
|
||||
*
|
||||
* @param baseline
|
||||
* baseline
|
||||
* @throws BaselineManagerException
|
||||
* if baseline has not previously been saved or an error occurs
|
||||
* while trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final void updateBaseline(final Baseline baseline) throws BaselineManagerException {
|
||||
LOGGER.debug("updating baseline: {}", baseline);
|
||||
try {
|
||||
super.update(baseline);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the database for a list of all the <code>Baseline</code>s of type <code>clazz</code>
|
||||
* that have not been soft-deleted.
|
||||
*
|
||||
* @param clazz
|
||||
* class type of <code>Baseline</code>s to return (may be null)
|
||||
* @return list of <code>Baseline</code> names
|
||||
* @throws BaselineManagerException
|
||||
* if unable to search the database
|
||||
*/
|
||||
@Override
|
||||
public final List<Baseline> getBaselineList(final Class<? extends Baseline> clazz)
|
||||
throws BaselineManagerException {
|
||||
LOGGER.debug("Getting baseline list");
|
||||
final List<Baseline> baselines = new ArrayList<>();
|
||||
|
||||
Class<? extends Baseline> searchClass = clazz;
|
||||
if (clazz == null) {
|
||||
LOGGER.debug("null clazz, using Baseline as the default search class");
|
||||
searchClass = Baseline.class;
|
||||
}
|
||||
|
||||
Session session = getFactory().getCurrentSession();
|
||||
Transaction tx = session.beginTransaction();
|
||||
try {
|
||||
Criteria criteria = session.createCriteria(searchClass)
|
||||
.add(Restrictions.isNull("archivedTime"))
|
||||
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
|
||||
List list = criteria.list();
|
||||
for (Object o : list) {
|
||||
if (o instanceof Baseline) {
|
||||
baselines.add((Baseline) o);
|
||||
}
|
||||
}
|
||||
tx.commit();
|
||||
LOGGER.debug("Got {} baselines", baselines.size());
|
||||
} catch (HibernateException e) {
|
||||
LOGGER.error("Unable to retrieve baselines", e);
|
||||
LOGGER.debug("Rolling back transaction");
|
||||
tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
|
||||
LOGGER.debug("Got {} baselines", baselines.size());
|
||||
return baselines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>Baseline</code>s that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables. Soft-deleted
|
||||
* <code>Baseline</code>s are not included in the returned list.
|
||||
*
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @param searchableColumns Map of String and boolean values with column
|
||||
* headers and whether they are to. Boolean is true if field provides
|
||||
* a typical String that can be searched by Hibernate without
|
||||
* transformation.
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
@Override
|
||||
public final FilteredRecordsList<Baseline> getOrderedBaselineList(
|
||||
final String columnToOrder, final boolean ascending,
|
||||
final int firstResult, final int maxResults, final String search,
|
||||
final Map<String, Boolean> searchableColumns)
|
||||
throws BaselineManagerException {
|
||||
|
||||
if (columnToOrder == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("object");
|
||||
}
|
||||
|
||||
// check that the baseline is not archived
|
||||
CriteriaModifier modifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
criteria.add(Restrictions.isNull("archivedTime"));
|
||||
}
|
||||
};
|
||||
|
||||
final FilteredRecordsList<Baseline> baselines;
|
||||
try {
|
||||
LOGGER.debug("querying db for baselines");
|
||||
baselines = super.getOrderedList(Baseline.class, columnToOrder, ascending, firstResult,
|
||||
maxResults, search, searchableColumns, modifier);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
return baselines;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all IMABaselineRecord that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param baselineId id of the baseline
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
@Override
|
||||
public final FilteredRecordsList<IMABaselineRecord> getOrderedRecordList(
|
||||
final UUID baselineId, final String columnToOrder, final boolean ascending,
|
||||
final int firstResult, final int maxResults, final String search)
|
||||
throws BaselineManagerException {
|
||||
if (columnToOrder == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("object");
|
||||
}
|
||||
|
||||
LOGGER.debug("Getting baseline list");
|
||||
//Object that will store query values
|
||||
FilteredRecordsList<IMABaselineRecord> queryResults = new FilteredRecordsList<>();
|
||||
|
||||
Transaction tx = null;
|
||||
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("updating object in db");
|
||||
tx = session.beginTransaction();
|
||||
|
||||
Criteria criteria = session
|
||||
.createCriteria(IMABaselineRecord.class, "record")
|
||||
.add(sqlRestriction("ima_baseline_id='" + baselineId + "'"))
|
||||
.setProjection(Projections.count("id"));
|
||||
Long totalResultCount = (Long) criteria.uniqueResult();
|
||||
|
||||
// Search for all words in all searchable columns
|
||||
Conjunction and = buildBaselineRecordSearchFilter(search);
|
||||
criteria.add(and);
|
||||
|
||||
Long recordsFiltered = (Long) criteria.uniqueResult();
|
||||
|
||||
criteria.setProjection(null)
|
||||
.setFirstResult(firstResult)
|
||||
.setMaxResults(maxResults);
|
||||
|
||||
if (ascending) {
|
||||
criteria.addOrder(Order.asc(columnToOrder));
|
||||
} else {
|
||||
criteria.addOrder(Order.desc(columnToOrder));
|
||||
}
|
||||
|
||||
//Stores results of all the queries for the JQuery Datatable
|
||||
queryResults.setRecordsTotal(totalResultCount);
|
||||
queryResults.setRecordsFiltered(recordsFiltered);
|
||||
|
||||
List list = criteria.list();
|
||||
for (Object o : list) {
|
||||
if (o instanceof IMABaselineRecord) {
|
||||
queryResults.add((IMABaselineRecord) o);
|
||||
}
|
||||
}
|
||||
tx.commit();
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to update object";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return queryResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all ImaBlacklistBaseline Records that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param baselineId id of the baseline
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
@Override
|
||||
public final FilteredRecordsList<ImaBlacklistRecord> getOrderedBlacklistRecordList(
|
||||
final UUID baselineId, final String columnToOrder, final boolean ascending,
|
||||
final int firstResult, final int maxResults, final String search)
|
||||
throws BaselineManagerException {
|
||||
if (columnToOrder == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("object");
|
||||
}
|
||||
|
||||
LOGGER.debug("Getting baseline list");
|
||||
//Object that will store query values
|
||||
FilteredRecordsList<ImaBlacklistRecord> queryResults = new FilteredRecordsList<>();
|
||||
|
||||
Transaction tx = null;
|
||||
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("updating object in db");
|
||||
tx = session.beginTransaction();
|
||||
|
||||
Criteria criteria = session
|
||||
.createCriteria(ImaBlacklistRecord.class, "record")
|
||||
.add(sqlRestriction("ima_baseline_id='" + baselineId + "'"))
|
||||
.setProjection(Projections.count("id"));
|
||||
Long totalResultCount = (Long) criteria.uniqueResult();
|
||||
|
||||
// Search for all words in all searchable columns
|
||||
Conjunction and = buildBaselineRecordSearchFilter(search);
|
||||
criteria.add(and);
|
||||
|
||||
Long recordsFiltered = (Long) criteria.uniqueResult();
|
||||
|
||||
criteria.setProjection(null)
|
||||
.setFirstResult(firstResult)
|
||||
.setMaxResults(maxResults);
|
||||
|
||||
if (ascending) {
|
||||
criteria.addOrder(Order.asc(columnToOrder));
|
||||
} else {
|
||||
criteria.addOrder(Order.desc(columnToOrder));
|
||||
}
|
||||
|
||||
//Stores results of all the queries for the JQuery Datatable
|
||||
queryResults.setRecordsTotal(totalResultCount);
|
||||
queryResults.setRecordsFiltered(recordsFiltered);
|
||||
List list = criteria.list();
|
||||
for (Object o : list) {
|
||||
if (o instanceof ImaBlacklistRecord) {
|
||||
queryResults.add((ImaBlacklistRecord) o);
|
||||
}
|
||||
}
|
||||
tx.commit();
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to update object";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return queryResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all RepoPackages that are ordered by a column
|
||||
* and direction (ASC, DESC) that is provided by the user. This method
|
||||
* helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param name name of the baseline
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws BaselineManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
@Override
|
||||
public final FilteredRecordsList<RepoPackage> getOrderedPackageList(
|
||||
final String name, final String columnToOrder, final boolean ascending,
|
||||
final int firstResult, final int maxResults, final String search)
|
||||
throws BaselineManagerException {
|
||||
if (columnToOrder == null) {
|
||||
LOGGER.debug("null columnToOrder argument");
|
||||
throw new NullPointerException("columnToOrder");
|
||||
}
|
||||
|
||||
LOGGER.debug("Getting package list");
|
||||
//Object that will store query values
|
||||
FilteredRecordsList<RepoPackage> queryResults = new FilteredRecordsList<>();
|
||||
|
||||
Transaction tx = null;
|
||||
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
|
||||
// first use a subquery to list the ids for the packages in the baseline
|
||||
Criteria criteria = session.createCriteria(BroadRepoImaBaseline.class)
|
||||
.createAlias("repoPackages", "pkg")
|
||||
.add(Restrictions.eq("name", name));
|
||||
|
||||
// Get the total result count
|
||||
long totalResultCount = (long) criteria
|
||||
.setProjection(Projections.countDistinct("pkg.id"))
|
||||
.uniqueResult();
|
||||
|
||||
queryResults.setRecordsTotal(totalResultCount);
|
||||
|
||||
if (totalResultCount > 0) {
|
||||
// Get the package ids related to the baseline
|
||||
List firstList = criteria.setProjection(Property.forName("pkg.id"))
|
||||
.list();
|
||||
final List<UUID> packageIds = new ArrayList<>();
|
||||
for (Object o : firstList) {
|
||||
if (o instanceof UUID) {
|
||||
packageIds.add((UUID) o);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the IDs for the packages that match the search filter
|
||||
criteria = session.createCriteria(RepoPackage.class)
|
||||
.createAlias("sourceRepository", "repo")
|
||||
.createAlias("packageRecords", "rec")
|
||||
.add(Restrictions.in("id", packageIds));
|
||||
|
||||
final long recordsFiltered;
|
||||
|
||||
// Add the search filters
|
||||
if (StringUtils.isNotBlank(search)) {
|
||||
Conjunction and = buildPackageSearchFilter(search, session);
|
||||
criteria.add(and);
|
||||
|
||||
recordsFiltered = (long) criteria
|
||||
.setProjection(Projections.countDistinct("id"))
|
||||
.uniqueResult();
|
||||
} else {
|
||||
// If there s no search, there are no filtered records
|
||||
recordsFiltered = totalResultCount;
|
||||
}
|
||||
|
||||
queryResults.setRecordsFiltered(recordsFiltered);
|
||||
|
||||
if (recordsFiltered > 0) {
|
||||
// Get the filtered ids
|
||||
List secondList = criteria.setProjection(
|
||||
Projections.distinct(Property.forName("id"))).list();
|
||||
|
||||
final List<UUID> morePackageIds = new ArrayList<>();
|
||||
for (Object o : secondList) {
|
||||
if (o instanceof UUID) {
|
||||
morePackageIds.add((UUID) o);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the count projection, and sort and page to get results
|
||||
criteria = session.createCriteria(RepoPackage.class)
|
||||
.createAlias("sourceRepository", "repo")
|
||||
.add(Restrictions.in("id", morePackageIds))
|
||||
.setFirstResult(firstResult)
|
||||
.setMaxResults(maxResults);
|
||||
|
||||
if (ascending) {
|
||||
criteria.addOrder(Order.asc(columnToOrder));
|
||||
} else {
|
||||
criteria.addOrder(Order.desc(columnToOrder));
|
||||
}
|
||||
|
||||
List list = criteria.list();
|
||||
for (Object o : list) {
|
||||
if (o instanceof RepoPackage) {
|
||||
queryResults.add((RepoPackage) o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tx.commit();
|
||||
} catch (SQLGrammarException ex) {
|
||||
// This sometimes happens when the result set is empty,
|
||||
// due to the ugly auto-built SQL
|
||||
LOGGER.error("Error getting (probably empty) package list", ex);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to get packages";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return queryResults;
|
||||
}
|
||||
|
||||
private Conjunction buildPackageSearchFilter(final String search, final Session session) {
|
||||
final List<String> searchableColumns = Arrays.asList(
|
||||
"repo.name", "name", "version", "release", "rec.path");
|
||||
// Search for all words in all searchable columns
|
||||
Conjunction and = Restrictions.conjunction();
|
||||
String[] searchWords = search.split(" ");
|
||||
for (String word : searchWords) {
|
||||
// Every word must be in at least one column
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
for (String column : searchableColumns) {
|
||||
or.add(ilike(column, word, MatchMode.ANYWHERE));
|
||||
}
|
||||
|
||||
// Add additional search filter for records, since aliasing wasn't
|
||||
// working properly for searching the hash/digest field
|
||||
or.add(Restrictions.in("rec.id", getMatchingRecordIds(word, session)));
|
||||
|
||||
and.add(or);
|
||||
}
|
||||
return and;
|
||||
}
|
||||
|
||||
private List<Long> getMatchingRecordIds(final String search, final Session session) {
|
||||
// Get the IDs for records that match the search filter.
|
||||
List<Long> matchingRecordIds = new ArrayList<>();
|
||||
if (StringUtils.isNotBlank(search)) {
|
||||
// Search for all words in all searchable columns
|
||||
Conjunction and = buildBaselineRecordSearchFilter(search);
|
||||
List list = session.createCriteria(IMABaselineRecord.class)
|
||||
.add(and)
|
||||
.setProjection(Property.forName("id"))
|
||||
.list();
|
||||
|
||||
for (Object o : list) {
|
||||
matchingRecordIds.add(Long.parseLong(o.toString()));
|
||||
}
|
||||
}
|
||||
return matchingRecordIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all IMABaselineRecords in the specified package.
|
||||
*
|
||||
* @param id id of the package
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @return List the records
|
||||
* @throws BaselineManagerException if unable to create the list
|
||||
*/
|
||||
@Override
|
||||
public List<IMABaselineRecord> getPackageRecords(final UUID id, final String search)
|
||||
throws BaselineManagerException {
|
||||
LOGGER.debug("Getting package records");
|
||||
|
||||
//Object that will store query values
|
||||
|
||||
Transaction tx = null;
|
||||
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
|
||||
// first use a subquery to list the ids for the records in the package
|
||||
DetachedCriteria ids = DetachedCriteria.forClass(RepoPackage.class)
|
||||
.createAlias("packageRecords", "rec")
|
||||
.add(Restrictions.eq("id", id))
|
||||
.setProjection(Property.forName("rec.id"));
|
||||
|
||||
Conjunction and = buildBaselineRecordSearchFilter(search);
|
||||
|
||||
// Get the records
|
||||
List list = session.createCriteria(IMABaselineRecord.class)
|
||||
.add(Subqueries.propertyIn("id", ids))
|
||||
.add(and)
|
||||
.addOrder(Order.asc("path"))
|
||||
.list();
|
||||
|
||||
List<IMABaselineRecord> records = new ArrayList<>();
|
||||
for (Object o : list) {
|
||||
if (o instanceof IMABaselineRecord) {
|
||||
records.add((IMABaselineRecord) o);
|
||||
}
|
||||
}
|
||||
|
||||
//Stores results of all the queries for the JQuery Datatable
|
||||
tx.commit();
|
||||
return records;
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "unable to get packages";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private Conjunction buildBaselineRecordSearchFilter(final String search) {
|
||||
// Search for all words in all searchable columns
|
||||
Conjunction and = Restrictions.conjunction();
|
||||
String[] searchWords = StringUtils.split(search);
|
||||
for (String word : searchWords) {
|
||||
// Every word must be in at least one column
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
or.add(ilike("path", word, MatchMode.ANYWHERE));
|
||||
or.add(ilikeHex("digest", word));
|
||||
and.add(or);
|
||||
}
|
||||
return and;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Baseline</code> from the database. This searches the
|
||||
* database for an entry whose name matches <code>name</code>. It then
|
||||
* reconstructs a <code>Baseline</code> object from the database entry
|
||||
*
|
||||
* @param name
|
||||
* name of the baseline
|
||||
* @return baseline if found, otherwise null.
|
||||
* @throws BaselineManagerException
|
||||
* if unable to search the database or recreate the
|
||||
* <code>Baseline</code>
|
||||
*/
|
||||
@Override
|
||||
public final Baseline getBaseline(final String name)
|
||||
throws BaselineManagerException {
|
||||
LOGGER.debug("getting baseline: {}", name);
|
||||
try {
|
||||
return super.get(name);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Baseline getBaseline(final Serializable id) {
|
||||
LOGGER.debug("getting baseline with id: {}", id);
|
||||
try {
|
||||
return super.get(id);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Baseline getCompleteBaseline(final String name) throws BaselineManagerException {
|
||||
LOGGER.debug("getting full baseline: {}", name);
|
||||
try {
|
||||
return super.getAndLoadLazyFields(name, true);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final FilteredRecordsList<SimpleBaselineBean> getOrderedBaselineListWithoutRecords(
|
||||
final String columnToOrder, final boolean ascending,
|
||||
final int firstResult, final int maxResults, final String search,
|
||||
final Map<String, Boolean> searchableColumns)
|
||||
throws BaselineManagerException {
|
||||
|
||||
if (columnToOrder == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("object");
|
||||
}
|
||||
|
||||
final FilteredRecordsList<SimpleBaselineBean> baselines =
|
||||
new FilteredRecordsList<>();
|
||||
final SessionFactory factory = getFactory();
|
||||
Transaction tx = null;
|
||||
Session session = factory.getCurrentSession();
|
||||
Long totalResultCount;
|
||||
Long filteredResultCount = 0L;
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
LOGGER.debug("retrieving baseline list without records");
|
||||
// The first query gets the total number of non-archived baselines
|
||||
Criteria cr = session.createCriteria(Baseline.class)
|
||||
.add(Restrictions.isNull("archivedTime"))
|
||||
.setProjection(Projections.countDistinct("id"));
|
||||
totalResultCount = (Long) cr.uniqueResult();
|
||||
|
||||
// This second query finds the number of non-archived baselines matching the filter
|
||||
cr = session.createCriteria(Baseline.class)
|
||||
.add(Restrictions.isNull("archivedTime"))
|
||||
.setProjection(Projections.countDistinct("id"));
|
||||
|
||||
// Filter using the search terms provided by the user
|
||||
Conjunction and = Restrictions.conjunction();
|
||||
if (totalResultCount != 0) {
|
||||
//Builds the search criteria from all of the searchable columns
|
||||
if (searchableColumns != null) {
|
||||
// Search for all words in all searchable columns
|
||||
String[] searchWords = search.split(" ");
|
||||
for (String word : searchWords) {
|
||||
// Every word must be in at least one column
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
for (Entry<String, Boolean> entry : searchableColumns.entrySet()) {
|
||||
if (entry.getValue()) {
|
||||
or.add(ilike(entry.getKey(), word, MatchMode.ANYWHERE));
|
||||
} else {
|
||||
or.add(ilikeCast(entry.getKey(), word));
|
||||
}
|
||||
}
|
||||
and.add(or);
|
||||
}
|
||||
}
|
||||
cr.add(and);
|
||||
filteredResultCount = (Long) cr.uniqueResult();
|
||||
}
|
||||
|
||||
if (filteredResultCount != 0) {
|
||||
// The third query builds a list from the filters, limits, and sorting options
|
||||
cr = session.createCriteria(Baseline.class)
|
||||
.add(Restrictions.isNull("archivedTime"))
|
||||
.add(and)
|
||||
.setProjection(Projections.projectionList()
|
||||
.add(Projections.property("id"), "id")
|
||||
.add(Projections.property("createTime"), "createTime")
|
||||
.add(Projections.property("name"), "name")
|
||||
.add(Projections.property("severity"), "severity")
|
||||
.add(Projections.property("type"), "type"))
|
||||
.setResultTransformer(Transformers.aliasToBean(SimpleBaselineBean.class))
|
||||
.setFirstResult(firstResult)
|
||||
.setMaxResults(maxResults);
|
||||
|
||||
if (ascending) {
|
||||
cr.addOrder(Order.asc(columnToOrder));
|
||||
} else {
|
||||
cr.addOrder(Order.desc(columnToOrder));
|
||||
}
|
||||
|
||||
// Perform the query and add all baselines to the list
|
||||
List list = cr.list();
|
||||
for (Object o : list) {
|
||||
if (o instanceof SimpleBaselineBean) {
|
||||
baselines.add((SimpleBaselineBean) o);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Update meta data for the Data Table.
|
||||
baselines.setRecordsTotal(totalResultCount);
|
||||
baselines.setRecordsFiltered(filteredResultCount);
|
||||
tx.commit();
|
||||
} catch (HibernateException e) {
|
||||
final String msg = "Error getting the SimpleBaselineBean list";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
} finally {
|
||||
if (session != null && session.isConnected()) {
|
||||
session.close();
|
||||
}
|
||||
}
|
||||
|
||||
return baselines;
|
||||
}
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceState;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* A <code>DBDeviceStateManager</code> manages <code>DeviceState</code> objects using a database.
|
||||
*/
|
||||
public class DBDeviceStateManager extends DBManager<DeviceState> implements DeviceStateManager {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBDeviceStateManager</code> that uses the default
|
||||
* database. The default database is used to store all of the
|
||||
* <code>DeviceState</code> objects.
|
||||
*
|
||||
* @param sessionFactory session factory used to access database connections
|
||||
*/
|
||||
public DBDeviceStateManager(final SessionFactory sessionFactory) {
|
||||
super(DeviceState.class, sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the <code>DeviceState</code> in the database and returns it.
|
||||
*
|
||||
* @param state
|
||||
* state to save
|
||||
* @return <code>DeviceState</code> that was saved
|
||||
* @throws DeviceStateManagerException
|
||||
* if state has previously been saved or an error occurs while
|
||||
* trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final DeviceState saveState(final DeviceState state)
|
||||
throws DeviceStateManagerException {
|
||||
LOGGER.debug("saving state: {}", state);
|
||||
try {
|
||||
return save(state);
|
||||
} catch (DBManagerException e) {
|
||||
throw new DeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>DeviceState</code> for a <code>Device</code>.
|
||||
*
|
||||
* @param device
|
||||
* device
|
||||
* @param clazz
|
||||
* Class to specify which type of <code>DeviceState</code> to retrieve
|
||||
* @return state
|
||||
* @throws DeviceStateManagerException
|
||||
* if state has not previously been saved or an error occurs
|
||||
* while trying to retrieve it from the database
|
||||
*/
|
||||
@Override
|
||||
public final DeviceState getState(final Device device, final Class<? extends DeviceState> clazz)
|
||||
throws DeviceStateManagerException {
|
||||
LOGGER.debug("getting state for device: {}", device);
|
||||
if (device == null) {
|
||||
LOGGER.error("null device argument");
|
||||
throw new NullPointerException("null device");
|
||||
}
|
||||
|
||||
DeviceState ret;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("retrieving state from db");
|
||||
tx = session.beginTransaction();
|
||||
CriteriaBuilder builder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<?> criteriaQuery = builder.createQuery(DeviceState.class);
|
||||
Root<?> root = criteriaQuery.from();
|
||||
Predicate recordPredicate = builder.and(
|
||||
|
||||
);
|
||||
criteriaQuery.select(root).where(recordPredicate).distinct(true);
|
||||
Query<?> query = session.createQuery(criteriaQuery);
|
||||
List<?> results = query.getResultList();
|
||||
|
||||
ret = (DeviceState) session.createCriteria(clazz)
|
||||
.add(Restrictions.eq("device", device)).uniqueResult();
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
final String msg = "unable to retrieve object";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw new DBManagerException(msg, e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a <code>List</code> of the <code>DeviceStates</code> associated with the
|
||||
* <code>Device</code>. If there are no states are associated, an empty list is returned.
|
||||
*
|
||||
* @param device
|
||||
* device
|
||||
* @return list of device states
|
||||
* @throws DeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the states
|
||||
*/
|
||||
@Override
|
||||
public final List<DeviceState> getStates(final Device device) throws
|
||||
DeviceStateManagerException {
|
||||
LOGGER.debug("getting all states for device: {}", device);
|
||||
if (device == null) {
|
||||
LOGGER.error("null device argument");
|
||||
throw new NullPointerException("null device");
|
||||
}
|
||||
|
||||
try {
|
||||
return super.getList(DeviceState.class);
|
||||
} catch (DBManagerException e) {
|
||||
throw new DeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a <code>DeviceState</code>. This updates the database entries
|
||||
* to reflect the new values that should be set.
|
||||
*
|
||||
* @param state
|
||||
* state
|
||||
* @throws DeviceStateManagerException
|
||||
* if state has not previously been saved or an error occurs
|
||||
* while trying to save it to the database
|
||||
*/
|
||||
@Override
|
||||
public final void updateState(final DeviceState state)
|
||||
throws DeviceStateManagerException {
|
||||
LOGGER.debug("updating state: {}", state);
|
||||
try {
|
||||
super.update(state);
|
||||
} catch (DBManagerException e) {
|
||||
throw new DeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>DeviceState</code> from the database.
|
||||
*
|
||||
* @param device
|
||||
* device whose state is to be remove
|
||||
* @param clazz
|
||||
* Class to specify which type of <code>DeviceState</code> to delete
|
||||
* @return true if successfully found and deleted the
|
||||
* <code>DeviceState</code>
|
||||
* @throws DeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to delete it from
|
||||
* the database
|
||||
*/
|
||||
@Override
|
||||
public final boolean deleteState(final Device device, final Class<? extends DeviceState> clazz)
|
||||
throws DeviceStateManagerException {
|
||||
LOGGER.debug("deleting state for device: {}", device);
|
||||
if (device == null) {
|
||||
LOGGER.error("null device argument");
|
||||
throw new NullPointerException("null device");
|
||||
}
|
||||
|
||||
boolean ret = false;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
LOGGER.debug("retrieving state from db");
|
||||
tx = session.beginTransaction();
|
||||
final DeviceState state = (DeviceState) session
|
||||
.createCriteria(clazz)
|
||||
.add(Restrictions.eq("device", device)).uniqueResult();
|
||||
if (state != null) {
|
||||
session.delete(state);
|
||||
ret = true;
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
final String msg = "unable to retrieve object";
|
||||
LOGGER.error(msg, e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw new DBManagerException(msg, e);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.IMADeviceState;
|
||||
|
||||
/**
|
||||
* A <code>DBIMADeviceStateManager</code> manages <code>IMADeviceState</code> objects using a
|
||||
* database.
|
||||
*/
|
||||
public class DBIMADeviceStateManager extends DBDeviceStateManager implements IMADeviceStateManager {
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBIMADeviceStateManager</code>. The optional SessionFactory parameter
|
||||
* is used to initialize a session factory to manage all hibernate sessions.
|
||||
*
|
||||
* @param factory session factory to manage connections to hibernate db
|
||||
*/
|
||||
public DBIMADeviceStateManager(final SessionFactory factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the <code>IMADeviceState</code> in the database and returns it.
|
||||
*
|
||||
* @param state
|
||||
* state to save
|
||||
* @return <code>IMADeviceState</code> that was saved
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if state has previously been saved or an error occurs while trying to save it
|
||||
* to the database
|
||||
*/
|
||||
@Override
|
||||
public final IMADeviceState saveState(final IMADeviceState state)
|
||||
throws IMADeviceStateManagerException {
|
||||
try {
|
||||
return (IMADeviceState) super.saveState(state);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new IMADeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>IMADeviceState</code> for a <code>Device</code>.
|
||||
*
|
||||
* @param device
|
||||
* device
|
||||
* @return state
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if state has not previously been saved or an error occurs while trying to
|
||||
* retrieve it from the database
|
||||
*/
|
||||
@Override
|
||||
public final IMADeviceState getState(final Device device)
|
||||
throws IMADeviceStateManagerException {
|
||||
try {
|
||||
return (IMADeviceState) super.getState(device, IMADeviceState.class);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new IMADeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an <code>IMADeviceState</code>. This updates the database entries to reflect the
|
||||
* new values that should be set.
|
||||
*
|
||||
* @param state
|
||||
* state
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if state has not previously been saved or an error occurs while trying to save
|
||||
* it to the database
|
||||
*/
|
||||
@Override
|
||||
public final void updateState(final IMADeviceState state)
|
||||
throws IMADeviceStateManagerException {
|
||||
try {
|
||||
super.updateState(state);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new IMADeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>IMADeviceState</code> from the database.
|
||||
*
|
||||
* @param device
|
||||
* device whose state is to be remove
|
||||
* @return true if successfully found and deleted the
|
||||
* <code>IMADeviceState</code>
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to delete it from the database
|
||||
*/
|
||||
@Override
|
||||
public final boolean deleteState(final Device device)
|
||||
throws IMADeviceStateManagerException {
|
||||
try {
|
||||
return super.deleteState(device, IMADeviceState.class);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new IMADeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -26,9 +26,8 @@ import java.util.Map;
|
||||
* Generic database manager for managing objects in a database. This provides create, read, update,
|
||||
* archive, and delete operations for managing objects in a database.
|
||||
*
|
||||
* @param <T> type of objects to manage by this manager
|
||||
*/
|
||||
public class DBManager<T> extends AbstractDbManager<T> {
|
||||
public class DBManager<AbstractEntity> extends AbstractDbManager<AbstractEntity> {
|
||||
private static final Logger LOGGER = LogManager.getLogger(DBManager.class);
|
||||
|
||||
/**
|
||||
@ -66,7 +65,7 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @param sessionFactory the session factory to use to connect to the database
|
||||
* unfortunately class type of T cannot be determined using only T
|
||||
*/
|
||||
public DBManager(final Class<T> clazz, final SessionFactory sessionFactory) {
|
||||
public DBManager(final AbstractEntity clazz, final SessionFactory sessionFactory) {
|
||||
super(clazz, sessionFactory);
|
||||
setRetryTemplate(DEFAULT_MAX_RETRY_ATTEMPTS, DEFAULT_RETRY_WAIT_TIME_MS);
|
||||
}
|
||||
@ -115,12 +114,12 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if an error is encountered while performing the query or creating
|
||||
* the result objects
|
||||
*/
|
||||
public final List<T> getWithCriteria(final Collection<Criterion> criteriaCollection)
|
||||
public final List<AbstractEntity> getWithCriteria(final Collection<Criterion> criteriaCollection)
|
||||
throws DBManagerException {
|
||||
return retryTemplate.execute(
|
||||
new RetryCallback<List<T>, DBManagerException>() {
|
||||
new RetryCallback<List<AbstractEntity>, DBManagerException>() {
|
||||
@Override
|
||||
public List<T> doWithRetry(final RetryContext context)
|
||||
public List<AbstractEntity> doWithRetry(final RetryContext context)
|
||||
throws DBManagerException {
|
||||
return doGetWithCriteria(criteriaCollection);
|
||||
}
|
||||
@ -131,8 +130,6 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* Runs a Criteria query using the given collection of Criterion over the
|
||||
* associated class.
|
||||
*
|
||||
* @param <U> the specific type of class to retrieve
|
||||
* (should extend this class' <T> parameter)
|
||||
* @param clazzToGet the class of object to retrieve
|
||||
* @param criteriaCollection the collection of Criterion to apply
|
||||
*
|
||||
@ -140,13 +137,13 @@ 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 <U extends T> List<U> getWithCriteria(
|
||||
final Class<U> clazzToGet,
|
||||
protected final List<AbstractEntity> getWithCriteria(
|
||||
final Class<AbstractEntity> clazzToGet,
|
||||
final Collection<Criterion> criteriaCollection) throws DBManagerException {
|
||||
return retryTemplate.execute(
|
||||
new RetryCallback<List<U>, DBManagerException>() {
|
||||
new RetryCallback<List<AbstractEntity>, DBManagerException>() {
|
||||
@Override
|
||||
public List<U> doWithRetry(final RetryContext context)
|
||||
public List<AbstractEntity> doWithRetry(final RetryContext context)
|
||||
throws DBManagerException {
|
||||
return doGetWithCriteria(clazzToGet, criteriaCollection);
|
||||
}
|
||||
@ -180,10 +177,10 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if object has previously been saved or an
|
||||
* error occurs while trying to save it to the database
|
||||
*/
|
||||
public final T save(final T object) throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<T, DBManagerException>() {
|
||||
public final AbstractEntity save(final AbstractEntity object) throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<AbstractEntity, DBManagerException>() {
|
||||
@Override
|
||||
public T doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
public AbstractEntity doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
return doSave(object);
|
||||
}
|
||||
});
|
||||
@ -196,7 +193,7 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @param object object to update
|
||||
* @throws DBManagerException if an error occurs while trying to save it to the database
|
||||
*/
|
||||
public final void update(final T object) throws DBManagerException {
|
||||
public final void update(final AbstractEntity object) throws DBManagerException {
|
||||
retryTemplate.execute(new RetryCallback<Void, DBManagerException>() {
|
||||
@Override
|
||||
public Void doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
@ -216,10 +213,10 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
public final T get(final String name) throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<T, DBManagerException>() {
|
||||
public final AbstractEntity get(final String name) throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<AbstractEntity, DBManagerException>() {
|
||||
@Override
|
||||
public T doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
public AbstractEntity doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
return doGet(name);
|
||||
}
|
||||
});
|
||||
@ -235,10 +232,10 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
public final T get(final Serializable id) throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<T, DBManagerException>() {
|
||||
public final AbstractEntity get(final Serializable id) throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<AbstractEntity, DBManagerException>() {
|
||||
@Override
|
||||
public T doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
public AbstractEntity doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
return doGet(id);
|
||||
}
|
||||
});
|
||||
@ -259,11 +256,11 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
public final T getAndLoadLazyFields(final String name, final boolean recurse)
|
||||
public final AbstractEntity getAndLoadLazyFields(final String name, final boolean recurse)
|
||||
throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<T, DBManagerException>() {
|
||||
return retryTemplate.execute(new RetryCallback<AbstractEntity, DBManagerException>() {
|
||||
@Override
|
||||
public T doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
public AbstractEntity doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
return doGetAndLoadLazyFields(name, recurse);
|
||||
}
|
||||
});
|
||||
@ -284,7 +281,7 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if unable to search the database or recreate
|
||||
* the <code>Object</code>
|
||||
*/
|
||||
public final T getAndLoadLazyFields(final Serializable id, final boolean recurse)
|
||||
public final AbstractEntity getAndLoadLazyFields(final Serializable id, final boolean recurse)
|
||||
throws DBManagerException {
|
||||
return doGetAndLoadLazyFields(id, recurse);
|
||||
}
|
||||
@ -297,14 +294,14 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* managed. This class argument allows the caller to limit which types of
|
||||
* <code>T</code> should be returned.
|
||||
*
|
||||
* @param clazz class type of <code>T</code>s to search for (may be null to
|
||||
* @param entity class type of <code>T</code>s to search for (may be null to
|
||||
* use Class<T>)
|
||||
* @return list of <code>T</code> names
|
||||
* @throws DBManagerException if unable to search the database
|
||||
*/
|
||||
public List<T> getList(final Class<? extends T> clazz)
|
||||
public List<AbstractEntity> getList(final AbstractEntity entity)
|
||||
throws DBManagerException {
|
||||
return getList(clazz, null);
|
||||
return getList(entity, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,19 +312,19 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* managed. This class argument allows the caller to limit which types of
|
||||
* <code>T</code> should be returned.
|
||||
*
|
||||
* @param clazz class type of <code>T</code>s to search for (may be null to
|
||||
* @param entity class type of <code>T</code>s to search for (may be null to
|
||||
* use Class<T>)
|
||||
* @param additionalRestriction additional restrictions to apply to criteria.
|
||||
* @return list of <code>T</code> names
|
||||
* @throws DBManagerException if unable to search the database
|
||||
*/
|
||||
@Override
|
||||
public List<T> getList(final Class<? extends T> clazz, final Criterion additionalRestriction)
|
||||
public List<AbstractEntity> getList(final AbstractEntity entity, final Criterion additionalRestriction)
|
||||
throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<List<T>, DBManagerException>() {
|
||||
return retryTemplate.execute(new RetryCallback<List<AbstractEntity>, DBManagerException>() {
|
||||
@Override
|
||||
public List<T> doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
return doGetList(clazz, additionalRestriction);
|
||||
public List<AbstractEntity> doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
return doGetList(entity, additionalRestriction);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -352,7 +349,7 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
*/
|
||||
@Override
|
||||
public final FilteredRecordsList getOrderedList(
|
||||
final Class<? extends T> clazz, final String columnToOrder,
|
||||
final AbstractEntity clazz, final String columnToOrder,
|
||||
final boolean ascending, final int firstResult,
|
||||
final int maxResults, final String search,
|
||||
final Map<String, Boolean> searchableColumns)
|
||||
@ -390,17 +387,17 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if unable to create the list
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
public final FilteredRecordsList<T> getOrderedList(
|
||||
final Class<? extends T> clazz, final String columnToOrder,
|
||||
public final FilteredRecordsList<AbstractEntity> getOrderedList(
|
||||
final AbstractEntity clazz, final String columnToOrder,
|
||||
final boolean ascending, final int firstResult,
|
||||
final int maxResults, final String search,
|
||||
final Map<String, Boolean> searchableColumns, final CriteriaModifier criteriaModifier)
|
||||
throws DBManagerException {
|
||||
|
||||
return retryTemplate.execute(
|
||||
new RetryCallback<FilteredRecordsList<T>, DBManagerException>() {
|
||||
new RetryCallback<FilteredRecordsList<AbstractEntity>, DBManagerException>() {
|
||||
@Override
|
||||
public FilteredRecordsList<T> doWithRetry(final RetryContext context)
|
||||
public FilteredRecordsList<AbstractEntity> doWithRetry(final RetryContext context)
|
||||
throws DBManagerException {
|
||||
return doGetOrderedList(clazz, columnToOrder, ascending,
|
||||
firstResult, maxResults,
|
||||
@ -466,7 +463,7 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
* @throws DBManagerException if unable to delete the object from the database
|
||||
*/
|
||||
@Override
|
||||
public final boolean delete(final T object) throws DBManagerException {
|
||||
public final boolean delete(final AbstractEntity object) throws DBManagerException {
|
||||
return retryTemplate.execute(new RetryCallback<Boolean, DBManagerException>() {
|
||||
@Override
|
||||
public Boolean doWithRetry(final RetryContext context) throws DBManagerException {
|
||||
@ -491,7 +488,7 @@ public class DBManager<T> extends AbstractDbManager<T> {
|
||||
return false;
|
||||
}
|
||||
|
||||
T target = get(name);
|
||||
AbstractEntity target = get(name);
|
||||
if (target == null) {
|
||||
return false;
|
||||
}
|
||||
|
@ -8,19 +8,14 @@ import org.hibernate.Criteria;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.DetachedCriteria;
|
||||
import org.hibernate.criterion.Order;
|
||||
import org.hibernate.criterion.ProjectionList;
|
||||
import org.hibernate.criterion.Projections;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.criterion.Subqueries;
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.criteria.Subquery;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -170,57 +165,6 @@ public class DBReportSummaryManager extends DBManager<ReportSummary>
|
||||
return reportSummaryList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>ReportSummary</code> objects that are ordered
|
||||
* by a column and direction (ASC, DESC) that is provided by the user. This
|
||||
* method helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @param searchableColumns Map of String and boolean values with column
|
||||
* headers and whether they are to. Boolean is true if field provides
|
||||
* a typical String that can be searched by Hibernate without
|
||||
* transformation.
|
||||
* @param hostname name of the device to filter on
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws ReportSummaryManagerException
|
||||
* if unable to create the list
|
||||
*/
|
||||
@Override
|
||||
public final FilteredRecordsList<ReportSummary> getOrderedReportSummaryList(
|
||||
final String columnToOrder, final boolean ascending, final int firstResult,
|
||||
final int maxResults, final String search,
|
||||
final Map<String, Boolean> searchableColumns,
|
||||
final String hostname) throws ReportSummaryManagerException {
|
||||
if (columnToOrder == null) {
|
||||
LOGGER.debug("null object argument");
|
||||
throw new NullPointerException("object");
|
||||
}
|
||||
|
||||
// allows filtering by specific hostname. If no hostname specified, always match.
|
||||
CriteriaModifier modifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
criteria.add(Restrictions.ilike("clientHostname",
|
||||
StringUtils.defaultIfBlank(hostname, "%")));
|
||||
}
|
||||
};
|
||||
|
||||
LOGGER.debug("Getting report summary list");
|
||||
final FilteredRecordsList<ReportSummary> summaries;
|
||||
try {
|
||||
summaries = super.getOrderedList(ReportSummary.class, columnToOrder,
|
||||
ascending, firstResult, maxResults, search,
|
||||
searchableColumns, modifier);
|
||||
} catch (DBManagerException e) {
|
||||
throw new BaselineManagerException(e);
|
||||
}
|
||||
LOGGER.debug("Got {} report summaries", summaries.size());
|
||||
return summaries;
|
||||
}
|
||||
/**
|
||||
* Retrieves the <code>ReportSummary</code> from the database. This
|
||||
* searches the database for an entry whose id matches <code>id</code>.
|
||||
@ -339,33 +283,30 @@ public class DBReportSummaryManager extends DBManager<ReportSummary>
|
||||
try {
|
||||
LOGGER.debug("retrieving objects from db");
|
||||
tx = session.beginTransaction();
|
||||
DetachedCriteria uniqueHosts = DetachedCriteria.forClass(
|
||||
ReportSummary.class);
|
||||
// DetachedCriteria uniqueHosts = DetachedCriteria.forClass(
|
||||
// ReportSummary.class);
|
||||
|
||||
ProjectionList properties = Projections.projectionList();
|
||||
properties.add(Projections.groupProperty("clientHostname"));
|
||||
properties.add(Projections.max("timestamp"), "timestamp");
|
||||
|
||||
uniqueHosts.setProjection(properties);
|
||||
|
||||
List list = session.createCriteria(ReportSummary.class)
|
||||
.add(Subqueries.propertiesIn(
|
||||
new String[]{"clientHostname", "timestamp"},
|
||||
uniqueHosts))
|
||||
.list();
|
||||
for (Object o : list) {
|
||||
if (o instanceof ReportSummary) {
|
||||
reportSummaryList.add((ReportSummary) o);
|
||||
}
|
||||
}
|
||||
// ProjectionList properties = Projections.projectionList();
|
||||
// properties.add(Projections.groupProperty("clientHostname"));
|
||||
// properties.add(Projections.max("timestamp"), "timestamp");
|
||||
//
|
||||
// uniqueHosts.setProjection(properties);
|
||||
//
|
||||
// List list = session.createCriteria(ReportSummary.class)
|
||||
// .add(Subqueries.propertiesIn(
|
||||
// new String[]{"clientHostname", "timestamp"},
|
||||
// uniqueHosts))
|
||||
// .list();
|
||||
// for (Object o : list) {
|
||||
// if (o instanceof ReportSummary) {
|
||||
// reportSummaryList.add((ReportSummary) o);
|
||||
// }
|
||||
// }
|
||||
|
||||
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||
CriteriaQuery<ReportSummary> criteriaQuery = criteriaBuilder.createQuery(ReportSummary.class);
|
||||
Root<ReportSummary> root = criteriaQuery.from(ReportSummary.class);
|
||||
Predicate recordPredicate = criteriaBuilder
|
||||
.exists();
|
||||
|
||||
criteriaQuery.select(root).where(recordPredicate);
|
||||
criteriaQuery.multiselect(root.get("clientHostname"), root.get("timestamp"));
|
||||
Query<ReportSummary> query = session.createQuery(criteriaQuery);
|
||||
List<ReportSummary> results = query.getResultList();
|
||||
if (results != null) {
|
||||
|
@ -1,103 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.TPMDeviceState;
|
||||
|
||||
/**
|
||||
* A <code>DBTPMDeviceStateManager</code> manages <code>TPMDeviceState</code> objects using a
|
||||
* database.
|
||||
*/
|
||||
public class DBTPMDeviceStateManager extends DBDeviceStateManager implements TPMDeviceStateManager {
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBTPMDeviceStateManager</code>. The optional SessionFactory parameter is
|
||||
* used to initialize a session factory to manage all hibernate sessions.
|
||||
*
|
||||
* @param factory
|
||||
* session factory to manage connections to hibernate db
|
||||
*/
|
||||
public DBTPMDeviceStateManager(final SessionFactory factory) {
|
||||
super(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the <code>TPMDeviceState</code> in the database and returns it.
|
||||
*
|
||||
* @param state
|
||||
* state to save
|
||||
* @return <code>TPMDeviceState</code> that was saved
|
||||
* @throws TPMDeviceStateManagerException
|
||||
* if state has previously been saved or an error occurs while trying to save it to
|
||||
* the database
|
||||
*/
|
||||
@Override
|
||||
public final TPMDeviceState saveState(final TPMDeviceState state)
|
||||
throws TPMDeviceStateManagerException {
|
||||
try {
|
||||
return (TPMDeviceState) super.saveState(state);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new TPMDeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>TPMDeviceState</code> for a <code>Device</code>.
|
||||
*
|
||||
* @param device
|
||||
* device
|
||||
* @return state
|
||||
* @throws TPMDeviceStateManagerException
|
||||
* if state has not previously been saved or an error occurs while trying to
|
||||
* retrieve it from the database
|
||||
*/
|
||||
@Override
|
||||
public final TPMDeviceState getState(final Device device)
|
||||
throws TPMDeviceStateManagerException {
|
||||
try {
|
||||
return (TPMDeviceState) super.getState(device, TPMDeviceState.class);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new TPMDeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an <code>TPMDeviceState</code>. This updates the database entries to reflect the new
|
||||
* values that should be set.
|
||||
*
|
||||
* @param state
|
||||
* state
|
||||
* @throws TPMDeviceStateManagerException
|
||||
* if state has not previously been saved or an error occurs while trying to save it
|
||||
* to the database
|
||||
*/
|
||||
@Override
|
||||
public final void updateState(final TPMDeviceState state)
|
||||
throws TPMDeviceStateManagerException {
|
||||
try {
|
||||
super.updateState(state);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new TPMDeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>TPMDeviceState</code> from the database.
|
||||
*
|
||||
* @param device
|
||||
* device whose state is to be remove
|
||||
* @return true if successfully found and deleted the <code>TPMDeviceState</code>
|
||||
* @throws TPMDeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to delete it from the database
|
||||
*/
|
||||
@Override
|
||||
public final boolean deleteState(final Device device) throws TPMDeviceStateManagerException {
|
||||
try {
|
||||
return super.deleteState(device, TPMDeviceState.class);
|
||||
} catch (DeviceStateManagerException e) {
|
||||
throw new TPMDeviceStateManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,344 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.OptionalDigest;
|
||||
import hirs.data.persist.baseline.QueryableRecordImaBaseline;
|
||||
import hirs.data.persist.baseline.SimpleImaBaseline;
|
||||
|
||||
import hirs.utils.Callback;
|
||||
import hirs.utils.Job;
|
||||
import hirs.utils.JobExecutor;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.transform.Transformers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class DbImaBaselineRecordManager extends DBManager<IMABaselineRecord>
|
||||
implements ImaBaselineRecordManager {
|
||||
|
||||
private static final Logger LOGGER =
|
||||
LogManager.getLogger(DbImaBaselineRecordManager.class);
|
||||
private static final int LOGGING_INTERVAL = 500;
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBImaBaselineRecordManager</code> that uses the default
|
||||
* database. The default database is used to store all of the
|
||||
* <code>IMABaselineRecord</code>s.
|
||||
*
|
||||
* @param sessionFactory session factory used to access database connections
|
||||
*/
|
||||
public DbImaBaselineRecordManager(final SessionFactory sessionFactory) {
|
||||
super(IMABaselineRecord.class, sessionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a new <code>IMABaselineRecord</code>. This stores a new
|
||||
* <code>IMABaselineRecord</code> to be managed by the <code>IMABaselineRecordManager</code>.
|
||||
* If the <code>IMABaselineRecord</code> is successfully saved then a reference to it is
|
||||
* returned.
|
||||
* <p>
|
||||
* Should only save the record to a <code>SimpleImaBaseline</code> Other baselines should
|
||||
* not be controlled by the user.
|
||||
* <p> Records added in this manner MUST have a baseline set to them.
|
||||
*
|
||||
* @param record
|
||||
* Record to save
|
||||
* @return reference to saved IMABaselineRecord
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if the record has previously been saved or unexpected error
|
||||
* occurs
|
||||
*/
|
||||
@Override
|
||||
public IMABaselineRecord saveRecord(final IMABaselineRecord record)
|
||||
throws ImaBaselineRecordManagerException {
|
||||
LOGGER.debug("saving ima baseline record: {}", record);
|
||||
|
||||
//When adding a record through the manager, the record should be associated with a baseline
|
||||
if (record == null || record.getBaseline() == null) {
|
||||
throw new ImaBaselineRecordManagerException("Record cannot be saved without setting"
|
||||
+ " baseline.");
|
||||
}
|
||||
|
||||
try {
|
||||
//Checks to make sure a duplicate record does not already exist in the baseline. This
|
||||
//is done in this fashion due to the inability to put constraints on the table.
|
||||
if (getRecord(record.getPath(), record.getHash(),
|
||||
(SimpleImaBaseline) record.getBaseline()) != null) {
|
||||
throw new ImaBaselineRecordManagerException("Record already exists.");
|
||||
} else {
|
||||
return super.save(record);
|
||||
}
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an <code>IMABaselineRecord</code> based on the id of the record.
|
||||
*
|
||||
* @param id
|
||||
* id of the <code>IMABaselineRecord</code>
|
||||
* @return
|
||||
* instance of the requested <code>IMABaselineRecord</code>
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if the record has previously been saved or unexpected error occurs
|
||||
*/
|
||||
@Override
|
||||
public IMABaselineRecord getRecord(final long id) throws ImaBaselineRecordManagerException {
|
||||
LOGGER.debug("getting baseline: {}", id);
|
||||
try {
|
||||
return super.get(id);
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves <code>IMABaselineRecord</code> with the given path, hash, and assigned IMA
|
||||
* baseline id.
|
||||
*
|
||||
* @param path
|
||||
* path of the record to be retrieved
|
||||
* @param hash
|
||||
* hash of the record to be retrieved
|
||||
* @param baseline
|
||||
* baseline that is associated with the desired record.
|
||||
* @return
|
||||
* IMABaselineRecord that matches the provided path, hash, and baseline ID
|
||||
*/
|
||||
private IMABaselineRecord getRecord(final String path, final OptionalDigest hash,
|
||||
final SimpleImaBaseline baseline) {
|
||||
LOGGER.debug("Getting object list");
|
||||
|
||||
if (path == null || hash == null || baseline == null) {
|
||||
LOGGER.error("path, hash, or baseline was null");
|
||||
return null;
|
||||
}
|
||||
|
||||
IMABaselineRecord record = null;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
record = (IMABaselineRecord) session.createCriteria(IMABaselineRecord.class)
|
||||
.add(Restrictions.eq("path", path))
|
||||
.add(Restrictions.eq("hash", hash))
|
||||
.add(Restrictions.eq("baseline", baseline))
|
||||
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).uniqueResult();
|
||||
tx.commit();
|
||||
LOGGER.debug("Retrieved record object");
|
||||
} catch (HibernateException e) {
|
||||
LOGGER.error("Unable to retrieve record", e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("Rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves <code>IMABaselineRecord</code> with the given path, hash, and assigned IMA
|
||||
* baseline id.
|
||||
*
|
||||
* @param path
|
||||
* path of the record to be retrieved
|
||||
* @param hash
|
||||
* hash of the record to be retrieved
|
||||
* @param baseline
|
||||
* baseline that is associated with the desired record.
|
||||
* @return
|
||||
* IMABaselineRecord that matches the provided path, hash, and baseline ID
|
||||
*/
|
||||
@Override
|
||||
public IMABaselineRecord getRecord(final String path, final Digest hash,
|
||||
final SimpleImaBaseline baseline) {
|
||||
OptionalDigest optionalDigest = null;
|
||||
if (hash != null) {
|
||||
optionalDigest = hash.asOptionalDigest();
|
||||
}
|
||||
return getRecord(path, optionalDigest, baseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> identified by <code>id</code>. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
* <p>
|
||||
* Will likely be used to delete records of a <code>SimpleImaBaseline</code> Other IMA
|
||||
* baselines would not be controlled by the user at this time.
|
||||
*
|
||||
* @param id
|
||||
* id of the <code>ImaBaselineRecord</code> to delete
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if unable to delete the ImaBaselineRecord for any reason other than
|
||||
* not found
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteRecord(final Long id) throws ImaBaselineRecordManagerException {
|
||||
LOGGER.debug("deleting ima baseline record: {}", id);
|
||||
try {
|
||||
return super.delete(id);
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> provided. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
* @param record
|
||||
* record object to be deleted.
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if unable to delete the ImaBaselineRecord for any reason other than
|
||||
* not found
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteRecord(final IMABaselineRecord record)
|
||||
throws ImaBaselineRecordManagerException {
|
||||
if (record == null || record.getBaseline() == null) {
|
||||
throw new ImaBaselineRecordManagerException("record or baseline of record not set");
|
||||
}
|
||||
LOGGER.debug("deleting ima baseline record: {}", record.getId());
|
||||
try {
|
||||
return super.delete(record);
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the {@link IMABaselineRecord}s in the given baseline, and calls the given
|
||||
* Callback on each record. If the callback returns a non-null value, the returned value will
|
||||
* be added to a collection, which is returned when iteration is finished.
|
||||
*
|
||||
* @param baseline the baseline whose {@link IMABaselineRecord}s we should iterate over
|
||||
* @param callback the callback to run on each record
|
||||
* @param <T> the return type of the callback
|
||||
* @return the total collection of objects returned as results from the given Callback
|
||||
*/
|
||||
public final <T> Collection<T> iterateOverBaselineRecords(
|
||||
final QueryableRecordImaBaseline baseline,
|
||||
final Callback<IMABaselineRecord, T> callback) {
|
||||
final Collection<T> allResults = new ConcurrentLinkedQueue<>();
|
||||
Collection<Callable<Void>> tasks = new ArrayList<>();
|
||||
|
||||
int fetchSize;
|
||||
switch (getConfiguredImplementation()) {
|
||||
case MYSQL:
|
||||
fetchSize = Integer.MIN_VALUE;
|
||||
break;
|
||||
case HSQL:
|
||||
default:
|
||||
fetchSize = 1;
|
||||
}
|
||||
|
||||
DBImpl impl = getConfiguredImplementation();
|
||||
if (impl == DBImpl.MYSQL) {
|
||||
// provides a hint to the JDBC connector that records should be streamed
|
||||
fetchSize = Integer.MIN_VALUE;
|
||||
} else if (impl == DBImpl.HSQL) {
|
||||
fetchSize = 1;
|
||||
}
|
||||
|
||||
final AtomicInteger recCounter = new AtomicInteger();
|
||||
for (int i = 0; i < IMABaselineRecord.FILENAME_HASH_BUCKET_COUNT; i++) {
|
||||
final int bucket = i;
|
||||
final int finalFetchSize = fetchSize;
|
||||
tasks.add(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
LOGGER.debug(String.format(
|
||||
"IMA record iteration: starting examiner thread %d",
|
||||
bucket
|
||||
));
|
||||
List<T> results = new LinkedList<>();
|
||||
|
||||
StatelessSession statelessSession = getStatelessSession();
|
||||
try {
|
||||
Transaction tx = statelessSession.beginTransaction();
|
||||
Criteria criteria = statelessSession.createCriteria(baseline.getClass());
|
||||
baseline.configureCriteriaForBaselineRecords(criteria, bucket);
|
||||
criteria.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
|
||||
criteria.setReadOnly(true);
|
||||
criteria.setFetchSize(finalFetchSize);
|
||||
ScrollableResults records = criteria.scroll(ScrollMode.FORWARD_ONLY);
|
||||
|
||||
Map entry;
|
||||
IMABaselineRecord baselineRecord;
|
||||
while (records.next()) {
|
||||
// get(0) guarantees other rows won't be initialized
|
||||
entry = (Map) records.get(0);
|
||||
String path = (String) entry.get(IMABaselineRecord.PATH_FIELD);
|
||||
OptionalDigest digest =
|
||||
(OptionalDigest) entry.get(IMABaselineRecord.HASH_FIELD);
|
||||
baselineRecord = new IMABaselineRecord(path, digest.asDigest());
|
||||
T result = callback.call(baselineRecord);
|
||||
if (result != null) {
|
||||
results.add(result);
|
||||
}
|
||||
int count = recCounter.incrementAndGet();
|
||||
if (count % LOGGING_INTERVAL == 0) {
|
||||
LOGGER.debug(String.format(
|
||||
"IMA record iteration: examined %d records", count
|
||||
));
|
||||
}
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
} finally {
|
||||
statelessSession.close();
|
||||
}
|
||||
|
||||
allResults.addAll(results);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
JobExecutor executor = new JobExecutor();
|
||||
Job<Void> job = new Job<>(tasks);
|
||||
executor.scheduleJob(job);
|
||||
|
||||
try {
|
||||
executor.shutdown();
|
||||
} catch (InterruptedException e) {
|
||||
throw new DBManagerException(e);
|
||||
}
|
||||
|
||||
if (job.getState() != Job.State.COMPLETED) {
|
||||
LOGGER.error("Appraisal job finished in state {}", job.getState().toString());
|
||||
for (String s : job.getAllFailures()) {
|
||||
throw new DBManagerException(s);
|
||||
}
|
||||
}
|
||||
|
||||
return allResults;
|
||||
}
|
||||
}
|
@ -1,344 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import hirs.data.persist.OptionalDigest;
|
||||
import hirs.data.persist.baseline.QueryableRecordImaBaseline;
|
||||
import hirs.data.persist.baseline.ImaBlacklistBaseline;
|
||||
|
||||
import hirs.utils.Callback;
|
||||
import hirs.utils.Job;
|
||||
import hirs.utils.JobExecutor;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.ScrollMode;
|
||||
import org.hibernate.ScrollableResults;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.StatelessSession;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.transform.Transformers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class DbImaBlacklistBaselineRecordManager extends DBManager<ImaBlacklistRecord>
|
||||
implements ImaBlacklistBaselineRecordManager {
|
||||
|
||||
private static final Logger LOGGER =
|
||||
LogManager.getLogger(DbImaBlacklistBaselineRecordManager.class);
|
||||
private static final int LOGGING_INTERVAL = 500;
|
||||
|
||||
/**
|
||||
* Creates a new <code>DBImaBaselineRecordManager</code>. The optional
|
||||
* SessionFactory parameter is used to manage sessions with a
|
||||
* hibernate db.
|
||||
*
|
||||
* @param factory session factory used to access database connections
|
||||
*/
|
||||
public DbImaBlacklistBaselineRecordManager(final SessionFactory factory) {
|
||||
super(ImaBlacklistRecord.class, factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a new <code>ImaBlacklistRecord</code>. This stores a new
|
||||
* <code>ImaBlacklistRecord</code> to be managed by the <code>IMABaselineRecordManager</code>.
|
||||
* If the <code>ImaBlacklistRecord</code> is successfully saved then a reference to it is
|
||||
* returned.
|
||||
* <p>
|
||||
* Should only save the record to a <code>ImaBlacklistBaseline</code> Other baselines should
|
||||
* not be controlled by the user.
|
||||
* <p> Records added in this manner MUST have a baseline set to them.
|
||||
*
|
||||
* @param record
|
||||
* Record to save
|
||||
* @return reference to saved ImaBlacklistRecord
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if the record has previously been saved or unexpected error
|
||||
* occurs
|
||||
*/
|
||||
@Override
|
||||
public ImaBlacklistRecord saveRecord(final ImaBlacklistRecord record)
|
||||
throws ImaBaselineRecordManagerException {
|
||||
LOGGER.debug("saving ima baseline record: {}", record);
|
||||
|
||||
//When adding a record through the manager, the record should be associated with a baseline
|
||||
if (record == null || record.getBaseline() == null) {
|
||||
throw new ImaBaselineRecordManagerException("Record cannot be saved without setting"
|
||||
+ " baseline.");
|
||||
}
|
||||
|
||||
try {
|
||||
//Checks to make sure a duplicate record does not already exist in the baseline. This
|
||||
//is done in this fashion due to the inability to put constraints on the table.
|
||||
if (getRecord(record.getPath(), record.getHash(),
|
||||
(ImaBlacklistBaseline) record.getBaseline()) != null) {
|
||||
throw new ImaBaselineRecordManagerException("Record already exists.");
|
||||
} else {
|
||||
return super.save(record);
|
||||
}
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an <code>ImaBlacklistRecord</code> based on the id of the record.
|
||||
*
|
||||
* @param id
|
||||
* id of the <code>ImaBlacklistRecord</code>
|
||||
* @return
|
||||
* instance of the requested <code>ImaBlacklistRecord</code>
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if the record has previously been saved or unexpected error occurs
|
||||
*/
|
||||
@Override
|
||||
public ImaBlacklistRecord getRecord(final long id) throws ImaBaselineRecordManagerException {
|
||||
LOGGER.debug("getting baseline: {}", id);
|
||||
try {
|
||||
return super.get(id);
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves <code>ImaBlacklistRecord</code> with the given path, hash, and assigned IMA
|
||||
* baseline id.
|
||||
*
|
||||
* @param path
|
||||
* path of the record to be retrieved
|
||||
* @param hash
|
||||
* hash of the record to be retrieved
|
||||
* @param baseline
|
||||
* baseline that is associated with the desired record.
|
||||
* @return
|
||||
* ImaBlacklistRecord that matches the provided path, hash, and baseline ID
|
||||
*/
|
||||
private ImaBlacklistRecord getRecord(final String path, final OptionalDigest hash,
|
||||
final ImaBlacklistBaseline baseline) {
|
||||
LOGGER.debug("Getting object list");
|
||||
|
||||
if (path == null || hash == null || baseline == null) {
|
||||
LOGGER.error("path, hash, or baseline was null");
|
||||
return null;
|
||||
}
|
||||
|
||||
ImaBlacklistRecord record = null;
|
||||
Transaction tx = null;
|
||||
Session session = getFactory().getCurrentSession();
|
||||
try {
|
||||
tx = session.beginTransaction();
|
||||
record = (ImaBlacklistRecord) session.createCriteria(ImaBlacklistRecord.class)
|
||||
.add(Restrictions.eq("path", path))
|
||||
.add(Restrictions.eq("hash", hash))
|
||||
.add(Restrictions.eq("baseline", baseline))
|
||||
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).uniqueResult();
|
||||
tx.commit();
|
||||
LOGGER.debug("Retrieved record object");
|
||||
} catch (HibernateException e) {
|
||||
LOGGER.error("Unable to retrieve record", e);
|
||||
if (tx != null) {
|
||||
LOGGER.debug("Rolling back transaction");
|
||||
tx.rollback();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves <code>ImaBlacklistRecord</code> with the given path, hash, and assigned IMA
|
||||
* baseline id.
|
||||
*
|
||||
* @param path
|
||||
* path of the record to be retrieved
|
||||
* @param hash
|
||||
* hash of the record to be retrieved
|
||||
* @param baseline
|
||||
* baseline that is associated with the desired record.
|
||||
* @return
|
||||
* ImaBlacklistRecord that matches the provided path, hash, and baseline ID
|
||||
*/
|
||||
@Override
|
||||
public ImaBlacklistRecord getRecord(final String path, final Digest hash,
|
||||
final ImaBlacklistBaseline baseline) {
|
||||
OptionalDigest optionalDigest = null;
|
||||
if (hash != null) {
|
||||
optionalDigest = hash.asOptionalDigest();
|
||||
}
|
||||
return getRecord(path, optionalDigest, baseline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> identified by <code>id</code>. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
* <p>
|
||||
* Will likely be used to delete records of a <code>ImaBlacklistBaseline</code> Other IMA
|
||||
* baselines would not be controlled by the user at this time.
|
||||
*
|
||||
* @param id
|
||||
* id of the <code>ImaBaselineRecord</code> to delete
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if unable to delete the ImaBaselineRecord for any reason other than
|
||||
* not found
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteRecord(final Long id) throws ImaBaselineRecordManagerException {
|
||||
LOGGER.debug("deleting ima baseline record: {}", id);
|
||||
try {
|
||||
return super.delete(id);
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> provided. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
* @param record
|
||||
* record object to be deleted.
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException
|
||||
* if unable to delete the ImaBaselineRecord for any reason other than
|
||||
* not found
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteRecord(final ImaBlacklistRecord record)
|
||||
throws ImaBaselineRecordManagerException {
|
||||
if (record == null || record.getBaseline() == null) {
|
||||
throw new ImaBaselineRecordManagerException("record or baseline of record not set");
|
||||
}
|
||||
LOGGER.debug("deleting ima baseline record: {}", record.getId());
|
||||
try {
|
||||
return super.delete(record);
|
||||
} catch (DBManagerException e) {
|
||||
throw new ImaBaselineRecordManagerException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the {@link ImaBlacklistRecord}s in the given baseline, and calls the given
|
||||
* Callback on each record. If the callback returns a non-null value, the returned value will
|
||||
* be added to a collection, which is returned when iteration is finished.
|
||||
*
|
||||
* @param baseline the baseline whose {@link ImaBlacklistRecord}s we should iterate over
|
||||
* @param callback the callback to run on each record
|
||||
* @param <T> the return type of the callback
|
||||
* @return the total collection of objects returned as results from the given Callback
|
||||
*/
|
||||
public final <T> Collection<T> iterateOverBaselineRecords(
|
||||
final QueryableRecordImaBaseline baseline,
|
||||
final Callback<ImaBlacklistRecord, T> callback) {
|
||||
final Collection<T> allResults = new ConcurrentLinkedQueue<>();
|
||||
Collection<Callable<Void>> tasks = new ArrayList<>();
|
||||
|
||||
int fetchSize;
|
||||
switch (getConfiguredImplementation()) {
|
||||
case MYSQL:
|
||||
fetchSize = Integer.MIN_VALUE;
|
||||
break;
|
||||
case HSQL:
|
||||
default:
|
||||
fetchSize = 1;
|
||||
}
|
||||
|
||||
DBImpl impl = getConfiguredImplementation();
|
||||
if (impl == DBImpl.MYSQL) {
|
||||
// provides a hint to the JDBC connector that records should be streamed
|
||||
fetchSize = Integer.MIN_VALUE;
|
||||
} else if (impl == DBImpl.HSQL) {
|
||||
fetchSize = 1;
|
||||
}
|
||||
|
||||
final AtomicInteger recCounter = new AtomicInteger();
|
||||
for (int i = 0; i < ImaBlacklistRecord.FILENAME_HASH_BUCKET_COUNT; i++) {
|
||||
final int bucket = i;
|
||||
final int finalFetchSize = fetchSize;
|
||||
tasks.add(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
LOGGER.debug(String.format(
|
||||
"IMA record iteration: starting examiner thread %d",
|
||||
bucket
|
||||
));
|
||||
List<T> results = new LinkedList<>();
|
||||
|
||||
StatelessSession statelessSession = getStatelessSession();
|
||||
try {
|
||||
Transaction tx = statelessSession.beginTransaction();
|
||||
Criteria criteria = statelessSession.createCriteria(baseline.getClass());
|
||||
baseline.configureCriteriaForBaselineRecords(criteria, bucket);
|
||||
criteria.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
|
||||
criteria.setReadOnly(true);
|
||||
criteria.setFetchSize(finalFetchSize);
|
||||
ScrollableResults records = criteria.scroll(ScrollMode.FORWARD_ONLY);
|
||||
|
||||
Map entry;
|
||||
ImaBlacklistRecord baselineRecord;
|
||||
while (records.next()) {
|
||||
// get(0) guarantees other rows won't be initialized
|
||||
entry = (Map) records.get(0);
|
||||
String path = (String) entry.get(ImaBlacklistRecord.PATH_FIELD);
|
||||
OptionalDigest digest =
|
||||
(OptionalDigest) entry.get(ImaBlacklistRecord.HASH_FIELD);
|
||||
baselineRecord = new ImaBlacklistRecord(path, digest.asDigest());
|
||||
T result = callback.call(baselineRecord);
|
||||
if (result != null) {
|
||||
results.add(result);
|
||||
}
|
||||
int count = recCounter.incrementAndGet();
|
||||
if (count % LOGGING_INTERVAL == 0) {
|
||||
LOGGER.debug(String.format(
|
||||
"IMA record iteration: examined %d records", count
|
||||
));
|
||||
}
|
||||
}
|
||||
tx.commit();
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
} finally {
|
||||
statelessSession.close();
|
||||
}
|
||||
|
||||
allResults.addAll(results);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
JobExecutor executor = new JobExecutor();
|
||||
Job<Void> job = new Job<>(tasks);
|
||||
executor.scheduleJob(job);
|
||||
|
||||
try {
|
||||
executor.shutdown();
|
||||
} catch (InterruptedException e) {
|
||||
throw new DBManagerException(e);
|
||||
}
|
||||
|
||||
if (job.getState() != Job.State.COMPLETED) {
|
||||
LOGGER.error("Appraisal job finished in state {}", job.getState().toString());
|
||||
for (String s : job.getAllFailures()) {
|
||||
throw new DBManagerException(s);
|
||||
}
|
||||
}
|
||||
|
||||
return allResults;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Class for managing the {@link hirs.data.persist.enums.HealthStatus}
|
||||
* of a {@link hirs.data.persist.Device}.
|
||||
*/
|
||||
public interface DeviceHealthManager {
|
||||
|
||||
/**
|
||||
* Updates the health of a device given the name of the device.
|
||||
*
|
||||
* Finds the latest report for the device. Finds all device state objects for the device to get
|
||||
* additional criterion to use to search for alerts. Device health is updated to UNKNOWN if
|
||||
* there are no previous reports, UNTRUSTED if there are still relevant alerts given the search
|
||||
* criteria, and TRUSTED if there are no relevant alerts.
|
||||
*
|
||||
* @param deviceName name of device
|
||||
*/
|
||||
void updateHealth(String deviceName);
|
||||
|
||||
/**
|
||||
* Updates the health of a device or devices given a list of alerts.
|
||||
*
|
||||
* Useful for updating health after resolving a list of alerts, this method pulls all the
|
||||
* unique device names from the alerts list and calls {@link #updateHealth(String)} for each
|
||||
* device once.
|
||||
*
|
||||
* @param alerts list of alerts
|
||||
*/
|
||||
void updateHealth(List<Alert> alerts);
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Alert;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceState;
|
||||
import hirs.data.persist.enums.HealthStatus;
|
||||
import hirs.data.persist.Report;
|
||||
import hirs.data.persist.ReportSummary;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.criterion.Criterion;
|
||||
import org.hibernate.criterion.Disjunction;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* Implementation class for DeviceHealthManager.
|
||||
*/
|
||||
public class DeviceHealthManagerImpl implements DeviceHealthManager {
|
||||
|
||||
private static final Logger LOGGER = getLogger(DeviceHealthManagerImpl.class);
|
||||
|
||||
@Autowired
|
||||
private DeviceManager deviceManager;
|
||||
|
||||
@Autowired
|
||||
private AlertManager alertManager;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(PersistenceConfiguration.DEVICE_STATE_MANAGER_BEAN_NAME)
|
||||
private DeviceStateManager deviceStateManager;
|
||||
|
||||
@Autowired
|
||||
private ReportSummaryManager reportSummaryManager;
|
||||
|
||||
@Override
|
||||
public void updateHealth(final String deviceName) {
|
||||
|
||||
Device device = deviceManager.getDevice(deviceName);
|
||||
|
||||
if (null == device) {
|
||||
throw new IllegalArgumentException("No device with name: " + deviceName);
|
||||
}
|
||||
|
||||
List<DeviceState> deviceStates = deviceStateManager.getStates(device);
|
||||
Report report = null;
|
||||
try {
|
||||
ReportSummary latestReportSummary =
|
||||
reportSummaryManager.getNewestReport(device.getName());
|
||||
// if there's no (latest) report for this device, set the health to Unknown
|
||||
if (null == latestReportSummary) {
|
||||
LOGGER.warn("No latest report for {}. Setting health status to Unknown", device);
|
||||
device.setHealthStatus(HealthStatus.UNKNOWN);
|
||||
} else {
|
||||
report = latestReportSummary.getReport();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn("Failed to get latest report for {}. "
|
||||
+ "Setting health status to Unknown", device, e);
|
||||
device.setHealthStatus(HealthStatus.UNKNOWN);
|
||||
}
|
||||
|
||||
if (null != report) {
|
||||
Disjunction disjunction = Restrictions.disjunction();
|
||||
boolean hasValidCriterions = false;
|
||||
for (DeviceState state : deviceStates) {
|
||||
Criterion criterion = state.getDeviceTrustAlertCriterion();
|
||||
if (null != criterion) {
|
||||
disjunction.add(criterion);
|
||||
hasValidCriterions = true;
|
||||
}
|
||||
}
|
||||
if (!hasValidCriterions) {
|
||||
disjunction = null;
|
||||
}
|
||||
|
||||
int alertCount = alertManager.getTrustAlertCount(device, report, disjunction);
|
||||
LOGGER.info("Found {} trust alerts for {}", alertCount, device);
|
||||
if (alertCount > 0) {
|
||||
device.setHealthStatus(HealthStatus.UNTRUSTED);
|
||||
} else {
|
||||
device.setHealthStatus(HealthStatus.TRUSTED);
|
||||
}
|
||||
}
|
||||
deviceManager.updateDevice(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHealth(final List<Alert> alerts) {
|
||||
if (alerts == null) {
|
||||
throw new NullPointerException("alert list");
|
||||
}
|
||||
Set<String> deviceNames = new HashSet<>();
|
||||
// get the set of unique device names for these alerts
|
||||
for (Alert alert : alerts) {
|
||||
String deviceName = alert.getDeviceName();
|
||||
if (StringUtils.isNotEmpty(deviceName)) {
|
||||
deviceNames.add(deviceName);
|
||||
}
|
||||
}
|
||||
|
||||
for (String deviceName : deviceNames) {
|
||||
updateHealth(deviceName);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Manages the device state for an appraisal. See {@link DeviceState} for more details.
|
||||
*
|
||||
* @see DeviceState
|
||||
*/
|
||||
public interface DeviceStateManager {
|
||||
|
||||
/**
|
||||
* Stores a new <code>DeviceState</code>. This stores a new <code>DeviceState</code> to be
|
||||
* managed by the <code>DeviceStateManager</code>. If the <code>DeviceState</code> is
|
||||
* successfully saved then a reference to it is returned.
|
||||
*
|
||||
* @param state
|
||||
* state to save
|
||||
* @return reference to saved <code>DeviceState</code>
|
||||
* @throws DeviceStateManagerException
|
||||
* if the Policy has previously been saved or unexpected error occurs
|
||||
*/
|
||||
DeviceState saveState(DeviceState state) throws DeviceStateManagerException;
|
||||
|
||||
/**
|
||||
* Returns the state associated with the <code>Device</code> or null if not found.
|
||||
*
|
||||
* @param device
|
||||
* device
|
||||
* @param clazz
|
||||
* Class to specify which type of <code>DeviceState</code> to retrieve
|
||||
* @return device state for <code>Device</code>
|
||||
* @throws DeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the state
|
||||
*/
|
||||
DeviceState getState(Device device, Class<? extends DeviceState> clazz)
|
||||
throws DeviceStateManagerException;
|
||||
|
||||
/**
|
||||
* Returns a <code>List</code> of the <code>DeviceStates</code> associated with the
|
||||
* <code>Device</code>. If there are no states are associated, an empty list is returned.
|
||||
*
|
||||
* @param device
|
||||
* device
|
||||
* @return list of device states
|
||||
* @throws DeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the states
|
||||
*/
|
||||
List<DeviceState> getStates(Device device) throws DeviceStateManagerException;
|
||||
|
||||
/**
|
||||
* Updates the state for the <code>Device</code>.
|
||||
*
|
||||
* @param state
|
||||
* new state for the <code>Device</code>
|
||||
* @throws DeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the state
|
||||
*/
|
||||
void updateState(DeviceState state) throws DeviceStateManagerException;
|
||||
|
||||
/**
|
||||
* Removes the saved state for the <code>Device</code>. If the device state was successfully
|
||||
* found and removed then true is returned. If there was no device state currently being managed
|
||||
* by this manager then false is returned. If device state is found but unable to be deleted
|
||||
* because of unexpected errors then an <code>DeviceStateManagerException</code> is thrown
|
||||
*
|
||||
* @param device
|
||||
* device whose state is to be removed
|
||||
* @param clazz
|
||||
* Class to specify which type of <code>DeviceState</code> to retrieve
|
||||
* @return true if successfully found state for device and deleted it, otherwise false
|
||||
* @throws DeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the state
|
||||
*/
|
||||
boolean deleteState(Device device, Class<? extends DeviceState> clazz)
|
||||
throws DeviceStateManagerException;
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>DeviceStateManager</code>.
|
||||
*/
|
||||
public class DeviceStateManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1266522688839309858L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>DeviceStateManagerException</code> that has the
|
||||
* message <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
DeviceStateManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>DeviceStateManagerException</code> that wraps the
|
||||
* given <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
DeviceStateManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>DeviceStateManagerException</code> that has the
|
||||
* message <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
DeviceStateManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.IMADeviceState;
|
||||
|
||||
|
||||
/**
|
||||
* Manages the device state for an IMA appraisal. See {@link IMADeviceState} for more details.
|
||||
*
|
||||
* @see IMADeviceState
|
||||
*/
|
||||
public interface IMADeviceStateManager {
|
||||
|
||||
/**
|
||||
* Stores a new <code>IMADeviceState</code>. This stores a new <code>IMADeviceState</code> to be
|
||||
* managed by the <code>IMADeviceStateManager</code>. If the <code>IMADeviceState</code> is
|
||||
* successfully saved then a reference to it is returned.
|
||||
*
|
||||
* @param state
|
||||
* state to save
|
||||
* @return reference to saved <code>IMADeviceState</code>
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if the Policy has previously been saved or unexpected error occurs
|
||||
*/
|
||||
IMADeviceState saveState(IMADeviceState state) throws IMADeviceStateManagerException;
|
||||
|
||||
/**
|
||||
* Returns the state associated with the <code>Device</code> or null if not found.
|
||||
*
|
||||
* @param device
|
||||
* device
|
||||
* @return device state for <code>Device</code>
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the state
|
||||
*/
|
||||
IMADeviceState getState(Device device) throws IMADeviceStateManagerException;
|
||||
|
||||
/**
|
||||
* Updates the state for the <code>Device</code>.
|
||||
*
|
||||
* @param state
|
||||
* new state for the <code>Device</code>
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the state
|
||||
*/
|
||||
void updateState(IMADeviceState state) throws IMADeviceStateManagerException;
|
||||
|
||||
/**
|
||||
* Removes the saved state for the <code>Device</code>. If the device state was successfully
|
||||
* found and removed then true is returned. If there was no device state currently being
|
||||
* managed by this manager then false is returned. If device state is found but unable to be
|
||||
* deleted because of unexpected errors then an <code>IMADeviceStateManagerException</code> is
|
||||
* thrown
|
||||
*
|
||||
* @param device
|
||||
* device whose state is to be removed
|
||||
* @return true if successfully found state for device and deleted it, otherwise false
|
||||
* @throws IMADeviceStateManagerException
|
||||
* if any unexpected errors occur while trying to retrieve the state
|
||||
*/
|
||||
boolean deleteState(Device device) throws IMADeviceStateManagerException;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>IMADeviceStateManageer</code>.
|
||||
*/
|
||||
public class IMADeviceStateManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1266522688839309858L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>IMADeviceStateManagerException</code> that has the
|
||||
* message <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
IMADeviceStateManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>IMADeviceStateManagerException</code> that wraps the
|
||||
* given <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
IMADeviceStateManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>IMADeviceStateManagerException</code> that has the
|
||||
* message <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
IMADeviceStateManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* List of valid IMAMeasurementRecord fields to prevent query injection since parameterization of
|
||||
* field names is not possible in HQL.
|
||||
*/
|
||||
public enum IMARecordField {
|
||||
|
||||
/**
|
||||
* The path associated with the record.
|
||||
*/
|
||||
PATH("path"),
|
||||
|
||||
/**
|
||||
* The hash associated with the record.
|
||||
*/
|
||||
HASH("hash");
|
||||
|
||||
private final String field;
|
||||
|
||||
/**
|
||||
* Constructor for {@link IMARecordField}.
|
||||
* @param field the field
|
||||
*/
|
||||
IMARecordField(final String field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HQL name for the field.
|
||||
*
|
||||
* @return the HQL name for the field.
|
||||
*/
|
||||
public String getHQL() {
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the HQL name of the field to an IMARecordField object.
|
||||
*
|
||||
* @param field the field name to get the value of
|
||||
* @return the DBIMARecordField matching the field name
|
||||
*/
|
||||
public static IMARecordField valueOfHQL(final String field) {
|
||||
for (IMARecordField f : IMARecordField.values()) {
|
||||
if (f.getHQL().equals(field)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No field matched string '" + field + "'.");
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* Scope of a query to search for IMAMeasurementRecords.
|
||||
*/
|
||||
public enum IMARecordScope {
|
||||
|
||||
/**
|
||||
* Scope not limited.
|
||||
*/
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Scope limited to a single report.
|
||||
*/
|
||||
REPORT,
|
||||
|
||||
/**
|
||||
* Scope limited to a single device.
|
||||
*/
|
||||
DEVICE;
|
||||
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.baseline.IMABaselineRecord;
|
||||
import hirs.data.persist.baseline.QueryableRecordImaBaseline;
|
||||
import hirs.data.persist.baseline.SimpleImaBaseline;
|
||||
import hirs.utils.Callback;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A <code>ImaBaselineRecordManager</code> manages <code>IMABaselineRecord</code>s. It has support
|
||||
* for the basic create, read, update, and delete methods.
|
||||
*/
|
||||
public interface ImaBaselineRecordManager {
|
||||
|
||||
/**
|
||||
* Stores a new <code>IMABaselineRecord</code>. This stores a new
|
||||
* <code>IMABaselineRecord</code> to be managed by the <code>IMABaselineRecordManager</code>.
|
||||
* If the <code>IMABaselineRecord</code> is successfully saved then a reference to it is
|
||||
* returned.
|
||||
*
|
||||
* @param record Alert to save
|
||||
* @return reference to saved IMABaselineRecord
|
||||
* @throws ImaBaselineRecordManagerException if the Alert has previously been saved or
|
||||
* unexpected error occurs
|
||||
*/
|
||||
IMABaselineRecord saveRecord(IMABaselineRecord record)
|
||||
throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>IMABaselineRecord</code> identified by <code>id</code>. If
|
||||
* the <code>IMABaselineRecord</code> cannot be found then null is returned.
|
||||
*
|
||||
* @param id id of the <code>IMABaselineRecord</code>
|
||||
* @return <code>IMABaselineRecord</code> whose name is <code>id</code> or null if
|
||||
* not found
|
||||
* @throws ImaBaselineRecordManagerException if unable to retrieve the IMABaselineRecord
|
||||
*/
|
||||
IMABaselineRecord getRecord(long id) throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves <code>IMABaselineRecord</code> with the given path, hash, and assigned IMA
|
||||
* baseline id.
|
||||
*
|
||||
* @param path path of the record to be retrieved
|
||||
* @param hash hash of the record to be retrieved
|
||||
* @param baseline baseline that is associated with the desired record.
|
||||
* @return IMABaselineRecord that matches the provided path, hash, and baseline ID
|
||||
*/
|
||||
IMABaselineRecord getRecord(String path, Digest hash,
|
||||
SimpleImaBaseline baseline);
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> identified by <code>id</code>. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
*
|
||||
* @param id id of the <code>ImaBaselineRecord</code> to delete
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException if unable to delete the ImaBaselineRecord for any
|
||||
* reason other than not found
|
||||
*/
|
||||
boolean deleteRecord(Long id) throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> provided. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
*
|
||||
* @param record record object to be deleted.
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException if unable to delete the ImaBaselineRecord for any
|
||||
* reason other than not found
|
||||
*/
|
||||
boolean deleteRecord(IMABaselineRecord record) throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Iterates over the {@link IMABaselineRecord}s in the given baseline, and calls the given
|
||||
* Callback on each record. If the callback returns a non-null value, the returned value will
|
||||
* be added to a collection, which is returned when iteration is finished.
|
||||
*
|
||||
* @param baseline the baseline whose {@link IMABaselineRecord}s we should iterate over
|
||||
* @param callback the callback to run on each record
|
||||
* @param <T> the return type of the callback
|
||||
* @return the total collection of objects returned as results from the given Callback
|
||||
*/
|
||||
<T> Collection<T> iterateOverBaselineRecords(QueryableRecordImaBaseline baseline,
|
||||
Callback<IMABaselineRecord, T> callback);
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
/**
|
||||
* This class represents an <code>Exception</code> generated by a
|
||||
* <code>ImaBaselineRecordManageer</code>.
|
||||
*/
|
||||
public class ImaBaselineRecordManagerException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 631895376025870284L;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ImaBaselineRecordManagerException</code> that has the message
|
||||
* <code>msg</code>.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
*/
|
||||
ImaBaselineRecordManagerException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ImaBaselineRecordManagerException</code> that wraps the given
|
||||
* <code>Throwable</code>.
|
||||
*
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
ImaBaselineRecordManagerException(final Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ImaBaselineRecordManagerException</code> that has the message
|
||||
* <code>msg</code> and wraps the root cause.
|
||||
*
|
||||
* @param msg
|
||||
* exception message
|
||||
* @param t
|
||||
* root cause
|
||||
*/
|
||||
ImaBaselineRecordManagerException(final String msg, final Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.Digest;
|
||||
import hirs.data.persist.ImaBlacklistRecord;
|
||||
import hirs.data.persist.baseline.QueryableRecordImaBaseline;
|
||||
import hirs.data.persist.baseline.ImaBlacklistBaseline;
|
||||
import hirs.utils.Callback;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A <code>ImaBaselineRecordManager</code> manages <code>ImaBlacklistRecord</code>s. It has support
|
||||
* for the basic create, read, update, and delete methods.
|
||||
*/
|
||||
public interface ImaBlacklistBaselineRecordManager {
|
||||
|
||||
/**
|
||||
* Stores a new <code>ImaBlacklistRecord</code>. This stores a new
|
||||
* <code>ImaBlacklistRecord</code> to be managed by the <code>IMABaselineRecordManager</code>.
|
||||
* If the <code>ImaBlacklistRecord</code> is successfully saved then a reference to it is
|
||||
* returned.
|
||||
*
|
||||
* @param record Alert to save
|
||||
* @return reference to saved ImaBlacklistRecord
|
||||
* @throws ImaBaselineRecordManagerException if the Alert has previously been saved or
|
||||
* unexpected error occurs
|
||||
*/
|
||||
ImaBlacklistRecord saveRecord(ImaBlacklistRecord record)
|
||||
throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves the <code>ImaBlacklistRecord</code> identified by <code>id</code>. If
|
||||
* the <code>ImaBlacklistRecord</code> cannot be found then null is returned.
|
||||
*
|
||||
* @param id id of the <code>ImaBlacklistRecord</code>
|
||||
* @return <code>ImaBlacklistRecord</code> whose name is <code>id</code> or null if
|
||||
* not found
|
||||
* @throws ImaBaselineRecordManagerException if unable to retrieve the ImaBlacklistRecord
|
||||
*/
|
||||
ImaBlacklistRecord getRecord(long id) throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Retrieves <code>ImaBlacklistRecord</code> with the given path, hash, and assigned IMA
|
||||
* baseline id.
|
||||
*
|
||||
* @param path path of the record to be retrieved
|
||||
* @param hash hash of the record to be retrieved
|
||||
* @param baseline baseline that is associated with the desired record.
|
||||
* @return ImaBlacklistRecord that matches the provided path, hash, and baseline ID
|
||||
*/
|
||||
ImaBlacklistRecord getRecord(String path, Digest hash,
|
||||
ImaBlacklistBaseline baseline);
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> identified by <code>id</code>. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
*
|
||||
* @param id id of the <code>ImaBaselineRecord</code> to delete
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException if unable to delete the ImaBaselineRecord for any
|
||||
* reason other than not found
|
||||
*/
|
||||
boolean deleteRecord(Long id) throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Deletes the <code>ImaBaselineRecord</code> provided. If the
|
||||
* <code>ImaBaselineRecord</code> is found and deleted then true is returned,
|
||||
* otherwise false.
|
||||
*
|
||||
* @param record record object to be deleted.
|
||||
* @return true if successfully found and deleted from database, otherwise false
|
||||
* @throws ImaBaselineRecordManagerException if unable to delete the ImaBaselineRecord for any
|
||||
* reason other than not found
|
||||
*/
|
||||
boolean deleteRecord(ImaBlacklistRecord record) throws ImaBaselineRecordManagerException;
|
||||
|
||||
/**
|
||||
* Iterates over the {@link ImaBlacklistRecord}s in the given baseline, and calls the given
|
||||
* Callback on each record. If the callback returns a non-null value, the returned value will
|
||||
* be added to a collection, which is returned when iteration is finished.
|
||||
*
|
||||
* @param baseline the baseline whose {@link ImaBlacklistRecord}s we should iterate over
|
||||
* @param callback the callback to run on each record
|
||||
* @param <T> the return type of the callback
|
||||
* @return the total collection of objects returned as results from the given Callback
|
||||
*/
|
||||
<T> Collection<T> iterateOverBaselineRecords(QueryableRecordImaBaseline baseline,
|
||||
Callback<ImaBlacklistRecord, T> callback);
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.ima.IMABaselineGeneratorException;
|
||||
import hirs.ima.ImaIgnoreSetBaselineGenerator;
|
||||
import hirs.ima.ImaIgnoreSetBaselineGeneratorException;
|
||||
import hirs.ima.ImaBlacklistBaselineGenerator;
|
||||
import hirs.ima.SimpleImaBaselineGenerator;
|
||||
import hirs.tpm.TPMBaselineGenerator;
|
||||
import hirs.tpm.TPMBaselineGeneratorException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* This class imports a baseline from a csv file uploaded to the HIRS portal.
|
||||
*/
|
||||
public final class ImportBaselineCSV {
|
||||
|
||||
/**
|
||||
* private entry so the class isn't invoked.
|
||||
*/
|
||||
private ImportBaselineCSV() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LogManager.getLogger(ImportBaselineCSV.class);
|
||||
|
||||
/**
|
||||
* Imports a new baseline.
|
||||
*
|
||||
* @param name User defined name of baseline
|
||||
* @param inputStream Input stream to the CSV file
|
||||
* @param type Represents the type of Baseline being created (IMA, TPM)
|
||||
* @return create baseline
|
||||
*/
|
||||
public static Baseline createBaseline(final String name, final InputStream inputStream,
|
||||
final String type) {
|
||||
LOGGER.debug("import csv started");
|
||||
|
||||
try (InputStream is = new BufferedInputStream(inputStream)) {
|
||||
Baseline baseline = null;
|
||||
|
||||
// IMA baselines only
|
||||
LOGGER.debug("specified IMA import");
|
||||
if (type.equalsIgnoreCase("IMA")) {
|
||||
final SimpleImaBaselineGenerator imaGenerator = new SimpleImaBaselineGenerator();
|
||||
baseline = imaGenerator.generateBaselineFromCSVFile(name, is);
|
||||
} else if (type.equalsIgnoreCase("Ignore")) {
|
||||
final ImaIgnoreSetBaselineGenerator ignoreGenerator =
|
||||
new ImaIgnoreSetBaselineGenerator();
|
||||
baseline = ignoreGenerator.generateBaselineFromCSVFile(name, is);
|
||||
} else if (type.equalsIgnoreCase("IMABlack")) {
|
||||
baseline = ImaBlacklistBaselineGenerator.generateBaselineFromCSV(name, is);
|
||||
} else if (type.equalsIgnoreCase("TPMWhite")) {
|
||||
final TPMBaselineGenerator tpmGenerator = new TPMBaselineGenerator();
|
||||
baseline = tpmGenerator.generateWhiteListBaselineFromCSVFile(name, is);
|
||||
} else if (type.equalsIgnoreCase("TPMBlack")) {
|
||||
final TPMBaselineGenerator tpmGenerator = new TPMBaselineGenerator();
|
||||
baseline = tpmGenerator.generateBlackListBaselineFromCSVFile(name, is);
|
||||
} else {
|
||||
String error = type + " baseline type not supported";
|
||||
LOGGER.error(error);
|
||||
throw new BaselineManagerException(error);
|
||||
}
|
||||
|
||||
/* CSV files only */
|
||||
LOGGER.debug("importing csv file");
|
||||
return baseline;
|
||||
} catch (IMABaselineGeneratorException e) {
|
||||
throw new RuntimeException("Type mismatch, verify import baseline type", e);
|
||||
} catch (IOException | ParseException | ImaIgnoreSetBaselineGeneratorException
|
||||
| TPMBaselineGeneratorException | BaselineManagerException e) {
|
||||
LOGGER.error("unable to generate baseline", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,16 +7,16 @@ import java.util.Map;
|
||||
/**
|
||||
* Interface defining methods for getting ordered lists from a data source. Includes
|
||||
* properties for sorting, paging, and searching.
|
||||
* @param <T> the record type, T.
|
||||
* @param <AbstractEntity> the record type, AbstractEntity.
|
||||
*/
|
||||
public interface OrderedListQuerier<T> {
|
||||
public interface OrderedListQuerier<AbstractEntity> {
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>T</code>s that are ordered by a column and
|
||||
* direction (ASC, DESC) that is provided by the user. This method helps
|
||||
* support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param clazz class type of <code>T</code>s to search for (may be null to
|
||||
* @param entity class type of <code>T</code>s to search for (may be null to
|
||||
* use Class<T>)
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
@ -30,7 +30,7 @@ public interface OrderedListQuerier<T> {
|
||||
* @throws DBManagerException if unable to create the list
|
||||
*/
|
||||
FilteredRecordsList getOrderedList(
|
||||
Class<? extends T> clazz, String columnToOrder,
|
||||
AbstractEntity entity, String columnToOrder,
|
||||
boolean ascending, int firstResult,
|
||||
int maxResults, String search,
|
||||
Map<String, Boolean> searchableColumns)
|
||||
@ -43,7 +43,7 @@ public interface OrderedListQuerier<T> {
|
||||
* support the server-side processing in the JQuery DataTables. For entities that support
|
||||
* soft-deletes, the returned list does not contain <code>T</code>s that have been soft-deleted.
|
||||
*
|
||||
* @param clazz class type of <code>T</code>s to search for (may be null to
|
||||
* @param entity class type of <code>T</code>s to search for (may be null to
|
||||
* use Class<T>)
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
@ -58,8 +58,8 @@ public interface OrderedListQuerier<T> {
|
||||
* @throws DBManagerException if unable to create the list
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:parameternumber")
|
||||
FilteredRecordsList<T> getOrderedList(
|
||||
Class<? extends T> clazz, String columnToOrder,
|
||||
FilteredRecordsList<AbstractEntity> getOrderedList(
|
||||
AbstractEntity entity, String columnToOrder,
|
||||
boolean ascending, int firstResult,
|
||||
int maxResults, String search,
|
||||
Map<String, Boolean> searchableColumns, CriteriaModifier criteriaModifier)
|
||||
|
@ -20,7 +20,7 @@ import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
|
||||
public class PersistenceConfiguration {
|
||||
|
||||
/**
|
||||
* The bean name to retrieve the default/general implementation of {@link DeviceStateManager}.
|
||||
* The bean name to retrieve the default/general implementation of {@link }.
|
||||
*/
|
||||
public static final String DEVICE_STATE_MANAGER_BEAN_NAME = "general_db_man_bean";
|
||||
|
||||
@ -45,30 +45,6 @@ public class PersistenceConfiguration {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link AlertManager} ready to use.
|
||||
*
|
||||
* @return {@link AlertManager}
|
||||
*/
|
||||
@Bean
|
||||
public AlertManager alertManager() {
|
||||
DBAlertManager manager = new DBAlertManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link BaselineManager} ready to use.
|
||||
*
|
||||
* @return {@link BaselineManager}
|
||||
*/
|
||||
@Bean
|
||||
public BaselineManager baselineManager() {
|
||||
DBBaselineManager manager = new DBBaselineManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PolicyManager} ready to use.
|
||||
*
|
||||
@ -180,41 +156,6 @@ public class PersistenceConfiguration {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DeviceStateManager} ready to use.
|
||||
*
|
||||
* @return {@link DeviceStateManager}
|
||||
*/
|
||||
@Bean(name = DEVICE_STATE_MANAGER_BEAN_NAME)
|
||||
public DeviceStateManager generalDeviceStateManager() {
|
||||
DBDeviceStateManager manager = new DBDeviceStateManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
/**
|
||||
* Creates a {@link IMADeviceStateManager} ready to use.
|
||||
*
|
||||
* @return {@link IMADeviceStateManager}
|
||||
*/
|
||||
@Bean
|
||||
public IMADeviceStateManager imaDeviceStateManager() {
|
||||
DBIMADeviceStateManager manager = new DBIMADeviceStateManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link TPMDeviceStateManager} ready to use.
|
||||
*
|
||||
* @return {@link TPMDeviceStateManager}
|
||||
*/
|
||||
@Bean
|
||||
public TPMDeviceStateManager tpmDeviceStateManager() {
|
||||
DBTPMDeviceStateManager manager = new DBTPMDeviceStateManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ReportRequestStateManager} ready to use.
|
||||
*
|
||||
@ -240,65 +181,6 @@ public class PersistenceConfiguration {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ImaBaselineRecordManager} ready to use.
|
||||
*
|
||||
* @return {@link ImaBaselineRecordManager}
|
||||
*/
|
||||
@Bean
|
||||
public ImaBaselineRecordManager imaBaselineRecordManager() {
|
||||
DbImaBaselineRecordManager manager =
|
||||
new DbImaBaselineRecordManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ImaBlacklistBaselineRecordManager} ready to use.
|
||||
*
|
||||
* @return {@link ImaBlacklistBaselineRecordManager}
|
||||
*/
|
||||
@Bean
|
||||
public ImaBlacklistBaselineRecordManager imaBlacklistBaselineRecordManager() {
|
||||
DbImaBlacklistBaselineRecordManager manager =
|
||||
new DbImaBlacklistBaselineRecordManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link AlertMonitorManager} ready to use.
|
||||
*
|
||||
* @return {@link AlertMonitorManager}
|
||||
*/
|
||||
@Bean
|
||||
public AlertMonitorManager alertMonitorManager() {
|
||||
DBAlertMonitorManager manager = new DBAlertMonitorManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link AlertServiceConfigManager} ready to use.
|
||||
*
|
||||
* @return {@link AlertServiceConfigManager}
|
||||
*/
|
||||
@Bean
|
||||
public AlertServiceConfigManager alertServiceConfigManager() {
|
||||
DBAlertServiceManager manager = new DBAlertServiceManager(sessionFactory.getObject());
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DeviceHealthManager} ready to use.
|
||||
* @return {@link DeviceHealthManager}
|
||||
*/
|
||||
@Bean
|
||||
public DeviceHealthManager deviceHealthManager() {
|
||||
return new DeviceHealthManagerImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link PortalInfoManager} ready to use.
|
||||
*
|
||||
@ -318,7 +200,7 @@ public class PersistenceConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public CrudManager<SupplyChainValidationSummary> supplyChainValidationSummaryManager() {
|
||||
DBManager<SupplyChainValidationSummary> manager = new DBManager<>(
|
||||
DBManager<SupplyChainValidationSummary> manager = new DBManager<SupplyChainValidationSummary>(
|
||||
SupplyChainValidationSummary.class,
|
||||
sessionFactory.getObject()
|
||||
);
|
||||
@ -326,21 +208,6 @@ public class PersistenceConfiguration {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DBManager} for TPM2ProvisionerState persistence, ready for use.
|
||||
*
|
||||
* @return {@link DBManager} for TPM2ProvisionerState
|
||||
*/
|
||||
@Bean
|
||||
public DBManager<TPM2ProvisionerState> tpm2ProvisionerStateDBManager() {
|
||||
DBManager<TPM2ProvisionerState> manager = new DBManager<>(
|
||||
TPM2ProvisionerState.class,
|
||||
sessionFactory.getObject()
|
||||
);
|
||||
setDbManagerRetrySettings(manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the spring-wired retry template settings to the db manager.
|
||||
* @param dbManager the manager to apply the retry settings to
|
||||
|
@ -1,7 +1,6 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.appraiser.Appraiser;
|
||||
import hirs.data.persist.baseline.Baseline;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.Policy;
|
||||
@ -59,18 +58,6 @@ public interface PolicyManager {
|
||||
List<Policy> getPolicyList(Class<? extends Policy> clazz)
|
||||
throws PolicyManagerException;
|
||||
|
||||
/**
|
||||
* Return a list of all the policies that contain the given baseline.
|
||||
*
|
||||
* @param clazz the class of Policy to search
|
||||
* @param baseline the baseline that should be a member of returned Policies
|
||||
* @return the list of matching Policies
|
||||
*/
|
||||
List<Policy> getPoliciesContainingBaseline(
|
||||
Class<? extends Policy> clazz,
|
||||
Baseline baseline
|
||||
);
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Policy</code> identified by <code>name</code>. If
|
||||
* the <code>Policy</code> cannot be found then null is returned.
|
||||
|
@ -1,10 +1,8 @@
|
||||
package hirs.persist;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.data.persist.ReportSummary;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@ -67,29 +65,6 @@ public interface ReportSummaryManager {
|
||||
List<ReportSummary> getReportSummaryListByHostname(String hostname)
|
||||
throws ReportSummaryManagerException;
|
||||
|
||||
/**
|
||||
* Returns a list of all <code>ReportSummary</code> objects that are ordered
|
||||
* by a column and direction (ASC, DESC) that is provided by the user. This
|
||||
* method helps support the server-side processing in the JQuery DataTables.
|
||||
*
|
||||
* @param columnToOrder Column to be ordered
|
||||
* @param ascending direction of sort
|
||||
* @param firstResult starting point of first result in set
|
||||
* @param maxResults total number we want returned for display in table
|
||||
* @param search string of criteria to be matched to visible columns
|
||||
* @param searchableColumns Map of String and boolean values with column
|
||||
* headers and whether they are to. Boolean is true if field provides
|
||||
* a typical String that can be searched by Hibernate without
|
||||
* transformation.
|
||||
* @param hostname name of the device to filter on
|
||||
* @return FilteredRecordsList object with fields for DataTables
|
||||
* @throws ReportSummaryManagerException if unable to create the list
|
||||
*/
|
||||
FilteredRecordsList<ReportSummary> getOrderedReportSummaryList(
|
||||
String columnToOrder, boolean ascending, int firstResult,
|
||||
int maxResults, String search,
|
||||
Map<String, Boolean> searchableColumns,
|
||||
String hostname) throws ReportSummaryManagerException;
|
||||
/**
|
||||
* Retrieves the <code>ReportSummary</code> identified by <code>id</code>.
|
||||
* If the <code>ReportSummary</code> cannot be found then null is returned.
|
||||
|
@ -9,13 +9,7 @@ import hirs.appraiser.IMAAppraiser;
|
||||
import hirs.appraiser.TPMAppraiser;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.HIRSPolicy;
|
||||
import hirs.data.persist.IMAPolicy;
|
||||
import hirs.data.persist.baseline.ImaAcceptableRecordBaseline;
|
||||
import hirs.data.persist.baseline.ImaIgnoreSetBaseline;
|
||||
import hirs.data.persist.Policy;
|
||||
import hirs.data.persist.baseline.SimpleImaBaseline;
|
||||
import hirs.data.persist.TPMPolicy;
|
||||
import hirs.data.persist.baseline.TpmWhiteListBaseline;
|
||||
import hirs.utils.HIRSProfiles;
|
||||
import hirs.utils.SpringContextProvider;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@ -25,7 +19,6 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
|
||||
import hirs.alert.ManagedAlertService;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@ -72,7 +65,6 @@ public final class SystemInit {
|
||||
scanner.addIncludeFilter(new AssignableTypeFilter(AppraiserPlugin.class));
|
||||
scanner.addIncludeFilter(new AssignableTypeFilter(SpringContextProvider.class));
|
||||
scanner.addIncludeFilter(new AssignableTypeFilter(AppraiserPluginManager.class));
|
||||
scanner.addIncludeFilter(new AssignableTypeFilter(ManagedAlertService.class));
|
||||
|
||||
// scan for appraiser plugins
|
||||
int registeredBeanCount = scanner.scan("hirs");
|
||||
@ -90,8 +82,6 @@ public final class SystemInit {
|
||||
final DeviceGroupManager deviceGroupManager = new DBDeviceGroupManager(sessionFactory);
|
||||
final AppraiserManager appraiserManager = new DBAppraiserManager(sessionFactory);
|
||||
final PolicyManager policyManager = new DBPolicyManager(sessionFactory);
|
||||
final BaselineManager baselineManager = new DBBaselineManager(sessionFactory);
|
||||
final DBAlertServiceManager alertServiceManager = new DBAlertServiceManager(sessionFactory);
|
||||
|
||||
// save the default group
|
||||
LOGGER.info("Checking for default device group...");
|
||||
@ -198,62 +188,6 @@ public final class SystemInit {
|
||||
LOGGER.info("HIRS policy found.");
|
||||
}
|
||||
|
||||
// initiate the default ima policy
|
||||
LOGGER.info("Checking for IMA policy...");
|
||||
IMAPolicy imaPolicy = (IMAPolicy) policyManager.getPolicy(IMA_POLICY_NAME);
|
||||
if (imaPolicy == null) {
|
||||
LOGGER.info("IMA policy not found, creating...");
|
||||
imaPolicy = new IMAPolicy(IMA_POLICY_NAME);
|
||||
imaPolicy.setFailOnUnknowns(false);
|
||||
imaPolicy.setWhitelist((ImaAcceptableRecordBaseline) baselineManager.saveBaseline(
|
||||
new SimpleImaBaseline("Test Policy Baseline")));
|
||||
imaPolicy.setRequiredSet((ImaAcceptableRecordBaseline) baselineManager.saveBaseline(
|
||||
new SimpleImaBaseline("Test Policy Required Set")));
|
||||
imaPolicy.setImaIgnoreSetBaseline((ImaIgnoreSetBaseline) baselineManager.saveBaseline(
|
||||
new ImaIgnoreSetBaseline("Test Policy Ignore Set")));
|
||||
imaPolicy = (IMAPolicy) policyManager.savePolicy(imaPolicy);
|
||||
policyManager.setDefaultPolicy(imaApp, imaPolicy);
|
||||
} else {
|
||||
LOGGER.info("IMA policy found.");
|
||||
}
|
||||
|
||||
// initiate the default tpm policy
|
||||
LOGGER.info("Checking for TPM policy...");
|
||||
TPMPolicy tpmPolicy = (TPMPolicy) policyManager.getPolicy(TPM_POLICY_NAME);
|
||||
if (tpmPolicy == null) {
|
||||
LOGGER.info("TPM policy not found, creating...");
|
||||
tpmPolicy = new TPMPolicy(TPM_POLICY_NAME);
|
||||
tpmPolicy.setAppraiseFullReport(true);
|
||||
tpmPolicy.setAppraisePcrMask(NONE_MASK);
|
||||
tpmPolicy.setDefaultPcrAppraisalValues();
|
||||
tpmPolicy.setReportPcrMask(ALL_MASK);
|
||||
tpmPolicy.setTpmWhiteListBaseline((TpmWhiteListBaseline) baselineManager.saveBaseline(
|
||||
new TpmWhiteListBaseline("Test TPM White List Baseline")));
|
||||
tpmPolicy = (TPMPolicy) policyManager.savePolicy(tpmPolicy);
|
||||
policyManager.setDefaultPolicy(tpmApp, tpmPolicy);
|
||||
} else {
|
||||
LOGGER.info("TPM policy found.");
|
||||
}
|
||||
|
||||
// ensure all alert services are created
|
||||
LOGGER.info("Checking for alert services...");
|
||||
LOGGER.info(String.format("Checking for presence of %d alert services.",
|
||||
context.getBeansOfType(ManagedAlertService.class).size())
|
||||
);
|
||||
|
||||
for (ManagedAlertService alertService
|
||||
: context.getBeansOfType(ManagedAlertService.class).values()) {
|
||||
String alertServiceName = alertService.getName();
|
||||
if (alertServiceManager.getAlertServiceConfig(alertServiceName) == null) {
|
||||
LOGGER.info(
|
||||
String.format("%s alert services not found; creating.", alertServiceName)
|
||||
);
|
||||
alertService.persist(alertServiceManager);
|
||||
} else {
|
||||
LOGGER.info(String.format("%s alert service found.", alertServiceName));
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("Complete.");
|
||||
}
|
||||
}
|
||||
|
@ -1,116 +0,0 @@
|
||||
package hirs.persist;
|
||||
|
||||
|
||||
import org.bouncycastle.util.Arrays;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Lob;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* This class is for saving the Identity Claim and the Nonce between the two passes of the
|
||||
* TPM 2.0 Provisioner.
|
||||
*/
|
||||
@Entity
|
||||
public class TPM2ProvisionerState {
|
||||
private static final int MAX_BLOB_SIZE = 65535;
|
||||
|
||||
@Id
|
||||
private Long firstPartOfNonce;
|
||||
|
||||
@Column(nullable = false)
|
||||
private byte[] nonce;
|
||||
|
||||
@Lob
|
||||
@Column(nullable = false, length = MAX_BLOB_SIZE)
|
||||
private byte[] identityClaim;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Date timestamp = new Date();
|
||||
|
||||
/**
|
||||
* 0-argument constructor for Hibernate use.
|
||||
*/
|
||||
protected TPM2ProvisionerState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param nonce the nonce
|
||||
* @param identityClaim the identity claim
|
||||
*/
|
||||
public TPM2ProvisionerState(final byte[] nonce, final byte[] identityClaim) {
|
||||
if (nonce == null) {
|
||||
throw new IllegalArgumentException("Nonce should not be null");
|
||||
}
|
||||
|
||||
if (identityClaim == null) {
|
||||
throw new IllegalArgumentException("Identity Claim should not be null");
|
||||
}
|
||||
|
||||
if (nonce.length < Long.BYTES) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Nonce must be larger than 8 bytes. (Received %d.)",
|
||||
nonce.length));
|
||||
}
|
||||
|
||||
this.nonce = Arrays.clone(nonce);
|
||||
this.identityClaim = Arrays.clone(identityClaim);
|
||||
|
||||
try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(nonce))) {
|
||||
firstPartOfNonce = dis.readLong();
|
||||
} catch (IOException e) {
|
||||
// This would only happen if there were not enough bytes; that is handled above.
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the nonce.
|
||||
*
|
||||
* @return the nonce
|
||||
*/
|
||||
public byte[] getNonce() {
|
||||
return Arrays.clone(nonce);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the identity claim.
|
||||
*
|
||||
* @return the identity claim
|
||||
*/
|
||||
public byte[] getIdentityClaim() {
|
||||
return Arrays.clone(identityClaim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for finding the {@link TPM2ProvisionerState} associated with the nonce.
|
||||
*
|
||||
* @param crudManager the {@link CrudManager} to use when looking for the
|
||||
* {@link TPM2ProvisionerState}
|
||||
* @param nonce the nonce to use as the key for the {@link TPM2ProvisionerState}
|
||||
* @return the {@link TPM2ProvisionerState} associated with the nonce;
|
||||
* null if a match is not found
|
||||
*/
|
||||
public static TPM2ProvisionerState getTPM2ProvisionerState(
|
||||
final CrudManager<TPM2ProvisionerState> crudManager,
|
||||
final byte[] nonce) {
|
||||
try (DataInputStream dis
|
||||
= new DataInputStream(new ByteArrayInputStream(nonce))) {
|
||||
long firstPartOfNonce = dis.readLong();
|
||||
TPM2ProvisionerState stateFound = crudManager.get(firstPartOfNonce);
|
||||
if (Arrays.areEqual(stateFound.getNonce(), nonce)) {
|
||||
return stateFound;
|
||||
}
|
||||
} catch (IOException | NullPointerException e) {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user