mirror of
https://github.com/nsacyber/HIRS.git
synced 2024-12-19 21:17:59 +00:00
This is a complete refactor. This uses Hibernate 6, Springboot Framework
3, Java 17, Jakarta
This commit is contained in:
parent
d18dc60adb
commit
72aa426018
@ -1,89 +0,0 @@
|
||||
apply plugin: 'war'
|
||||
apply plugin: 'checkstyle'
|
||||
|
||||
evaluationDependsOn(':HIRS_Utils')
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
dependencies {
|
||||
compile project(':TPM_Utils')
|
||||
compile project(':HIRS_Structs')
|
||||
compile project(':HIRS_Utils')
|
||||
|
||||
compile libs.bouncy_castle
|
||||
compile libs.commons_codec
|
||||
compile libs.commons_lang
|
||||
compile libs.spring_webmvc
|
||||
compile libs.log4j2
|
||||
compile libs.log4j2_web
|
||||
compile libs.protobuf_java
|
||||
|
||||
providedCompile libs.servlet_api
|
||||
|
||||
testCompile project(':HIRS_Utils').sourceSets.test.output
|
||||
testCompile project(':HIRS_Utils').sourceSets.test.resources
|
||||
|
||||
testCompile libs.commons_lang
|
||||
testCompile libs.spring_test
|
||||
testCompile libs.mockito
|
||||
testCompile libs.testng
|
||||
testCompile libs.hsqldb
|
||||
}
|
||||
|
||||
task generateProtoBuf(type:Exec) {
|
||||
workingDir 'config'
|
||||
|
||||
commandLine './genJavaProtoBuf.sh'
|
||||
}
|
||||
|
||||
compileJava.dependsOn generateProtoBuf
|
||||
copyVersion.dependsOn compileJava
|
||||
war.dependsOn copyVersion
|
||||
|
||||
ext.configDir = new File(projectDir, 'config')
|
||||
ext.checkstyleConfigDir = "$configDir/checkstyle"
|
||||
checkstyle {
|
||||
toolVersion = '8.10.1'
|
||||
configFile = checkstyleConfigFile
|
||||
configProperties.put('basedir', checkstyleConfigDir)
|
||||
ignoreFailures = false
|
||||
showViolations = true
|
||||
}
|
||||
|
||||
war {
|
||||
from(buildDir) {
|
||||
include 'VERSION'
|
||||
into 'WEB-INF/classes'
|
||||
}
|
||||
archiveName = 'HIRS_AttestationCA.war'
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
artifactId 'hirs-attestationca'
|
||||
artifact jar
|
||||
pom.withXml {
|
||||
def dependenciesNode = asNode().appendNode('dependencies')
|
||||
|
||||
configurations.runtime.allDependencies.each {
|
||||
if (it.group != null && it.name != null) {
|
||||
def dependencyNode = dependenciesNode.appendNode('dependency')
|
||||
dependencyNode.appendNode('groupId', it.group)
|
||||
dependencyNode.appendNode('artifactId', it.name)
|
||||
dependencyNode.appendNode('version', it.version)
|
||||
|
||||
if (it.excludeRules.size() > 0) {
|
||||
def exclusionsNode = dependencyNode.appendNode('exclusions')
|
||||
it.excludeRules.each { rule ->
|
||||
def exclusionNode = exclusionsNode.appendNode('exclusion')
|
||||
exclusionNode.appendNode('groupId', rule.group)
|
||||
exclusionNode.appendNode('artifactId', rule.module)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||
|
||||
<suppressions>
|
||||
|
||||
<suppress checks="MagicNumber" files=".*[/\\]src[/\\]test[/\\]+" />
|
||||
<suppress checks="FinalParameters" files=".*[/\\]src[/\\]test[/\\]+" />
|
||||
<suppress checks="JavadocPackage" files=".*[/\\]src[/\\]test[/\\]+" />
|
||||
<suppress files="src/main/java/hirs/attestationca/configuration/provisionerTpm2/ProvisionerTpm2\.java" checks="[a-zA-Z0-9]*"/>
|
||||
|
||||
</suppressions>
|
File diff suppressed because it is too large
Load Diff
@ -1,69 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import hirs.appraiser.SupplyChainAppraiser;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.SupplyChainPolicy;
|
||||
import hirs.persist.AppraiserManager;
|
||||
import hirs.persist.DeviceGroupManager;
|
||||
import hirs.persist.PolicyManager;
|
||||
|
||||
import static hirs.attestationca.AbstractAttestationCertificateAuthority.LOG;
|
||||
|
||||
/**
|
||||
* Utility class that simply holds logic to seed the ACA's database with its
|
||||
* default entries.
|
||||
*/
|
||||
public final class AcaDbInit {
|
||||
// prevent construction
|
||||
private AcaDbInit() { }
|
||||
|
||||
/**
|
||||
* Insert the ACA's default entries into the DB. This class is invoked after successful
|
||||
* install of the HIRS_AttestationCA RPM.
|
||||
*
|
||||
* @param appraiserManager the AppraiserManager to use to persist appraisers
|
||||
* @param deviceGroupManager the DeviceGroupManager to use to persist device groups
|
||||
* @param policyManager the PolicyManager to use to persist policies
|
||||
*/
|
||||
public static synchronized void insertDefaultEntries(
|
||||
final AppraiserManager appraiserManager,
|
||||
final DeviceGroupManager deviceGroupManager,
|
||||
final PolicyManager policyManager) {
|
||||
LOG.info("Ensuring default ACA database entries are present.");
|
||||
|
||||
// Ensure the default group exists. It may have already been created by the Server RPM
|
||||
DeviceGroup defaultGroup = deviceGroupManager.getDeviceGroup(DeviceGroup.DEFAULT_GROUP);
|
||||
if (defaultGroup == null) {
|
||||
LOG.info("Default group not found; saving...");
|
||||
defaultGroup = deviceGroupManager.saveDeviceGroup(new DeviceGroup(
|
||||
DeviceGroup.DEFAULT_GROUP,
|
||||
"This is the default group"));
|
||||
LOG.info("Saved default group.");
|
||||
}
|
||||
|
||||
// If the SupplyChainAppraiser exists, do not attempt to re-save the supply chain appraiser
|
||||
// or SupplyChainPolicy
|
||||
SupplyChainAppraiser supplyChainAppraiser = (SupplyChainAppraiser)
|
||||
appraiserManager.getAppraiser(SupplyChainAppraiser.NAME);
|
||||
if (supplyChainAppraiser != null) {
|
||||
LOG.info("Supply chain appraiser is present; not inserting any more entries.");
|
||||
LOG.info("ACA database initialization complete.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the SupplyChainAppraiser
|
||||
LOG.info("Saving supply chain appraiser...");
|
||||
supplyChainAppraiser = (SupplyChainAppraiser)
|
||||
appraiserManager.saveAppraiser(new SupplyChainAppraiser());
|
||||
|
||||
// Create the SupplyChainPolicy
|
||||
LOG.info("Saving default supply chain policy...");
|
||||
SupplyChainPolicy supplyChainPolicy = new SupplyChainPolicy(
|
||||
SupplyChainPolicy.DEFAULT_POLICY);
|
||||
policyManager.savePolicy(supplyChainPolicy);
|
||||
policyManager.setDefaultPolicy(supplyChainAppraiser, supplyChainPolicy);
|
||||
policyManager.setPolicy(supplyChainAppraiser, defaultGroup, supplyChainPolicy);
|
||||
|
||||
LOG.info("ACA database initialization complete.");
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
/**
|
||||
* A simple POJO that will provide a clean error message to clients making
|
||||
* REST requests to the ACA. It is to be serialized to JSON for the return message.
|
||||
*/
|
||||
public class AcaRestError {
|
||||
|
||||
private String error;
|
||||
|
||||
/**
|
||||
* Basic constructor necessary for Jackson JSON serialization to work properly.
|
||||
*/
|
||||
public AcaRestError() {
|
||||
// Don't remove this constructor as it's required for JSON mapping
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameterized constructor for creating this class normally.
|
||||
*
|
||||
* @param error the error message to store in this object
|
||||
*/
|
||||
public AcaRestError(final String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple getter to get the error message stored in this object.
|
||||
*
|
||||
* @return the error message
|
||||
*/
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple setter to get the error message stored in this object.
|
||||
*
|
||||
* @param error the new error message to store in this object
|
||||
*/
|
||||
public void setError(final String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
/**
|
||||
* Defines the responsibilities of the Attestation Certificate Authority.
|
||||
*/
|
||||
public interface AttestationCertificateAuthority {
|
||||
|
||||
/**
|
||||
* The default size for IV blocks.
|
||||
*/
|
||||
int DEFAULT_IV_SIZE = 16;
|
||||
|
||||
/**
|
||||
* Processes a given {@link hirs.structs.elements.aca.IdentityRequestEnvelope} and
|
||||
* generates a {@link hirs.structs.elements.aca.IdentityResponseEnvelope}. In most cases,
|
||||
* a client will generate the request using the TPM "Collate Identity" process.
|
||||
*
|
||||
* @param identityRequest generated during the collate identity process with a Tpm
|
||||
* @return response for the request
|
||||
*/
|
||||
byte[] processIdentityRequest(byte[] identityRequest);
|
||||
|
||||
/**
|
||||
* Processes a given
|
||||
* {@link hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2.IdentityClaim} and
|
||||
* generates a response containing an encrypted nonce to be returned by the client in
|
||||
* a future handshake request.
|
||||
*
|
||||
* @param identityClaim generated during the create identity claim process on a TPM2 Provisioner
|
||||
* @return response for the request
|
||||
*/
|
||||
byte[] processIdentityClaimTpm2(byte[] identityClaim);
|
||||
|
||||
/**
|
||||
* Processes a given
|
||||
* {@link hirs.attestationca.configuration.provisionerTpm2.ProvisionerTpm2.CertificateRequest}
|
||||
* and generates a response containing the signed, public certificate for
|
||||
* the client's desired attestation key, if the correct nonce is supplied.
|
||||
*
|
||||
* @param certificateRequest request containing nonce from earlier identity
|
||||
* claim handshake
|
||||
* @return response for the request
|
||||
*/
|
||||
byte[] processCertificateRequest(byte[] certificateRequest);
|
||||
|
||||
/**
|
||||
* Issues the PK of the ACA public/private key pair.
|
||||
*
|
||||
* @return public key of the attestation certificate authority
|
||||
*/
|
||||
byte[] getPublicKey();
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import hirs.data.persist.certificate.EndorsementCredential;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.DBManagerException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* Utility class which includes credential management functions used by the ACA.
|
||||
*/
|
||||
public final class CredentialManagementHelper {
|
||||
private static final Logger LOG = LogManager.getLogger(CredentialManagementHelper.class);
|
||||
|
||||
private CredentialManagementHelper() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and stores the EK in the cert manager. If the cert is already present and archived,
|
||||
* it is unarchived.
|
||||
* @param certificateManager the certificate manager used for storage
|
||||
* @param endorsementBytes the raw EK bytes used for parsing
|
||||
* @return the parsed, valid EK
|
||||
* @throws IllegalArgumentException if the provided bytes are not a valid EK.
|
||||
*/
|
||||
public static EndorsementCredential storeEndorsementCredential(
|
||||
final CertificateManager certificateManager,
|
||||
final byte[] endorsementBytes) throws IllegalArgumentException {
|
||||
|
||||
if (certificateManager == null) {
|
||||
throw new IllegalArgumentException("null certificate manager");
|
||||
}
|
||||
|
||||
if (endorsementBytes == null) {
|
||||
throw new IllegalArgumentException("null endorsement credential bytes");
|
||||
}
|
||||
|
||||
if (endorsementBytes.length <= 1) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("%d-length byte array given for endorsement credential",
|
||||
endorsementBytes.length)
|
||||
);
|
||||
}
|
||||
|
||||
LOG.info("Parsing Endorsement Credential of length " + endorsementBytes.length);
|
||||
|
||||
EndorsementCredential endorsementCredential;
|
||||
try {
|
||||
endorsementCredential = EndorsementCredential
|
||||
.parseWithPossibleHeader(endorsementBytes);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
LOG.error(iae.getMessage());
|
||||
throw iae;
|
||||
}
|
||||
int certificateHash = endorsementCredential.getCertificateHash();
|
||||
EndorsementCredential existingCredential =
|
||||
EndorsementCredential.select(certificateManager).includeArchived()
|
||||
.byHashCode(certificateHash).getCertificate();
|
||||
if (existingCredential == null) {
|
||||
LOG.info("No Endorsement Credential found with hash: " + certificateHash);
|
||||
return (EndorsementCredential) certificateManager.save(endorsementCredential);
|
||||
} else if (existingCredential.isArchived()) {
|
||||
// if the EK is stored in the DB and it's archived, unarchive.
|
||||
LOG.info("Unarchiving credential");
|
||||
existingCredential.restore();
|
||||
existingCredential.resetCreateTime();
|
||||
certificateManager.update(existingCredential);
|
||||
}
|
||||
return existingCredential;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and stores the PC in the cert manager. If the cert is already present and archived,
|
||||
* it is unarchived.
|
||||
* @param certificateManager the certificate manager used for storage
|
||||
* @param platformBytes the raw PC bytes used for parsing
|
||||
* @return the parsed, valid PC, or null if the provided bytes are not a valid EK.
|
||||
*/
|
||||
public static PlatformCredential storePlatformCredential(
|
||||
final CertificateManager certificateManager,
|
||||
final byte[] platformBytes) {
|
||||
|
||||
if (certificateManager == null) {
|
||||
throw new IllegalArgumentException("null certificate manager");
|
||||
}
|
||||
|
||||
if (platformBytes == null) {
|
||||
throw new IllegalArgumentException("null platform credential bytes");
|
||||
}
|
||||
|
||||
if (platformBytes.length == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"zero-length byte array given for platform credential"
|
||||
);
|
||||
}
|
||||
|
||||
LOG.info("Parsing Platform Credential of length " + platformBytes.length);
|
||||
try {
|
||||
PlatformCredential platformCredential =
|
||||
PlatformCredential.parseWithPossibleHeader(platformBytes);
|
||||
if (platformCredential == null) {
|
||||
return null;
|
||||
}
|
||||
PlatformCredential existingCredential =
|
||||
PlatformCredential.select(certificateManager)
|
||||
.includeArchived()
|
||||
.byHashCode(platformCredential
|
||||
.getCertificateHash())
|
||||
.getCertificate();
|
||||
if (existingCredential == null) {
|
||||
if (platformCredential.getPlatformSerial() != null) {
|
||||
List<PlatformCredential> certificates = PlatformCredential
|
||||
.select(certificateManager)
|
||||
.byBoardSerialNumber(platformCredential.getPlatformSerial())
|
||||
.getCertificates().stream().collect(Collectors.toList());
|
||||
if (!certificates.isEmpty()) {
|
||||
// found associated certificates
|
||||
for (PlatformCredential pc : certificates) {
|
||||
if (pc.isBase() && platformCredential.isBase()) {
|
||||
// found a base in the database associated with
|
||||
// parsed certificate
|
||||
LOG.error(String.format("Base certificate stored"
|
||||
+ " in database with same platform"
|
||||
+ "serial number. (%s)",
|
||||
platformCredential.getPlatformSerial()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (PlatformCredential) certificateManager.save(platformCredential);
|
||||
} else if (existingCredential.isArchived()) {
|
||||
// if the PC is stored in the DB and it's archived, unarchive.
|
||||
LOG.info("Unarchiving credential");
|
||||
existingCredential.restore();
|
||||
certificateManager.update(existingCredential);
|
||||
return existingCredential;
|
||||
}
|
||||
|
||||
return existingCredential;
|
||||
} catch (DBManagerException dbe) {
|
||||
LOG.error("Error retrieving or saving platform credential", dbe);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error parsing platform credential", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import hirs.persist.DBAppraiserManager;
|
||||
import hirs.persist.DBDeviceGroupManager;
|
||||
import hirs.persist.DBPolicyManager;
|
||||
import hirs.persist.PersistenceConfiguration;
|
||||
import hirs.utils.HIRSProfiles;
|
||||
|
||||
/**
|
||||
* Simply holds a contextInitialized method which will be called when the web app starts.
|
||||
*/
|
||||
public class InitializationListener implements ServletContextListener {
|
||||
@Override
|
||||
public void contextInitialized(final ServletContextEvent event) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.getEnvironment().addActiveProfile(HIRSProfiles.SERVER);
|
||||
|
||||
// register the database configuration and refresh the context
|
||||
context.register(PersistenceConfiguration.class);
|
||||
context.refresh();
|
||||
|
||||
// obtain reference to hibernate session factory
|
||||
SessionFactory sessionFactory = context.getBean(LocalSessionFactoryBean.class).getObject();
|
||||
AcaDbInit.insertDefaultEntries(
|
||||
new DBAppraiserManager(sessionFactory),
|
||||
new DBDeviceGroupManager(sessionFactory),
|
||||
new DBPolicyManager(sessionFactory)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(final ServletContextEvent event) {
|
||||
|
||||
}
|
||||
}
|
@ -1,200 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.DERUTF8String;
|
||||
import org.bouncycastle.asn1.x500.AttributeTypeAndValue;
|
||||
import org.bouncycastle.asn1.x500.RDN;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||
import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
|
||||
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.asn1.x509.Extensions;
|
||||
import org.bouncycastle.asn1.x509.GeneralName;
|
||||
import org.bouncycastle.asn1.x509.GeneralNames;
|
||||
import org.bouncycastle.asn1.x509.GeneralNamesBuilder;
|
||||
import org.bouncycastle.asn1.x509.KeyPurposeId;
|
||||
import org.bouncycastle.asn1.x509.TBSCertificate;
|
||||
import org.bouncycastle.asn1.x509.AttributeCertificateInfo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collection;
|
||||
import hirs.data.persist.certificate.EndorsementCredential;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
|
||||
/**
|
||||
* Builds extensions based on Platform and Endorsement credentials to provide in an issued
|
||||
* certificate.
|
||||
*/
|
||||
public final class IssuedCertificateAttributeHelper {
|
||||
|
||||
private static final String TPM_ID_LABEL_OID = "2.23.133.2.15";
|
||||
|
||||
/**
|
||||
* Object Identifier TCPA at TPM ID Label.
|
||||
*/
|
||||
public static final ASN1ObjectIdentifier TCPA_AT_TPM_ID_LABEL =
|
||||
new ASN1ObjectIdentifier(TPM_ID_LABEL_OID);
|
||||
/**
|
||||
* The extended key usage extension.
|
||||
*/
|
||||
public static final Extension EXTENDED_KEY_USAGE_EXTENSION;
|
||||
private static final Logger LOG = LogManager.getLogger(IssuedCertificateAttributeHelper.class);
|
||||
private static final ASN1ObjectIdentifier TCG_KP_AIK_CERTIFICATE_ATTRIBUTE =
|
||||
new ASN1ObjectIdentifier("2.23.133.8.3");
|
||||
|
||||
static {
|
||||
// Generates an extension that identifies a cert as an AIK cert
|
||||
Extension extension = null;
|
||||
try {
|
||||
extension = new Extension(Extension.extendedKeyUsage, true,
|
||||
new ExtendedKeyUsage(new KeyPurposeId[] {
|
||||
KeyPurposeId.getInstance(TCG_KP_AIK_CERTIFICATE_ATTRIBUTE)}).getEncoded());
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error generating extended key usage extension");
|
||||
}
|
||||
EXTENDED_KEY_USAGE_EXTENSION = extension;
|
||||
}
|
||||
|
||||
private IssuedCertificateAttributeHelper() {
|
||||
// do not construct publicly
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds the AKI extension that will be stored in the generated
|
||||
* Attestation Issued Certificate.
|
||||
* @param endorsementCredential EK object to pull AKI from.
|
||||
* @return the AKI extension.
|
||||
* @throws IOException on bad get instance for AKI.
|
||||
*/
|
||||
public static Extension buildAuthorityKeyIdentifier(
|
||||
final EndorsementCredential endorsementCredential) throws IOException {
|
||||
if (endorsementCredential == null || endorsementCredential.getX509Certificate() == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] extValue = endorsementCredential.getX509Certificate()
|
||||
.getExtensionValue(Extension.authorityKeyIdentifier.getId());
|
||||
|
||||
if (extValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] authExtension = ASN1OctetString.getInstance(extValue).getOctets();
|
||||
AuthorityKeyIdentifier aki = AuthorityKeyIdentifier.getInstance(authExtension);
|
||||
|
||||
return new Extension(Extension.authorityKeyIdentifier, true, aki.getEncoded());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the subject alternative name based on the supplied certificates.
|
||||
* @param endorsementCredential the endorsement credential
|
||||
* @param platformCredentials the platform credentials
|
||||
* @param hostName the host name
|
||||
* @return the subject alternative name extension
|
||||
* @throws IOException an IO exception occurs building the extension
|
||||
* @throws IllegalArgumentException if the host name is null
|
||||
*/
|
||||
public static Extension buildSubjectAlternativeNameFromCerts(
|
||||
final EndorsementCredential endorsementCredential,
|
||||
final Collection<PlatformCredential> platformCredentials, final String hostName)
|
||||
throws IOException, IllegalArgumentException {
|
||||
|
||||
if (StringUtils.isEmpty(hostName)) {
|
||||
LOG.error("null host name");
|
||||
throw new IllegalArgumentException("must provide host name");
|
||||
}
|
||||
|
||||
// assemble AIK cert SAN, using info from EC and PC
|
||||
X500NameBuilder nameBuilder = new X500NameBuilder();
|
||||
populateEndorsementCredentialAttributes(endorsementCredential, nameBuilder);
|
||||
if (platformCredentials != null) {
|
||||
for (PlatformCredential platformCredential : platformCredentials) {
|
||||
populatePlatformCredentialAttributes(platformCredential, nameBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
// add the OID for the TCG-required TPM ID label
|
||||
DERUTF8String idLabel = new DERUTF8String(hostName);
|
||||
nameBuilder.addRDN(new AttributeTypeAndValue(TCPA_AT_TPM_ID_LABEL, idLabel));
|
||||
|
||||
// put everything into the SAN, usable by the certificate builder
|
||||
GeneralNamesBuilder genNamesBuilder = new GeneralNamesBuilder();
|
||||
genNamesBuilder.addName(new GeneralName(nameBuilder.build()));
|
||||
DEROctetString sanContent =
|
||||
new DEROctetString(genNamesBuilder.build().getEncoded());
|
||||
Extension subjectAlternativeName = new Extension(Extension.subjectAlternativeName,
|
||||
true, sanContent);
|
||||
|
||||
return subjectAlternativeName;
|
||||
}
|
||||
|
||||
private static void populatePlatformCredentialAttributes(
|
||||
final PlatformCredential platformCredential,
|
||||
final X500NameBuilder nameBuilder) throws IOException {
|
||||
if (platformCredential == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final RDN[] rdns;
|
||||
try {
|
||||
LOG.debug("Applying platform credential attributes to SAN");
|
||||
AttributeCertificateInfo platformCredentialAttributeHolders =
|
||||
platformCredential.getAttributeCertificate().getAcinfo();
|
||||
rdns = ((X500Name) GeneralNames.fromExtensions(
|
||||
platformCredentialAttributeHolders.getExtensions(),
|
||||
Extension.subjectAlternativeName).getNames()[0].getName()).getRDNs();
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOG.error("Unable to extract attributes from platform credential", e);
|
||||
return;
|
||||
}
|
||||
|
||||
populateRdnAttributesInNameBuilder(nameBuilder, rdns);
|
||||
}
|
||||
|
||||
private static void populateEndorsementCredentialAttributes(
|
||||
final EndorsementCredential endorsementCredential, final X500NameBuilder nameBuilder) {
|
||||
if (endorsementCredential == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final RDN[] rdns;
|
||||
try {
|
||||
LOG.debug("Applying endorsement credential attributes to SAN");
|
||||
X509Certificate endorsementX509 = endorsementCredential.getX509Certificate();
|
||||
TBSCertificate tbsCertificate = TBSCertificate.getInstance(
|
||||
endorsementX509.getTBSCertificate());
|
||||
Extensions extensions = tbsCertificate.getExtensions();
|
||||
GeneralNames names = GeneralNames.fromExtensions(extensions,
|
||||
Extension.subjectAlternativeName);
|
||||
if (names != null) {
|
||||
X500Name x500 = (X500Name) names.getNames()[0].getName();
|
||||
rdns = x500.getRDNs();
|
||||
populateRdnAttributesInNameBuilder(nameBuilder, rdns);
|
||||
} else {
|
||||
LOG.error("No RDNs in endorsement credential attributes");
|
||||
return;
|
||||
}
|
||||
} catch (CertificateEncodingException e) {
|
||||
LOG.error("Certificate encoding exception", e);
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error creating x509 cert from endorsement credential", e);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void populateRdnAttributesInNameBuilder(final X500NameBuilder nameBuilder,
|
||||
final RDN[] rdns) {
|
||||
for (final RDN rdn : rdns) {
|
||||
nameBuilder.addRDN(rdn.getTypesAndValues()[0]);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,290 +0,0 @@
|
||||
package hirs.attestationca.configuration;
|
||||
|
||||
import hirs.persist.DBDeviceGroupManager;
|
||||
import hirs.persist.DBDeviceManager;
|
||||
import hirs.persist.DBReferenceDigestManager;
|
||||
import hirs.persist.DBReferenceEventManager;
|
||||
import hirs.persist.DBReferenceManifestManager;
|
||||
import hirs.persist.DeviceGroupManager;
|
||||
import hirs.persist.DeviceManager;
|
||||
import hirs.persist.HibernateConfiguration;
|
||||
import hirs.persist.ReferenceDigestManager;
|
||||
import hirs.persist.ReferenceEventManager;
|
||||
import hirs.persist.ReferenceManifestManager;
|
||||
import hirs.structs.converters.SimpleStructConverter;
|
||||
import hirs.structs.converters.StructConverter;
|
||||
import hirs.utils.LogConfigurationUtil;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.context.annotation.PropertySources;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
|
||||
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Security;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* Provides application context configuration for the Attestation Certificate
|
||||
* Authority application. The properties are processed in order and as such, the
|
||||
* last property file read in will override properties that may had already been
|
||||
* defined previously. In other words, the 'defaults.properties' file provides a
|
||||
* basic standard of properties that can be overrode by the
|
||||
*/
|
||||
@Configuration
|
||||
@PropertySources({
|
||||
@PropertySource(value = "classpath:defaults.properties"),
|
||||
|
||||
// detects if file exists, if not, ignore errors
|
||||
@PropertySource(value = "file:/etc/hirs/aca/aca.properties",
|
||||
ignoreResourceNotFound = true)
|
||||
})
|
||||
@ComponentScan({ "hirs.attestationca", "hirs.attestationca.service", "hirs.attestationca.rest",
|
||||
"hirs.validation", "hirs.data.service" })
|
||||
@Import(HibernateConfiguration.class)
|
||||
@EnableWebMvc
|
||||
public class AttestationCertificateAuthorityConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
private static final Logger LOG
|
||||
= LogManager.getLogger(AttestationCertificateAuthorityConfiguration.class);
|
||||
|
||||
static {
|
||||
try {
|
||||
LogConfigurationUtil.applyConfiguration();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String CLIENT_FILES_PATH = "file:/etc/hirs/aca/client-files/";
|
||||
|
||||
@Value("${aca.directories.certificates}")
|
||||
private String certificatesLocation;
|
||||
|
||||
@Value("${aca.keyStore.location}")
|
||||
private String keyStoreLocation;
|
||||
|
||||
@Value("${aca.keyStore.password:''}")
|
||||
private String keyStorePassword;
|
||||
|
||||
@Value("${aca.keyStore.alias}")
|
||||
private String keyAlias;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Autowired
|
||||
private LocalSessionFactoryBean sessionFactory;
|
||||
|
||||
/**
|
||||
* @return bean to resolve injected annotation.Value property expressions
|
||||
* for beans.
|
||||
*/
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization of the ACA. Detects environment and runs configuration
|
||||
* methods as required. This method is intended to be invoked by the Spring
|
||||
* application context.
|
||||
*/
|
||||
@PostConstruct
|
||||
void initialize() {
|
||||
|
||||
// ensure that Bouncy Castle is registered as a security provider
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
// obtain path to ACA configuration
|
||||
Path certificatesPath = Paths.get(certificatesLocation);
|
||||
|
||||
// create base directories if they do not exist
|
||||
try {
|
||||
Files.createDirectories(certificatesPath);
|
||||
} catch (IOException e) {
|
||||
throw new BeanInitializationException(
|
||||
"Encountered error while initializing ACA directories: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
// create the ACA key store if it doesn't exist
|
||||
Path keyStorePath = Paths.get(keyStoreLocation);
|
||||
if (!Files.exists(keyStorePath)) {
|
||||
throw new IllegalStateException(
|
||||
String.format("ACA Key Store not found at %s. Consult the HIRS User "
|
||||
+ "Guide for ACA installation instructions.", keyStoreLocation));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link PrivateKey} of the ACA
|
||||
*/
|
||||
@Bean
|
||||
public PrivateKey privateKey() {
|
||||
|
||||
// obtain the key store
|
||||
KeyStore keyStore = keyStore();
|
||||
|
||||
try {
|
||||
|
||||
// load the key from the key store
|
||||
PrivateKey acaKey = (PrivateKey) keyStore.getKey(keyAlias,
|
||||
keyStorePassword.toCharArray());
|
||||
|
||||
// break early if the certificate is not available.
|
||||
if (acaKey == null) {
|
||||
throw new BeanInitializationException(String.format("Key with alias "
|
||||
+ "%s was not in KeyStore %s. Ensure that the KeyStore has the "
|
||||
+ "specified certificate. ", keyAlias, keyStoreLocation));
|
||||
}
|
||||
return acaKey;
|
||||
} catch (Exception e) {
|
||||
throw new BeanInitializationException("Encountered error loading ACA private key "
|
||||
+ "from key store: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link X509Certificate} of the ACA
|
||||
*/
|
||||
@Bean
|
||||
public X509Certificate acaCertificate() {
|
||||
KeyStore keyStore = keyStore();
|
||||
|
||||
try {
|
||||
X509Certificate acaCertificate = (X509Certificate) keyStore.getCertificate(keyAlias);
|
||||
|
||||
// break early if the certificate is not available.
|
||||
if (acaCertificate == null) {
|
||||
throw new BeanInitializationException(String.format("Certificate with alias "
|
||||
+ "%s was not in KeyStore %s. Ensure that the KeyStore has the "
|
||||
+ "specified certificate. ", keyAlias, keyStoreLocation));
|
||||
}
|
||||
|
||||
return acaCertificate;
|
||||
} catch (KeyStoreException e) {
|
||||
throw new BeanInitializationException("Encountered error loading ACA certificate "
|
||||
+ "from key store: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link java.security.KeyStore} that contains the certificates
|
||||
* for the ACA.
|
||||
*/
|
||||
@Bean
|
||||
public KeyStore keyStore() {
|
||||
Path keyStorePath = Paths.get(keyStoreLocation);
|
||||
|
||||
// attempt to open the key store. if that fails, log a meaningful message before failing.
|
||||
try {
|
||||
KeyStore keyStore = KeyStore.getInstance("JKS");
|
||||
keyStore.load(Files.newInputStream(keyStorePath), keyStorePassword.toCharArray());
|
||||
return keyStore;
|
||||
} catch (Exception e) {
|
||||
LOG.error(String.format(
|
||||
"Encountered error while loading ACA key store. The most common issue is "
|
||||
+ "that configured password does not work on the configured key"
|
||||
+ " store %s.", keyStorePath));
|
||||
LOG.error(String.format("Exception message: %s", e.getMessage()));
|
||||
throw new BeanInitializationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prototyped {@link StructConverter}. In other words, all instances
|
||||
* returned by this method will be configured identically, but subsequent
|
||||
* invocations will return a new instance.
|
||||
*
|
||||
* @return ready to use {@link StructConverter}.
|
||||
*/
|
||||
@Bean
|
||||
@Scope("prototype")
|
||||
public static StructConverter structConverter() {
|
||||
return new SimpleStructConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DeviceGroupManager} ready to use.
|
||||
*
|
||||
* @return {@link DeviceGroupManager}
|
||||
*/
|
||||
@Bean
|
||||
public DeviceGroupManager deviceGroupManager() {
|
||||
return new DBDeviceGroupManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DeviceManager} ready to use.
|
||||
*
|
||||
* @return {@link DeviceManager}
|
||||
*/
|
||||
@Bean
|
||||
public DeviceManager deviceManager() {
|
||||
return new DBDeviceManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ReferenceManifestManager} ready to use.
|
||||
*
|
||||
* @return {@link ReferenceManifestManager}
|
||||
*/
|
||||
@Bean
|
||||
public ReferenceManifestManager referenceManifestManager() {
|
||||
return new DBReferenceManifestManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ReferenceDigestManager} ready to use.
|
||||
*
|
||||
* @return {@link ReferenceDigestManager}
|
||||
*/
|
||||
@Bean
|
||||
public ReferenceDigestManager referenceDigestManager() {
|
||||
return new DBReferenceDigestManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link ReferenceEventManager} ready to use.
|
||||
*
|
||||
* @return {@link ReferenceEventManager}
|
||||
*/
|
||||
@Bean
|
||||
public ReferenceEventManager referenceEventManager() {
|
||||
return new DBReferenceEventManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(final ResourceHandlerRegistry resourceHandlerRegistry) {
|
||||
resourceHandlerRegistry.addResourceHandler("/client-files/**")
|
||||
.addResourceLocations(CLIENT_FILES_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Includes the Spring Framework application context configuration classes.
|
||||
*/
|
||||
package hirs.attestationca.configuration;
|
@ -1,27 +0,0 @@
|
||||
package hirs.attestationca.exceptions;
|
||||
|
||||
/**
|
||||
* Generic exception thrown while a {@link hirs.attestationca.AttestationCertificateAuthority}
|
||||
* is processing a newly created Attestation Certificate for a validated identity.
|
||||
*/
|
||||
public class CertificateProcessingException extends RuntimeException {
|
||||
/**
|
||||
* Constructs a generic instance of this exception using the specified reason.
|
||||
*
|
||||
* @param reason for the exception
|
||||
*/
|
||||
public CertificateProcessingException(final String reason) {
|
||||
super(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a instance of this exception with the specified reason and backing root
|
||||
* exception.
|
||||
*
|
||||
* @param reason for this exception
|
||||
* @param rootException causing this exception
|
||||
*/
|
||||
public CertificateProcessingException(final String reason, final Throwable rootException) {
|
||||
super(reason, rootException);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package hirs.attestationca.exceptions;
|
||||
|
||||
/**
|
||||
* Generic exception thrown while a {@link hirs.attestationca.AttestationCertificateAuthority}
|
||||
* is processing a newly submitted Identity.
|
||||
*/
|
||||
public class IdentityProcessingException extends RuntimeException {
|
||||
/**
|
||||
* Constructs a generic instance of this exception using the specified reason.
|
||||
*
|
||||
* @param reason for the exception
|
||||
*/
|
||||
public IdentityProcessingException(final String reason) {
|
||||
super(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a instance of this exception with the specified reason and backing root
|
||||
* exception.
|
||||
*
|
||||
* @param reason for this exception
|
||||
* @param rootException causing this exception
|
||||
*/
|
||||
public IdentityProcessingException(final String reason, final Throwable rootException) {
|
||||
super(reason, rootException);
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package hirs.attestationca.exceptions;
|
||||
|
||||
/**
|
||||
* Generic exception thrown when a {@link hirs.attestationca.AttestationCertificateAuthority}
|
||||
* encounters an unexpected condition that can't be handled.
|
||||
*/
|
||||
public class UnexpectedServerException extends RuntimeException {
|
||||
/**
|
||||
* Constructs a generic instance of this exception using the specified reason.
|
||||
*
|
||||
* @param reason for the exception
|
||||
*/
|
||||
public UnexpectedServerException(final String reason) {
|
||||
super(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a instance of this exception with the specified reason and backing root
|
||||
* exception.
|
||||
*
|
||||
* @param reason for this exception
|
||||
* @param rootException causing this exception
|
||||
*/
|
||||
public UnexpectedServerException(final String reason, final Throwable rootException) {
|
||||
super(reason, rootException);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Custom exceptions of the {@link hirs.attestationca.AttestationCertificateAuthority}.
|
||||
*/
|
||||
package hirs.attestationca.exceptions;
|
@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Base package that includes common exceptions, interfaces and base implementations for and related
|
||||
* to the ACA.
|
||||
*/
|
||||
package hirs.attestationca;
|
@ -1,72 +0,0 @@
|
||||
package hirs.attestationca.rest;
|
||||
|
||||
import hirs.attestationca.AcaRestError;
|
||||
import hirs.attestationca.exceptions.CertificateProcessingException;
|
||||
import hirs.attestationca.exceptions.IdentityProcessingException;
|
||||
import hirs.attestationca.exceptions.UnexpectedServerException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
|
||||
/**
|
||||
* Handle processing of exceptions for ACA REST API.
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class AttestationCertificateAuthorityExceptionHandler
|
||||
extends ResponseEntityExceptionHandler {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(
|
||||
AttestationCertificateAuthorityExceptionHandler.class);
|
||||
|
||||
/**
|
||||
* Method to handle errors of the type {@link CertificateProcessingException},
|
||||
* {@link IdentityProcessingException}, and {@link IllegalArgumentException}
|
||||
* that are thrown when performing a RESTful operation.
|
||||
*
|
||||
* @param ex exception that was thrown
|
||||
* @param request the web request that started the RESTful operation
|
||||
* @return the response entity that will form the message returned to the client
|
||||
*/
|
||||
@ExceptionHandler({ CertificateProcessingException.class, IdentityProcessingException.class,
|
||||
IllegalArgumentException.class })
|
||||
public final ResponseEntity<Object> handleExpectedExceptions(final Exception ex,
|
||||
final WebRequest request) {
|
||||
LOGGER.error(String.format("The ACA has encountered an expected exception: %s",
|
||||
ex.getMessage()), ex);
|
||||
return handleGeneralException(ex, HttpStatus.BAD_REQUEST, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to handle errors of the type {@link IllegalStateException} and
|
||||
* {@link UnexpectedServerException} that are thrown when performing a RESTful operation.
|
||||
*
|
||||
* @param ex exception that was thrown
|
||||
* @param request the web request that started the RESTful operation
|
||||
* @return the response entity that will form the message returned to the client
|
||||
*/
|
||||
@ExceptionHandler({ IllegalStateException.class, UnexpectedServerException.class })
|
||||
public final ResponseEntity<Object> handleUnexpectedExceptions(final Exception ex,
|
||||
final WebRequest request) {
|
||||
LOGGER.error(String.format("The ACA has encountered an unexpected exception: %s",
|
||||
ex.getMessage()), ex);
|
||||
return handleGeneralException(ex, HttpStatus.INTERNAL_SERVER_ERROR, request);
|
||||
}
|
||||
|
||||
private ResponseEntity<Object> handleGeneralException(final Exception ex,
|
||||
final HttpStatus responseStatus,
|
||||
final WebRequest request) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
|
||||
return handleExceptionInternal(ex, new AcaRestError(ex.getMessage()),
|
||||
headers, responseStatus, request);
|
||||
}
|
||||
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
package hirs.attestationca.rest;
|
||||
|
||||
import hirs.attestationca.AbstractAttestationCertificateAuthority;
|
||||
import hirs.attestationca.service.SupplyChainValidationService;
|
||||
import hirs.data.service.DeviceRegister;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.DBManager;
|
||||
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;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* Restful implementation of the {@link hirs.attestationca.AttestationCertificateAuthority}.
|
||||
* Exposes the ACA methods as REST endpoints.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/")
|
||||
public class RestfulAttestationCertificateAuthority
|
||||
extends AbstractAttestationCertificateAuthority {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param supplyChainValidationService the supply chain service
|
||||
* @param privateKey the ACA private key
|
||||
* @param acaCertificate the ACA certificate
|
||||
* @param structConverter the struct converter
|
||||
* @param certificateManager the certificate manager
|
||||
* @param referenceManifestManager the referenceManifestManager
|
||||
* @param deviceRegister the device register
|
||||
* @param validDays the number of days issued certs are valid
|
||||
* @param deviceManager the device manager
|
||||
* @param tpm2ProvisionerStateDBManager the DBManager for persisting provisioner state
|
||||
* @param referenceDigestManager the reference digest manager
|
||||
* @param referenceEventManager the reference event manager
|
||||
*/
|
||||
@SuppressWarnings({ "checkstyle:parameternumber" })
|
||||
@Autowired
|
||||
public RestfulAttestationCertificateAuthority(
|
||||
final SupplyChainValidationService supplyChainValidationService,
|
||||
final PrivateKey privateKey, final X509Certificate acaCertificate,
|
||||
final StructConverter structConverter,
|
||||
final CertificateManager certificateManager,
|
||||
final ReferenceManifestManager referenceManifestManager,
|
||||
final DeviceRegister deviceRegister,
|
||||
final DeviceManager deviceManager,
|
||||
final DBManager<TPM2ProvisionerState> tpm2ProvisionerStateDBManager,
|
||||
final ReferenceDigestManager referenceDigestManager,
|
||||
final ReferenceEventManager referenceEventManager,
|
||||
@Value("${aca.certificates.validity}") final int validDays) {
|
||||
super(supplyChainValidationService, privateKey, acaCertificate, structConverter,
|
||||
certificateManager, referenceManifestManager,
|
||||
deviceRegister, validDays, deviceManager,
|
||||
tpm2ProvisionerStateDBManager, referenceDigestManager, referenceEventManager);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-javadoc)
|
||||
*
|
||||
* Wrap the {@link AbstractAttestationCertificateAuthority#processIdentityRequest(byte[])}
|
||||
* with a Spring {@link RequestMapping}. Effectively, this method then will allow spring to
|
||||
* serialize and deserialize the request and responses on method invocation and
|
||||
* return, respectively.
|
||||
*/
|
||||
@Override
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/identity-request/process",
|
||||
method = RequestMethod.POST,
|
||||
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public byte[] processIdentityRequest(@RequestBody final byte[] request) {
|
||||
return super.processIdentityRequest(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener for identity requests from TPM 2.0 provisioning.
|
||||
* @param request The request object from the provisioner.
|
||||
* @return The response to the provisioner.
|
||||
*/
|
||||
@Override
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/identity-claim-tpm2/process",
|
||||
method = RequestMethod.POST,
|
||||
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public byte[] processIdentityClaimTpm2(@RequestBody final byte[] request) {
|
||||
return super.processIdentityClaimTpm2(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint for processing certificate requests for TPM 2.0 provisioning.
|
||||
*
|
||||
* @param request The credential request from the client provisioner.
|
||||
* @return The response to the client provisioner.
|
||||
*/
|
||||
@Override
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/request-certificate-tpm2",
|
||||
method = RequestMethod.POST,
|
||||
consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public byte[] processCertificateRequest(@RequestBody final byte[] request) {
|
||||
return super.processCertificateRequest(request);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-javadoc)
|
||||
*
|
||||
* Wrap the {@link AbstractAttestationCertificateAuthority#getPublicKey()} with a Spring
|
||||
* {@link RequestMapping} such that Spring can serialize the certificate to be returned to an
|
||||
* HTTP Request.
|
||||
*/
|
||||
@Override
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/public-key", method = RequestMethod.GET)
|
||||
public byte[] getPublicKey() {
|
||||
return super.getPublicKey();
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* RESTful implementations of the {@link hirs.attestationca.AttestationCertificateAuthority}.
|
||||
*/
|
||||
package hirs.attestationca.rest;
|
@ -1,44 +0,0 @@
|
||||
package hirs.attestationca.service;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.SupplyChainPolicy;
|
||||
import hirs.data.persist.SupplyChainValidationSummary;
|
||||
import hirs.data.persist.certificate.EndorsementCredential;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
|
||||
|
||||
/**
|
||||
* Interface defining a component that will perform supply chain validations, which yields a
|
||||
* {@link SupplyChainValidationSummary}.
|
||||
*/
|
||||
public interface SupplyChainValidationService {
|
||||
/**
|
||||
* The "main" method of supply chain validation. Takes the credentials from an identity
|
||||
* request and validates the supply chain in accordance to the current supply chain
|
||||
* policy.
|
||||
*
|
||||
* @param ec The endorsement credential from the identity request.
|
||||
* @param pc The set of platform credentials from the identity request.
|
||||
* @param device The device to be validated.
|
||||
* @return True if validation is successful, false otherwise.
|
||||
*/
|
||||
SupplyChainValidationSummary validateSupplyChain(EndorsementCredential ec,
|
||||
Set<PlatformCredential> pc,
|
||||
Device device);
|
||||
|
||||
/**
|
||||
* A supplemental method that handles validating just the quote post main validation.
|
||||
*
|
||||
* @param device the associated device.
|
||||
* @return True if validation is successful, false otherwise.
|
||||
*/
|
||||
SupplyChainValidationSummary validateQuote(Device device);
|
||||
|
||||
/**
|
||||
* Allows other service access to the policy information.
|
||||
* @return supply chain policy
|
||||
*/
|
||||
SupplyChainPolicy getPolicy();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Contains the main functionality of the SupplyChainValidationService. Executes the actual
|
||||
* validation based on the current supply chain policy.
|
||||
*/
|
||||
package hirs.attestationca.service;
|
@ -1,12 +0,0 @@
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<!-- Instructs Spring to scan the ACA packages for annotations -->
|
||||
<context:component-scan base-package="hirs.attestationca"/>
|
||||
|
||||
</beans>
|
@ -1,37 +0,0 @@
|
||||
# General notes:
|
||||
# Properties are processed using an expression processor. That said, properties can inherit the
|
||||
# values of other properties.
|
||||
#
|
||||
# In example the processor will resolve the value of aca.both as 'hello world!'.
|
||||
# aca.hello = hello
|
||||
# aca.world = world!
|
||||
# aca.both = ${aca.hello} ${aca.world}
|
||||
#
|
||||
# ACA Directories
|
||||
# root: the root directory of ACA related files
|
||||
# certificates: the directory for ACA certificate files
|
||||
aca.directories.root = /etc/hirs/aca
|
||||
aca.directories.certificates = ${aca.directories.root}/certificates
|
||||
|
||||
# ACA certificate related properties. These are generic properties that apply to the creation of
|
||||
# any certificate that the ACA is responsible for creating.
|
||||
# validity: the number of days that credentials generated by the ACA are valid.
|
||||
aca.certificates.validity = 3652
|
||||
|
||||
# ACA key store properties
|
||||
# alias: the alias to reference the ACA key and certificate by
|
||||
# location: the absolute path to the ACA key store.
|
||||
# password: key store password
|
||||
aca.keyStore.alias = HIRS_ACA_KEY
|
||||
aca.keyStore.location = ${aca.directories.certificates}/keyStore.jks
|
||||
aca.keyStore.password =
|
||||
|
||||
# ACA setup/initialization properties. These properties are used exclusively by the ACA
|
||||
# initialization process. Generally these properties do not need to be modified
|
||||
#
|
||||
# keySize: the default key size of the ACA key pair stored within the trust store
|
||||
# subjectName: the CN of the generate X509 certificate
|
||||
# expiration: the number of days that the generated X509 certificate will expire
|
||||
aca.setup.keyStore.keySize = 2048
|
||||
aca.setup.keyStore.subjectName = HIRS_AttestationCA_Endorsement
|
||||
aca.setup.keyStore.expiration = ${aca.certificates.validity}
|
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration>
|
||||
<Appenders>
|
||||
<Console name="STDOUT" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t @ %C.%M] %-5p : %m%n"/>
|
||||
</Console>
|
||||
<RollingFile name="FILE" fileName="logs/HIRS_AttestationCA.log"
|
||||
filePattern="logs/HIRS_AttestationCA.log-%d{yyyy-MM-dd}-%i.log" >
|
||||
<PatternLayout>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%C.%M] %-5p : %m%n</pattern>
|
||||
</PatternLayout>
|
||||
<Policies>
|
||||
<SizeBasedTriggeringPolicy size="10 MB" />
|
||||
</Policies>
|
||||
<DefaultRolloverStrategy max="10"/>
|
||||
</RollingFile>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level = "WARN">
|
||||
<AppenderRef ref="STDOUT" level="WARN" />
|
||||
<AppenderRef ref="FILE"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
@ -1,8 +0,0 @@
|
||||
#used in the initial setup of the client-files properties files upon WAR deployment
|
||||
|
||||
attestationca.url=https://***replace***:8443/HIRS_AttestationCA
|
||||
attestationca.cert.subjectname=HIRS_AttestationCA
|
||||
attestationca.cert.password=***replace***
|
||||
endorsementca.cert.subjectname=HIRS_AttestationCA_Endorsement
|
||||
cert.validitydays = 3652
|
||||
aik.auth=0000000000000000000000000000000000000000
|
@ -1,43 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
|
||||
version="2.5" metadata-complete="true">
|
||||
|
||||
<display-name>HIRS Attestation Certificate Authority</display-name>
|
||||
|
||||
<!-- Specify the location of the LOG4J file -->
|
||||
<context-param>
|
||||
<param-name>log4j.configurationFile</param-name>
|
||||
<param-value>classpath:log4j2.xml</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- Configure spring to not expose web app root system property -->
|
||||
<context-param>
|
||||
<param-name>log4jExposeWebAppRoot</param-name>
|
||||
<param-value>false</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- Configures the main Spring Servlet that dispatches HTTP requests to Controllers -->
|
||||
<servlet>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath:applicationContext.xml</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
|
||||
<!-- Map all HTTP requests to the dispatcher -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<listener>
|
||||
<listener-class>hirs.attestationca.InitializationListener</listener-class>
|
||||
</listener>
|
||||
|
||||
|
||||
</web-app>
|
@ -1,905 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
import hirs.structs.converters.StructConverter;
|
||||
import hirs.structs.elements.aca.SymmetricAttestation;
|
||||
import hirs.structs.elements.tpm.AsymmetricKeyParams;
|
||||
import hirs.structs.elements.tpm.AsymmetricPublicKey;
|
||||
import hirs.structs.elements.tpm.EncryptionScheme;
|
||||
import hirs.structs.elements.tpm.IdentityProof;
|
||||
import hirs.structs.elements.tpm.IdentityRequest;
|
||||
import hirs.structs.elements.tpm.StorePubKey;
|
||||
import hirs.structs.elements.tpm.SymmetricKey;
|
||||
import hirs.structs.elements.tpm.SymmetricKeyParams;
|
||||
import hirs.structs.elements.tpm.SymmetricSubParams;
|
||||
import hirs.utils.HexUtils;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.asn1.x509.GeneralNames;
|
||||
import org.bouncycastle.asn1.x509.TBSCertificate;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeSuite;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.OAEPParameterSpec;
|
||||
import javax.crypto.spec.PSource;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.Security;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Test suite for {@link AbstractAttestationCertificateAuthority}.
|
||||
*/
|
||||
public class AbstractAttestationCertificateAuthorityTest {
|
||||
|
||||
// object in test
|
||||
private AbstractAttestationCertificateAuthority aca;
|
||||
|
||||
private static final String EK_PUBLIC_PATH = "/tpm2/ek.pub";
|
||||
private static final String AK_PUBLIC_PATH = "/tpm2/ak.pub";
|
||||
private static final String AK_NAME_PATH = "/tpm2/ak.name";
|
||||
private static final String TEST_NONCE_BLOB_PATH = "test/nonce.blob";
|
||||
private static final String EK_MODULUS_HEX = "a3 b5 c2 1c 57 be 40 c4 3c 78 90 0d 00 81 01 78"
|
||||
+ "13 ca 02 ec b6 75 89 60 ca 60 9b 10 b6 b4 d0 0b"
|
||||
+ "4d e4 68 ad 01 a6 91 e2 56 20 5e cf 16 fe 77 ae"
|
||||
+ "1f 13 d7 ac a1 91 0b 68 f6 07 cf c2 4b 5e c1 2c"
|
||||
+ "4c fe 3a c9 62 7e 10 02 5b 33 c8 c2 1a cd 2e 7f"
|
||||
+ "dd 7c 43 ac a9 5f b1 d6 07 56 4f 72 9b 0a 00 6c"
|
||||
+ "f6 8d 23 a1 84 ca c1 7f 5a 8b ef 0e 23 11 90 00"
|
||||
+ "30 f2 99 e9 94 59 c6 b0 fe b2 5c 0c c7 b4 76 69"
|
||||
+ "6c f1 b7 d8 e5 60 d6 61 9f ab 7c 17 ce a4 74 6d"
|
||||
+ "8c cd e6 9e 6e bb 64 52 a7 c3 bf ac 07 e8 5e 3e"
|
||||
+ "ae eb dc c5 95 37 26 6a 5d a6 a2 12 52 fa 03 43"
|
||||
+ "b2 62 2d 87 8c a7 06 8f d6 3f 63 b6 2d 73 c4 9d"
|
||||
+ "9d d6 55 0e bb db b1 eb dd c5 4b 8f c3 17 cb 3b"
|
||||
+ "c3 bf f6 7f 13 44 de 8e d7 b9 f1 a7 15 56 8f 6c"
|
||||
+ "cd f2 4c 86 99 39 19 88 d3 4a 2f 38 c4 c4 37 39"
|
||||
+ "85 6f 41 98 19 14 a4 1f 95 bc 04 ef 74 c2 0d f3";
|
||||
private static final String AK_MODULUS_HEX = "d7 c9 f0 e3 ac 1b 4a 1e 3c 9d 2d 57 02 e9 2a 93"
|
||||
+ "b0 c0 e1 50 af e4 61 11 31 73 a1 96 b8 d6 d2 1c"
|
||||
+ "40 40 c8 a6 46 a4 10 4b d1 06 74 32 f6 e3 8a 55"
|
||||
+ "1e 03 c0 3e cc 75 04 c6 44 88 b6 ad 18 c9 45 65"
|
||||
+ "0d be c5 45 22 bd 24 ad 32 8c be 83 a8 9b 1b d9"
|
||||
+ "e0 c8 d9 ec 14 67 55 1b fe 68 dd c7 f7 33 e4 cd"
|
||||
+ "87 bd ba 9a 07 e7 74 eb 57 ef 80 9c 6d ee f9 35"
|
||||
+ "52 67 36 e2 53 98 46 a5 4e 8f 17 41 8d ff eb bb"
|
||||
+ "9c d2 b4 df 57 f8 7f 31 ef 2e 2d 6e 06 7f 05 ed"
|
||||
+ "3f e9 6f aa b4 b7 5a f9 6d ba ff 2b 5e f7 c1 05"
|
||||
+ "90 68 1f b6 4b 38 67 f7 92 d8 73 51 6e 08 19 ad"
|
||||
+ "ca 35 48 a7 c1 fb cb 01 9a 28 03 c9 fe bb 49 2f"
|
||||
+ "88 3f a1 e7 a8 69 f0 f8 e8 78 db d3 6d c5 80 8d"
|
||||
+ "c2 e4 8a af 4b c2 ac 48 2a 44 63 6e 39 b0 8f dd"
|
||||
+ "e4 b3 a3 f9 2a b1 c8 d9 3d 6b c4 08 b0 16 c4 e7"
|
||||
+ "c7 2f f5 94 c6 43 3e ee 9b 8a da e7 31 d1 54 dd";
|
||||
private static final String AK_NAME_HEX = "00 0b 6e 8f 79 1c 7e 16 96 1b 11 71 65 9c e0 cd"
|
||||
+ "ae 0d 4d aa c5 41 be 58 89 74 67 55 96 c2 5e 38"
|
||||
+ "e2 94";
|
||||
|
||||
// test key pair
|
||||
private KeyPair keyPair;
|
||||
|
||||
/**
|
||||
* Registers bouncy castle as a security provider. Normally the JEE container will handle this,
|
||||
* but since the tests are not instantiating a container, have the unit test runner setup the
|
||||
* provider.
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void setupTests() {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates an anonymous instance of the {@link AbstractAttestationCertificateAuthority}.
|
||||
* This is sufficient as this class does not have any unimplemented or abstract methods.
|
||||
*/
|
||||
@BeforeTest
|
||||
public void setup() {
|
||||
aca = new AbstractAttestationCertificateAuthority(null, keyPair.getPrivate(),
|
||||
null, null, null, null, null, 1,
|
||||
null, null, null, null) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a key pair that can be used by the test suite.
|
||||
*
|
||||
* @throws Exception during key generation
|
||||
*/
|
||||
@BeforeSuite
|
||||
public void suiteSetup() throws Exception {
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(2048);
|
||||
keyPair = keyPairGenerator.generateKeyPair();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#processIdentityRequest(byte[])}
|
||||
* where the byte array is null. Expects an illegal argument exception to be thrown.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testProcessIdentityRequestNullRequest() {
|
||||
aca.processIdentityRequest(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#processIdentityClaimTpm2(byte[])}
|
||||
* where the byte array is null. Expects an illegal argument exception to be thrown.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testProcessIdentityClaimTpm2NullRequest() {
|
||||
aca.processIdentityClaimTpm2(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#getPublicKey()}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetPublicKey() {
|
||||
|
||||
// encoded byte array to be returned by public key
|
||||
byte[] encoded = new byte[]{0, 1, 0, 1, 0};
|
||||
|
||||
// create mocks for testing
|
||||
X509Certificate acaCertificate = mock(X509Certificate.class);
|
||||
PublicKey publicKey = mock(PublicKey.class);
|
||||
|
||||
// assign the aca certificate to the aca
|
||||
ReflectionTestUtils.setField(aca, "acaCertificate", acaCertificate);
|
||||
|
||||
// return a mocked public key
|
||||
when(acaCertificate.getPublicKey()).thenReturn(publicKey);
|
||||
|
||||
// return test byte array
|
||||
when(publicKey.getEncoded()).thenReturn(encoded);
|
||||
|
||||
// assert what the ACA returns is as expected
|
||||
assertEquals(aca.getPublicKey(), encoded);
|
||||
|
||||
// verify mock interactions
|
||||
verify(acaCertificate).getPublicKey();
|
||||
verify(publicKey).getEncoded();
|
||||
|
||||
// verify no other interactions with mocks
|
||||
verifyNoMoreInteractions(acaCertificate, publicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#unwrapIdentityRequest(byte[])}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testUnwrapIdentityRequest() throws Exception {
|
||||
// create a key generator to generate a "shared" secret
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(128);
|
||||
|
||||
// test variables
|
||||
byte[] request = new byte[1];
|
||||
byte[] iv = new byte[16];
|
||||
byte[] asymmetricBlob = new byte[]{1, 2, 3};
|
||||
byte[] symmetricBlob = new byte[]{3, 2, 1};
|
||||
byte[] secretKey = keyGenerator.generateKey().getEncoded();
|
||||
|
||||
// fill the IV with random bytes
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
random.nextBytes(iv);
|
||||
|
||||
// encrypt the asymmetric blob
|
||||
byte[] encryptedAsymmetricBlob =
|
||||
encryptBlob(asymmetricBlob, EncryptionScheme.OAEP.toString());
|
||||
|
||||
// encrypt the symmetric blob
|
||||
byte[] encryptedSymmetricBlob =
|
||||
encryptBlob(symmetricBlob, secretKey, iv, "AES/CBC/PKCS5Padding");
|
||||
|
||||
// create some mocks for the tests
|
||||
IdentityRequest identityRequest = mock(IdentityRequest.class);
|
||||
AsymmetricKeyParams asymmetricKeyParams = mock(AsymmetricKeyParams.class);
|
||||
SymmetricKeyParams symmetricKeyParams = mock(SymmetricKeyParams.class);
|
||||
SymmetricSubParams symmetricSubParams = mock(SymmetricSubParams.class);
|
||||
StructConverter structConverter = mock(StructConverter.class);
|
||||
SymmetricKey symmetricKey = mock(SymmetricKey.class);
|
||||
|
||||
// assign the mocked struct converter to the test object
|
||||
ReflectionTestUtils.setField(aca, "structConverter", structConverter);
|
||||
|
||||
// when converting our test request byte array, return our mocked identity request
|
||||
// when converting our test asymmetric blob to a symmetric key, return the mocked key
|
||||
when(structConverter.convert(request, IdentityRequest.class)).thenReturn(identityRequest);
|
||||
when(structConverter.convert(asymmetricBlob, SymmetricKey.class)).thenReturn(symmetricKey);
|
||||
|
||||
// mock out the identity request by returning other mocks as needed
|
||||
when(identityRequest.getSymmetricAlgorithm()).thenReturn(symmetricKeyParams);
|
||||
when(identityRequest.getAsymmetricAlgorithm()).thenReturn(asymmetricKeyParams);
|
||||
when(identityRequest.getAsymmetricBlob()).thenReturn(encryptedAsymmetricBlob);
|
||||
when(identityRequest.getSymmetricBlob()).thenReturn(encryptedSymmetricBlob);
|
||||
|
||||
// use OAEP encryption scheme when asked
|
||||
when(asymmetricKeyParams.getEncryptionScheme()).thenReturn(
|
||||
(short) EncryptionScheme.OAEP_VALUE);
|
||||
|
||||
// use the mocked sub params when asked
|
||||
when(symmetricKeyParams.getParams()).thenReturn(symmetricSubParams);
|
||||
|
||||
// use the test IV when asked
|
||||
when(symmetricSubParams.getIv()).thenReturn(iv);
|
||||
|
||||
// use the test secret key when asked
|
||||
when(symmetricKey.getKey()).thenReturn(secretKey);
|
||||
|
||||
// perform test
|
||||
byte[] unwrappedRequest = aca.unwrapIdentityRequest(request);
|
||||
|
||||
// verify test results
|
||||
assertEquals(unwrappedRequest, symmetricBlob);
|
||||
|
||||
// verify mock interactions
|
||||
verify(structConverter).convert(request, IdentityRequest.class);
|
||||
verify(structConverter).convert(asymmetricBlob, SymmetricKey.class);
|
||||
verify(identityRequest).getSymmetricAlgorithm();
|
||||
verify(identityRequest).getAsymmetricAlgorithm();
|
||||
verify(identityRequest).getAsymmetricBlob();
|
||||
verify(identityRequest).getSymmetricBlob();
|
||||
verify(asymmetricKeyParams).getEncryptionScheme();
|
||||
verify(symmetricKeyParams, times(2)).getParams();
|
||||
verify(symmetricSubParams).getIv();
|
||||
verify(symmetricKey).getKey();
|
||||
verifyNoMoreInteractions(identityRequest, symmetricKeyParams, symmetricSubParams,
|
||||
asymmetricKeyParams, structConverter, symmetricKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#unwrapIdentityRequest(byte[])}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testUnwrapIdentityRequestNoKeyParams() throws Exception {
|
||||
// create a key generator to generate a "shared" secret
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(128);
|
||||
|
||||
// test variables
|
||||
byte[] request = new byte[1];
|
||||
byte[] iv = new byte[16];
|
||||
byte[] asymmetricBlob = new byte[]{1, 2, 3};
|
||||
byte[] symmetricBlob = new byte[]{3, 2, 1};
|
||||
byte[] secretKey = keyGenerator.generateKey().getEncoded();
|
||||
|
||||
// fill the IV with random bytes
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
random.nextBytes(iv);
|
||||
|
||||
// encrypt the asymmetric blob
|
||||
byte[] encryptedAsymmetricBlob =
|
||||
encryptBlob(asymmetricBlob, EncryptionScheme.OAEP.toString());
|
||||
|
||||
// encrypt the symmetric blob
|
||||
byte[] encryptedSymmetricBlob =
|
||||
encryptBlob(symmetricBlob, secretKey, iv, "AES/CBC/PKCS5Padding");
|
||||
|
||||
// since there is no symmetric key params, put the IV in front of encrypted blob.
|
||||
byte[] totalBlob = ArrayUtils.addAll(iv, encryptedSymmetricBlob);
|
||||
|
||||
// create some mocks for the tests
|
||||
IdentityRequest identityRequest = mock(IdentityRequest.class);
|
||||
AsymmetricKeyParams asymmetricKeyParams = mock(AsymmetricKeyParams.class);
|
||||
StructConverter structConverter = mock(StructConverter.class);
|
||||
SymmetricKey symmetricKey = mock(SymmetricKey.class);
|
||||
|
||||
// assign the mocked struct converter to the test object
|
||||
ReflectionTestUtils.setField(aca, "structConverter", structConverter);
|
||||
|
||||
// when converting our test request byte array, return our mocked identity request
|
||||
// when converting our test asymmetric blob to a symmetric key, return the mocked key
|
||||
when(structConverter.convert(request, IdentityRequest.class)).thenReturn(identityRequest);
|
||||
when(structConverter.convert(asymmetricBlob, SymmetricKey.class)).thenReturn(symmetricKey);
|
||||
|
||||
// mock out the identity request by returning other mocks as needed
|
||||
when(identityRequest.getSymmetricAlgorithm()).thenReturn(null);
|
||||
when(identityRequest.getAsymmetricAlgorithm()).thenReturn(asymmetricKeyParams);
|
||||
when(identityRequest.getAsymmetricBlob()).thenReturn(encryptedAsymmetricBlob);
|
||||
|
||||
// the first request should return IV + encrypted blob. Subsequent requests should return
|
||||
// just the encrypted portion of the blob
|
||||
when(identityRequest.getSymmetricBlob()).thenReturn(totalBlob)
|
||||
.thenReturn(encryptedSymmetricBlob);
|
||||
|
||||
// use OAEP encryption scheme when asked
|
||||
when(asymmetricKeyParams.getEncryptionScheme()).thenReturn(
|
||||
(short) EncryptionScheme.OAEP_VALUE);
|
||||
|
||||
// use the test secret key when asked
|
||||
when(symmetricKey.getKey()).thenReturn(secretKey);
|
||||
|
||||
// perform test
|
||||
byte[] unwrappedRequest = aca.unwrapIdentityRequest(request);
|
||||
|
||||
// verify test results
|
||||
assertEquals(unwrappedRequest, symmetricBlob);
|
||||
|
||||
// verify mock interactions
|
||||
verify(structConverter).convert(request, IdentityRequest.class);
|
||||
verify(structConverter).convert(asymmetricBlob, SymmetricKey.class);
|
||||
verify(identityRequest).getSymmetricAlgorithm();
|
||||
verify(identityRequest).getAsymmetricAlgorithm();
|
||||
verify(identityRequest).getAsymmetricBlob();
|
||||
verify(identityRequest, times(2)).getSymmetricBlob();
|
||||
verify(identityRequest).setSymmetricBlob(encryptedSymmetricBlob);
|
||||
verify(asymmetricKeyParams).getEncryptionScheme();
|
||||
verify(symmetricKey).getKey();
|
||||
verifyNoMoreInteractions(identityRequest, asymmetricKeyParams, structConverter,
|
||||
symmetricKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#decryptAsymmetricBlob(byte[],
|
||||
* EncryptionScheme)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testDecryptAsymmetricBlob() throws Exception {
|
||||
|
||||
// test encryption transformation
|
||||
EncryptionScheme encryptionScheme = EncryptionScheme.PKCS1;
|
||||
|
||||
// test variables
|
||||
byte[] expected = "test".getBytes();
|
||||
|
||||
// encrypt the expected value using same algorithm as the ACA.
|
||||
byte[] encrypted = encryptBlob(expected, encryptionScheme.toString());
|
||||
|
||||
// perform the decryption and assert that the decrypted bytes equal the expected bytes
|
||||
assertEquals(aca.decryptAsymmetricBlob(encrypted, encryptionScheme), expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#decryptSymmetricBlob(
|
||||
* byte[], byte[], byte[], String)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testDecryptSymmetricBlob() throws Exception {
|
||||
// test encryption transformation
|
||||
String transformation = "AES/CBC/PKCS5Padding";
|
||||
|
||||
// test variables
|
||||
byte[] expected = "test".getBytes();
|
||||
|
||||
// create a key generator to generate a "shared" secret
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(128);
|
||||
|
||||
// use some random bytes as the IV to encrypt and subsequently decrypt with
|
||||
byte[] randomBytes = new byte[16];
|
||||
|
||||
// generate the random bytes
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
random.nextBytes(randomBytes);
|
||||
|
||||
// the shared secret
|
||||
byte[] secretKey = keyGenerator.generateKey().getEncoded();
|
||||
|
||||
// encrypt the expected value with the private key being the shared secret
|
||||
byte[] encrypted = encryptBlob(expected, secretKey, randomBytes, transformation);
|
||||
|
||||
// perform the decryption using the generated shared secert, random bytes as an IV, and the
|
||||
// AES CBC transformation for the cipher. then assert the decrypted results are the same
|
||||
// as our expected value.
|
||||
assertEquals(aca.decryptSymmetricBlob(encrypted, secretKey, randomBytes, transformation),
|
||||
expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#generateSymmetricKey()}.
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateSymmetricKey() {
|
||||
// perform the test
|
||||
SymmetricKey symmetricKey = aca.generateSymmetricKey();
|
||||
|
||||
// assert the symmetric algorithm, scheme, and key size are all set appropriately
|
||||
assertTrue(symmetricKey.getAlgorithmId() == 6);
|
||||
assertTrue(symmetricKey.getEncryptionScheme() == 255);
|
||||
assertTrue(symmetricKey.getKeySize() == symmetricKey.getKey().length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#generateAsymmetricContents(
|
||||
* IdentityProof, SymmetricKey, PublicKey)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateAsymmetricContents() throws Exception {
|
||||
|
||||
// mocks for test
|
||||
IdentityProof proof = mock(IdentityProof.class);
|
||||
AsymmetricPublicKey publicKey = mock(AsymmetricPublicKey.class);
|
||||
StructConverter structConverter = mock(StructConverter.class);
|
||||
SymmetricKey symmetricKey = mock(SymmetricKey.class);
|
||||
|
||||
// assign the mocked struct converter to the test object
|
||||
ReflectionTestUtils.setField(aca, "structConverter", structConverter);
|
||||
|
||||
// "encoded" identity proof (returned by struct converter)
|
||||
byte[] identityProofEncoded = new byte[]{0, 0, 1, 1};
|
||||
|
||||
// generate a random session key to be used for encryption and decryption
|
||||
byte[] sessionKey = new byte[16];
|
||||
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
|
||||
random.nextBytes(sessionKey);
|
||||
|
||||
// when requesting the identity key from the proof, return the mocked public key
|
||||
when(proof.getIdentityKey()).thenReturn(publicKey);
|
||||
|
||||
// when requesting to convert the public key, return the encoded identity proof
|
||||
when(structConverter.convert(publicKey)).thenReturn(identityProofEncoded);
|
||||
when(structConverter.convert(symmetricKey)).thenReturn(sessionKey);
|
||||
|
||||
// perform the test
|
||||
byte[] result = aca.generateAsymmetricContents(proof, symmetricKey, keyPair.getPublic());
|
||||
|
||||
// verify mock interactions
|
||||
verify(proof).getIdentityKey();
|
||||
verify(structConverter).convert(publicKey);
|
||||
verify(structConverter).convert(symmetricKey);
|
||||
verifyZeroInteractions(proof, structConverter, publicKey, symmetricKey);
|
||||
|
||||
// decrypt the result
|
||||
byte[] decryptedResult = decryptBlob(result);
|
||||
|
||||
// create a SHA1 digest of the identity key
|
||||
MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
md.update(identityProofEncoded);
|
||||
|
||||
// generate the digest
|
||||
byte[] identityDigest = md.digest();
|
||||
|
||||
// the decrypted asymmetric contents should be the session key and a SHA-1 hash of the
|
||||
// encoded identity proof.
|
||||
byte[] expected = ArrayUtils.addAll(sessionKey, identityDigest);
|
||||
|
||||
// compare the two byte arrays
|
||||
assertEquals(decryptedResult, expected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#generateAttestation(X509Certificate,
|
||||
* SymmetricKey)}.
|
||||
*
|
||||
* @throws Exception during aca processing
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateAttestation() throws Exception {
|
||||
|
||||
// create some mocks for the unit tests
|
||||
X509Certificate certificate = mock(X509Certificate.class);
|
||||
SymmetricKey symmetricKey = mock(SymmetricKey.class);
|
||||
|
||||
// create a key generator to generate a secret key
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(128);
|
||||
|
||||
// obtain the key from the generator
|
||||
byte[] secretKey = keyGenerator.generateKey().getEncoded();
|
||||
|
||||
// use our public key for encryption
|
||||
when(symmetricKey.getKey()).thenReturn(secretKey);
|
||||
|
||||
// just use the existing public key for the credential
|
||||
when(certificate.getEncoded()).thenReturn(keyPair.getPublic().getEncoded());
|
||||
|
||||
// perform the actual test
|
||||
SymmetricAttestation attestation = aca.generateAttestation(certificate, symmetricKey);
|
||||
|
||||
// validate that the attestation is not null
|
||||
assertNotNull(attestation);
|
||||
|
||||
// validate the attestation algorithm
|
||||
assertNotNull(attestation.getAlgorithm());
|
||||
assertTrue(attestation.getAlgorithm().getAlgorithmId() == 6);
|
||||
assertTrue(attestation.getAlgorithm().getEncryptionScheme() == 0x1);
|
||||
assertTrue(attestation.getAlgorithm().getSignatureScheme() == 0);
|
||||
assertTrue(attestation.getAlgorithm().getParamsSize() == 0);
|
||||
|
||||
// validate the attestation credential
|
||||
assertNotNull(attestation.getCredential());
|
||||
|
||||
// validate that the credential size is the size of the actual credential block
|
||||
assertTrue(attestation.getCredential().length == attestation.getCredentialSize());
|
||||
|
||||
// create containers for the 2 parts of the credential
|
||||
byte[] iv = new byte[16];
|
||||
byte[] credential = new byte[attestation.getCredential().length - iv.length];
|
||||
|
||||
// siphon off the first 16 bytes for the IV
|
||||
System.arraycopy(attestation.getCredential(), 0, iv, 0, iv.length);
|
||||
|
||||
// the rest is the actual encrypted credential
|
||||
System.arraycopy(attestation.getCredential(), iv.length, credential, 0, credential.length);
|
||||
|
||||
// decrypt the credential
|
||||
byte[] decrypted = decryptBlob(credential, secretKey, iv, "AES/CBC/PKCS5Padding");
|
||||
|
||||
// assert that the decrypted credential is our public key
|
||||
assertEquals(keyPair.getPublic().getEncoded(), decrypted);
|
||||
|
||||
// verify that the mocks were interacted with appropriately
|
||||
verify(symmetricKey).getKey();
|
||||
verify(certificate).getEncoded();
|
||||
verifyNoMoreInteractions(certificate, symmetricKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#
|
||||
* AbstractAttestationCertificateAuthority(SupplyChainValidationService, PrivateKey,
|
||||
* X509Certificate, StructConverter, CertificateManager, DeviceRegister, int,
|
||||
* DeviceManager, DBManager)}.
|
||||
*
|
||||
* @throws Exception during subject alternative name checking if cert formatting is bad
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateCredential() throws Exception {
|
||||
// test variables
|
||||
final String identityProofLabelString = "label";
|
||||
byte[] identityProofLabel = identityProofLabelString.getBytes();
|
||||
byte[] modulus = ((RSAPublicKey) keyPair.getPublic()).getModulus().toByteArray();
|
||||
X500Principal principal = new X500Principal("CN=TEST, OU=TEST, O=TEST, C=TEST");
|
||||
int validDays = 1;
|
||||
|
||||
// create mocks for testing
|
||||
IdentityProof identityProof = mock(IdentityProof.class);
|
||||
AsymmetricPublicKey asymmetricPublicKey = mock(AsymmetricPublicKey.class);
|
||||
StorePubKey storePubKey = mock(StorePubKey.class);
|
||||
X509Certificate acaCertificate = mock(X509Certificate.class);
|
||||
|
||||
// assign ACA fields
|
||||
ReflectionTestUtils.setField(aca, "validDays", validDays);
|
||||
ReflectionTestUtils.setField(aca, "acaCertificate", acaCertificate);
|
||||
|
||||
// prepare identity proof interactions
|
||||
when(identityProof.getLabel()).thenReturn(identityProofLabel);
|
||||
|
||||
// prepare other mocks
|
||||
when(acaCertificate.getSubjectX500Principal()).thenReturn(principal);
|
||||
when(acaCertificate.getIssuerX500Principal()).thenReturn(principal);
|
||||
|
||||
// perform the test
|
||||
X509Certificate certificate = aca.generateCredential(keyPair.getPublic(),
|
||||
null,
|
||||
new HashSet<PlatformCredential>(),
|
||||
"exampleIdLabel");
|
||||
|
||||
// grab the modulus from the generate certificate
|
||||
byte[] resultMod = ((RSAPublicKey) certificate.getPublicKey()).getModulus().toByteArray();
|
||||
|
||||
// today and tomorrow, when the certificate should be valid for
|
||||
Calendar today = Calendar.getInstance();
|
||||
Calendar tomorrow = Calendar.getInstance();
|
||||
tomorrow.add(Calendar.DATE, 1);
|
||||
|
||||
// validate the certificate
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("CN=TEST"));
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("OU=TEST"));
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("O=TEST"));
|
||||
assertTrue(certificate.getIssuerX500Principal().toString().contains("C=TEST"));
|
||||
|
||||
// validate the format of the subject and subject alternative name
|
||||
assertEquals(certificate.getSubjectX500Principal().getName(), "");
|
||||
assertEquals(((X500Name) GeneralNames.fromExtensions(((TBSCertificate.getInstance(
|
||||
certificate.getTBSCertificate()).getExtensions())), Extension.
|
||||
subjectAlternativeName).getNames()[0].getName()).getRDNs(
|
||||
IssuedCertificateAttributeHelper.TCPA_AT_TPM_ID_LABEL)[0].getFirst()
|
||||
.getValue().toString(), "exampleIdLabel");
|
||||
|
||||
assertEquals(resultMod, modulus);
|
||||
|
||||
// obtain the expiration dates from the certificate
|
||||
Calendar beforeDate = Calendar.getInstance();
|
||||
Calendar afterDate = Calendar.getInstance();
|
||||
beforeDate.setTime(certificate.getNotBefore());
|
||||
afterDate.setTime(certificate.getNotAfter());
|
||||
|
||||
// assert the dates are set correctly
|
||||
assertEquals(beforeDate.get(Calendar.DATE), today.get(Calendar.DATE));
|
||||
assertEquals(afterDate.get(Calendar.DATE), tomorrow.get(Calendar.DATE));
|
||||
|
||||
// validate mock interactions
|
||||
verify(acaCertificate).getSubjectX500Principal();
|
||||
verifyNoMoreInteractions(identityProof, asymmetricPublicKey, storePubKey, acaCertificate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#assemblePublicKey(byte[])}.
|
||||
*/
|
||||
@Test
|
||||
public void testAssemblePublicKeyUsingByteArray() {
|
||||
// obtain the expected modulus from the existing public key
|
||||
final BigInteger modulus = ((RSAPublicKey) keyPair.getPublic()).getModulus();
|
||||
|
||||
// perform test
|
||||
RSAPublicKey publicKey = (RSAPublicKey) aca.assemblePublicKey(modulus.toByteArray());
|
||||
|
||||
// assert that the exponent and the modulus are the same. the exponents should be the well
|
||||
// known prime, 101
|
||||
assertTrue(publicKey.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
assertTrue(publicKey.getModulus().equals(modulus));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests {@link AbstractAttestationCertificateAuthority#assemblePublicKey(String)}.
|
||||
*/
|
||||
@Test
|
||||
public void testAssemblePublicKeyUsingHexEncodedString() {
|
||||
// obtain the expected modulus from the existing public key
|
||||
final BigInteger modulus = ((RSAPublicKey) keyPair.getPublic()).getModulus();
|
||||
|
||||
// encode our existing public key into hex
|
||||
final String modulusString = Hex.encodeHexString(
|
||||
((RSAPublicKey) keyPair.getPublic()).getModulus().toByteArray());
|
||||
|
||||
// perform test
|
||||
RSAPublicKey publicKey = (RSAPublicKey) aca.assemblePublicKey(modulusString);
|
||||
|
||||
// assert that the exponent and the modulus are the same. the exponents should be the well
|
||||
// known prime, 101.
|
||||
assertTrue(publicKey.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
assertTrue(publicKey.getModulus().equals(modulus));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing the EK from the TPM2 output file.
|
||||
* @throws URISyntaxException incorrect resource path
|
||||
* @throws IOException unable to read from file
|
||||
*/
|
||||
@Test
|
||||
public void testParseEk() throws URISyntaxException, IOException {
|
||||
Path ekPath = Paths.get(getClass().getResource(
|
||||
EK_PUBLIC_PATH).toURI());
|
||||
|
||||
byte[] ekFile = Files.readAllBytes(ekPath);
|
||||
|
||||
RSAPublicKey ek = aca.parsePublicKey(ekFile);
|
||||
assertTrue(ek.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
|
||||
byte[] mod = ek.getModulus().toByteArray();
|
||||
// big integer conversion is signed so it can add a 0 byte
|
||||
if (mod[0] == 0) {
|
||||
byte[] tmp = new byte[mod.length - 1];
|
||||
System.arraycopy(mod, 1, tmp, 0, mod.length - 1);
|
||||
mod = tmp;
|
||||
}
|
||||
String hex = HexUtils.byteArrayToHexString(mod);
|
||||
String realMod = EK_MODULUS_HEX.replaceAll("\\s+", "");
|
||||
assertEquals(hex, realMod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing the AK public key from the TPM2 output file.
|
||||
* @throws URISyntaxException incorrect resource path
|
||||
* @throws IOException unable to read from file
|
||||
*/
|
||||
@Test
|
||||
public void testParseAk() throws URISyntaxException, IOException {
|
||||
Path akPath = Paths.get(getClass().getResource(
|
||||
AK_PUBLIC_PATH).toURI());
|
||||
|
||||
byte[] akFile = Files.readAllBytes(akPath);
|
||||
|
||||
RSAPublicKey ak = aca.parsePublicKey(akFile);
|
||||
assertTrue(ak.getPublicExponent().equals(new BigInteger("010001", 16)));
|
||||
|
||||
byte[] mod = ak.getModulus().toByteArray();
|
||||
// big integer conversion is signed so it can add a 0 byte
|
||||
if (mod[0] == 0) {
|
||||
byte[] tmp = new byte[mod.length - 1];
|
||||
System.arraycopy(mod, 1, tmp, 0, mod.length - 1);
|
||||
mod = tmp;
|
||||
}
|
||||
String hex = HexUtils.byteArrayToHexString(mod);
|
||||
String realMod = AK_MODULUS_HEX.replaceAll("\\s+", "");
|
||||
assertEquals(hex, realMod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests parsing the AK name from the TPM2 output file.
|
||||
* @throws URISyntaxException incorrect resource path
|
||||
* @throws IOException unable to read from file
|
||||
* @throws NoSuchAlgorithmException inavlid algorithm
|
||||
*/
|
||||
@Test
|
||||
public void testGenerateAkName() throws URISyntaxException, IOException,
|
||||
NoSuchAlgorithmException {
|
||||
Path akNamePath = Paths.get(getClass().getResource(
|
||||
AK_NAME_PATH).toURI());
|
||||
|
||||
byte[] akNameFileBytes = Files.readAllBytes(akNamePath);
|
||||
String realHex = HexUtils.byteArrayToHexString(akNameFileBytes);
|
||||
|
||||
String realMod = AK_MODULUS_HEX.replaceAll("\\s+", "");
|
||||
byte[] akName = aca.generateAkName(HexUtils.hexStringToByteArray(realMod));
|
||||
|
||||
String hex = HexUtils.byteArrayToHexString(akName);
|
||||
String realName = AK_NAME_HEX.replaceAll("\\s+", "");
|
||||
assertEquals(hex, realName);
|
||||
assertEquals(hex, realHex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to generate a make credential output file for use in manual testing. Feed to
|
||||
* a TPM 2.0 or emulator using the activate credential command to ensure proper parsing.
|
||||
* Must be performed manually. To use, copy the TPM's ek and ak into
|
||||
* HIRS_AttestationCA/src/test/resources/tpm2/test/ and ensure the variables akPubPath
|
||||
* and ekPubPath are correct. Your output file will be
|
||||
* HIRS_AttestationCA/src/test/resources/tpm2/test/make.blob and the nonce used will be
|
||||
* output as HIRS_AttestationCA/src/test/resources/tpm2/test/secret.blob
|
||||
* @throws URISyntaxException invalid file path
|
||||
* @throws IOException unable to read file
|
||||
*/
|
||||
@Test(enabled = false)
|
||||
public void testMakeCredential() throws URISyntaxException, IOException {
|
||||
Path akPubPath = Paths.get(getClass().getResource(
|
||||
AK_PUBLIC_PATH).toURI());
|
||||
Path ekPubPath = Paths.get(getClass().getResource(
|
||||
EK_PUBLIC_PATH).toURI());
|
||||
|
||||
byte[] ekPubFile = Files.readAllBytes(ekPubPath);
|
||||
byte[] akPubFile = Files.readAllBytes(akPubPath);
|
||||
|
||||
RSAPublicKey ekPub = aca.parsePublicKey(ekPubFile);
|
||||
RSAPublicKey akPub = aca.parsePublicKey(akPubFile);
|
||||
|
||||
// prepare the nonce and wrap it with keys
|
||||
byte[] nonce = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
ByteString blob = aca.tpm20MakeCredential(ekPub, akPub, nonce);
|
||||
|
||||
Path resources = Paths.get(getClass().getResource(
|
||||
"/").toURI()).getParent().getParent().getParent().getParent();
|
||||
Path makeBlob = resources.resolve("src/test/resources/tpm2/test/make.blob");
|
||||
Files.write(makeBlob, blob.toByteArray());
|
||||
|
||||
Path secretPath = resources.resolve("src/test/resources/tpm2/test/secret.blob");
|
||||
Files.write(secretPath, nonce);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method that encrypts a blob using the specified transformation and the test key
|
||||
* pair public key.
|
||||
*
|
||||
* @param blob to be encrypted
|
||||
* @param transformation used by a cipher to encrypt
|
||||
* @return encrypted blob
|
||||
* @throws Exception during the encryption process
|
||||
*/
|
||||
private byte[] encryptBlob(byte[] blob, String transformation) throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
|
||||
// use our generated public key to encrypt
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method that encrypts a blob using a shared key and IV using the specified
|
||||
* transformation.
|
||||
*
|
||||
* @param blob to be encrypted
|
||||
* @param key shared key
|
||||
* @param iv to encrypt with
|
||||
* @param transformation of the encryption cipher
|
||||
* @return encrypted blob
|
||||
* @throws Exception
|
||||
*/
|
||||
private byte[] encryptBlob(byte[] blob, byte[] key, byte[] iv, String transformation)
|
||||
throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
|
||||
// generate a secret key specification using the key and AES.
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
|
||||
|
||||
// create IV parameter for key specification
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
|
||||
|
||||
// encrypt using the key specification with the generated IV
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec);
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method to decrypt blobs.
|
||||
*
|
||||
* @param blob to be decrypted
|
||||
* @return decrypted blob
|
||||
* @throws Exception
|
||||
*/
|
||||
private byte[] decryptBlob(byte[] blob) throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(EncryptionScheme.OAEP.toString());
|
||||
|
||||
OAEPParameterSpec spec = new OAEPParameterSpec("Sha1", "MGF1",
|
||||
MGF1ParameterSpec.SHA1, new PSource.PSpecified("TCPA".getBytes()));
|
||||
|
||||
// use our generated public key to encrypt
|
||||
cipher.init(Cipher.PRIVATE_KEY, keyPair.getPrivate(), spec);
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper method that decrypts a blob using a shared key and IV using the specified.
|
||||
* transformation.
|
||||
*
|
||||
* @param blob to be decrypted
|
||||
* @param key shared key
|
||||
* @param iv to decrypt with
|
||||
* @param transformation of the decryption cipher
|
||||
* @return decrypted blob
|
||||
* @throws Exception
|
||||
*/
|
||||
private byte[] decryptBlob(byte[] blob, byte[] key, byte[] iv, String transformation)
|
||||
throws Exception {
|
||||
// initialize a cipher using the specified transformation
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
|
||||
// generate a secret key specification using the key and AES.
|
||||
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
|
||||
|
||||
// create IV parameter for key specification
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
|
||||
|
||||
// encrypt using the key specification with the generated IV
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivParameterSpec);
|
||||
|
||||
// return the cipher text
|
||||
return cipher.doFinal(blob);
|
||||
}
|
||||
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.persist.CertificateManager;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for {@see CredentialManagementHelper}.
|
||||
*/
|
||||
public class CredentialManagementHelperTest {
|
||||
|
||||
private CertificateManager certMan;
|
||||
|
||||
private static final String EK_HEADER_TRUNCATED
|
||||
= "/certificates/nuc-1/ek_cert_7_byte_header_removed.cer";
|
||||
private static final String EK_UNTOUCHED
|
||||
= "/certificates/nuc-1/ek_cert_untouched.cer";
|
||||
|
||||
/**
|
||||
* Setup mocks.
|
||||
*/
|
||||
@BeforeMethod
|
||||
public void setUp() {
|
||||
certMan = mock(CertificateManager.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exception generated if providing a null cert manager.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void processNullCertMan() {
|
||||
CredentialManagementHelper.storeEndorsementCredential(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exception generated when providing a null EK byte array.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void processNullEndorsementCredential() {
|
||||
CredentialManagementHelper.storeEndorsementCredential(certMan, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests exception generated when providing an empty array of bytes as the EK.
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void processEmptyEndorsementCredential() {
|
||||
CredentialManagementHelper.storeEndorsementCredential(certMan, new byte[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests processing an invalid EK (too small of an array).
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void processInvalidEndorsementCredentialCase1() {
|
||||
byte[] ekBytes = new byte[] {1};
|
||||
CredentialManagementHelper.storeEndorsementCredential(certMan, ekBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests processing an invalid EK (garbage bytes of a reasonable length).
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void processInvalidEndorsementCredentialCase2() {
|
||||
byte[] ekBytes = new byte[] {1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0};
|
||||
CredentialManagementHelper.storeEndorsementCredential(certMan, ekBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests processing a valid EK with the 7 byte header in tact.
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
@Test
|
||||
public void parseUntouchedEndorsementCredential() throws IOException {
|
||||
String path = CredentialManagementHelperTest.class.getResource(EK_UNTOUCHED).getPath();
|
||||
byte[] ekBytes = IOUtils.toByteArray(new FileInputStream(path));
|
||||
|
||||
CredentialManagementHelper.storeEndorsementCredential(certMan, ekBytes);
|
||||
verify(certMan).save(any(Certificate.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests processing a valid EK with the 7 byte header already stripped.
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
@Test
|
||||
public void parseHeaderTruncatedEndorsementCredential() throws IOException {
|
||||
String path = CredentialManagementHelperTest.class.getResource(EK_HEADER_TRUNCATED)
|
||||
.getPath();
|
||||
byte[] ekBytes = IOUtils.toByteArray(new FileInputStream(path));
|
||||
|
||||
CredentialManagementHelper.storeEndorsementCredential(certMan, ekBytes);
|
||||
verify(certMan).save(any(Certificate.class));
|
||||
}
|
||||
}
|
@ -1,204 +0,0 @@
|
||||
package hirs.attestationca;
|
||||
|
||||
import org.bouncycastle.asn1.DERSequence;
|
||||
import org.bouncycastle.asn1.DERSet;
|
||||
import org.bouncycastle.asn1.DERTaggedObject;
|
||||
import org.bouncycastle.asn1.DLSequence;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import hirs.data.persist.certificate.EndorsementCredential;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Tests for {@see IssuedCertificateAttributeHelper}.
|
||||
*/
|
||||
public class IssuedCertificateAttributeHelperTest {
|
||||
|
||||
private static final String NUC1_EC = "/certificates/nuc-1/tpmcert.pem";
|
||||
|
||||
private static final String INTEL_PC = "/certificates/platform_certs_2/"
|
||||
+ "Intel_pc.pem";
|
||||
|
||||
private static final String TEST_HOSTNAME = "box1";
|
||||
|
||||
private static final String TPM_MANUFACTURER = "2.23.133.2.1";
|
||||
|
||||
private static final String TPM_MODEL = "2.23.133.2.2";
|
||||
|
||||
private static final String TPM_VERSION = "2.23.133.2.3";
|
||||
|
||||
private static final String TPM_ID_LABEL_OID = "2.23.133.2.15";
|
||||
|
||||
private static final String PLATFORM_MANUFACTURER = "2.23.133.2.4";
|
||||
|
||||
private static final String PLATFORM_MODEL = "2.23.133.2.5";
|
||||
|
||||
private static final String PLATFORM_VERSION = "2.23.133.2.6";
|
||||
|
||||
/**
|
||||
* Test that provide a null host name and is rejected.
|
||||
* @throws IOException an IO error occurs
|
||||
*/
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void rejectNullHostName() throws IOException {
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(null, null, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that subject alt name can be built without an EC or PC.
|
||||
* @throws IOException an IO error occurs
|
||||
*/
|
||||
@Test
|
||||
public void buildAttributesNoEndorsementNoPlatform() throws IOException {
|
||||
Extension subjectAlternativeName =
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(
|
||||
null, new ArrayList<PlatformCredential>(), TEST_HOSTNAME);
|
||||
|
||||
Map<String, String> subjectAlternativeNameAttrMap = getSubjectAlternativeNameAttributes(
|
||||
subjectAlternativeName);
|
||||
|
||||
assertNull(subjectAlternativeNameAttrMap.get(TPM_MANUFACTURER));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(TPM_MODEL));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(TPM_VERSION));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(PLATFORM_MANUFACTURER));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(PLATFORM_MODEL));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(PLATFORM_VERSION));
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_ID_LABEL_OID), TEST_HOSTNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that subject alt name can be built with an EC but no PC.
|
||||
* @throws IOException an IO error occurs
|
||||
* @throws URISyntaxException unrecognized URI for EC Path
|
||||
*/
|
||||
@Test
|
||||
public void buildAttributesEndorsementNoPlatform() throws IOException, URISyntaxException {
|
||||
Path endorsementCredentialPath = Paths.get(getClass().getResource(
|
||||
NUC1_EC).toURI());
|
||||
EndorsementCredential endorsementCredential = new EndorsementCredential(
|
||||
endorsementCredentialPath);
|
||||
Extension subjectAlternativeName =
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(
|
||||
endorsementCredential, new ArrayList<PlatformCredential>(), TEST_HOSTNAME);
|
||||
|
||||
Map<String, String> subjectAlternativeNameAttrMap = getSubjectAlternativeNameAttributes(
|
||||
subjectAlternativeName);
|
||||
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_MANUFACTURER),
|
||||
endorsementCredential.getManufacturer());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_MODEL),
|
||||
endorsementCredential.getModel());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_VERSION),
|
||||
endorsementCredential.getVersion());
|
||||
assertNull(subjectAlternativeNameAttrMap.get(PLATFORM_MANUFACTURER));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(PLATFORM_MODEL));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(PLATFORM_VERSION));
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_ID_LABEL_OID),
|
||||
TEST_HOSTNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that subject alt name can be built with an PC but no EC.
|
||||
* @throws IOException an IO error occurs
|
||||
* @throws URISyntaxException unrecognized URI for PC Path
|
||||
*/
|
||||
@Test
|
||||
public void buildAttributesPlatformNoEndorsement() throws IOException, URISyntaxException {
|
||||
Path platformCredentialPath = Paths.get(getClass().getResource(
|
||||
INTEL_PC).toURI());
|
||||
PlatformCredential platformCredential = new PlatformCredential(
|
||||
platformCredentialPath);
|
||||
List<PlatformCredential> platformCredentialList = new ArrayList<>();
|
||||
platformCredentialList.add(platformCredential);
|
||||
Extension subjectAlternativeName =
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(
|
||||
null, platformCredentialList, TEST_HOSTNAME);
|
||||
|
||||
Map<String, String> subjectAlternativeNameAttrMap = getSubjectAlternativeNameAttributes(
|
||||
subjectAlternativeName);
|
||||
|
||||
assertNull(subjectAlternativeNameAttrMap.get(TPM_MANUFACTURER));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(TPM_MODEL));
|
||||
assertNull(subjectAlternativeNameAttrMap.get(TPM_VERSION));
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(PLATFORM_MANUFACTURER),
|
||||
platformCredential.getManufacturer());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(PLATFORM_MODEL),
|
||||
platformCredential.getModel());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(PLATFORM_VERSION),
|
||||
platformCredential.getVersion());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_ID_LABEL_OID),
|
||||
TEST_HOSTNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that subject alt name can be built with a PC and an EC.
|
||||
* @throws IOException an IO error occurs
|
||||
* @throws URISyntaxException unrecognized URI for EC or PC Path
|
||||
*/
|
||||
@Test
|
||||
public void buildAttributesPlatformAndEndorsement() throws IOException, URISyntaxException {
|
||||
Path endorsementCredentialPath = Paths.get(getClass().getResource(
|
||||
NUC1_EC).toURI());
|
||||
Path platformCredentialPath = Paths.get(getClass().getResource(
|
||||
INTEL_PC).toURI());
|
||||
EndorsementCredential endorsementCredential = new EndorsementCredential(
|
||||
endorsementCredentialPath);
|
||||
PlatformCredential platformCredential = new PlatformCredential(
|
||||
platformCredentialPath);
|
||||
List<PlatformCredential> platformCredentialList = new ArrayList<>();
|
||||
platformCredentialList.add(platformCredential);
|
||||
Extension subjectAlternativeName =
|
||||
IssuedCertificateAttributeHelper.buildSubjectAlternativeNameFromCerts(
|
||||
endorsementCredential, platformCredentialList, TEST_HOSTNAME);
|
||||
|
||||
Map<String, String> subjectAlternativeNameAttrMap = getSubjectAlternativeNameAttributes(
|
||||
subjectAlternativeName);
|
||||
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_MANUFACTURER),
|
||||
endorsementCredential.getManufacturer());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_MODEL),
|
||||
endorsementCredential.getModel());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_VERSION),
|
||||
endorsementCredential.getVersion());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(PLATFORM_MANUFACTURER),
|
||||
platformCredential.getManufacturer());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(PLATFORM_MODEL),
|
||||
platformCredential.getModel());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(PLATFORM_VERSION),
|
||||
platformCredential.getVersion());
|
||||
assertEquals(subjectAlternativeNameAttrMap.get(TPM_ID_LABEL_OID),
|
||||
TEST_HOSTNAME);
|
||||
}
|
||||
|
||||
private Map<String, String> getSubjectAlternativeNameAttributes(
|
||||
Extension subjectAlternativeName) {
|
||||
Map<String, String> subjectAlternativeNameAttrMap = new HashMap<>();
|
||||
|
||||
DLSequence dlSequence = (DLSequence) subjectAlternativeName.getParsedValue();
|
||||
DERTaggedObject derTaggedObject = (DERTaggedObject) dlSequence.getObjectAt(0);
|
||||
DERSequence derSequence = (DERSequence) derTaggedObject.getObject();
|
||||
|
||||
Enumeration enumeration = derSequence.getObjects();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
DERSet set = (DERSet) enumeration.nextElement();
|
||||
DERSequence innerDerSequence = (DERSequence) set.getObjectAt(0);
|
||||
|
||||
subjectAlternativeNameAttrMap.put(innerDerSequence.getObjectAt(0).toString(),
|
||||
innerDerSequence.getObjectAt(1).toString());
|
||||
}
|
||||
return subjectAlternativeNameAttrMap;
|
||||
}
|
||||
}
|
@ -1,828 +0,0 @@
|
||||
package hirs.attestationca.service;
|
||||
|
||||
import hirs.appraiser.SupplyChainAppraiser;
|
||||
import hirs.data.persist.AppraisalStatus;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.DeviceGroup;
|
||||
import hirs.data.persist.DeviceInfoReport;
|
||||
import hirs.data.persist.SpringPersistenceTest;
|
||||
import hirs.data.persist.SupplyChainPolicy;
|
||||
import hirs.data.persist.SupplyChainValidation;
|
||||
import hirs.data.persist.SupplyChainValidationSummary;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.data.persist.certificate.CertificateAuthorityCredential;
|
||||
import hirs.data.persist.certificate.DeviceAssociatedCertificate;
|
||||
import hirs.data.persist.certificate.EndorsementCredential;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
import hirs.persist.AppraiserManager;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.CrudManager;
|
||||
import hirs.persist.DBCertificateManager;
|
||||
import hirs.persist.DBDeviceGroupManager;
|
||||
import hirs.persist.DBDeviceManager;
|
||||
import hirs.persist.DeviceGroupManager;
|
||||
import hirs.persist.DeviceManager;
|
||||
import hirs.persist.PolicyManager;
|
||||
import hirs.persist.ReferenceDigestManager;
|
||||
import hirs.persist.ReferenceEventManager;
|
||||
import hirs.validation.CredentialValidator;
|
||||
import hirs.validation.SupplyChainCredentialValidator;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static hirs.data.persist.AppraisalStatus.Status.FAIL;
|
||||
import static hirs.data.persist.AppraisalStatus.Status.PASS;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyMapOf;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.atLeast;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Tests for the {@see SupplyChainValidationServiceImpl}.
|
||||
*/
|
||||
public class SupplyChainValidationServiceImplTest extends SpringPersistenceTest {
|
||||
private static final String NUC1_EC = "/certificates/nuc-1/tpmcert.pem";
|
||||
private static final String STM_ROOT_CA = "/certificates/stMicroCaCerts/stmtpmekroot.crt";
|
||||
private static final String GS_ROOT_CA = "/certificates/stMicroCaCerts/gstpmroot.crt";
|
||||
private static final String INTEL_CA = "/certificates/IntelSigningKey_20April2017.pem";
|
||||
private static final String NUC_PC = "/certificates/platform_certs_2/Intel_pc.pem";
|
||||
private static final String STM_TPM_EK_INTERMEDIATE_CA_02 =
|
||||
"/certificates/STM TPM EK Intermediate CA.CER";
|
||||
private static final String NUC_EC = "/certificates/nuc_ec.pem";
|
||||
|
||||
@Mock
|
||||
private PolicyManager policyManager;
|
||||
|
||||
@Mock
|
||||
private AppraiserManager appraiserManager;
|
||||
|
||||
@Mock
|
||||
private CertificateManager certificateManager;
|
||||
|
||||
@Mock
|
||||
private CredentialValidator supplyChainCredentialValidator;
|
||||
|
||||
@Mock
|
||||
private CrudManager<SupplyChainValidationSummary> supplyChainValidationSummaryDBManager;
|
||||
|
||||
@Mock
|
||||
private ReferenceDigestManager referenceDigestManager;
|
||||
|
||||
@Mock
|
||||
private ReferenceEventManager referenceEventManager;
|
||||
|
||||
@InjectMocks
|
||||
private SupplyChainValidationServiceImpl service;
|
||||
|
||||
// mocked
|
||||
private SupplyChainPolicy policy;
|
||||
private PlatformCredential pc;
|
||||
private PlatformCredential delta;
|
||||
private EndorsementCredential ec;
|
||||
private HashSet<PlatformCredential> pcs;
|
||||
private Device device;
|
||||
|
||||
/**
|
||||
* Sets up the mocks.
|
||||
*
|
||||
@throws IOException won't actually throw, the method is being mocked instead of actually
|
||||
* called
|
||||
*/
|
||||
@BeforeMethod
|
||||
public void beforeClass() throws IOException {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
device = mock(Device.class);
|
||||
|
||||
SupplyChainAppraiser appraiser = mock(SupplyChainAppraiser.class);
|
||||
policy = mock(SupplyChainPolicy.class);
|
||||
|
||||
when(appraiserManager.getAppraiser(SupplyChainAppraiser.NAME)).thenReturn(appraiser);
|
||||
when(policyManager.getDefaultPolicy(appraiser)).thenReturn(policy);
|
||||
|
||||
// mock endorsement credential
|
||||
ec = mock(EndorsementCredential.class);
|
||||
when(ec.getEncodedPublicKey()).thenReturn(new byte[] {0x0});
|
||||
when(ec.getIssuerSorted()).thenReturn("STMicroelectronics NV");
|
||||
|
||||
Set<Certificate> resultEcs = new HashSet<>();
|
||||
resultEcs.add(ec);
|
||||
|
||||
// mock platform credential
|
||||
X509Certificate cert = mock(X509Certificate.class);
|
||||
pc = mock(PlatformCredential.class);
|
||||
when(pc.getId()).thenReturn(UUID.randomUUID());
|
||||
when(pc.getX509Certificate()).thenReturn(cert);
|
||||
when(pc.getSerialNumber()).thenReturn(BigInteger.ONE);
|
||||
when(pc.getPlatformSerial()).thenReturn(String.valueOf(Integer.MIN_VALUE));
|
||||
when(pc.getIssuerSorted()).thenReturn("STMicroelectronics NV");
|
||||
when(pc.isBase()).thenReturn(true);
|
||||
when(pc.getBeginValidity()).thenReturn(new Date(System.currentTimeMillis()));
|
||||
when(pc.getSubjectSorted()).thenReturn("STMicroelectronics NV");
|
||||
pcs = new HashSet<PlatformCredential>();
|
||||
pcs.add(pc);
|
||||
|
||||
//Mock delta platform credential
|
||||
X509Certificate deltaCert = mock(X509Certificate.class);
|
||||
delta = mock(PlatformCredential.class);
|
||||
when(delta.getId()).thenReturn(UUID.randomUUID());
|
||||
when(delta.getX509Certificate()).thenReturn(deltaCert);
|
||||
when(delta.getSerialNumber()).thenReturn(BigInteger.valueOf(2));
|
||||
when(delta.getPlatformSerial()).thenReturn(String.valueOf(Integer.MIN_VALUE));
|
||||
when(delta.getIssuerSorted()).thenReturn("STMicroelectronics NV");
|
||||
when(delta.isBase()).thenReturn(false);
|
||||
when(delta.getBeginValidity()).thenReturn(new Date(System.currentTimeMillis() + 1));
|
||||
when(delta.getSubjectSorted()).thenReturn("STMicroelectronics NV Delta");
|
||||
pcs.add(delta);
|
||||
|
||||
Set<Certificate> resultPcs = new HashSet<>();
|
||||
resultPcs.add(pc);
|
||||
resultPcs.add(delta);
|
||||
|
||||
// mock credential retrieval
|
||||
when(certificateManager.get(any(EndorsementCredential.Selector.class)))
|
||||
.thenReturn(resultEcs);
|
||||
when(certificateManager.get(any(PlatformCredential.Selector.class)))
|
||||
.thenReturn(resultPcs);
|
||||
when(certificateManager.get(any(CertificateAuthorityCredential.Selector.class)))
|
||||
.thenReturn(Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove test certificates and close the session factory.
|
||||
*/
|
||||
@AfterMethod
|
||||
public void teardown() {
|
||||
DBCertificateManager certMan = new DBCertificateManager(sessionFactory);
|
||||
DBDeviceManager deviceMan = new DBDeviceManager(sessionFactory);
|
||||
DBDeviceGroupManager groupMan = new DBDeviceGroupManager(sessionFactory);
|
||||
|
||||
certMan.deleteAll();
|
||||
deviceMan.deleteAll();
|
||||
groupMan.deleteAll();
|
||||
}
|
||||
/**
|
||||
* All validations enabled, all pass.
|
||||
*/
|
||||
@Test
|
||||
public final void testFullSuccessfulValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(true);
|
||||
when(policy.isExpiredCertificateValidationEnabled()).thenReturn(true);
|
||||
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator).
|
||||
validateEndorsementCredential(eq(ec), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(pc), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(delta), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
|
||||
any(EndorsementCredential.class));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
|
||||
eq(pc), anyMapOf(PlatformCredential.class, SupplyChainValidation.class));
|
||||
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
|
||||
device).getOverallValidationResult(), PASS);
|
||||
verify(supplyChainValidationSummaryDBManager).save(any(SupplyChainValidationSummary.class));
|
||||
|
||||
// verify the certs were updated with the test device object and saved in the cert man
|
||||
ArgumentCaptor<DeviceAssociatedCertificate> certificatesCaptor
|
||||
= ArgumentCaptor.forClass(DeviceAssociatedCertificate.class);
|
||||
verify(certificateManager, times(3)).update(certificatesCaptor.capture());
|
||||
|
||||
List<DeviceAssociatedCertificate> certificateArgs = certificatesCaptor.getAllValues();
|
||||
for (DeviceAssociatedCertificate certArg : certificateArgs) {
|
||||
verify(certArg, atLeast(1)).setDevice(device);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All validations enabled, fail EC.
|
||||
*/
|
||||
@Test
|
||||
public final void testFailEcValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(true);
|
||||
when(policy.isExpiredCertificateValidationEnabled()).thenReturn(true);
|
||||
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator).
|
||||
validateEndorsementCredential(eq(ec), any(KeyStore.class), any(Boolean.class));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(pc), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(delta), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
|
||||
any(EndorsementCredential.class));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
|
||||
eq(pc), anyMapOf(PlatformCredential.class, SupplyChainValidation.class));
|
||||
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
verify(supplyChainValidationSummaryDBManager).save(any(SupplyChainValidationSummary.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* All validations enabled, fail Pc Cert.
|
||||
*/
|
||||
@Test
|
||||
public final void testFailPcValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(true);
|
||||
when(policy.isExpiredCertificateValidationEnabled()).thenReturn(true);
|
||||
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator).
|
||||
validateEndorsementCredential(eq(ec), any(KeyStore.class), any(Boolean.class));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(pc), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(delta), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
|
||||
any(EndorsementCredential.class));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
|
||||
eq(pc), anyMapOf(PlatformCredential.class, SupplyChainValidation.class));
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
verify(supplyChainValidationSummaryDBManager).save(any(SupplyChainValidationSummary.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* All validations enabled, Pc Attrib. fails.
|
||||
*/
|
||||
@Test
|
||||
public final void testFailPcAttributeValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(true);
|
||||
when(policy.isExpiredCertificateValidationEnabled()).thenReturn(true);
|
||||
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator).
|
||||
validateEndorsementCredential(eq(ec), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(pc), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(delta), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
|
||||
any(EndorsementCredential.class));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
|
||||
eq(pc), anyMapOf(PlatformCredential.class, SupplyChainValidation.class));
|
||||
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
verify(supplyChainValidationSummaryDBManager).save(any(SupplyChainValidationSummary.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ec not enabled, all others pass.
|
||||
*/
|
||||
@Test
|
||||
public final void testNoEcValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(false);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(true);
|
||||
when(policy.isExpiredCertificateValidationEnabled()).thenReturn(true);
|
||||
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator).
|
||||
validateEndorsementCredential(eq(ec), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(pc), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(delta), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
|
||||
any(EndorsementCredential.class));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
|
||||
eq(pc), anyMapOf(PlatformCredential.class, SupplyChainValidation.class));
|
||||
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
|
||||
device).getOverallValidationResult(), PASS);
|
||||
verify(supplyChainValidationSummaryDBManager).save(any(SupplyChainValidationSummary.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pc cert not enabled, all others pass.
|
||||
*/
|
||||
@Test
|
||||
public final void testNoPcValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(false);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(true);
|
||||
when(policy.isExpiredCertificateValidationEnabled()).thenReturn(true);
|
||||
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator).
|
||||
validateEndorsementCredential(eq(ec), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(pc), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(delta), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
|
||||
any(EndorsementCredential.class));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
|
||||
eq(pc), anyMapOf(PlatformCredential.class, SupplyChainValidation.class));
|
||||
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
verify(supplyChainValidationSummaryDBManager).save(any(SupplyChainValidationSummary.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pc attrib not enabled, all others pass.
|
||||
*/
|
||||
@Test
|
||||
public final void testNoPcAttributeValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(false);
|
||||
when(policy.isExpiredCertificateValidationEnabled()).thenReturn(true);
|
||||
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator).
|
||||
validateEndorsementCredential(eq(ec), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(pc), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(PASS, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredential(eq(delta), any(KeyStore.class), eq(true));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validatePlatformCredentialAttributes(eq(pc), any(DeviceInfoReport.class),
|
||||
any(EndorsementCredential.class));
|
||||
doReturn(new AppraisalStatus(FAIL, "")).when(supplyChainCredentialValidator)
|
||||
.validateDeltaPlatformCredentialAttributes(eq(delta), any(DeviceInfoReport.class),
|
||||
eq(pc), anyMapOf(PlatformCredential.class, SupplyChainValidation.class));
|
||||
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, pcs,
|
||||
device).getOverallValidationResult(), PASS);
|
||||
verify(supplyChainValidationSummaryDBManager).save(any(SupplyChainValidationSummary.class));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* All enabled, EC is null.
|
||||
*/
|
||||
@Test
|
||||
public final void testNullEcValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
Assert.assertEquals(service.validateSupplyChain(null, pcs,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* All enabled, PC is null. Then PC set is empty.
|
||||
*/
|
||||
@Test
|
||||
public final void testNullPcValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(false);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(true);
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, null,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
final HashSet<PlatformCredential> emptySet = new HashSet<>();
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, emptySet,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* All enabled, PC is null. Then PC set is empty.
|
||||
*/
|
||||
@Test
|
||||
public final void testNullPcAttributeValidation() {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(false);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(false);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(true);
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, null,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
final HashSet<PlatformCredential> emptySet = new HashSet<>();
|
||||
Assert.assertEquals(service.validateSupplyChain(ec, emptySet,
|
||||
device).getOverallValidationResult(), FAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an EC, STM CA, and GS CA in the DB, attempts to retrieve the CAs from the EC.
|
||||
* @throws URISyntaxException failed to parse certificate file location.
|
||||
* @throws IOException couldn't create certificates from file.
|
||||
* @throws KeyStoreException was unable to retrieve keystore.
|
||||
*/
|
||||
@Test
|
||||
public final void testGetCaChain() throws URISyntaxException, IOException, KeyStoreException {
|
||||
CertificateManager realCertMan = new DBCertificateManager(sessionFactory);
|
||||
|
||||
// the main service in this class only uses mocked managers, we need a real DB certificate
|
||||
// manager for this test, so we make a second service.
|
||||
SupplyChainValidationServiceImpl mostlyMockedService = new SupplyChainValidationServiceImpl(
|
||||
policyManager,
|
||||
appraiserManager,
|
||||
realCertMan,
|
||||
null,
|
||||
supplyChainValidationSummaryDBManager,
|
||||
supplyChainCredentialValidator,
|
||||
referenceDigestManager,
|
||||
referenceEventManager
|
||||
);
|
||||
|
||||
CertificateAuthorityCredential globalSignCaCert = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
GS_ROOT_CA).toURI())));
|
||||
|
||||
CertificateAuthorityCredential rootCa = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
STM_ROOT_CA).toURI()))
|
||||
);
|
||||
|
||||
EndorsementCredential endorsementCredential = new EndorsementCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
NUC1_EC).toURI())));
|
||||
|
||||
realCertMan.save(endorsementCredential);
|
||||
realCertMan.save(rootCa);
|
||||
realCertMan.save(globalSignCaCert);
|
||||
|
||||
KeyStore ks = mostlyMockedService.getCaChain(endorsementCredential);
|
||||
|
||||
String stmCaAlias = rootCa.getId().toString();
|
||||
String gsCaAlias = globalSignCaCert.getId().toString();
|
||||
|
||||
// cyrus-dev note: these were changed to fail so the unit test
|
||||
// passes. #308 changes how the CAs are looked up and these
|
||||
// tests certificates don't match up with SKI or AKI
|
||||
// and the issuer O= matches but the #308 changes make it
|
||||
// so that the entire string matches because O= is not
|
||||
// a required field.
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
Assert.assertNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertNull(ks.getCertificate(gsCaAlias));
|
||||
|
||||
realCertMan.delete(endorsementCredential);
|
||||
realCertMan.delete(rootCa);
|
||||
realCertMan.delete(globalSignCaCert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an EC, and STM CA in the DB, attempts to retrieve the CAs from the EC. The STM CA
|
||||
* points to a GS CA that is not present.
|
||||
* @throws URISyntaxException failed to parse certificate file location.
|
||||
* @throws IOException couldn't create certificates from file.
|
||||
* @throws KeyStoreException was unable to retrieve keystore.
|
||||
*/
|
||||
@Test
|
||||
public final void testGetNotFullCaChain() throws URISyntaxException, IOException,
|
||||
KeyStoreException {
|
||||
CertificateManager realCertMan = new DBCertificateManager(sessionFactory);
|
||||
|
||||
// the main service in this class only uses mocked managers, we need a real DB certificate
|
||||
// manager for this test, so we make a second service.
|
||||
SupplyChainValidationServiceImpl mostlyMockedService = new SupplyChainValidationServiceImpl(
|
||||
policyManager,
|
||||
appraiserManager,
|
||||
realCertMan,
|
||||
null,
|
||||
supplyChainValidationSummaryDBManager,
|
||||
supplyChainCredentialValidator,
|
||||
referenceDigestManager,
|
||||
referenceEventManager
|
||||
);
|
||||
|
||||
CertificateAuthorityCredential rootCa = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
STM_ROOT_CA).toURI()))
|
||||
);
|
||||
|
||||
EndorsementCredential endorsementCredential = new EndorsementCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
NUC1_EC).toURI())));
|
||||
|
||||
realCertMan.save(endorsementCredential);
|
||||
realCertMan.save(rootCa);
|
||||
|
||||
KeyStore ks = mostlyMockedService.getCaChain(endorsementCredential);
|
||||
|
||||
String stmCaAlias = rootCa.getId().toString();
|
||||
|
||||
// see cyrus-dev note above
|
||||
Assert.assertNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
|
||||
realCertMan.delete(endorsementCredential);
|
||||
realCertMan.delete(rootCa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an EC in the DB, attempts to retrieve the CA from the EC.
|
||||
* @throws URISyntaxException failed to parse certificate file location.
|
||||
* @throws IOException couldn't create certificates from file.
|
||||
* @throws KeyStoreException was unable to retrieve keystore.
|
||||
*/
|
||||
@Test
|
||||
public final void testGetEmptyCaChain() throws URISyntaxException, IOException,
|
||||
KeyStoreException {
|
||||
CertificateManager realCertMan = new DBCertificateManager(sessionFactory);
|
||||
|
||||
// the main service in this class only uses mocked managers, we need a real DB certificate
|
||||
// manager for this test, so we make a second service.
|
||||
SupplyChainValidationServiceImpl mostlyMockedService = new SupplyChainValidationServiceImpl(
|
||||
policyManager,
|
||||
appraiserManager,
|
||||
realCertMan,
|
||||
null,
|
||||
supplyChainValidationSummaryDBManager,
|
||||
supplyChainCredentialValidator,
|
||||
referenceDigestManager,
|
||||
referenceEventManager
|
||||
);
|
||||
|
||||
EndorsementCredential endorsementCredential = new EndorsementCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
NUC1_EC).toURI())));
|
||||
|
||||
realCertMan.save(endorsementCredential);
|
||||
|
||||
KeyStore ks = mostlyMockedService.getCaChain(endorsementCredential);
|
||||
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
|
||||
realCertMan.delete(endorsementCredential);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an EC, STM CA, GS CA, and an Intel CA in the DB, attempts to retrieve the CAs
|
||||
* from the EC.
|
||||
* @throws URISyntaxException failed to parse certificate file location.
|
||||
* @throws IOException couldn't create certificates from file.
|
||||
* @throws KeyStoreException was unable to retrieve keystore.
|
||||
*/
|
||||
@Test
|
||||
public final void testGetCaChainWithExtraCerts() throws URISyntaxException, IOException,
|
||||
KeyStoreException {
|
||||
CertificateManager realCertMan = new DBCertificateManager(sessionFactory);
|
||||
|
||||
// the main service in this class only uses mocked managers, we need a real DB certificate
|
||||
// manager for this test, so we make a second service.
|
||||
SupplyChainValidationServiceImpl mostlyMockedService = new SupplyChainValidationServiceImpl(
|
||||
policyManager,
|
||||
appraiserManager,
|
||||
realCertMan,
|
||||
null,
|
||||
supplyChainValidationSummaryDBManager,
|
||||
supplyChainCredentialValidator,
|
||||
referenceDigestManager,
|
||||
referenceEventManager
|
||||
);
|
||||
|
||||
CertificateAuthorityCredential globalSignCaCert = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
GS_ROOT_CA).toURI())));
|
||||
|
||||
CertificateAuthorityCredential rootCa = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
STM_ROOT_CA).toURI()))
|
||||
);
|
||||
|
||||
CertificateAuthorityCredential intelCa = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
INTEL_CA).toURI()))
|
||||
);
|
||||
|
||||
EndorsementCredential endorsementCredential = new EndorsementCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
NUC1_EC).toURI())));
|
||||
|
||||
realCertMan.save(endorsementCredential);
|
||||
realCertMan.save(rootCa);
|
||||
realCertMan.save(globalSignCaCert);
|
||||
realCertMan.save(intelCa);
|
||||
|
||||
KeyStore ks = mostlyMockedService.getCaChain(endorsementCredential);
|
||||
|
||||
String stmCaAlias = rootCa.getId().toString();
|
||||
String gsCaAlias = globalSignCaCert.getId().toString();
|
||||
|
||||
// See cyrus-dev note above
|
||||
Assert.assertNull(ks.getCertificate(stmCaAlias));
|
||||
Assert.assertNull(ks.getCertificate(gsCaAlias));
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
|
||||
realCertMan.delete(endorsementCredential);
|
||||
realCertMan.delete(rootCa);
|
||||
realCertMan.delete(globalSignCaCert);
|
||||
realCertMan.delete(intelCa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an Intel PC and Intel CA in the DB, attempts to retrieve the CA from the PC.
|
||||
* @throws URISyntaxException failed to parse certificate file location.
|
||||
* @throws IOException couldn't create certificates from file.
|
||||
* @throws KeyStoreException was unable to retrieve keystore.
|
||||
*/
|
||||
@Test
|
||||
public final void testGetPcCaChain() throws URISyntaxException, IOException, KeyStoreException {
|
||||
CertificateManager realCertMan = new DBCertificateManager(sessionFactory);
|
||||
|
||||
// the main service in this class only uses mocked managers, we need a real DB certificate
|
||||
// manager for this test, so we make a second service.
|
||||
SupplyChainValidationServiceImpl mostlyMockedService = new SupplyChainValidationServiceImpl(
|
||||
policyManager,
|
||||
appraiserManager,
|
||||
realCertMan,
|
||||
null,
|
||||
supplyChainValidationSummaryDBManager,
|
||||
supplyChainCredentialValidator,
|
||||
referenceDigestManager,
|
||||
referenceEventManager
|
||||
);
|
||||
|
||||
CertificateAuthorityCredential intelCa = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
INTEL_CA).toURI()))
|
||||
);
|
||||
|
||||
PlatformCredential platformCredential = new PlatformCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
NUC_PC).toURI())));
|
||||
|
||||
realCertMan.save(platformCredential);
|
||||
realCertMan.save(intelCa);
|
||||
|
||||
KeyStore ks = mostlyMockedService.getCaChain(platformCredential);
|
||||
|
||||
String intelCaAlias = intelCa.getId().toString();
|
||||
|
||||
Assert.assertNotNull(ks.getCertificate(intelCaAlias));
|
||||
Assert.assertEquals(ks.size(), 1);
|
||||
|
||||
realCertMan.delete(platformCredential);
|
||||
realCertMan.delete(intelCa);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an Intel PC, STM CA, and GS CA in the DB, attempts to retrieve the CAs from the PC. None
|
||||
* should match.
|
||||
* @throws URISyntaxException failed to parse certificate file location.
|
||||
* @throws IOException couldn't create certificates from file.
|
||||
* @throws KeyStoreException was unable to retrieve keystore.
|
||||
*/
|
||||
@Test
|
||||
public final void testGetPcCaChainNoMatches() throws URISyntaxException, IOException,
|
||||
KeyStoreException {
|
||||
CertificateManager realCertMan = new DBCertificateManager(sessionFactory);
|
||||
|
||||
// the main service in this class only uses mocked managers, we need a real DB certificate
|
||||
// manager for this test, so we make a second service.
|
||||
SupplyChainValidationServiceImpl mostlyMockedService = new SupplyChainValidationServiceImpl(
|
||||
policyManager,
|
||||
appraiserManager,
|
||||
realCertMan,
|
||||
null,
|
||||
supplyChainValidationSummaryDBManager,
|
||||
supplyChainCredentialValidator,
|
||||
referenceDigestManager,
|
||||
referenceEventManager
|
||||
);
|
||||
|
||||
CertificateAuthorityCredential globalSignCaCert = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
GS_ROOT_CA).toURI())));
|
||||
|
||||
CertificateAuthorityCredential rootCa = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
STM_ROOT_CA).toURI()))
|
||||
);
|
||||
|
||||
PlatformCredential platformCredential = new PlatformCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
NUC_PC).toURI())));
|
||||
|
||||
realCertMan.save(platformCredential);
|
||||
realCertMan.save(rootCa);
|
||||
realCertMan.save(globalSignCaCert);
|
||||
|
||||
KeyStore ks = mostlyMockedService.getCaChain(platformCredential);
|
||||
|
||||
Assert.assertEquals(ks.size(), 0);
|
||||
|
||||
realCertMan.delete(platformCredential);
|
||||
realCertMan.delete(rootCa);
|
||||
realCertMan.delete(globalSignCaCert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an STM intermediate CA, STM 'root' CA, and GlobalSign root CA into the in-memory
|
||||
* database, and then runs supply chain validation on a given endorsement credential.
|
||||
*
|
||||
* @throws URISyntaxException if building the path to a certificate resource fails
|
||||
* @throws IOException if there is a problem deserializing a certificate
|
||||
*/
|
||||
@Test
|
||||
public void testVerifyEcAgainstCaChain() throws URISyntaxException, IOException {
|
||||
when(policy.isEcValidationEnabled()).thenReturn(true);
|
||||
when(policy.isPcValidationEnabled()).thenReturn(false);
|
||||
when(policy.isPcAttributeValidationEnabled()).thenReturn(false);
|
||||
|
||||
CertificateManager realCertMan = new DBCertificateManager(sessionFactory);
|
||||
Device storedDevice = getStoredTestDevice();
|
||||
|
||||
SupplyChainValidationServiceImpl mostlyMockedService = new SupplyChainValidationServiceImpl(
|
||||
policyManager,
|
||||
appraiserManager,
|
||||
realCertMan,
|
||||
null,
|
||||
supplyChainValidationSummaryDBManager,
|
||||
new SupplyChainCredentialValidator(),
|
||||
referenceDigestManager,
|
||||
referenceEventManager
|
||||
);
|
||||
|
||||
CertificateAuthorityCredential stmEkRootCa = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
STM_ROOT_CA).toURI())));
|
||||
|
||||
CertificateAuthorityCredential stmTpmEkIntermediateCA = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
STM_TPM_EK_INTERMEDIATE_CA_02).toURI())));
|
||||
|
||||
CertificateAuthorityCredential globalSignTpmRoot = new CertificateAuthorityCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(
|
||||
GS_ROOT_CA).toURI()))
|
||||
);
|
||||
|
||||
realCertMan.save(stmTpmEkIntermediateCA);
|
||||
realCertMan.save(globalSignTpmRoot);
|
||||
realCertMan.save(stmEkRootCa);
|
||||
|
||||
EndorsementCredential nucEc = new EndorsementCredential(
|
||||
Files.readAllBytes(Paths.get(getClass().getResource(NUC_EC).toURI()))
|
||||
);
|
||||
|
||||
realCertMan.save(nucEc);
|
||||
|
||||
SupplyChainValidationSummary summary = mostlyMockedService.validateSupplyChain(
|
||||
nucEc, Collections.emptySet(), storedDevice
|
||||
);
|
||||
|
||||
Assert.assertEquals(summary.getOverallValidationResult(), PASS);
|
||||
for (SupplyChainValidation validation : summary.getValidations()) {
|
||||
Assert.assertEquals(
|
||||
validation.getValidationType(),
|
||||
SupplyChainValidation.ValidationType.ENDORSEMENT_CREDENTIAL
|
||||
);
|
||||
}
|
||||
|
||||
// verify the EC was updated with the test device object and saved in the cert man
|
||||
EndorsementCredential updatedStoredEc =
|
||||
EndorsementCredential.select(realCertMan).bySerialNumber(nucEc.getSerialNumber())
|
||||
.getCertificate();
|
||||
|
||||
Assert.assertEquals(updatedStoredEc.getDevice().getId(), storedDevice.getId());
|
||||
|
||||
realCertMan.delete(stmTpmEkIntermediateCA);
|
||||
realCertMan.delete(globalSignTpmRoot);
|
||||
realCertMan.delete(stmEkRootCa);
|
||||
realCertMan.delete(nucEc);
|
||||
}
|
||||
|
||||
private Device getStoredTestDevice() {
|
||||
DeviceManager deviceManager = new DBDeviceManager(sessionFactory);
|
||||
DeviceGroupManager deviceGroupManager = new DBDeviceGroupManager(sessionFactory);
|
||||
|
||||
DeviceGroup testGroup = new DeviceGroup("group1");
|
||||
Device testDevice = new Device("SCVSI-test");
|
||||
|
||||
testDevice.setDeviceGroup(deviceGroupManager.saveDeviceGroup(testGroup));
|
||||
return deviceManager.saveDevice(testDevice);
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDrzCCApegAwIBAgIEJVDCpzANBgkqhkiG9w0BAQUFADCBhzELMAkGA1UEBhMCVVMxCzAJBgNV
|
||||
BAgTAkNBMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEaMBgGA1UEChMRSW50ZWwgQ29ycG9yYXRpb24x
|
||||
ITAfBgNVBAsTGFRyYW5zcGFyZW50IFN1cHBseSBDaGFpbjEWMBQGA1UEAxMNd3d3LmludGVsLmNv
|
||||
bTAeFw0xNzA0MTkwMDAyMTBaFw0zNzEwMzEwMDAyMTBaMIGHMQswCQYDVQQGEwJVUzELMAkGA1UE
|
||||
CBMCQ0ExFDASBgNVBAcTC1NhbnRhIENsYXJhMRowGAYDVQQKExFJbnRlbCBDb3Jwb3JhdGlvbjEh
|
||||
MB8GA1UECxMYVHJhbnNwYXJlbnQgU3VwcGx5IENoYWluMRYwFAYDVQQDEw13d3cuaW50ZWwuY29t
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo7Cu8Y3uWKoTQW/RnmNJG5h3PlYdvE2B
|
||||
v0c2+WUz0AprrVMpUvbJaNoMx47ev9CYvoxuJU0t9JjMm2i1u6Ol6VlK5yAWqr/qySvkryKTUuSx
|
||||
7sOtkayF4LqD16LlTIAmUhC0KabbrEitpBa1BtKsy8yhGjbm+bYs0D19jjqHH9rOT3I8j04tc5a4
|
||||
r86dPuCZX8RJTV8tZd51ULFhl+70rIwPY/Ecbl5lzx786v9xW3XnC4/XplvMJXw2wkUo8G98qyeD
|
||||
Odvha4Y49NswlqyUHnAlk+n4bIF7cvSDi+vb4YRaV2g5u2K3290ePUcNyzGTYgdpBnvOQlna/IZ0
|
||||
NifXQQIDAQABoyEwHzAdBgNVHQ4EFgQUIQWBMO10djQycITwJ5XfZw6L13MwDQYJKoZIhvcNAQEF
|
||||
BQADggEBADgcp+GI5S6HSVhQD7wyqKIBCLUk5nC0FzE0W1vBuLrwCagXHXwMC09uDXOXtfNOoQVZ
|
||||
duS3oaju5i40lSbFmp7V2hewQo6vlum/M05Lg/O7vndKxnKss/PeT5jMyjJ4t00HQ3KEm2aZL1BR
|
||||
AJZjbH+hZ08bh5pY5uP7husjjcur0xqhFw9Afq4SUbXtA47QBaUuJTtBwTf2r/Nesq4a6zRAtqF/
|
||||
gmGD8VOSahBrtuIS30GRgcpsk6kKO4fLCvCZwyJ2/Mn+ySMB3+G6XqgDekkykCnnvMVUr+nzasug
|
||||
d/4I62L3eZ2j5Xpa3O1kFZ+zIMrbLRh7Bu8OdjFdvodwmRU=
|
||||
-----END CERTIFICATE-----
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,26 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEXjCCA0agAwIBAgIUS5gujeW5kYvYdMJZlIUT6s3F0cwwDQYJKoZIhvcNAQEF
|
||||
BQAwVTELMAkGA1UEBhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBO
|
||||
VjEmMCQGA1UEAxMdU1RNIFRQTSBFSyBJbnRlcm1lZGlhdGUgQ0EgMDIwHhcNMTQw
|
||||
MjIyMDAwMDAwWhcNMjQwMjIyMDAwMDAwWjAAMIIBNzAiBgkqhkiG9w0BAQcwFaIT
|
||||
MBEGCSqGSIb3DQEBCQQEVENQQQOCAQ8AMIIBCgKCAQEAsdTxu5pRjEOgA0tCNYgn
|
||||
NmAqLzIxBTBft4pMBGdEk922dvBLvQySN13YnvVF6FnYCc0Y+5hSAZiRCcXpr/M3
|
||||
6wx5YkePCPss06KQMujy3X9jwxTU0cDbKTjKCmFpQqCqiGIk2f7mss8yIABlwT3R
|
||||
cBBbcDpGn2wYi5s9UhUfCOQ6D7qEPKJEi5IQC7/oyu5zT5FMUANdsebxrYpALcKK
|
||||
8/mp5Rwj+xmaAg/+OC9jIeFGLYYu/hQr/1BPYSVicfuIFdc/0VzyJO5KMRozvV3I
|
||||
2dbzQwqUD4xUxPR+f7VC+3p641Mb7WobIZH7wJm2k0M8HWeErytA66WtAoueU89O
|
||||
iQIDAQABo4IBZDCCAWAwHwYDVR0jBBgwFoAUVx+Aa0fM55v6NZR87Yi40QBa4J4w
|
||||
QgYDVR0gBDswOTA3BgRVHSAAMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cuc3Qu
|
||||
Y29tL1RQTS9yZXBvc2l0b3J5LzBVBgNVHREBAf8ESzBJpEcwRTEWMBQGBWeBBQIB
|
||||
DAtpZDo1MzU0NEQyMDEXMBUGBWeBBQICDAxTVDMzWlAyNFBWU1AxEjAQBgVngQUC
|
||||
AwwHaWQ6MEQwQzB/BgNVHQkEeDB2MBYGBWeBBQIQMQ0wCwwDMS4yAgECAgF0MCAG
|
||||
BWeBBQISMRcwFQIBAAEB/6ADCgEBoQMKAQCiAwoBADA6BgNVBTQxMzAkMCIGCSqG
|
||||
SIb3DQEBBzAVohMwEQYJKoZIhvcNAQEJBARUQ1BBMAswCQYFKw4DAhoFADAMBgNV
|
||||
HRMBAf8EAjAAMBMGA1UdJQEB/wQJMAcGBWeBBQgBMA0GCSqGSIb3DQEBBQUAA4IB
|
||||
AQAb50G/d9D18ahy6RScXObaazgrNZHcF0otH9W1uJzXgSQPjFFYbHAh2+EGI8uD
|
||||
90Hj9XgZYmcGv0pUHcFw7msNamr3c/Or8+pLPnu5OZtr4jCEZ7/Z75v0Z825Ov8R
|
||||
N+JIxB9RT0Yd3KAPQsp4d45NHWOPBQPgBi/pW/eJqPO2MJD0uraRqAlNrUD3ppc7
|
||||
xxsmOoOhyUFcs14KyrgIWNazx+4EElAKU3PthU70cszFAQM2hw/EYBfRwQ5rVZd7
|
||||
V2x9hMC4POgACE6gVIDV/mHoZe6AfGQKveblJEX9gOccI28vnT14d0CwhN/SvgZF
|
||||
JigA9V7w26ecFRWXpm79utMU
|
||||
-----END CERTIFICATE-----
|
@ -1,26 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEXjCCA0agAwIBAgIUBwCBhWf/NXkWkNLUBJRd9WsObccwDQYJKoZIhvcNAQEF
|
||||
BQAwVTELMAkGA1UEBhMCQ0gxHjAcBgNVBAoTFVNUTWljcm9lbGVjdHJvbmljcyBO
|
||||
VjEmMCQGA1UEAxMdU1RNIFRQTSBFSyBJbnRlcm1lZGlhdGUgQ0EgMDIwHhcNMTQw
|
||||
MjIzMDAwMDAwWhcNMjQwMjIzMDAwMDAwWjAAMIIBNzAiBgkqhkiG9w0BAQcwFaIT
|
||||
MBEGCSqGSIb3DQEBCQQEVENQQQOCAQ8AMIIBCgKCAQEAvcrvqYUTomoUC5zk5Jhd
|
||||
myVzoEe94eXX1YFHyElCCpLM4/86ZbADKTHeGwygR4AWClb0Jmmloj+aIRUY3pZD
|
||||
2GVxDnmD9CBS+60doM1cN0+D01hhg7J/dnaigAbFxPZauSyV9XfTqq1MQlxWpUEf
|
||||
J4IALc+MhVd0kqSzzqSDxoneu83w1Ssvmah73wqWpansqQRYr1D7ABbkvouO56iu
|
||||
4z6UditUSbrk3FrZBs+e73tzy9OAzQBg617kU+BKhHCRuRIPYk3tPXHq53Y7Jwvf
|
||||
CkiEVWAU+MEMZJc/RRIOnWdSdDMxHZVnaxywrC8KUKZ1G3id/GVJfeivPxZVRBdh
|
||||
sQIDAQABo4IBZDCCAWAwHwYDVR0jBBgwFoAUVx+Aa0fM55v6NZR87Yi40QBa4J4w
|
||||
QgYDVR0gBDswOTA3BgRVHSAAMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cuc3Qu
|
||||
Y29tL1RQTS9yZXBvc2l0b3J5LzBVBgNVHREBAf8ESzBJpEcwRTEWMBQGBWeBBQIB
|
||||
DAtpZDo1MzU0NEQyMDEXMBUGBWeBBQICDAxTVDMzWlAyNFBWU1AxEjAQBgVngQUC
|
||||
AwwHaWQ6MEQwQzB/BgNVHQkEeDB2MBYGBWeBBQIQMQ0wCwwDMS4yAgECAgF0MCAG
|
||||
BWeBBQISMRcwFQIBAAEB/6ADCgEBoQMKAQCiAwoBADA6BgNVBTQxMzAkMCIGCSqG
|
||||
SIb3DQEBBzAVohMwEQYJKoZIhvcNAQEJBARUQ1BBMAswCQYFKw4DAhoFADAMBgNV
|
||||
HRMBAf8EAjAAMBMGA1UdJQEB/wQJMAcGBWeBBQgBMA0GCSqGSIb3DQEBBQUAA4IB
|
||||
AQAAbZng7i2L22p05GpbURYk6o7bYH3LZ+nusEGvi0tRkpqr9Qc8vMp8fgYQMaZV
|
||||
8QiDa5JfYD3vzOjQBRvUdqz8UrzemsuErk4w3yzsBh2lIY54jcXWmJFVk4HVp2wV
|
||||
xL5EysIII9Fkt2gfcoPSGyIDX4p83Vou5nhNOQPowahMuS6BUfcBKzMM7pK40GUj
|
||||
N+cijK61zPkvAQArEkAnVNuTxvLS41WW3x1kTtkLUPuTh7SynNAYwoVfl19uNPOs
|
||||
UTxDrFA7But7Vo0xoj+zSBQqzk0Gp3Pldw6mOUc3uI1UBmVtQGRy7cgsbLJ3bu/6
|
||||
fLuuAG5/ywVpo4MiG+PkFYXh
|
||||
-----END CERTIFICATE-----
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,94 +1,77 @@
|
||||
apply plugin: 'checkstyle'
|
||||
apply plugin: 'findbugs'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'jacoco'
|
||||
apply plugin: 'pmd'
|
||||
apply plugin: 'war'
|
||||
plugins {
|
||||
id 'application'
|
||||
id 'java'
|
||||
id 'war'
|
||||
id "nebula.ospackage" version "9.1.1"
|
||||
id 'org.springframework.boot' version '3.0.1'
|
||||
id 'io.spring.dependency-management' version '1.1.0'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(17)
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
compileOnly {
|
||||
extendsFrom annotationProcessor
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs 'libs'
|
||||
}
|
||||
flatDir { dirs "lib" }
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
providedCompile 'javax.servlet:javax.servlet-api:3.1.0' //libs.servlet_api
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.springframework.plugin:spring-plugin-core:3.0.0'
|
||||
implementation 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl:3.0.0'
|
||||
implementation 'org.apache.httpcomponents.client5:httpclient5:5.2.1'
|
||||
implementation 'commons-codec:commons-codec:1.15'
|
||||
implementation 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||
implementation 'org.apache.logging.log4j:log4j-api:2.19.0'
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
|
||||
|
||||
compile(project(':HIRS_Utils')) {
|
||||
exclude module: "javassist"
|
||||
}
|
||||
compile(project(':HIRS_AttestationCA'))
|
||||
|
||||
compile libs.commons_io
|
||||
compile libs.commons_lang
|
||||
compile libs.commons_upload
|
||||
compile libs.gson
|
||||
compile libs.guava // for com.google.common
|
||||
compile libs.hibernate
|
||||
compile libs.http
|
||||
compile libs.jstl
|
||||
compile libs.log4j2
|
||||
compile libs.log4j2_web
|
||||
compile libs.pci_ids
|
||||
compile 'javax.servlet:javax.servlet-api:3.1.0' //libs.servlet_api
|
||||
compile libs.spring_webmvc
|
||||
compile 'org.springframework:spring-context-support:4.3.30.RELEASE'
|
||||
compile 'org.hibernate:hibernate-validator:5.3.4.Final'
|
||||
|
||||
compileOnly libs.checkstyle
|
||||
compileOnly libs.findbugs
|
||||
|
||||
runtime fileTree(dir: 'build/plugins', include: ['*.jar'])
|
||||
|
||||
testCompile 'org.hamcrest:hamcrest-all:1.3'
|
||||
// override the servlet API for testing. Required for Spring Integration tests
|
||||
testCompile 'javax.servlet:javax.servlet-api:3.1.0'
|
||||
|
||||
testCompile libs.hsqldb
|
||||
testCompile libs.spring_test
|
||||
testCompile libs.testng
|
||||
testCompile libs.mockito
|
||||
testCompile libs.testng
|
||||
testCompile 'org.skyscreamer:jsonassert:1.2.3' // for .andExpect(content().json(json))
|
||||
|
||||
testRuntime 'com.jayway.jsonpath:json-path:2.1.0'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
||||
test {
|
||||
useTestNG()
|
||||
}
|
||||
|
||||
copyVersion.dependsOn compileJava
|
||||
war.dependsOn copyVersion
|
||||
war.dependsOn addPlugins
|
||||
|
||||
war {
|
||||
from(buildDir) {
|
||||
include 'VERSION'
|
||||
into 'WEB-INF/classes'
|
||||
}
|
||||
archiveName = 'HIRS_AttestationCAPortal.war'
|
||||
archiveFileName = 'HIRS_AttestationCAPortal.war'
|
||||
}
|
||||
|
||||
ext.configDir = new File(projectDir, 'config')
|
||||
|
||||
ext.checkstyleConfigDir = "$configDir/checkstyle"
|
||||
|
||||
checkstyle {
|
||||
toolVersion = '8.10.1'
|
||||
configFile = checkstyleConfigFile
|
||||
configProperties.put('basedir', checkstyleConfigDir)
|
||||
ignoreFailures = false
|
||||
showViolations = true
|
||||
}
|
||||
|
||||
ext.findbugsConfigDir = "$configDir/findbugs"
|
||||
|
||||
findbugs {
|
||||
toolVersion = '3.0.0'
|
||||
ignoreFailures = false
|
||||
effort = 'max'
|
||||
excludeFilter = new File(findbugsConfigDir, 'suppressions.xml')
|
||||
}
|
||||
//ospackage {
|
||||
// packageName = 'HIRS_AttestationCA'
|
||||
// os = LINUX
|
||||
// arch = NOARCH
|
||||
// release = '1'
|
||||
//
|
||||
// user 'root'
|
||||
// fileMode = 0755
|
||||
//
|
||||
// addParentDirs = true
|
||||
// createDirectoryEntry true
|
||||
//
|
||||
// into ("/opt/tomcat/webapps") {
|
||||
// from war.outputs.files
|
||||
// from '../HIRS_AttestationCAPortal/build/libs/HIRS_AttestationCAPortal.war'
|
||||
// user 'root'
|
||||
// fileMode = 0755
|
||||
// }
|
||||
//
|
||||
// buildRpm {
|
||||
// arch = X86_64
|
||||
// }
|
||||
//}
|
@ -0,0 +1,28 @@
|
||||
package hirs.attestationca.portal;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan({"hirs.attestationca.portal", "hirs.attestationca.portal.page.controllers", "hirs.attestationca.portal.entity", "hirs.attestationca.portal.service"})
|
||||
public class HIRSApplication extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(HIRSApplication.class);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication springApplication = new SpringApplication(HIRSApplication.class);
|
||||
springApplication.setDefaultProperties(Collections.singletonMap("server.servlet.context-path", "/portal"));
|
||||
springApplication.run(args);
|
||||
// SpringApplication.run(HIRSApplication.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package hirs.attestationca.portal;
|
||||
|
||||
import hirs.attestationca.portal.service.SettingsServiceImpl;
|
||||
import jakarta.servlet.ServletContextListener;
|
||||
import jakarta.servlet.annotation.WebListener;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
@WebListener
|
||||
public class HIRSDbInitializer implements ServletContextListener {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(HIRSDbInitializer.class);
|
||||
|
||||
@Autowired
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
@Autowired
|
||||
static SettingsServiceImpl settingsService = new SettingsServiceImpl();
|
||||
//
|
||||
// public void contextInitialized(final ServletContextEvent servletContextEvent) {
|
||||
//// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
// context.getEnvironment().addActiveProfile("server");
|
||||
// context.register(PersistenceJPAConfig.class);
|
||||
// context.refresh();
|
||||
//
|
||||
// // obtain reference to hibernate session factory
|
||||
// EntityManager entityManager = context.getBean(EntityManagerFactory.class)
|
||||
// .createEntityManager();
|
||||
// /**
|
||||
// * This fails if there is an entry already.
|
||||
// */
|
||||
//// entityManager.getTransaction().begin();
|
||||
//// entityManager.persist(context.getBean("default-settings"));
|
||||
//// entityManager.getTransaction().commit();
|
||||
//
|
||||
// insertDefaultEntries();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Insert the ACA's default entries into the DB. This class is invoked after successful
|
||||
// * install of the HIRS_AttestationCA RPM.
|
||||
// *
|
||||
// */
|
||||
// public static synchronized void insertDefaultEntries() {
|
||||
// LOGGER.error("Ensuring default ACA database entries are present.");
|
||||
//
|
||||
// // If the SupplyChainAppraiser exists, do not attempt to re-save the supply chain appraiser
|
||||
// // or SupplyChainSettings
|
||||
//
|
||||
// // Create the SupplyChainAppraiser
|
||||
// LOGGER.error("Saving supply chain appraiser...");
|
||||
//
|
||||
//
|
||||
// // Create the SupplyChainSettings
|
||||
// LOGGER.error("Saving default supply chain policy...");
|
||||
//// SupplyChainSettings supplyChainPolicy = new SupplyChainSettings(
|
||||
//// SupplyChainSettings.DEFAULT_POLICY);
|
||||
// settingsService.saveSettings(new SupplyChainSettings("Default", "Settings are configured for no validation flags set."));
|
||||
//
|
||||
// LOGGER.error("ACA database initialization complete.");
|
||||
// }
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package hirs.attestationca.portal;
|
||||
|
||||
import hirs.attestationca.portal.entity.userdefined.SupplyChainSettings;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@PropertySource({ "classpath:hibernate.properties" })
|
||||
@ComponentScan({ "hirs.attestationca.portal" })
|
||||
@EnableJpaRepositories(basePackages = "hirs.attestationca.portal.entity")
|
||||
public class PersistenceJPAConfig {
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
final LocalContainerEntityManagerFactoryBean entityManagerBean = new LocalContainerEntityManagerFactoryBean();
|
||||
entityManagerBean.setDataSource(dataSource());
|
||||
entityManagerBean.setPackagesToScan(new String[] {"hirs.attestationca.portal.entity"});
|
||||
|
||||
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
entityManagerBean.setJpaVendorAdapter(vendorAdapter);
|
||||
entityManagerBean.setJpaProperties(additionalProperties());
|
||||
|
||||
return entityManagerBean;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName(environment.getProperty("hibernate.connection.driver_class"));
|
||||
dataSource.setUrl(environment.getProperty("hibernate.connection.url"));
|
||||
dataSource.setUsername(environment.getProperty("hibernate.connection.username"));
|
||||
dataSource.setPassword(environment.getProperty("hibernate.connection.password"));
|
||||
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager() {
|
||||
final JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
|
||||
final Properties additionalProperties() {
|
||||
final Properties hibernateProperties = new Properties();
|
||||
hibernateProperties.setProperty("hibernate.hbm2ddl.auto",
|
||||
environment.getProperty("hibernate.hbm2ddl.auto"));
|
||||
hibernateProperties.setProperty("hibernate.dialect",
|
||||
environment.getProperty("hibernate.dialect"));
|
||||
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache",
|
||||
"false");
|
||||
|
||||
return hibernateProperties;
|
||||
}
|
||||
|
||||
@Bean(name="default-settings")
|
||||
public SupplyChainSettings supplyChainSettings() {
|
||||
SupplyChainSettings scSettings = new SupplyChainSettings("Default", "Settings are configured for no validation flags set.");
|
||||
|
||||
return scSettings;
|
||||
}
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
package hirs.attestationca.portal.datatables;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* Java representation of a jQuery DataTables Column.
|
||||
*/
|
||||
public class Column {
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public Column() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param data the data
|
||||
* @param name the name
|
||||
* @param searchable true if searchable
|
||||
* @param orderable true if orderable
|
||||
* @param search the Search structure.
|
||||
*/
|
||||
public Column(final String data, final String name, final boolean searchable,
|
||||
final boolean orderable, final Search search) {
|
||||
this.data = data;
|
||||
this.name = name;
|
||||
this.searchable = searchable;
|
||||
this.orderable = orderable;
|
||||
this.search = search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Column's data source.
|
||||
*
|
||||
* @see http://datatables.net/reference/option/columns.data
|
||||
*/
|
||||
@NotBlank
|
||||
private String data;
|
||||
|
||||
/**
|
||||
* Column's name.
|
||||
*
|
||||
* @see http://datatables.net/reference/option/columns.name
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Flag to indicate if this column is searchable (true) or not (false).
|
||||
*
|
||||
* @see http://datatables.net/reference/option/columns.searchable
|
||||
*/
|
||||
@NotNull
|
||||
private boolean searchable;
|
||||
|
||||
/**
|
||||
* Flag to indicate if this column is orderable (true) or not (false).
|
||||
*
|
||||
* @see http://datatables.net/reference/option/columns.orderable
|
||||
*/
|
||||
@NotNull
|
||||
private boolean orderable;
|
||||
|
||||
/**
|
||||
* Search value to apply to this specific column.
|
||||
*/
|
||||
@NotNull
|
||||
private Search search;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the data
|
||||
*/
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data.
|
||||
* @param data the data
|
||||
*/
|
||||
public void setData(final String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name.
|
||||
* @param name the name
|
||||
*/
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the searchable flag.
|
||||
* @return true if searchable, false otherwise
|
||||
*/
|
||||
public boolean isSearchable() {
|
||||
return searchable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the searchable flag.
|
||||
* @param searchable true if searchable, false otherwise
|
||||
*/
|
||||
public void setSearchable(final boolean searchable) {
|
||||
this.searchable = searchable;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if orderable, false otherwise
|
||||
*/
|
||||
public boolean isOrderable() {
|
||||
return orderable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the orderable flag.
|
||||
* @param orderable true if orderable, false otherwise
|
||||
*/
|
||||
public void setOrderable(final boolean orderable) {
|
||||
this.orderable = orderable;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the search
|
||||
*/
|
||||
public Search getSearch() {
|
||||
return search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the search.
|
||||
* @param search the search
|
||||
*/
|
||||
public void setSearch(final Search search) {
|
||||
this.search = search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the search value to apply to this column.
|
||||
*
|
||||
* @param searchValue if any, the search value to apply
|
||||
*/
|
||||
public void setSearchValue(final String searchValue) {
|
||||
this.search.setValue(searchValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Column{"
|
||||
+ "data='" + data + '\''
|
||||
+ ", name='" + name + '\''
|
||||
+ ", searchable=" + searchable
|
||||
+ ", orderable=" + orderable
|
||||
+ ", search=" + search
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,295 +0,0 @@
|
||||
package hirs.attestationca.portal.datatables;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a data table input in a jQuery DataTable.
|
||||
*/
|
||||
public class DataTableInput {
|
||||
|
||||
private static final int DEFAULT_LENGTH = 10;
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
public DataTableInput() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param draw the draw counter
|
||||
* @param start the paging start indicator
|
||||
* @param length the number of records in current draw
|
||||
* @param search the search parameter
|
||||
* @param order the orderings
|
||||
* @param columns the columns of the input
|
||||
*/
|
||||
public DataTableInput(final Integer draw, final Integer start, final Integer length,
|
||||
final Search search, final List<Order> order,
|
||||
final List<Column> columns) {
|
||||
this.draw = draw;
|
||||
this.start = start;
|
||||
this.length = length;
|
||||
this.search = search;
|
||||
this.order.addAll(order);
|
||||
this.columns.addAll(columns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw counter. This is used by DataTables to ensure that the Ajax returns from server-side
|
||||
* processing requests are drawn in sequence by DataTables (Ajax requests are asynchronous and
|
||||
* thus can return out of sequence). This is used as part of the draw return parameter (see
|
||||
* below).
|
||||
*/
|
||||
@NotNull
|
||||
@Min(0)
|
||||
private int draw = 1;
|
||||
|
||||
/**
|
||||
* Paging first record indicator. This is the start point in the current data set
|
||||
* (0 index based - i.e. 0 is the first record).
|
||||
*/
|
||||
@NotNull
|
||||
@Min(0)
|
||||
private int start = 0;
|
||||
|
||||
/**
|
||||
* Number of records that the table can display in the current draw. It is expected that the
|
||||
* number of records returned will be equal to this number,
|
||||
* unless the server has fewer records to return. Note that this can be -1 to indicate that
|
||||
* all records should be returned (although that
|
||||
* negates any benefits of server-side processing!)
|
||||
*/
|
||||
@NotNull
|
||||
@Min(-1)
|
||||
private int length = DEFAULT_LENGTH;
|
||||
|
||||
/**
|
||||
* Global search parameter.
|
||||
*/
|
||||
@NotNull
|
||||
private Search search = new Search();
|
||||
|
||||
/**
|
||||
* Order parameter.
|
||||
*/
|
||||
@NotEmpty
|
||||
private List<Order> order = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Per-column search parameter.
|
||||
*/
|
||||
@NotEmpty
|
||||
private List<Column> columns = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the draw counter
|
||||
*/
|
||||
public int getDraw() {
|
||||
return draw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the draw counter.
|
||||
* @param draw the draw counter
|
||||
*/
|
||||
public void setDraw(final int draw) {
|
||||
this.draw = draw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the start indicator.
|
||||
* @return the start indicator
|
||||
*/
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the start indicator.
|
||||
* @param start the start indicator
|
||||
*/
|
||||
public void setStart(final int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the table length for the current draw
|
||||
*/
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table length for the current draw.
|
||||
* @param length the table length for the current draw
|
||||
*/
|
||||
public void setLength(final int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the Search
|
||||
*/
|
||||
public Search getSearch() {
|
||||
return search;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the search.
|
||||
* @param search the search
|
||||
*/
|
||||
public void setSearch(final Search search) {
|
||||
this.search = search;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the orders
|
||||
*/
|
||||
public List<Order> getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the orders.
|
||||
* @param order the orders
|
||||
*/
|
||||
public void setOrder(final List<Order> order) {
|
||||
this.order.clear();
|
||||
this.order.addAll(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the table columns.
|
||||
* @return the columns
|
||||
*/
|
||||
public List<Column> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table columns.
|
||||
* @param columns the columns
|
||||
*/
|
||||
public void setColumns(final List<Column> columns) {
|
||||
this.columns.clear();
|
||||
this.columns.addAll(columns);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return a {@link Map} of {@link Column} indexed by name
|
||||
*/
|
||||
public Map<String, Column> getColumnsAsMap() {
|
||||
Map<String, Column> map = new HashMap<String, Column>();
|
||||
for (Column column : columns) {
|
||||
map.put(column.getData(), column);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a column by its name.
|
||||
*
|
||||
* @param columnName the name of the column
|
||||
* @return the given Column, or <code>null</code> if not found
|
||||
*/
|
||||
public Column getColumn(final String columnName) {
|
||||
if (columnName == null) {
|
||||
return null;
|
||||
}
|
||||
for (Column column : columns) {
|
||||
if (columnName.equals(column.getData())) {
|
||||
return column;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new column.
|
||||
*
|
||||
* @param columnName the name of the column
|
||||
* @param searchable whether the column is searchable or not
|
||||
* @param orderable whether the column is orderable or not
|
||||
* @param searchValue if any, the search value to apply
|
||||
*/
|
||||
public void addColumn(final String columnName, final boolean searchable,
|
||||
final boolean orderable, final String searchValue) {
|
||||
this.columns.add(new Column(columnName, "", searchable, orderable,
|
||||
new Search(searchValue, false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an order on the given column.
|
||||
*
|
||||
* @param columnName the name of the column
|
||||
* @param ascending whether the sorting is ascending or descending
|
||||
*/
|
||||
public void addOrder(final String columnName, final boolean ascending) {
|
||||
if (columnName == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
if (!columnName.equals(columns.get(i).getData())) {
|
||||
continue;
|
||||
}
|
||||
order.add(new Order(i, ascending));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the order column name, given the order ordinal value.
|
||||
* @return the order column name
|
||||
*/
|
||||
public String getOrderColumnName() {
|
||||
// attempt to get the column property based on the order index.
|
||||
String orderColumnName = "id";
|
||||
List<Order> orders = getOrder();
|
||||
if (!CollectionUtils.isEmpty(orders)) {
|
||||
int orderColumnIndex = orders.get(0).getColumn();
|
||||
|
||||
final Column column = getColumns().get(orderColumnIndex);
|
||||
|
||||
// use the column's name as the order field for hibernate if set,
|
||||
// otherwise, use the columns' data field
|
||||
if (StringUtils.isNotEmpty(column.getName())) {
|
||||
orderColumnName = column.getName();
|
||||
} else {
|
||||
orderColumnName = column.getData();
|
||||
}
|
||||
}
|
||||
return orderColumnName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates a string for this object.
|
||||
* @return the string
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DataTableInput{"
|
||||
+ "draw=" + draw
|
||||
+ ", start=" + start
|
||||
+ ", length=" + length
|
||||
+ ", search=" + search
|
||||
+ ", order=" + order
|
||||
+ ", columns=" + columns
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,9 +1,13 @@
|
||||
package hirs.attestationca.portal.datatables;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import hirs.FilteredRecordsList;
|
||||
|
||||
/**
|
||||
* A Wrapper for Data Table JSON responses. Allows Spring to serialize a data object with additional
|
||||
@ -11,42 +15,38 @@ import hirs.FilteredRecordsList;
|
||||
*
|
||||
* @param <T> the type of object that is being wrapped.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PUBLIC)
|
||||
public final class DataTableResponse<T> {
|
||||
|
||||
private List<T> data = new LinkedList<T>();
|
||||
@Getter @Setter
|
||||
private int draw;
|
||||
private long recordsTotal;
|
||||
private long recordsFiltered;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public DataTableResponse() {
|
||||
|
||||
}
|
||||
@Getter @Setter
|
||||
private long recordsTotal, recordsFiltered;
|
||||
|
||||
/**
|
||||
* Builds a data table response using a FilteredRecordList.
|
||||
*
|
||||
* @param recordList the filtered record list
|
||||
* @param inputQuery the data table input (used for draw)
|
||||
*/
|
||||
public DataTableResponse(final FilteredRecordsList<T> recordList,
|
||||
final DataTableInput inputQuery) {
|
||||
this(recordList, inputQuery.getDraw(),
|
||||
recordList.getRecordsTotal(), recordList.getRecordsFiltered());
|
||||
}
|
||||
// public DataTableResponse(final FilteredRecordsList<T> recordList,
|
||||
// final DataTableInput inputQuery) {
|
||||
// this(recordList, inputQuery.getDraw(),
|
||||
// recordList.getRecordsTotal(), recordList.getRecordsFiltered());
|
||||
// }
|
||||
|
||||
/**
|
||||
* Constructs a data table response using the specified data with the data table specific
|
||||
* information.
|
||||
*
|
||||
* @param data that is to be displayed by data table
|
||||
* @param draw the originating draw request ID (usually from a web request)
|
||||
* @param recordsTotal total number of records inside the data
|
||||
* @param data that is to be displayed by data table
|
||||
* @param draw the originating draw request ID (usually from a web request)
|
||||
* @param recordsTotal total number of records inside the data
|
||||
* @param recordsFiltered number of records excluded from the request
|
||||
*/
|
||||
public DataTableResponse(final List<T> data, final int draw, final long recordsTotal,
|
||||
final long recordsFiltered) {
|
||||
final long recordsFiltered) {
|
||||
setData(data);
|
||||
this.draw = draw;
|
||||
this.recordsTotal = recordsTotal;
|
||||
@ -55,6 +55,7 @@ public final class DataTableResponse<T> {
|
||||
|
||||
/**
|
||||
* Gets the data table data.
|
||||
*
|
||||
* @return the data
|
||||
*/
|
||||
public List<T> getData() {
|
||||
@ -63,58 +64,11 @@ public final class DataTableResponse<T> {
|
||||
|
||||
/**
|
||||
* Sets the data table data.
|
||||
*
|
||||
* @param data the data
|
||||
*/
|
||||
public void setData(final List<T> data) {
|
||||
this.data.clear();
|
||||
this.data.addAll(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the table draw index of the table.
|
||||
* @return the draw index
|
||||
*/
|
||||
public int getDraw() {
|
||||
return draw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table draw index of the table.
|
||||
* @param draw the draw index
|
||||
*/
|
||||
public void setDraw(final int draw) {
|
||||
this.draw = draw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total records.
|
||||
* @return the total records count
|
||||
*/
|
||||
public long getRecordsTotal() {
|
||||
return recordsTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the total record count.
|
||||
* @param recordsTotal the total records count
|
||||
*/
|
||||
public void setRecordsTotal(final long recordsTotal) {
|
||||
this.recordsTotal = recordsTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the total filtered record count.
|
||||
* @return the total filtered record count
|
||||
*/
|
||||
public long getRecordsFiltered() {
|
||||
return recordsFiltered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the total filtered record count.
|
||||
* @param recordsFiltered the total filtered record count
|
||||
*/
|
||||
public void setRecordsFiltered(final long recordsFiltered) {
|
||||
this.recordsFiltered = recordsFiltered;
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
package hirs.attestationca.portal.datatables;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.servlet.view.AbstractUrlBasedView;
|
||||
|
||||
/**
|
||||
* Serializes the DataTableResponse from the view as JSON and writes it to the HTTP response.
|
||||
*
|
||||
*/
|
||||
public class DataTableView extends AbstractUrlBasedView {
|
||||
|
||||
private static final Gson GSON = new GsonBuilder().create();
|
||||
private static final String MODEL_FIELD;
|
||||
static {
|
||||
final String name = DataTableResponse.class.getSimpleName();
|
||||
MODEL_FIELD = name.substring(0, 1).toLowerCase() + name.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes the DataTableResponse from the view as JSON and writes it to the HTTP response.
|
||||
*
|
||||
* @param model combined output Map (never {@code null}), with dynamic values taking precedence
|
||||
* over static attributes
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
* @throws Exception if rendering failed
|
||||
*/
|
||||
@Override
|
||||
protected void renderMergedOutputModel(
|
||||
final Map<String, Object> model,
|
||||
final HttpServletRequest request,
|
||||
final HttpServletResponse response) throws Exception {
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
DataTableResponse dataTable = (DataTableResponse) model.get(MODEL_FIELD);
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
String json = GSON.toJson(dataTable);
|
||||
out.print(json);
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
package hirs.attestationca.portal.datatables;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a column ordering with regards to a jQuery DataTable.
|
||||
*/
|
||||
public class Order {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public Order() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param column the column index
|
||||
* @param dir the order direction
|
||||
*/
|
||||
public Order(final int column, final String dir) {
|
||||
this.column = column;
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param column the column index
|
||||
* @param isAscending true if ascending order
|
||||
*/
|
||||
public Order(final int column, final boolean isAscending) {
|
||||
this.column = column;
|
||||
if (isAscending) {
|
||||
this.dir = "asc";
|
||||
} else {
|
||||
this.dir = "desc";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Column to which ordering should be applied. This is an index reference
|
||||
* to the columns array of information that is also submitted to the server.
|
||||
*/
|
||||
@NotNull
|
||||
@Min(0)
|
||||
private int column;
|
||||
|
||||
/**
|
||||
* Ordering direction for this column. It will be asc or desc to indicate ascending ordering or
|
||||
* descending ordering, respectively.
|
||||
*/
|
||||
@NotNull
|
||||
@Pattern(regexp = "(desc|asc)")
|
||||
private String dir;
|
||||
|
||||
|
||||
/**
|
||||
* Gets the column index.
|
||||
* @return the column index
|
||||
*/
|
||||
public int getColumn() {
|
||||
return column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the column index.
|
||||
* @param column the column index
|
||||
*/
|
||||
public void setColumn(final int column) {
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the direction order.
|
||||
* @return the direction order
|
||||
*/
|
||||
public String getDir() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the direction order.
|
||||
* @param dir the direction order
|
||||
*/
|
||||
public void setDir(final String dir) {
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if ascending order, false otherwise.
|
||||
*/
|
||||
public boolean isAscending() {
|
||||
if (dir.equalsIgnoreCase("asc")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Order{"
|
||||
+ "column=" + column
|
||||
+ ", dir='" + dir + '\''
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
package hirs.attestationca.portal.datatables;
|
||||
|
||||
import org.hibernate.Criteria;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.persist.CriteriaModifier;
|
||||
import hirs.persist.OrderedListQuerier;
|
||||
|
||||
/**
|
||||
* A class to adapt the Javascript DataTable java class abstractions to the DBManager's getting
|
||||
* of ordered lists.
|
||||
* @param <T> The type of object to query
|
||||
*/
|
||||
public final class OrderedListQueryDataTableAdapter<T> {
|
||||
|
||||
private OrderedListQueryDataTableAdapter() {
|
||||
// do not construct
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ordered list of records using a default, no-op criteria modifier.
|
||||
* @param clazz the type of objects to query for
|
||||
* @param dbManager the db manager to execute the actual query
|
||||
* @param dataTableInput the JS DataTable query abstraction
|
||||
* @param orderColumnName the name of the column (java object field name) to query on
|
||||
* @param <T> the parameter type
|
||||
* @return the filtered record list
|
||||
*/
|
||||
public static <T> FilteredRecordsList<T> getOrderedList(final Class<? extends T> clazz,
|
||||
final OrderedListQuerier<T> dbManager,
|
||||
final DataTableInput dataTableInput,
|
||||
final String orderColumnName) {
|
||||
|
||||
CriteriaModifier defaultModifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
return getOrderedList(clazz, dbManager, dataTableInput, orderColumnName, defaultModifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ordered list of records.
|
||||
* @param clazz the type of objects to query for
|
||||
* @param dbManager the db manager to execute the actual query
|
||||
* @param dataTableInput the JS DataTable query abstraction
|
||||
* @param orderColumnName the name of the column (java object field name) to query on
|
||||
* @param criteriaModifier the criteria modifier
|
||||
* @param <T> the parameter type
|
||||
* @return the filtered record list
|
||||
*/
|
||||
public static <T> FilteredRecordsList<T> getOrderedList(final Class<? extends T> clazz,
|
||||
final OrderedListQuerier<T> dbManager, final DataTableInput dataTableInput,
|
||||
final String orderColumnName,
|
||||
final CriteriaModifier criteriaModifier) {
|
||||
|
||||
Map<String, Boolean> searchableColumnMap = new HashMap<>();
|
||||
for (Column column : dataTableInput.getColumns()) {
|
||||
searchableColumnMap.put(column.getData(), column.isSearchable());
|
||||
}
|
||||
|
||||
List<Order> orders = dataTableInput.getOrder();
|
||||
boolean isAscending = true;
|
||||
if (!CollectionUtils.isEmpty(orders)) {
|
||||
isAscending = orders.get(0).isAscending();
|
||||
}
|
||||
|
||||
return dbManager.getOrderedList(clazz, orderColumnName, isAscending,
|
||||
dataTableInput.getStart(), dataTableInput.getLength(),
|
||||
dataTableInput.getSearch().getValue(),
|
||||
searchableColumnMap, criteriaModifier);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
package hirs.attestationca.portal.datatables;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Represents a jQuery DataTables search parameter.
|
||||
*/
|
||||
public class Search {
|
||||
|
||||
/**
|
||||
* Default Constructor.
|
||||
*/
|
||||
public Search() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for a non-regex search.
|
||||
* @param value the search value
|
||||
*/
|
||||
public Search(final String value) {
|
||||
this(value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param value the search value
|
||||
* @param regex the search regex
|
||||
*/
|
||||
public Search(final String value, final boolean regex) {
|
||||
this.value = value;
|
||||
this.regex = regex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global search value. To be applied to all columns which have searchable as true.
|
||||
*/
|
||||
@NotNull
|
||||
private String value = "";
|
||||
|
||||
/**
|
||||
* true if the global filter should be treated as a regular expression for advanced searching,
|
||||
* false otherwise. Note that normally server-side processing scripts will not perform regular
|
||||
* expression searching for performance reasons on large data sets,
|
||||
* but it is technically possible and at the discretion of your script.
|
||||
*/
|
||||
@NotNull
|
||||
private boolean regex;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the global search value, applied to all columns.
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the global search value.
|
||||
* @param value the global search value
|
||||
*/
|
||||
public void setValue(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if search should be treated as a regex, false otherwise
|
||||
*/
|
||||
public boolean isRegex() {
|
||||
return regex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the regex flag.
|
||||
* @param regex true if the search should be treated as a regex, false otherwise
|
||||
*/
|
||||
public void setRegex(final boolean regex) {
|
||||
this.regex = regex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Search{"
|
||||
+ "value='" + value + '\''
|
||||
+ ", regex=" + regex
|
||||
+ '}';
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
/**
|
||||
* This packages provides classes to serve jQuery dataTable requests.
|
||||
*
|
||||
* DataTableInput, Column, Order, and Search from:
|
||||
* https://github.com/darrachequesne/spring-data-jpa-datatables
|
||||
*
|
||||
* The rest of the package was unnecessary and introduced dependency conflicts.
|
||||
*/
|
||||
package hirs.attestationca.portal.datatables;
|
@ -1,99 +1,87 @@
|
||||
package hirs.data.persist;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
* An abstract database entity.
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractEntity {
|
||||
|
||||
/**
|
||||
* static value for the length of a status message for objects that
|
||||
* can have extremely long values, potentially.
|
||||
*/
|
||||
protected static final int RESULT_MESSAGE_LENGTH = 1000000;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "uuid-char")
|
||||
private UUID id;
|
||||
|
||||
@Column (name = "create_time")
|
||||
private final Date createTime = new Date();
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected AbstractEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique ID associated with this entity.
|
||||
*
|
||||
* @return unique ID
|
||||
*/
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the creation time of this entity.
|
||||
*
|
||||
* @return creation time
|
||||
*/
|
||||
public final Date getCreateTime() {
|
||||
return (Date) createTime.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the creation time to the current time.
|
||||
*/
|
||||
public final void resetCreateTime() {
|
||||
createTime.setTime(new Date().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (id != null) {
|
||||
return id.hashCode();
|
||||
}
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(this.getClass().equals(obj.getClass()))) {
|
||||
return false;
|
||||
}
|
||||
return this.hashCode() == obj.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return String.format("UUID=%s, createTime=%s",
|
||||
getId(), getCreateTime().toString());
|
||||
} catch (NullPointerException npEx) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
package hirs.attestationca.portal.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import org.hibernate.annotations.ColumnDefault;
|
||||
import org.hibernate.annotations.Generated;
|
||||
import org.hibernate.annotations.GenerationTime;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* An abstract database entity.
|
||||
*/
|
||||
@ToString
|
||||
@MappedSuperclass
|
||||
public abstract class AbstractEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* static value for the length of a status message for objects that
|
||||
* can have extremely long values, potentially.
|
||||
*/
|
||||
protected static final int RESULT_MESSAGE_LENGTH = 1000000;
|
||||
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2", strategy= GenerationType.AUTO)
|
||||
@Getter
|
||||
private UUID id;
|
||||
|
||||
@Column (name = "create_time")
|
||||
@ColumnDefault(value = "CURRENT_TIMESTAMP")
|
||||
@Generated(GenerationTime.INSERT)
|
||||
private Date createTime;// = new Date();
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected AbstractEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the creation time of this entity.
|
||||
*
|
||||
* @return creation time
|
||||
*/
|
||||
public Date getCreateTime() {
|
||||
return (Date) createTime.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the creation time to the current time.
|
||||
*/
|
||||
public void resetCreateTime() {
|
||||
createTime.setTime(new Date().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (id != null) {
|
||||
return id.hashCode();
|
||||
}
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(this.getClass().equals(obj.getClass()))) {
|
||||
return false;
|
||||
}
|
||||
return this.hashCode() == obj.hashCode();
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package hirs.attestationca.portal.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* The <code>Appraiser</code> class represents an appraiser that can appraise a <code>Report</code>.
|
||||
* <code>Appraiser</code>s are invoked to validate the integrity of client's platform. An
|
||||
* <code>Appraiser</code> does this by examining a <code>Report</code> sent from the client's
|
||||
* machine.
|
||||
* <p>
|
||||
* Supported <code>Report</code> types are kept track of in three ways: <ul> <li>The type of report
|
||||
* received for appraisal is getAppraiseReportType() (e.g. the <code>DeviceInfoAppraiser</code>
|
||||
* takes in a <code>DeviceInfoReport</code> and the <code>TPMAppraiser</code> takes in an
|
||||
* <code>IntegrityReport</code>)</li> <li>The type requested in getReportRequest is
|
||||
* getRequestReportType(). This tends to be the specific report type for that type of appraiser
|
||||
* (e.g. the <code>IMAAppraiser</code> requests an <code>IMAReport</code> and the
|
||||
* <code>TPMAppraiser</code> requests a <code>TPMReport</code>)</li> <li>The set of types this
|
||||
* appraiser relies on extracting from the top-level report is getRequiredReportTypes() (e.g. if the
|
||||
* top-level report is <code>IntegrityReport</code> then the <code>IMAAppraiser</code> needs to
|
||||
* extract both a <code>DeviceInfoReport</code> and a <code>IMAReport</code> from the
|
||||
* <code>IntegrityReport</code>)</li> </ul>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "Appraiser")
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Appraiser {
|
||||
/**
|
||||
* Name set for every instance of <code>TPMAppraiser</code>.
|
||||
*/
|
||||
public static final String TPM_NAME = "TPM Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>SupplyChainAppraiser</code>.
|
||||
*/
|
||||
public static final String SC_NAME = "Supply Chain Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>IMAAppraiser</code>.
|
||||
*/
|
||||
public static final String IMA_NAME = "IMA Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>HIRSAppraiser</code>.
|
||||
*/
|
||||
public static final String HIRS_NAME = "HIRS Appraiser";
|
||||
/**
|
||||
* Name set for every instance of <code>DeviceInfoAppraiser</code>.
|
||||
*/
|
||||
public static final String DI_NAME = "Device Info Appraiser";
|
||||
|
||||
@Getter
|
||||
@ToString.Exclude
|
||||
@EqualsAndHashCode.Exclude
|
||||
@Id
|
||||
@Column(name = "Appraiser_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* Creates a new <code>Appraiser</code> with the specified name. The name should be universally
|
||||
* unique as this is how other components will identify <code>Appraiser</code>s. Web portals,
|
||||
* for instance, could display a list of <code>Appraiser</code> names to display which
|
||||
* <code>Appraiser</code>s are available.
|
||||
* <p>
|
||||
* The name will be tested for uniqueness when it is added to a repository. It is not tested for
|
||||
* uniqueness in the class.
|
||||
*
|
||||
* @param name unique name
|
||||
*/
|
||||
public Appraiser(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -1,127 +1,95 @@
|
||||
package hirs.data.persist;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An abstract archivable entity that can be deleted.
|
||||
*/
|
||||
@MappedSuperclass
|
||||
public abstract class ArchivableEntity extends AbstractEntity {
|
||||
|
||||
/**
|
||||
* Defining the size of a message field for error display.
|
||||
*/
|
||||
public static final int MAX_MESSAGE_LENGTH = 2400;
|
||||
|
||||
@Column(name = "archived_time")
|
||||
private Date archivedTime;
|
||||
|
||||
@Column(name = "archived_description")
|
||||
private String archivedDescription;
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected ArchivableEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean representing whether or not this entity has been soft-deleted.
|
||||
*
|
||||
* @return true if this entity has been soft-deleted, false otherwise
|
||||
*/
|
||||
public final boolean isArchived() {
|
||||
return archivedTime != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that this entity has been archived, by setting the archivedTime to the current date
|
||||
* and time.
|
||||
*
|
||||
* @return
|
||||
* true if time was null and date was set.
|
||||
* false is archived time is already set, signifying the entity has been archived.
|
||||
*/
|
||||
public final boolean archive() {
|
||||
if (this.archivedTime == null) {
|
||||
this.archivedTime = new Date();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a description for the resolution if one is provided. This is done for accounting
|
||||
* purposes so the reason for action taken can be referenced.
|
||||
*
|
||||
* @param description - description of the action taken for resolution
|
||||
* @return
|
||||
* boolean result is dependent on the return value of the archive() method
|
||||
*/
|
||||
public final boolean archive(final String description) {
|
||||
if (archive()) {
|
||||
this.archivedDescription = description;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the archivedTime to null. The archivedTime being null signifies that the entity has
|
||||
* not been archived. If the time is already null then this call was unnecessary.
|
||||
*
|
||||
* @return
|
||||
* true if the time is changed to null.
|
||||
* false if time was already set to null.
|
||||
*/
|
||||
public final boolean restore() {
|
||||
if (this.archivedTime != null) {
|
||||
this.archivedTime = null;
|
||||
this.archivedDescription = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp of when the entity was archived if applicable. If the
|
||||
* entity has not been resolved, then null is returned.
|
||||
*
|
||||
* @return archivedTime
|
||||
* If entity was archived, timestamp of the occurrence, null otherwise.
|
||||
*/
|
||||
public final Date getArchivedTime() {
|
||||
if (archivedTime == null) {
|
||||
return null;
|
||||
} else {
|
||||
return (Date) archivedTime.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of the action taken during resolution. The description can be null.
|
||||
*
|
||||
* @return
|
||||
* description string of the action taken during resolution
|
||||
*/
|
||||
public final String getArchivedDescription() {
|
||||
return this.archivedDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(super.toString());
|
||||
if (archivedTime != null) {
|
||||
sb.append(String.format(", archivedTime=%s, archiveDescription=%s",
|
||||
archivedTime.toString(), archivedDescription));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
package hirs.attestationca.portal.entity;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* An abstract archivable entity that can be deleted.
|
||||
*/
|
||||
@ToString
|
||||
@Getter
|
||||
@MappedSuperclass
|
||||
public abstract class ArchivableEntity extends AbstractEntity {
|
||||
|
||||
/**
|
||||
* Defining the size of a message field for error display.
|
||||
*/
|
||||
public static final int MAX_MESSAGE_LENGTH = 2400;
|
||||
|
||||
@Column(name = "archived_time")
|
||||
private Date archivedTime;
|
||||
|
||||
@Column(name = "archived_description")
|
||||
private String archivedDescription;
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected ArchivableEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean representing whether or not this entity has been soft-deleted.
|
||||
*
|
||||
* @return true if this entity has been soft-deleted, false otherwise
|
||||
*/
|
||||
public final boolean isArchived() {
|
||||
return archivedTime != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals that this entity has been archived, by setting the archivedTime to the current date
|
||||
* and time.
|
||||
*
|
||||
* @return
|
||||
* true if time was null and date was set.
|
||||
* false is archived time is already set, signifying the entity has been archived.
|
||||
*/
|
||||
public final boolean archive() {
|
||||
if (this.archivedTime == null) {
|
||||
this.archivedTime = new Date();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a description for the resolution if one is provided. This is done for accounting
|
||||
* purposes so the reason for action taken can be referenced.
|
||||
*
|
||||
* @param description - description of the action taken for resolution
|
||||
* @return
|
||||
* boolean result is dependent on the return value of the archive() method
|
||||
*/
|
||||
public final boolean archive(final String description) {
|
||||
if (archive()) {
|
||||
this.archivedDescription = description;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the archivedTime to null. The archivedTime being null signifies that the entity has
|
||||
* not been archived. If the time is already null then this call was unnecessary.
|
||||
*
|
||||
* @return
|
||||
* true if the time is changed to null.
|
||||
* false if time was already set to null.
|
||||
*/
|
||||
public final boolean restore() {
|
||||
if (this.archivedTime != null) {
|
||||
this.archivedTime = null;
|
||||
this.archivedDescription = null;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
package hirs.data.persist;
|
||||
package hirs.attestationca.portal.entity;
|
||||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.Table;
|
||||
import jakarta.persistence.Access;
|
||||
import jakarta.persistence.AccessType;
|
||||
import jakarta.persistence.Inheritance;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
/**
|
||||
* The <code>Policy</code> class represents a policy. This is an abstract class
|
||||
@ -14,11 +13,18 @@ import javax.persistence.Table;
|
||||
* <code>Baseline</code> at the very least. A <code>Policy</code> is identified
|
||||
* by its name, so the name for a <code>Policy</code> must be unique.
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "Policy")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
@Access(AccessType.FIELD)
|
||||
public abstract class Policy extends UserDefinedEntity {
|
||||
@MappedSuperclass
|
||||
public abstract class Policy extends UserDefinedEntity {
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected Policy() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>Policy</code> with the specified name.
|
||||
@ -43,14 +49,6 @@ public abstract class Policy extends UserDefinedEntity {
|
||||
super(name, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected Policy() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this object has been persisted. Used in determining whether
|
||||
* an Appraiser should request the full Policy (and baselines) for appraisal
|
||||
@ -62,12 +60,13 @@ public abstract class Policy extends UserDefinedEntity {
|
||||
}
|
||||
|
||||
/**
|
||||
* When {@link Policy} are serialized to be sent to the browser, this can be used
|
||||
* to determine the type of {@link Policy}.
|
||||
* When {@link hirs.attestationca.portal.entity.Policy} are serialized to be sent to the browser, this can be used
|
||||
* to determine the type of {@link hirs.attestationca.portal.entity.Policy}.
|
||||
*
|
||||
* @return The class name for the {@link Policy}
|
||||
* @return The class name for the {@link hirs.attestationca.portal.entity.Policy}
|
||||
*/
|
||||
public String getType() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
package hirs.attestationca.portal.entity;
|
||||
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* An abstract archivable entity that can be given a user-defined name and description.
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@AllArgsConstructor
|
||||
@MappedSuperclass
|
||||
public abstract class UserDefinedEntity extends ArchivableEntity {
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
@ToString.Exclude
|
||||
@EqualsAndHashCode.Exclude
|
||||
@Column(nullable = false, unique = false)
|
||||
private String description = "";
|
||||
|
||||
/**
|
||||
* Default empty constructor is required for Hibernate. It is protected to
|
||||
* prevent code from calling it directly.
|
||||
*/
|
||||
protected UserDefinedEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entity with the specified name.
|
||||
*
|
||||
* @param name name
|
||||
*/
|
||||
public UserDefinedEntity(final String name) {
|
||||
this(name, "");
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package hirs.attestationca.portal.entity.manager;
|
||||
|
||||
import hirs.attestationca.portal.entity.userdefined.Device;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface DeviceRepository extends CrudRepository<Device, UUID> {
|
||||
|
||||
List<Device> findByName(String deviceName);
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package hirs.attestationca.portal.entity.manager;
|
||||
|
||||
import hirs.attestationca.portal.entity.userdefined.SupplyChainSettings;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface SettingsRepository extends JpaRepository<SupplyChainSettings, UUID> {
|
||||
SupplyChainSettings findByName(String name);
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* This package has objects for hibernate entity.
|
||||
*/
|
||||
package hirs.attestationca.portal.entity;
|
@ -0,0 +1,63 @@
|
||||
package hirs.attestationca.portal.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.portal.entity.AbstractEntity;
|
||||
import hirs.attestationca.portal.enums.AppraisalStatus;
|
||||
import hirs.attestationca.portal.enums.HealthStatus;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EnumType;
|
||||
import jakarta.persistence.Enumerated;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Entity
|
||||
@Table(name = "Device")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
@AllArgsConstructor
|
||||
public class Device extends AbstractEntity {
|
||||
|
||||
@Column(name = "name", unique = true)
|
||||
private String name;
|
||||
|
||||
// @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER,
|
||||
// optional = true, orphanRemoval = true)
|
||||
// private DeviceInfoReport deviceInfo;
|
||||
|
||||
@Column
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private HealthStatus healthStatus;
|
||||
|
||||
@Column
|
||||
@Enumerated(EnumType.ORDINAL)
|
||||
private AppraisalStatus.Status supplyChainValidationStatus;
|
||||
|
||||
/**
|
||||
* Time stamp for the report.
|
||||
*/
|
||||
@Column(name = "last_report_timestamp")
|
||||
private Timestamp lastReportTimestamp;
|
||||
|
||||
@Column(name = "is_state_overridden")
|
||||
private boolean isStateOverridden;
|
||||
|
||||
@Column(name = "state_override_reason")
|
||||
private String overrideReason;
|
||||
|
||||
@Column(name = "summary_id")
|
||||
private String summaryId;
|
||||
|
||||
public String toString() {
|
||||
return String.format("Device Name: %s%nStatus: %s%nSummary: %s",
|
||||
name, healthStatus.getStatus(),
|
||||
// supplyChainValidationStatus.toString(),
|
||||
summaryId);
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
package hirs.attestationca.portal.entity.userdefined;
|
||||
|
||||
import hirs.attestationca.portal.entity.UserDefinedEntity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Class represents Supply Chain policy. Supply Chain Policy identifies the methods in
|
||||
* SupplyChainValidator that should be used in order to validate a supply chain.
|
||||
* By default, the policy does not enable any validations.
|
||||
*/
|
||||
@Table(name = "SupplyChainSettings")
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
public class SupplyChainSettings extends UserDefinedEntity {
|
||||
/**
|
||||
* Name of the default Supply Chain Policy.
|
||||
*/
|
||||
public static final String DEFAULT_POLICY = "Default Supply Chain Policy";
|
||||
/**
|
||||
* Number of days in 10 years.
|
||||
*/
|
||||
public static final String TEN_YEARS = "3651";
|
||||
/**
|
||||
* Number of days in 1 year.
|
||||
*/
|
||||
public static final String YEAR = "365";
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ecValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean pcValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean pcAttributeValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean firmwareValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean utcValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean expiredCertificateValidationEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean replaceEC = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default true")
|
||||
private boolean issueAttestationCertificate = true;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default true")
|
||||
private boolean issueDevIdCertificate = true;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String validityDays = TEN_YEARS;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String devIdValidityDays = TEN_YEARS;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String reissueThreshold = YEAR;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String devIdReissueThreshold = YEAR;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean generateOnExpiration = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean devIdExpirationFlag = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ignoreImaEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ignoretBootEnabled = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean linuxOs = false;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default true")
|
||||
private boolean ignoreGptEnabled = true;
|
||||
|
||||
@Column(nullable = false, columnDefinition = "boolean default false")
|
||||
private boolean ignoreOsEvtEnabled = false;
|
||||
|
||||
/**
|
||||
* Default constructor necessary for Hibernate.
|
||||
*/
|
||||
protected SupplyChainSettings() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to initialize SupplyChainSettings object.
|
||||
*
|
||||
* @param name
|
||||
* A name used to uniquely identify and reference the Supply Chain policy.
|
||||
*/
|
||||
public SupplyChainSettings(final String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor used to initialize SupplyChainSettings object.
|
||||
*
|
||||
* @param name
|
||||
* A name used to uniquely identify and reference the supply chain policy.
|
||||
* @param description
|
||||
* Optional description of the policy that can be added by the user
|
||||
*/
|
||||
public SupplyChainSettings(final String name, final String description) {
|
||||
super(name, description);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package hirs.data.persist;
|
||||
package hirs.attestationca.portal.enums;
|
||||
|
||||
/**
|
||||
* Class to capture appraisal results and corresponding messages.
|
||||
@ -30,7 +30,6 @@ public class AppraisalStatus {
|
||||
}
|
||||
|
||||
private Status appStatus;
|
||||
|
||||
private String message;
|
||||
private String additionalInfo;
|
||||
|
@ -1,4 +1,7 @@
|
||||
package hirs.data.persist.enums;
|
||||
package hirs.attestationca.portal.enums;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <code>HealthStatus</code> is used to represent the health of a device.
|
||||
@ -19,16 +22,16 @@ public enum HealthStatus {
|
||||
*/
|
||||
UNKNOWN("unknown");
|
||||
|
||||
private String status;
|
||||
private String healthStatus;
|
||||
|
||||
/**
|
||||
* Creates a new <code>HealthStatus</code> object given a String.
|
||||
*
|
||||
* @param status
|
||||
* @param healthStatus
|
||||
* "trusted", "untrusted", or "unknown"
|
||||
*/
|
||||
HealthStatus(final String status) {
|
||||
this.status = status;
|
||||
HealthStatus(final String healthStatus) {
|
||||
this.healthStatus = healthStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -37,11 +40,18 @@ public enum HealthStatus {
|
||||
* @return the status
|
||||
*/
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
return this.healthStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getStatus();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isValidStatus(final String healthStatus) {
|
||||
return Arrays.stream(HealthStatus.values())
|
||||
.map(HealthStatus::name)
|
||||
.collect(Collectors.toSet())
|
||||
.contains(healthStatus);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package hirs.attestationca.portal.page;
|
||||
package hirs.attestationca.portal.enums;
|
||||
|
||||
import hirs.utils.VersionHelper;
|
||||
import hirs.attestationca.portal.utils.VersionHelper;
|
||||
|
||||
/**
|
||||
* Contains attributes required to display a portal page and its menu link.
|
||||
@ -11,53 +11,11 @@ public enum Page {
|
||||
* Site landing page.
|
||||
*/
|
||||
INDEX("HIRS Attestation CA", "Version: " + VersionHelper.getVersion(),
|
||||
null, false, false, null, null),
|
||||
/**
|
||||
* Page to import and manage trust chains.
|
||||
*/
|
||||
TRUST_CHAIN("Trust Chain Management", "ic_store",
|
||||
null, "certificate-request/"),
|
||||
/**
|
||||
* Page to display and manage endorsement key credentials.
|
||||
*/
|
||||
ENDORSEMENT_KEY_CREDENTIALS("Endorsement Key Certificates", "ic_vpn_key",
|
||||
"first", "certificate-request/"),
|
||||
/**
|
||||
* Page to display and manage platform credentials.
|
||||
*/
|
||||
PLATFORM_CREDENTIALS("Platform Certificates", "ic_important_devices",
|
||||
null, "certificate-request/"),
|
||||
/**
|
||||
* Page to display issued certificates.
|
||||
*/
|
||||
ISSUED_CERTIFICATES("Issued Certificates", "ic_library_books",
|
||||
null, "certificate-request/"),
|
||||
/**
|
||||
* Page to display certificate validation reports.
|
||||
*/
|
||||
VALIDATION_REPORTS("Validation Reports", "ic_assignment", "first"),
|
||||
/**
|
||||
* Non-menu page to display certificate. Reachable from all certificate pages.
|
||||
*/
|
||||
CERTIFICATE_DETAILS("Certificate Details", "", null, true, false, null, null),
|
||||
null, false, false, null, null),
|
||||
/**
|
||||
* Page to display registered devices.
|
||||
*/
|
||||
DEVICES("Devices", "ic_devices", "first"),
|
||||
/**
|
||||
* Page to display RIMs.
|
||||
*/
|
||||
REFERENCE_MANIFESTS("Reference Integrity Manifests",
|
||||
"ic_important_devices", "first"),
|
||||
/**
|
||||
* Non-menu page to display rims.
|
||||
*/
|
||||
RIM_DETAILS("Reference Integrity Manifest Details",
|
||||
"", null, true, false, null, null),
|
||||
/**
|
||||
* Page to display RIM event digest table.
|
||||
*/
|
||||
RIM_DATABASE("RIM Database", "ic_important_devices", "first"),
|
||||
/**
|
||||
* Page that manages Attestation CA Policy.
|
||||
*/
|
||||
@ -90,12 +48,12 @@ public enum Page {
|
||||
* @param prefixPath prefix path that appears in the URL for this page
|
||||
*/
|
||||
Page(final String title,
|
||||
final String subtitle,
|
||||
final String icon,
|
||||
final boolean hasMenu,
|
||||
final boolean inMenu,
|
||||
final String menuLinkClass,
|
||||
final String prefixPath) {
|
||||
final String subtitle,
|
||||
final String icon,
|
||||
final boolean hasMenu,
|
||||
final boolean inMenu,
|
||||
final String menuLinkClass,
|
||||
final String prefixPath) {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
this.icon = icon;
|
||||
@ -116,9 +74,9 @@ public enum Page {
|
||||
* @param prefixPath prefix path that appears in the URL for this page
|
||||
*/
|
||||
Page(final String title,
|
||||
final String icon,
|
||||
final String menuLinkClass,
|
||||
final String prefixPath) {
|
||||
final String icon,
|
||||
final String menuLinkClass,
|
||||
final String prefixPath) {
|
||||
this(title, null, icon, true, true, menuLinkClass, prefixPath);
|
||||
}
|
||||
|
||||
@ -130,8 +88,8 @@ public enum Page {
|
||||
* @param menuLinkClass the category to which this page belongs
|
||||
*/
|
||||
Page(final String title,
|
||||
final String icon,
|
||||
final String menuLinkClass) {
|
||||
final String icon,
|
||||
final String menuLinkClass) {
|
||||
this(title, null, icon, true, true, menuLinkClass, null);
|
||||
}
|
||||
|
||||
@ -142,7 +100,7 @@ public enum Page {
|
||||
* @param icon icon for the page
|
||||
*/
|
||||
Page(final String title,
|
||||
final String icon) {
|
||||
final String icon) {
|
||||
this(title, null, icon, true, true, null, null);
|
||||
}
|
||||
|
||||
@ -221,3 +179,4 @@ public enum Page {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
package hirs.attestationca.portal.enums;
|
@ -1,626 +0,0 @@
|
||||
package hirs.attestationca.portal.model;
|
||||
|
||||
import hirs.data.persist.SupplyChainPolicy;
|
||||
|
||||
/**
|
||||
* PolicyPage model object to demonstrate data exchange between policy.jsp page
|
||||
* form form and controller.
|
||||
*/
|
||||
public class PolicyPageModel {
|
||||
|
||||
// Variables to communicate policy settings to page
|
||||
private boolean enableEcValidation;
|
||||
private boolean enablePcCertificateValidation;
|
||||
private boolean enablePcCertificateAttributeValidation;
|
||||
private boolean enableFirmwareValidation;
|
||||
private boolean issueAttestationCertificate;
|
||||
private boolean issueDevIdCertificate;
|
||||
private boolean generateOnExpiration;
|
||||
private boolean devIdExpirationFlag;
|
||||
private boolean enableIgnoreIma;
|
||||
private boolean enableIgnoreTboot;
|
||||
private boolean enableIgnoreGpt;
|
||||
private boolean enableIgnoreOsEvt;
|
||||
|
||||
// Variables to get policy settings from page
|
||||
private String pcValidate;
|
||||
private String pcAttributeValidate;
|
||||
private String ecValidate;
|
||||
private String fmValidate;
|
||||
private String attestationCertificateIssued;
|
||||
private String devIdCertificateIssued;
|
||||
private String generationExpirationOn;
|
||||
private String devIdExpirationChecked;
|
||||
private String numOfValidDays;
|
||||
private String reissueThreshold;
|
||||
private String devIdReissueThreshold;
|
||||
private String ignoreIma;
|
||||
private String ignoretBoot;
|
||||
private String ignoreGpt;
|
||||
private String ignoreOsEvt;
|
||||
private String expirationValue;
|
||||
private String devIdExpirationValue;
|
||||
private String thresholdValue;
|
||||
private String devIdThresholdValue;
|
||||
|
||||
/**
|
||||
* Constructor. Sets fields from policy.
|
||||
*
|
||||
* @param policy The supply chain policy
|
||||
*/
|
||||
public PolicyPageModel(final SupplyChainPolicy policy) {
|
||||
this.enableEcValidation = policy.isEcValidationEnabled();
|
||||
this.enablePcCertificateValidation = policy.isPcValidationEnabled();
|
||||
this.enablePcCertificateAttributeValidation = policy.isPcAttributeValidationEnabled();
|
||||
this.enableFirmwareValidation = policy.isFirmwareValidationEnabled();
|
||||
this.issueAttestationCertificate = policy.isIssueAttestationCertificate();
|
||||
this.issueDevIdCertificate = policy.isIssueDevIdCertificate();
|
||||
this.generateOnExpiration = policy.isGenerateOnExpiration();
|
||||
this.devIdExpirationFlag = policy.isDevIdExpirationFlag();
|
||||
this.numOfValidDays = policy.getValidityDays();
|
||||
this.reissueThreshold = policy.getReissueThreshold();
|
||||
this.enableIgnoreIma = policy.isIgnoreImaEnabled();
|
||||
this.enableIgnoreTboot = policy.isIgnoreTbootEnabled();
|
||||
this.enableIgnoreGpt = policy.isIgnoreGptEnabled();
|
||||
this.enableIgnoreOsEvt = policy.isIgnoreOsEvtEnabled();
|
||||
this.expirationValue = policy.getValidityDays();
|
||||
this.thresholdValue = policy.getReissueThreshold();
|
||||
this.devIdExpirationValue = policy.getDevIdValidityDays();
|
||||
this.devIdReissueThreshold = policy.getDevIdReissueThreshold();
|
||||
this.devIdThresholdValue = policy.getDevIdReissueThreshold();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor required by Spring.
|
||||
*/
|
||||
public PolicyPageModel() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EC Validation state.
|
||||
*
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnableEcValidation() {
|
||||
return enableEcValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Platform Certificate Validation state.
|
||||
*
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnablePcCertificateValidation() {
|
||||
return enablePcCertificateValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Platform Certificate AttributeValidation state.
|
||||
*
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnablePcCertificateAttributeValidation() {
|
||||
return enablePcCertificateAttributeValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Firmware Validation state.
|
||||
*
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnableFirmwareValidation() {
|
||||
return enableFirmwareValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Attestation Certificate issued State.
|
||||
*
|
||||
* @return the issued state.
|
||||
*/
|
||||
public boolean isIssueAttestationCertificate() {
|
||||
return issueAttestationCertificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Dev ID Certificate issued State.
|
||||
*
|
||||
* @return the issued state.
|
||||
*/
|
||||
public boolean isIssueDevIdCertificate() {
|
||||
return issueDevIdCertificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the state of generating a certificate.
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean isGenerateOnExpiration() {
|
||||
return generateOnExpiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Enable Ignore IMA state.
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnableIgnoreIma() {
|
||||
return enableIgnoreIma;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Enable Ignore TBoot state.
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnableIgnoreTboot() {
|
||||
return enableIgnoreTboot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Enable Ignore GPT state.
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnableIgnoreGpt() {
|
||||
return enableIgnoreGpt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Enable Ignore Os Events state.
|
||||
* @return the validation state.
|
||||
*/
|
||||
public boolean getEnableIgnoreOsEvt() {
|
||||
return enableIgnoreOsEvt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EC Validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getEcValidate() {
|
||||
return ecValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Platform Certificate Validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getPcValidate() {
|
||||
return pcValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the platform certificate attribute validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getPcAttributeValidate() {
|
||||
return pcAttributeValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Firmware Validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getFmValidate() {
|
||||
return fmValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attestation certificate issued state.
|
||||
*
|
||||
* @return the model string representation of this field.
|
||||
*/
|
||||
public String getAttestationCertificateIssued() {
|
||||
return attestationCertificateIssued;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DevID certificate issued state.
|
||||
*
|
||||
* @return the model string representation of this field.
|
||||
*/
|
||||
public String getDevIdCertificateIssued() {
|
||||
return devIdCertificateIssued;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of selected valid days.
|
||||
*
|
||||
* @return the number of the days for validity
|
||||
*/
|
||||
public String getNumOfValidDays() {
|
||||
return numOfValidDays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of selected threshold days.
|
||||
*
|
||||
* @return the number of the days for reissue
|
||||
*/
|
||||
public String getReissueThreshold() {
|
||||
return reissueThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of selected threshold days.
|
||||
*
|
||||
* @return the number of the days for reissue
|
||||
*/
|
||||
public String getDevIdReissueThreshold() {
|
||||
return devIdReissueThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Ignore IMA validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getIgnoreIma() {
|
||||
return ignoreIma;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Ignore TBoot validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getIgnoretBoot() {
|
||||
return ignoretBoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Ignore GPT validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getIgnoreGpt() {
|
||||
return ignoreGpt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Ignore Os Evt validation value.
|
||||
*
|
||||
* @return the model string representation of this field (checked or unchecked)
|
||||
*/
|
||||
public String getIgnoreOsEvt() {
|
||||
return ignoreOsEvt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the EC Validation state.
|
||||
*
|
||||
* @param enableEcValidation true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnableEcValidation(final boolean enableEcValidation) {
|
||||
this.enableEcValidation = enableEcValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Platform Certificate Validation state.
|
||||
*
|
||||
* @param enablePcCertificateValidation true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnablePcCertificateValidation(final boolean enablePcCertificateValidation) {
|
||||
this.enablePcCertificateValidation = enablePcCertificateValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Platform Certificate Attribute Validation state.
|
||||
*
|
||||
* @param enablePcCertificateAttributeValidation true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnablePcCertificateAttributeValidation(
|
||||
final boolean enablePcCertificateAttributeValidation) {
|
||||
this.enablePcCertificateAttributeValidation = enablePcCertificateAttributeValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Firmware Validation state.
|
||||
*
|
||||
* @param enableFirmwareValidation true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnableFirmwareValidation(final boolean enableFirmwareValidation) {
|
||||
this.enableFirmwareValidation = enableFirmwareValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Attestation Certificate Issued state.
|
||||
*
|
||||
* @param issueAttestationCertificate true if generating Certificates.
|
||||
*/
|
||||
public void setIssueAttestationCertificate(final boolean issueAttestationCertificate) {
|
||||
this.issueAttestationCertificate = issueAttestationCertificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Dev ID Certificate Issued state.
|
||||
*
|
||||
* @param issueDevIdCertificate true if generating Certificates.
|
||||
*/
|
||||
public void setIssueDevIdCertificate(final boolean issueDevIdCertificate) {
|
||||
this.issueDevIdCertificate = issueDevIdCertificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the state of generating a certificate.
|
||||
*
|
||||
* @param generateOnExpiration true or false
|
||||
*/
|
||||
public void setGenerateOnExpiration(final boolean generateOnExpiration) {
|
||||
this.generateOnExpiration = generateOnExpiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Enable Ignore IMA state.
|
||||
*
|
||||
* @param enableIgnoreIma true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnableIgnoreIma(final boolean enableIgnoreIma) {
|
||||
this.enableIgnoreIma = enableIgnoreIma;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Enable Ignore TBoot state.
|
||||
*
|
||||
* @param enableIgnoreTboot true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnableIgnoreTboot(final boolean enableIgnoreTboot) {
|
||||
this.enableIgnoreTboot = enableIgnoreTboot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Enable Ignore GPT state.
|
||||
*
|
||||
* @param enableIgnoreGpt true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnableIgnoreGpt(final boolean enableIgnoreGpt) {
|
||||
this.enableIgnoreGpt = enableIgnoreGpt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Enable Ignore Os Events state.
|
||||
*
|
||||
* @param enableIgnoreOsEvt true if performing validation, false otherwise
|
||||
*/
|
||||
public void setEnableIgnoreOsEvt(final boolean enableIgnoreOsEvt) {
|
||||
this.enableIgnoreOsEvt = enableIgnoreOsEvt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Platform Certificate Validation state.
|
||||
*
|
||||
* @param pcValidate "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setPcValidate(final String pcValidate) {
|
||||
this.pcValidate = pcValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the EC Validation state.
|
||||
*
|
||||
* @param ecValidate "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setEcValidate(final String ecValidate) {
|
||||
this.ecValidate = ecValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the PC Attribute Validation state.
|
||||
*
|
||||
* @param pcAttributeValidate "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setPcAttributeValidate(final String pcAttributeValidate) {
|
||||
this.pcAttributeValidate = pcAttributeValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Firmware state.
|
||||
*
|
||||
* @param fmValidate "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setFmValidate(final String fmValidate) {
|
||||
this.fmValidate = fmValidate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Issued Attestation Certificate state.
|
||||
*
|
||||
* @param attestationCertificateIssued "checked" if generating certificates.
|
||||
*/
|
||||
public void setAttestationCertificateIssued(
|
||||
final String attestationCertificateIssued) {
|
||||
this.attestationCertificateIssued = attestationCertificateIssued;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Issued DevID Certificate state.
|
||||
*
|
||||
* @param devIdCertificateIssued "checked" if generating certificates.
|
||||
*/
|
||||
public void setDevIdCertificateIssued(final String devIdCertificateIssued) {
|
||||
this.devIdCertificateIssued = devIdCertificateIssued;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attestation certificate issued state.
|
||||
*
|
||||
* @return the model string representation of this field.
|
||||
*/
|
||||
public String getGenerationExpirationOn() {
|
||||
return generationExpirationOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the generation expiration state.
|
||||
*
|
||||
* @param generationExpirationOn "checked" if generating expiration is on.
|
||||
*/
|
||||
public void setGenerationExpirationOn(
|
||||
final String generationExpirationOn) {
|
||||
this.generationExpirationOn = generationExpirationOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attestation certificate issued state.
|
||||
*
|
||||
* @return the model string representation of this field.
|
||||
*/
|
||||
public String getDevIdExpirationChecked() {
|
||||
return devIdExpirationChecked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the generation expiration state.
|
||||
*
|
||||
* @param devIdExpirationChecked "checked" if generating expiration is on.
|
||||
*/
|
||||
public void setDevIdExpirationChecked(
|
||||
final String devIdExpirationChecked) {
|
||||
this.devIdExpirationChecked = devIdExpirationChecked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DevID certificate issued state.
|
||||
*
|
||||
* @return the model string representation of this field.
|
||||
*/
|
||||
public boolean getDevIdExpirationFlag() {
|
||||
return devIdExpirationFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the generation expiration state.
|
||||
*
|
||||
* @param devIdExpirationFlag "checked" if generating expiration is on.
|
||||
*/
|
||||
public void setDevIdExpirationFlag(final boolean devIdExpirationFlag) {
|
||||
this.devIdExpirationFlag = devIdExpirationFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Ignore IMA state.
|
||||
*
|
||||
* @param ignoreIma "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setIgnoreIma(final String ignoreIma) {
|
||||
this.ignoreIma = ignoreIma;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Ignore Tboot state.
|
||||
*
|
||||
* @param ignoretBoot "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setIgnoretBoot(final String ignoretBoot) {
|
||||
this.ignoretBoot = ignoretBoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Ignore GPT state.
|
||||
*
|
||||
* @param ignoreGpt "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setIgnoreGpt(final String ignoreGpt) {
|
||||
this.ignoreGpt = ignoreGpt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Ignore Os Events state.
|
||||
*
|
||||
* @param ignoreOsEvt "checked" if enabling validation, false otherwise
|
||||
*/
|
||||
public void setIgnoreOsEvt(final String ignoreOsEvt) {
|
||||
this.ignoreOsEvt = ignoreOsEvt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the expiration value.
|
||||
* @return the value
|
||||
*/
|
||||
public String getExpirationValue() {
|
||||
return expirationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the expiration value.
|
||||
* @param expirationValue string value
|
||||
*/
|
||||
public void setExpirationValue(final String expirationValue) {
|
||||
this.expirationValue = expirationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the DevID expiration value.
|
||||
* @return the value
|
||||
*/
|
||||
public String getDevIdExpirationValue() {
|
||||
return devIdExpirationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the DevID expiration value.
|
||||
* @param devIdExpirationValue string value
|
||||
*/
|
||||
public void setDevIdExpirationValue(final String devIdExpirationValue) {
|
||||
this.devIdExpirationValue = devIdExpirationValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the expiration value.
|
||||
* @return the thresholdValue
|
||||
*/
|
||||
public String getThresholdValue() {
|
||||
return thresholdValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the expiration value.
|
||||
* @param thresholdValue string value
|
||||
*/
|
||||
public void setThresholdValue(final String thresholdValue) {
|
||||
this.thresholdValue = thresholdValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the expiration value.
|
||||
* @return the devIdThresholdValue
|
||||
*/
|
||||
public String getDevIdThresholdValue() {
|
||||
return devIdThresholdValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the expiration value.
|
||||
* @param devIdThresholdValue string value
|
||||
*/
|
||||
public void setDevIdThresholdValue(final String devIdThresholdValue) {
|
||||
this.devIdThresholdValue = devIdThresholdValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PolicyPageModel{"
|
||||
+ "enableEcValidation=" + enableEcValidation
|
||||
+ ", enablePcCertificateValidation=" + enablePcCertificateValidation
|
||||
+ ", enablePcCertificateAttributeValidation="
|
||||
+ enablePcCertificateAttributeValidation
|
||||
+ ", enableFirmwareValidation=" + enableFirmwareValidation
|
||||
+ ", issueAttestationCertificate=" + issueAttestationCertificate
|
||||
+ ", issueDevIdCertificate=" + issueDevIdCertificate
|
||||
+ ", generateOnExpiration=" + generateOnExpiration
|
||||
+ ", numOfValidDays=" + numOfValidDays
|
||||
+ ", reissueThreshold=" + reissueThreshold
|
||||
+ ", enableIgnoreIma=" + enableIgnoreIma
|
||||
+ ", enableIgnoreTboot=" + enableIgnoreTboot
|
||||
+ ", enableIgnoreGpt=" + enableIgnoreGpt
|
||||
+ ", enableIgnoreOsEvt=" + enableIgnoreOsEvt
|
||||
+ ", expirationValue=" + expirationValue
|
||||
+ ", thresholdValue=" + thresholdValue
|
||||
+ ", devIdExpirationValue=" + devIdExpirationValue
|
||||
+ ", devIdReissueThreshold=" + devIdReissueThreshold
|
||||
+ ", devIdThresholdValue=" + devIdThresholdValue
|
||||
+ "}";
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This packages provides data model classes for the HIRS Attestation CA portal.
|
||||
*/
|
||||
package hirs.attestationca.portal.model;
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
* Root Package for HIRS Attestation CA Portal.
|
||||
*/
|
||||
package hirs.attestationca.portal;
|
||||
/**
|
||||
* Root Package for HIRS Attestation CA Portal.
|
||||
*/
|
||||
package hirs.attestationca.portal;
|
||||
|
@ -1,80 +0,0 @@
|
||||
package hirs.attestationca.portal.page;
|
||||
|
||||
import hirs.attestationca.portal.datatables.DataTableView;
|
||||
import hirs.attestationca.portal.persistence.PersistenceConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
import org.springframework.web.servlet.view.UrlBasedViewResolver;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Specifies the location to scan for page controllers, view resolver for JSON data, and view
|
||||
* resolver to map view names to jsp files.
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ComponentScan("hirs.attestationca.portal.page.controllers")
|
||||
@Import({ PersistenceConfiguration.class })
|
||||
public class CommonPageConfiguration {
|
||||
|
||||
|
||||
/**
|
||||
* @return bean to resolve injected annotation.Value
|
||||
* property expressions for beans.
|
||||
*/
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes all URLs that end in "dataTable" use DataTableView to serialize DataTableResponse.
|
||||
*
|
||||
* @return ViewResolver that uses DataTableView.
|
||||
*/
|
||||
@Bean
|
||||
public ViewResolver dataTableViewResolver() {
|
||||
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
|
||||
resolver.setViewClass(DataTableView.class);
|
||||
resolver.setViewNames("*dataTable");
|
||||
resolver.setOrder(0);
|
||||
return resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps view names to the appropriate jsp file.
|
||||
*
|
||||
* Only seems to apply to GET requests.
|
||||
*
|
||||
* @return a ViewResolver bean containing the mapping.
|
||||
*/
|
||||
@Bean
|
||||
public ViewResolver pageViewResolver() {
|
||||
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
|
||||
resolver.setPrefix("/WEB-INF/jsp/");
|
||||
resolver.setSuffix(".jsp");
|
||||
return resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Spring Resolver for Multi-part form uploads. This is required
|
||||
* for spring controllers to be able to process Spring MultiPartFiles
|
||||
*
|
||||
* @return bean to handle multipart form requests
|
||||
*/
|
||||
@Bean
|
||||
public CommonsMultipartResolver multipartResolver() {
|
||||
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
|
||||
resolver.setDefaultEncoding(StandardCharsets.UTF_8.name());
|
||||
return resolver;
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package hirs.attestationca.portal.page;
|
||||
|
||||
import hirs.attestationca.configuration.AttestationCertificateAuthorityConfiguration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* Main Spring configuration class for the ACA Portal. Uses the Common page configuration,
|
||||
* as well as the ACA configuration for accessing the ACA certificate.
|
||||
*/
|
||||
@Import({ CommonPageConfiguration.class, AttestationCertificateAuthorityConfiguration.class })
|
||||
public class PageConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
}
|
@ -1,12 +1,11 @@
|
||||
package hirs.attestationca.portal.page;
|
||||
|
||||
import hirs.utils.BannerConfiguration;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import hirs.attestationca.portal.enums.Page;
|
||||
import hirs.attestationca.portal.utils.BannerConfiguration;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.ui.ModelMap;
|
||||
@ -16,12 +15,21 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Abstract class to provide common functionality for page Controllers.
|
||||
*
|
||||
* @param <P> PageParams class used by the subclass.
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public abstract class PageController<P extends PageParams> {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(PageController.class);
|
||||
|
||||
/**
|
||||
* Model attribute name used by initPage for the initial data passed to the page.
|
||||
*/
|
||||
@ -52,16 +60,6 @@ public abstract class PageController<P extends PageParams> {
|
||||
|
||||
private final Page page;
|
||||
|
||||
/**
|
||||
* Constructor requiring the Page's display and routing specification.
|
||||
*
|
||||
* @param page The page specification for this controller.
|
||||
*/
|
||||
public PageController(final Page page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
@ -118,7 +116,7 @@ public abstract class PageController<P extends PageParams> {
|
||||
* @param model The model data to pass to the page.
|
||||
* @param attr The request's RedirectAttributes to hold the model data.
|
||||
* @return RedirectView back to the page with the specified parameters.
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
protected final RedirectView redirectToSelf(
|
||||
final P params,
|
||||
@ -136,7 +134,7 @@ public abstract class PageController<P extends PageParams> {
|
||||
* @param model The model data to pass to the page.
|
||||
* @param attr The request's RedirectAttributes to hold the model data.
|
||||
* @return RedirectView back to the page with the specified parameters.
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
protected final RedirectView redirectTo(
|
||||
final Page newPage,
|
||||
@ -144,25 +142,27 @@ public abstract class PageController<P extends PageParams> {
|
||||
final Map<String, ?> model,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
String defaultUri = "../" + newPage.getViewName();
|
||||
// create uri with specified parameters
|
||||
URIBuilder uri = new URIBuilder("../" + newPage.getViewName());
|
||||
LOGGER.error(uri.toString());
|
||||
|
||||
if (params != null) {
|
||||
for (Entry<String, ?> e : params.asMap().entrySet()) {
|
||||
for (Map.Entry<String, ?> e : params.asMap().entrySet()) {
|
||||
Object v = Optional.ofNullable(e.getValue()).orElse("");
|
||||
uri.addParameter(e.getKey(), v.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// create view
|
||||
RedirectView redirect = new RedirectView(uri.toString());
|
||||
RedirectView redirect = new RedirectView(defaultUri);
|
||||
|
||||
// do not put model attributes in the url
|
||||
redirect.setExposeModelAttributes(false);
|
||||
|
||||
// add model data to forward to redirected page
|
||||
if (model != null) {
|
||||
for (Entry<String, ?> e : model.entrySet()) {
|
||||
for (Map.Entry<String, ?> e : model.entrySet()) {
|
||||
attr.addFlashAttribute(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ public interface PageParams {
|
||||
*/
|
||||
LinkedHashMap<String, ?> asMap();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package hirs.attestationca.portal.page;
|
||||
|
||||
import hirs.attestationca.portal.entity.userdefined.SupplyChainSettings;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
/**
|
||||
* PolicyPage model object to demonstrate data exchange between policy.jsp page
|
||||
* form form and controller.
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
public class PolicyPageModel {
|
||||
// Variables to communicate policy settings to page
|
||||
private boolean enableEcValidation;
|
||||
private boolean enablePcCertificateValidation;
|
||||
private boolean enablePcCertificateAttributeValidation;
|
||||
private boolean enableFirmwareValidation;
|
||||
private boolean issueAttestationCertificate;
|
||||
private boolean issueDevIdCertificate;
|
||||
private boolean generateOnExpiration;
|
||||
private boolean devIdExpirationFlag;
|
||||
private boolean enableIgnoreIma;
|
||||
private boolean enableIgnoreTboot;
|
||||
private boolean enableIgnoreGpt;
|
||||
private boolean enableIgnoreOsEvt;
|
||||
|
||||
// Variables to get policy settings from page
|
||||
private String pcValidate;
|
||||
private String pcAttributeValidate;
|
||||
private String ecValidate;
|
||||
private String fmValidate;
|
||||
private String attestationCertificateIssued;
|
||||
private String devIdCertificateIssued;
|
||||
private String generationExpirationOn;
|
||||
private String devIdExpirationChecked;
|
||||
private String numOfValidDays;
|
||||
private String reissueThreshold;
|
||||
private String devIdReissueThreshold;
|
||||
private String ignoreIma;
|
||||
private String ignoretBoot;
|
||||
private String ignoreGpt;
|
||||
private String ignoreOsEvt;
|
||||
private String expirationValue;
|
||||
private String devIdExpirationValue;
|
||||
private String thresholdValue;
|
||||
private String devIdThresholdValue;
|
||||
|
||||
/**
|
||||
* Constructor. Sets fields from policy.
|
||||
*
|
||||
* @param policy The supply chain policy
|
||||
*/
|
||||
public PolicyPageModel(final SupplyChainSettings policy) {
|
||||
this.enableEcValidation = policy.isEcValidationEnabled();
|
||||
this.enablePcCertificateValidation = policy.isPcValidationEnabled();
|
||||
this.enablePcCertificateAttributeValidation = policy.isPcAttributeValidationEnabled();
|
||||
this.enableFirmwareValidation = policy.isFirmwareValidationEnabled();
|
||||
this.issueAttestationCertificate = policy.isIssueAttestationCertificate();
|
||||
this.issueDevIdCertificate = policy.isIssueDevIdCertificate();
|
||||
this.generateOnExpiration = policy.isGenerateOnExpiration();
|
||||
this.devIdExpirationFlag = policy.isDevIdExpirationFlag();
|
||||
this.numOfValidDays = policy.getValidityDays();
|
||||
this.reissueThreshold = policy.getReissueThreshold();
|
||||
this.expirationValue = policy.getValidityDays();
|
||||
this.thresholdValue = policy.getReissueThreshold();
|
||||
this.devIdExpirationValue = policy.getDevIdValidityDays();
|
||||
this.devIdReissueThreshold = policy.getDevIdReissueThreshold();
|
||||
this.devIdThresholdValue = policy.getDevIdReissueThreshold();
|
||||
// pcrPolicy
|
||||
this.enableIgnoreIma = policy.isIgnoreImaEnabled();
|
||||
this.enableIgnoreTboot = policy.isIgnoretBootEnabled();
|
||||
this.enableIgnoreGpt = policy.isIgnoreGptEnabled();
|
||||
this.enableIgnoreOsEvt = policy.isIgnoreOsEvtEnabled();
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
import hirs.attestationca.portal.page.params.CertificateDetailsPageParams;
|
||||
import hirs.attestationca.portal.util.CertificateStringMapBuilder;
|
||||
import hirs.persist.CertificateManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import static hirs.attestationca.portal.page.Page.CERTIFICATE_DETAILS;
|
||||
|
||||
/**
|
||||
* Controller for the Certificate Details page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/certificate-details")
|
||||
public class CertificateDetailsPageController extends PageController<CertificateDetailsPageParams> {
|
||||
|
||||
/**
|
||||
* Model attribute name used by initPage for the initial data passed to the page.
|
||||
*/
|
||||
static final String INITIAL_DATA = "initialData";
|
||||
|
||||
private final CertificateManager certificateManager;
|
||||
private static final Logger LOGGER =
|
||||
LogManager.getLogger(CertificateDetailsPageController.class);
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
* @param certificateManager the certificate manager
|
||||
*/
|
||||
@Autowired
|
||||
public CertificateDetailsPageController(final CertificateManager certificateManager) {
|
||||
super(CERTIFICATE_DETAILS);
|
||||
this.certificateManager = certificateManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final CertificateDetailsPageParams params, final Model model) {
|
||||
// get the basic information to render the page
|
||||
ModelAndView mav = getBaseModelAndView();
|
||||
PageMessages messages = new PageMessages();
|
||||
|
||||
// Map with the certificate information
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
|
||||
// Check if parameters were set
|
||||
if (params.getId() == null) {
|
||||
String typeError = "ID was not provided";
|
||||
messages.addError(typeError);
|
||||
LOGGER.error(typeError);
|
||||
mav.addObject(MESSAGES_ATTRIBUTE, messages);
|
||||
} else if (params.getType() == null) {
|
||||
String typeError = "Type was not provided";
|
||||
messages.addError(typeError);
|
||||
LOGGER.error(typeError);
|
||||
mav.addObject(MESSAGES_ATTRIBUTE, messages);
|
||||
} else {
|
||||
try {
|
||||
String type = params.getType().toLowerCase();
|
||||
UUID uuid = UUID.fromString(params.getId());
|
||||
switch (type) {
|
||||
case "certificateauthority":
|
||||
data.putAll(CertificateStringMapBuilder.getCertificateAuthorityInformation(
|
||||
uuid, certificateManager));
|
||||
break;
|
||||
case "endorsement":
|
||||
data.putAll(CertificateStringMapBuilder.getEndorsementInformation(uuid,
|
||||
certificateManager));
|
||||
break;
|
||||
case "platform":
|
||||
data.putAll(CertificateStringMapBuilder.getPlatformInformation(uuid,
|
||||
certificateManager));
|
||||
break;
|
||||
case "issued":
|
||||
data.putAll(CertificateStringMapBuilder.getIssuedInformation(uuid,
|
||||
certificateManager));
|
||||
break;
|
||||
default:
|
||||
String typeError = "Invalid certificate type: " + params.getType();
|
||||
messages.addError(typeError);
|
||||
LOGGER.error(typeError);
|
||||
mav.addObject(MESSAGES_ATTRIBUTE, messages);
|
||||
break;
|
||||
}
|
||||
} catch (IllegalArgumentException | IOException ex) {
|
||||
String uuidError = "Failed to parse ID from: " + params.getId();
|
||||
messages.addError(uuidError);
|
||||
LOGGER.error(uuidError, ex);
|
||||
}
|
||||
|
||||
if (data.isEmpty()) {
|
||||
String notFoundMessage = "Unable to find certificate with ID: " + params.getId();
|
||||
messages.addError(notFoundMessage);
|
||||
LOGGER.warn(notFoundMessage);
|
||||
mav.addObject(MESSAGES_ATTRIBUTE, messages);
|
||||
} else {
|
||||
mav.addObject(INITIAL_DATA, data);
|
||||
}
|
||||
}
|
||||
|
||||
// return the model and view
|
||||
return mav;
|
||||
}
|
||||
}
|
@ -1,955 +0,0 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.attestationca.portal.datatables.DataTableInput;
|
||||
import hirs.attestationca.portal.datatables.DataTableResponse;
|
||||
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
|
||||
import hirs.attestationca.portal.page.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.attestationca.portal.util.CertificateStringMapBuilder;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.data.persist.certificate.CertificateAuthorityCredential;
|
||||
import hirs.data.persist.certificate.EndorsementCredential;
|
||||
import hirs.data.persist.certificate.IssuedAttestationCertificate;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.CriteriaModifier;
|
||||
import hirs.persist.CrudManager;
|
||||
import hirs.persist.DBManagerException;
|
||||
import hirs.persist.OrderedListQuerier;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.util.encoders.DecoderException;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.sql.JoinType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* Controller for the Certificates list all pages.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/certificate-request")
|
||||
public class CertificateRequestPageController extends PageController<NoPageParams> {
|
||||
|
||||
private final CertificateManager certificateManager;
|
||||
private final OrderedListQuerier<Certificate> dataTableQuerier;
|
||||
|
||||
private CertificateAuthorityCredential certificateAuthorityCredential;
|
||||
|
||||
private static final Logger LOGGER = getLogger(CertificateRequestPageController.class);
|
||||
|
||||
private static final String TRUSTCHAIN = "trust-chain";
|
||||
private static final String PLATFORMCREDENTIAL = "platform-credentials";
|
||||
private static final String ENDORSEMENTCREDENTIAL = "endorsement-key-credentials";
|
||||
private static final String ISSUEDCERTIFICATES = "issued-certificates";
|
||||
|
||||
/**
|
||||
* Model attribute name used by initPage for the aca cert info.
|
||||
*/
|
||||
static final String ACA_CERT_DATA = "acaCertData";
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*
|
||||
* @param certificateManager the certificate manager
|
||||
* @param crudManager the CRUD manager for certificates
|
||||
* @param acaCertificate the ACA's X509 certificate
|
||||
*/
|
||||
@Autowired
|
||||
public CertificateRequestPageController(
|
||||
final CertificateManager certificateManager,
|
||||
final CrudManager<Certificate> crudManager,
|
||||
final X509Certificate acaCertificate) {
|
||||
super(Page.TRUST_CHAIN);
|
||||
this.certificateManager = certificateManager;
|
||||
this.dataTableQuerier = crudManager;
|
||||
|
||||
try {
|
||||
certificateAuthorityCredential
|
||||
= new CertificateAuthorityCredential(acaCertificate.getEncoded());
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to read ACA certificate", e);
|
||||
} catch (CertificateEncodingException e) {
|
||||
LOGGER.error("Error getting encoded ACA certificate", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from
|
||||
* redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from
|
||||
* redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@RequestMapping("/{certificateType}")
|
||||
public ModelAndView initPage(@PathVariable("certificateType") final String certificateType,
|
||||
final NoPageParams params, final Model model) {
|
||||
|
||||
ModelAndView mav = null;
|
||||
HashMap<String, String> data = new HashMap<>();
|
||||
// add page information
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
mav = getBaseModelAndView(Page.PLATFORM_CREDENTIALS);
|
||||
break;
|
||||
case ENDORSEMENTCREDENTIAL:
|
||||
mav = getBaseModelAndView(Page.ENDORSEMENT_KEY_CREDENTIALS);
|
||||
break;
|
||||
case ISSUEDCERTIFICATES:
|
||||
mav = getBaseModelAndView(Page.ISSUED_CERTIFICATES);
|
||||
break;
|
||||
case TRUSTCHAIN:
|
||||
mav = getBaseModelAndView(Page.TRUST_CHAIN);
|
||||
// Map with the ACA certificate information
|
||||
data.putAll(CertificateStringMapBuilder.getCertificateAuthorityInformation(
|
||||
certificateAuthorityCredential, this.certificateManager));
|
||||
mav.addObject(ACA_CERT_DATA, data);
|
||||
break;
|
||||
default:
|
||||
// send to an error page
|
||||
break;
|
||||
}
|
||||
|
||||
return mav;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries for the list of Certificates and returns a data table response
|
||||
* with the records.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param input the DataTables search/query parameters
|
||||
* @return the data table
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/{certificateType}/list",
|
||||
produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
method = RequestMethod.GET)
|
||||
@SuppressWarnings("unchecked")
|
||||
public DataTableResponse<? extends Certificate> getTableData(
|
||||
@PathVariable("certificateType") final String certificateType,
|
||||
final DataTableInput input) {
|
||||
|
||||
LOGGER.debug("Handling list request: " + input);
|
||||
|
||||
// attempt to get the column property based on the order index.
|
||||
String orderColumnName = input.getOrderColumnName();
|
||||
|
||||
LOGGER.debug("Ordering on column: " + orderColumnName);
|
||||
|
||||
// check that the alert is not archived and that it is in the specified report
|
||||
CriteriaModifier criteriaModifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
criteria.add(Restrictions.isNull(Certificate.ARCHIVE_FIELD));
|
||||
|
||||
// add a device alias if this query includes the device table
|
||||
// for getting the device (e.g. device name).
|
||||
// use left join, since device may be null. Query will return all
|
||||
// Certs of this type, whether it has a Device or not (device field may be null)
|
||||
if (hasDeviceTableToJoin(certificateType)) {
|
||||
criteria.createAlias("device", "device", JoinType.LEFT_OUTER_JOIN);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
FilteredRecordsList records
|
||||
= OrderedListQueryDataTableAdapter.getOrderedList(
|
||||
getCertificateClass(certificateType), dataTableQuerier,
|
||||
input, orderColumnName, criteriaModifier);
|
||||
|
||||
// special parsing for platform credential
|
||||
// Add the EndorsementCredential for each PlatformCredential based on the
|
||||
// serial number. (pc.HolderSerialNumber = ec.SerialNumber)
|
||||
if (certificateType.equals(PLATFORMCREDENTIAL)) {
|
||||
EndorsementCredential associatedEC;
|
||||
|
||||
if (!records.isEmpty()) {
|
||||
// loop all the platform certificates
|
||||
for (int i = 0; i < records.size(); i++) {
|
||||
PlatformCredential pc = (PlatformCredential) records.get(i);
|
||||
// find the EC using the PC's "holder serial number"
|
||||
associatedEC = EndorsementCredential
|
||||
.select(certificateManager)
|
||||
.bySerialNumber(pc.getHolderSerialNumber())
|
||||
.getCertificate();
|
||||
|
||||
if (associatedEC != null) {
|
||||
LOGGER.debug("EC ID for holder s/n " + pc
|
||||
.getHolderSerialNumber() + " = " + associatedEC.getId());
|
||||
}
|
||||
|
||||
pc.setEndorsementCredential(associatedEC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.debug("Returning list of size: " + records.size());
|
||||
return new DataTableResponse<>(records, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Archives (soft delete) the credential.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param id the UUID of the cert to delete
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return redirect to this page
|
||||
* @throws URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "/{certificateType}/delete", method = RequestMethod.POST)
|
||||
public RedirectView delete(
|
||||
@PathVariable("certificateType") final String certificateType,
|
||||
@RequestParam final String id,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
LOGGER.info("Handling request to delete " + id);
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
|
||||
try {
|
||||
UUID uuid = UUID.fromString(id);
|
||||
Certificate certificate = getCertificateById(certificateType, uuid, certificateManager);
|
||||
if (certificate == null) {
|
||||
// Use the term "record" here to avoid user confusion b/t cert and cred
|
||||
String notFoundMessage = "Unable to locate record with ID: " + uuid;
|
||||
messages.addError(notFoundMessage);
|
||||
LOGGER.warn(notFoundMessage);
|
||||
} else {
|
||||
if (certificateType.equals(PLATFORMCREDENTIAL)) {
|
||||
PlatformCredential platformCertificate = (PlatformCredential) certificate;
|
||||
if (platformCertificate.isBase()) {
|
||||
// only do this if the base is being deleted.
|
||||
List<PlatformCredential> sharedCertificates = getCertificateByBoardSN(
|
||||
certificateType,
|
||||
platformCertificate.getPlatformSerial(),
|
||||
certificateManager);
|
||||
|
||||
if (sharedCertificates != null) {
|
||||
for (PlatformCredential pc : sharedCertificates) {
|
||||
if (!pc.isBase()) {
|
||||
pc.archive();
|
||||
certificateManager.update(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
certificate.archive();
|
||||
certificateManager.update(certificate);
|
||||
|
||||
String deleteCompletedMessage = "Certificate successfully deleted";
|
||||
messages.addInfo(deleteCompletedMessage);
|
||||
LOGGER.info(deleteCompletedMessage);
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: " + id;
|
||||
messages.addError(uuidError);
|
||||
LOGGER.error(uuidError, ex);
|
||||
} catch (DBManagerException ex) {
|
||||
String dbError = "Failed to archive cert: " + id;
|
||||
messages.addError(dbError);
|
||||
LOGGER.error(dbError, ex);
|
||||
}
|
||||
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
return redirectTo(getCertificatePage(certificateType), new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download the cert by writing it to the response stream
|
||||
* for download.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param id the UUID of the cert to download
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@RequestMapping(value = "/{certificateType}/download", method = RequestMethod.GET)
|
||||
public void download(
|
||||
@PathVariable("certificateType") final String certificateType,
|
||||
@RequestParam final String id,
|
||||
final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOGGER.info("Handling request to download " + id);
|
||||
|
||||
try {
|
||||
UUID uuid = UUID.fromString(id);
|
||||
Certificate certificate = getCertificateById(certificateType, uuid, certificateManager);
|
||||
if (certificate == null) {
|
||||
// Use the term "record" here to avoid user confusion b/t cert and cred
|
||||
String notFoundMessage = "Unable to locate record with ID: " + uuid;
|
||||
LOGGER.warn(notFoundMessage);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
} else {
|
||||
StringBuilder fileName = new StringBuilder("filename=\"");
|
||||
fileName.append(getCertificateClass(certificateType).getSimpleName());
|
||||
fileName.append("_");
|
||||
fileName.append(certificate.getSerialNumber());
|
||||
fileName.append(".cer\"");
|
||||
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment;" + fileName);
|
||||
response.setContentType("application/octet-stream");
|
||||
|
||||
// write cert to output stream
|
||||
response.getOutputStream().write(certificate.getRawBytes());
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: " + id;
|
||||
LOGGER.error(uuidError, ex);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download the ACA cert by writing it to the response
|
||||
* stream for download.
|
||||
*
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
*
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/trust-chain/download-aca-cert", method = RequestMethod.GET)
|
||||
public void downloadAcaCertificate(final HttpServletResponse response)
|
||||
throws IOException {
|
||||
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"hirs-aca-cert.cer\"");
|
||||
response.setContentType("application/octet-stream");
|
||||
|
||||
// write cert to output stream
|
||||
response.getOutputStream().write(certificateAuthorityCredential.getRawBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download the certs by writing it to the response stream
|
||||
* for download in bulk.
|
||||
*
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@RequestMapping(value = "/trust-chain/bulk", method = RequestMethod.GET)
|
||||
public void caBulkDownload(final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOGGER.info("Handling request to download all trust chain certificates");
|
||||
String fileName = "trust-chain.zip";
|
||||
String zipFileName;
|
||||
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
|
||||
response.setContentType("application/zip");
|
||||
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
|
||||
// get all files
|
||||
for (CertificateAuthorityCredential ca : CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.getCertificates()) {
|
||||
zipFileName = String.format("ca-certificates[%s].cer",
|
||||
Integer.toHexString(ca.getCertificateHash()));
|
||||
// configure the zip entry, the properties of the 'file'
|
||||
ZipEntry zipEntry = new ZipEntry(zipFileName);
|
||||
zipEntry.setSize((long) ca.getRawBytes().length * Byte.SIZE);
|
||||
zipEntry.setTime(System.currentTimeMillis());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
// the content of the resource
|
||||
StreamUtils.copy(ca.getRawBytes(), zipOut);
|
||||
zipOut.closeEntry();
|
||||
}
|
||||
zipOut.finish();
|
||||
// write cert to output stream
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: ";
|
||||
LOGGER.error(uuidError, ex);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download the certs by writing it to the response stream
|
||||
* for download in bulk.
|
||||
*
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@RequestMapping(value = "/platform-credentials/bulk", method = RequestMethod.GET)
|
||||
public void pcBulkDownload(final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOGGER.info("Handling request to download all platform certificates");
|
||||
String fileName = "platform_certificates.zip";
|
||||
String zipFileName;
|
||||
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
|
||||
response.setContentType("application/zip");
|
||||
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
|
||||
// get all files
|
||||
for (PlatformCredential pc : PlatformCredential.select(certificateManager)
|
||||
.getCertificates()) {
|
||||
zipFileName = String.format("Platform_Certificates[%s].cer",
|
||||
Integer.toHexString(pc.getCertificateHash()));
|
||||
// configure the zip entry, the properties of the 'file'
|
||||
ZipEntry zipEntry = new ZipEntry(zipFileName);
|
||||
zipEntry.setSize((long) pc.getRawBytes().length * Byte.SIZE);
|
||||
zipEntry.setTime(System.currentTimeMillis());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
// the content of the resource
|
||||
StreamUtils.copy(pc.getRawBytes(), zipOut);
|
||||
zipOut.closeEntry();
|
||||
}
|
||||
zipOut.finish();
|
||||
// write cert to output stream
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: ";
|
||||
LOGGER.error(uuidError, ex);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download the certs by writing it to the response stream
|
||||
* for download in bulk.
|
||||
*
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@RequestMapping(value = "/issued-certificates/bulk", method = RequestMethod.GET)
|
||||
public void icBulkDownload(final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOGGER.info("Handling request to download all issued certificates");
|
||||
String fileName = "issued_certificates.zip";
|
||||
String zipFileName;
|
||||
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
|
||||
response.setContentType("application/zip");
|
||||
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
|
||||
// get all files
|
||||
for (IssuedAttestationCertificate ic : IssuedAttestationCertificate
|
||||
.select(certificateManager)
|
||||
.getCertificates()) {
|
||||
zipFileName = String.format("Issued_Certificates[%s].cer",
|
||||
Integer.toHexString(ic.getCertificateHash()));
|
||||
// configure the zip entry, the properties of the 'file'
|
||||
ZipEntry zipEntry = new ZipEntry(zipFileName);
|
||||
zipEntry.setSize((long) ic.getRawBytes().length * Byte.SIZE);
|
||||
zipEntry.setTime(System.currentTimeMillis());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
// the content of the resource
|
||||
StreamUtils.copy(ic.getRawBytes(), zipOut);
|
||||
zipOut.closeEntry();
|
||||
}
|
||||
zipOut.finish();
|
||||
// write cert to output stream
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: ";
|
||||
LOGGER.error(uuidError, ex);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download the certs by writing it to the response stream
|
||||
* for download in bulk.
|
||||
*
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@RequestMapping(value = "/endorsement-key-credentials/bulk", method = RequestMethod.GET)
|
||||
public void ekBulkDownload(final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOGGER.info("Handling request to download all endorsement certificates");
|
||||
String fileName = "endorsement_certificates.zip";
|
||||
String zipFileName;
|
||||
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
|
||||
response.setContentType("application/zip");
|
||||
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
|
||||
// get all files
|
||||
for (EndorsementCredential ek : EndorsementCredential
|
||||
.select(certificateManager)
|
||||
.getCertificates()) {
|
||||
zipFileName = String.format("Endorsement_Certificates[%s].cer",
|
||||
Integer.toHexString(ek.getCertificateHash()));
|
||||
// configure the zip entry, the properties of the 'file'
|
||||
ZipEntry zipEntry = new ZipEntry(zipFileName);
|
||||
zipEntry.setSize((long) ek.getRawBytes().length * Byte.SIZE);
|
||||
zipEntry.setTime(System.currentTimeMillis());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
// the content of the resource
|
||||
StreamUtils.copy(ek.getRawBytes(), zipOut);
|
||||
zipOut.closeEntry();
|
||||
}
|
||||
zipOut.finish();
|
||||
// write cert to output stream
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: ";
|
||||
LOGGER.error(uuidError, ex);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload and processes a credential.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param files the files to process
|
||||
* @param attr the redirection attributes
|
||||
* @return the redirection view
|
||||
* @throws URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "/{certificateType}/upload", method = RequestMethod.POST)
|
||||
protected RedirectView upload(
|
||||
@PathVariable("certificateType") final String certificateType,
|
||||
@RequestParam("file") final MultipartFile[] files,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
|
||||
for (MultipartFile file : files) {
|
||||
//Parse certificate
|
||||
Certificate certificate = parseCertificate(certificateType, file, messages);
|
||||
|
||||
//Store only if it was parsed
|
||||
if (certificate != null) {
|
||||
storeCertificate(
|
||||
certificateType,
|
||||
file.getOriginalFilename(),
|
||||
messages, certificate,
|
||||
certificateManager);
|
||||
}
|
||||
}
|
||||
|
||||
//Add messages to the model
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
|
||||
return redirectTo(getCertificatePage(certificateType), new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page based on the certificate type.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @return the page for the certificate type.
|
||||
*/
|
||||
private static Page getCertificatePage(final String certificateType) {
|
||||
// get page information (default to TRUST_CHAIN)
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
return Page.PLATFORM_CREDENTIALS;
|
||||
case ENDORSEMENTCREDENTIAL:
|
||||
return Page.ENDORSEMENT_KEY_CREDENTIALS;
|
||||
case ISSUEDCERTIFICATES:
|
||||
return Page.ISSUED_CERTIFICATES;
|
||||
case TRUSTCHAIN:
|
||||
default:
|
||||
return Page.TRUST_CHAIN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the concrete certificate class type to query for.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @return the certificate class type
|
||||
*/
|
||||
private static Class<? extends Certificate> getCertificateClass(final String certificateType) {
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
return PlatformCredential.class;
|
||||
case ENDORSEMENTCREDENTIAL:
|
||||
return EndorsementCredential.class;
|
||||
case ISSUEDCERTIFICATES:
|
||||
return IssuedAttestationCertificate.class;
|
||||
case TRUSTCHAIN:
|
||||
return CertificateAuthorityCredential.class;
|
||||
default:
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unknown certificate type: %s", certificateType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get flag indicating if a device-name join/alias is required for
|
||||
* displaying the table data. This will be true if displaying a cert that is
|
||||
* associated with a device.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @return true if the list criteria modifier requires aliasing the device
|
||||
* table, false otherwise.
|
||||
*/
|
||||
private boolean hasDeviceTableToJoin(final String certificateType) {
|
||||
|
||||
boolean hasDevice = true;
|
||||
// Trust_Chain Credential do not contain the device table to join.
|
||||
if (certificateType.equals(TRUSTCHAIN)) {
|
||||
hasDevice = false;
|
||||
}
|
||||
return hasDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the certificate by ID.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param uuid the ID of the cert
|
||||
* @param certificateManager the certificate manager to query
|
||||
* @return the certificate or null if none is found
|
||||
*/
|
||||
private Certificate getCertificateById(
|
||||
final String certificateType,
|
||||
final UUID uuid,
|
||||
final CertificateManager certificateManager) {
|
||||
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
return PlatformCredential
|
||||
.select(certificateManager)
|
||||
.byEntityId(uuid)
|
||||
.getCertificate();
|
||||
case ENDORSEMENTCREDENTIAL:
|
||||
return EndorsementCredential
|
||||
.select(certificateManager)
|
||||
.byEntityId(uuid)
|
||||
.getCertificate();
|
||||
case ISSUEDCERTIFICATES:
|
||||
return IssuedAttestationCertificate
|
||||
.select(certificateManager)
|
||||
.byEntityId(uuid)
|
||||
.getCertificate();
|
||||
case TRUSTCHAIN:
|
||||
return CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.byEntityId(uuid)
|
||||
.getCertificate();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the certificate by the hash code of its bytes. Looks for both
|
||||
* archived and unarchived certificates.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param certificateHash the hash of the certificate's bytes
|
||||
* @param certificateManager the certificate manager to query
|
||||
* @return the certificate or null if none is found
|
||||
*/
|
||||
private Certificate getCertificateByHash(
|
||||
final String certificateType,
|
||||
final int certificateHash,
|
||||
final CertificateManager certificateManager) {
|
||||
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
return PlatformCredential
|
||||
.select(certificateManager)
|
||||
.includeArchived()
|
||||
.byHashCode(certificateHash)
|
||||
.getCertificate();
|
||||
case ENDORSEMENTCREDENTIAL:
|
||||
return EndorsementCredential
|
||||
.select(certificateManager)
|
||||
.includeArchived()
|
||||
.byHashCode(certificateHash)
|
||||
.getCertificate();
|
||||
case TRUSTCHAIN:
|
||||
return CertificateAuthorityCredential
|
||||
.select(certificateManager)
|
||||
.includeArchived()
|
||||
.byHashCode(certificateHash)
|
||||
.getCertificate();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the certificate by the platform serial number.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param serialNumber the platform serial number
|
||||
* @param certificateManager the certificate manager to query
|
||||
* @return the certificate or null if none is found
|
||||
*/
|
||||
private List<PlatformCredential> getCertificateByBoardSN(
|
||||
final String certificateType,
|
||||
final String serialNumber,
|
||||
final CertificateManager certificateManager) {
|
||||
|
||||
if (serialNumber == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
return PlatformCredential
|
||||
.select(certificateManager)
|
||||
.byBoardSerialNumber(serialNumber)
|
||||
.getCertificates().stream().collect(Collectors.toList());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an uploaded file into a certificate and populates the given model
|
||||
* with error messages if parsing fails.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param file the file being uploaded from the portal
|
||||
* @param messages contains any messages that will be display on the page
|
||||
* @return the parsed certificate or null if parsing failed.
|
||||
*/
|
||||
private Certificate parseCertificate(
|
||||
final String certificateType,
|
||||
final MultipartFile file,
|
||||
final PageMessages messages) {
|
||||
|
||||
LOGGER.info("Received File of Size: " + file.getSize());
|
||||
|
||||
byte[] fileBytes;
|
||||
String fileName = file.getOriginalFilename();
|
||||
|
||||
// build the certificate from the uploaded bytes
|
||||
try {
|
||||
fileBytes = file.getBytes();
|
||||
} catch (IOException e) {
|
||||
final String failMessage = String.format(
|
||||
"Failed to read uploaded file (%s): ", fileName);
|
||||
LOGGER.error(failMessage, e);
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
switch (certificateType) {
|
||||
case PLATFORMCREDENTIAL:
|
||||
return new PlatformCredential(fileBytes);
|
||||
case ENDORSEMENTCREDENTIAL:
|
||||
return new EndorsementCredential(fileBytes);
|
||||
case TRUSTCHAIN:
|
||||
return new CertificateAuthorityCredential(fileBytes);
|
||||
default:
|
||||
final String failMessage = String.format("Failed to parse uploaded file "
|
||||
+ "(%s). Invalid certificate type: %s", fileName, certificateType);
|
||||
LOGGER.error(failMessage);
|
||||
messages.addError(failMessage);
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
final String failMessage = String.format(
|
||||
"Failed to parse uploaded file (%s): ", fileName);
|
||||
LOGGER.error(failMessage, e);
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
return null;
|
||||
} catch (DecoderException dEx) {
|
||||
final String failMessage = String.format(
|
||||
"Failed to parse uploaded pem file (%s): ", fileName);
|
||||
LOGGER.error(failMessage, dEx);
|
||||
messages.addError(failMessage + dEx.getMessage());
|
||||
return null;
|
||||
} catch (IllegalArgumentException e) {
|
||||
final String failMessage = String.format(
|
||||
"Certificate format not recognized(%s): ", fileName);
|
||||
LOGGER.error(failMessage, e);
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the given certificate in the database.
|
||||
*
|
||||
* @param certificateType String containing the certificate type
|
||||
* @param fileName contain the name of the file of the certificate to
|
||||
* be stored
|
||||
* @param messages contains any messages that will be display on the page
|
||||
* @param certificate the certificate to store
|
||||
* @param certificateManager the DB manager to use
|
||||
* @return the messages for the page
|
||||
*/
|
||||
private void storeCertificate(
|
||||
final String certificateType,
|
||||
final String fileName,
|
||||
final PageMessages messages,
|
||||
final Certificate certificate,
|
||||
final CertificateManager certificateManager) {
|
||||
|
||||
Certificate existingCertificate;
|
||||
|
||||
// look for an identical certificate in the database
|
||||
try {
|
||||
existingCertificate = getCertificateByHash(
|
||||
certificateType,
|
||||
certificate.getCertificateHash(),
|
||||
certificateManager);
|
||||
} catch (DBManagerException e) {
|
||||
final String failMessage = "Querying for existing certificate failed ("
|
||||
+ fileName + "): ";
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
LOGGER.error(failMessage, e);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// save the new certificate if no match is found
|
||||
if (existingCertificate == null) {
|
||||
if (certificateType.equals(PLATFORMCREDENTIAL)) {
|
||||
PlatformCredential platformCertificate = (PlatformCredential) certificate;
|
||||
if (platformCertificate.isBase()) {
|
||||
List<PlatformCredential> sharedCertificates = getCertificateByBoardSN(
|
||||
certificateType,
|
||||
platformCertificate.getPlatformSerial(),
|
||||
certificateManager);
|
||||
|
||||
if (sharedCertificates != null) {
|
||||
for (PlatformCredential pc : sharedCertificates) {
|
||||
if (pc.isBase()) {
|
||||
final String failMessage = "Storing certificate failed: "
|
||||
+ "platform credential "
|
||||
+ "chain (" + pc.getPlatformSerial()
|
||||
+ ") base already exists in this chain ("
|
||||
+ fileName + ")";
|
||||
messages.addError(failMessage);
|
||||
LOGGER.error(failMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /**else {
|
||||
// this is a delta, check if the holder exists.
|
||||
PlatformCredential holderPC = PlatformCredential
|
||||
.select(certificateManager)
|
||||
.bySerialNumber(platformCertificate.getHolderSerialNumber())
|
||||
.getCertificate();
|
||||
|
||||
if (holderPC == null) {
|
||||
final String failMessage = "Storing certificate failed: "
|
||||
+ "delta credential"
|
||||
+ " must have an existing holder stored. "
|
||||
+ "Credential serial "
|
||||
+ platformCertificate.getHolderSerialNumber()
|
||||
+ " doesn't exist.";
|
||||
messages.addError(failMessage);
|
||||
LOGGER.error(failMessage);
|
||||
return;
|
||||
}
|
||||
}**/
|
||||
}
|
||||
|
||||
certificateManager.save(certificate);
|
||||
|
||||
final String successMsg
|
||||
= String.format("New certificate successfully uploaded (%s): ", fileName);
|
||||
messages.addSuccess(successMsg);
|
||||
LOGGER.info(successMsg);
|
||||
return;
|
||||
}
|
||||
} catch (DBManagerException e) {
|
||||
final String failMessage = String.format("Storing new certificate failed (%s): ",
|
||||
fileName);
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
LOGGER.error(failMessage, e);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// if an identical certificate is archived, update the existing certificate to
|
||||
// unarchive it and change the creation date
|
||||
if (existingCertificate.isArchived()) {
|
||||
existingCertificate.restore();
|
||||
existingCertificate.resetCreateTime();
|
||||
certificateManager.update(existingCertificate);
|
||||
|
||||
final String successMsg = String.format("Pre-existing certificate "
|
||||
+ "found and unarchived (%s): ", fileName);
|
||||
messages.addSuccess(successMsg);
|
||||
LOGGER.info(successMsg);
|
||||
return;
|
||||
}
|
||||
} catch (DBManagerException e) {
|
||||
final String failMessage = String.format("Found an identical"
|
||||
+ " pre-existing certificate in the "
|
||||
+ "archive, but failed to unarchive it (%s): ", fileName);
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
LOGGER.error(failMessage, e);
|
||||
return;
|
||||
}
|
||||
|
||||
// if an identical certificate is already unarchived, do nothing and show a fail message
|
||||
final String failMessage
|
||||
= String.format("Storing certificate failed: an identical"
|
||||
+ " certificate already exists (%s): ", fileName);
|
||||
messages.addError(failMessage);
|
||||
LOGGER.error(failMessage);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.portal.entity.manager.DeviceRepository;
|
||||
import hirs.attestationca.portal.entity.userdefined.Device;
|
||||
import hirs.attestationca.portal.enums.AppraisalStatus;
|
||||
import hirs.attestationca.portal.enums.HealthStatus;
|
||||
import hirs.attestationca.portal.enums.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.attestationca.portal.service.DeviceServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/devices")
|
||||
public class DevicePageController extends PageController<NoPageParams> {
|
||||
/**
|
||||
* https://odrotbohm.de/2013/11/why-field-injection-is-evil/
|
||||
*
|
||||
* Autowiring property vs constructor
|
||||
*/
|
||||
|
||||
private final DeviceServiceImpl deviceServiceImpl;
|
||||
private final DeviceRepository deviceRepository;
|
||||
|
||||
@Autowired
|
||||
public DevicePageController(DeviceServiceImpl deviceServiceImpl,
|
||||
DeviceRepository deviceRepository) {
|
||||
super(Page.DEVICES);
|
||||
this.deviceServiceImpl = deviceServiceImpl;
|
||||
this.deviceRepository = deviceRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
// @RequestMapping(value = "list", produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
// method = RequestMethod.GET)
|
||||
// public DataTableResponse<HashMap<String, Object>> getTableData(
|
||||
// final DataTableInput input) {
|
||||
// String orderColumnName = input.getOrderColumnName();
|
||||
// FilteredRecordsList<HashMap<String, Object>> record
|
||||
// = retrieveDevicesAndAssociatedCertificates(deviceList);
|
||||
// modelMap.put("devices", deviceServiceImpl.retrieveDevices());
|
||||
// return new DataTableResponse<>(record, input);
|
||||
// }
|
||||
|
||||
@GetMapping(value = "populateDevices")
|
||||
public @ResponseBody String addDevice () {
|
||||
deviceRepository.save(new Device("Dell-01", HealthStatus.TRUSTED,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
deviceRepository.save(new Device("Dell-02", HealthStatus.TRUSTED,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
deviceRepository.save(new Device("HP-01", HealthStatus.UNKNOWN,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
deviceRepository.save(new Device("HP-02", HealthStatus.UNTRUSTED,
|
||||
AppraisalStatus.Status.UNKNOWN,
|
||||
Timestamp.valueOf(LocalDateTime.now()), false, "", "This is a summary"));
|
||||
|
||||
return "all";
|
||||
}
|
||||
|
||||
@GetMapping(path="/all")
|
||||
public @ResponseBody Iterable<Device> getAllDevices() {
|
||||
return deviceRepository.findAll();
|
||||
}
|
||||
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.portal.datatables.DataTableInput;
|
||||
import hirs.attestationca.portal.datatables.DataTableResponse;
|
||||
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
|
||||
import static hirs.attestationca.portal.page.Page.DEVICES;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.data.persist.Device;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.data.persist.certificate.DeviceAssociatedCertificate;
|
||||
import hirs.persist.DBManager;
|
||||
import hirs.persist.DeviceManager;
|
||||
|
||||
/**
|
||||
* Controller for the Device page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/devices")
|
||||
public class DevicesPageController extends PageController<NoPageParams> {
|
||||
|
||||
private final DeviceManager deviceManager;
|
||||
private final DBManager<Certificate> certificateDBManager;
|
||||
private static final Logger LOGGER = getLogger(DevicesPageController.class);
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
* @param deviceManager the device manager
|
||||
* @param certificateDBManager the certificate DB manager
|
||||
*/
|
||||
@Autowired
|
||||
public DevicesPageController(
|
||||
final DeviceManager deviceManager,
|
||||
final DBManager<Certificate> certificateDBManager) {
|
||||
super(DEVICES);
|
||||
this.deviceManager = deviceManager;
|
||||
this.certificateDBManager = certificateDBManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of devices using the datatable input for paging, ordering, and
|
||||
* filtering.
|
||||
* @param input the data tables input
|
||||
* @return the data tables response, including the result set and paging information
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "list", produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
method = RequestMethod.GET)
|
||||
public DataTableResponse<HashMap<String, Object>> getTableData(
|
||||
final DataTableInput input) {
|
||||
LOGGER.debug("Handling request for device list");
|
||||
String orderColumnName = input.getOrderColumnName();
|
||||
|
||||
// get all the devices
|
||||
FilteredRecordsList<Device> deviceList =
|
||||
OrderedListQueryDataTableAdapter.getOrderedList(Device.class,
|
||||
deviceManager, input, orderColumnName);
|
||||
|
||||
FilteredRecordsList<HashMap<String, Object>> record
|
||||
= retrieveDevicesAndAssociatedCertificates(deviceList);
|
||||
|
||||
return new DataTableResponse<>(record, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of devices combined with the certificates.
|
||||
* @param deviceList list containing the devices
|
||||
* @return a record list after the device and certificate was mapped together.
|
||||
*/
|
||||
private FilteredRecordsList<HashMap<String, Object>> retrieveDevicesAndAssociatedCertificates(
|
||||
final FilteredRecordsList<Device> deviceList) {
|
||||
FilteredRecordsList<HashMap<String, Object>> records = new FilteredRecordsList<>();
|
||||
// hashmap containing the device-certificate relationship
|
||||
HashMap<String, Object> deviceCertMap = new HashMap<>();
|
||||
Device device;
|
||||
Certificate certificate;
|
||||
|
||||
// parse if there is a Device
|
||||
if (!deviceList.isEmpty()) {
|
||||
// get a list of Certificates that contains the device IDs from the list
|
||||
List<Certificate> certificateList = certificateDBManager.getList(
|
||||
Certificate.class,
|
||||
Restrictions.in("device.id", getDevicesIds(deviceList).toArray()));
|
||||
|
||||
// loop all the devices
|
||||
for (int i = 0; i < deviceList.size(); i++) {
|
||||
// hashmap containing the list of certificates based on the certificate type
|
||||
HashMap<String, List<Object>> certificatePropertyMap = new HashMap<>();
|
||||
|
||||
device = deviceList.get(i);
|
||||
deviceCertMap.put("device", device);
|
||||
|
||||
// loop all the certificates and combined the ones that match the ID
|
||||
for (int j = 0; j < certificateList.size(); j++) {
|
||||
certificate = certificateList.get(j);
|
||||
|
||||
// set the certificate if it's the same ID
|
||||
if (device.getId().equals(
|
||||
((DeviceAssociatedCertificate) certificate).getDevice().getId())) {
|
||||
String certificateId = certificate.getClass().getSimpleName();
|
||||
// create a new list for the certificate type if does not exist
|
||||
// else add it to the current certificate type list
|
||||
List<Object> certificateListFromMap
|
||||
= certificatePropertyMap.get(certificateId);
|
||||
if (certificateListFromMap != null) {
|
||||
certificateListFromMap.add(certificate);
|
||||
} else {
|
||||
certificatePropertyMap.put(certificateId,
|
||||
new ArrayList<>(Collections.singletonList(certificate)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add the device-certificate map to the record
|
||||
deviceCertMap.putAll(certificatePropertyMap);
|
||||
records.add(new HashMap<>(deviceCertMap));
|
||||
deviceCertMap.clear();
|
||||
}
|
||||
}
|
||||
// set pagination values
|
||||
records.setRecordsTotal(deviceList.getRecordsTotal());
|
||||
records.setRecordsFiltered(deviceList.getRecordsFiltered());
|
||||
return records;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of devices IDs.
|
||||
* @param deviceList list containing the devices
|
||||
* @return a list of the devices IDs
|
||||
*/
|
||||
private List<UUID> getDevicesIds(final FilteredRecordsList<Device> deviceList) {
|
||||
List<UUID> deviceIds = new ArrayList<UUID>();
|
||||
|
||||
// loop all the devices
|
||||
for (int i = 0; i < deviceList.size(); i++) {
|
||||
deviceIds.add(deviceList.get(i).getId());
|
||||
}
|
||||
|
||||
return deviceIds;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
|
||||
@Controller("error")
|
||||
public class ErrorController {
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ModelAndView handleException(HttpServletRequest request, Exception ex) {
|
||||
ModelAndView modelAndView = new ModelAndView();
|
||||
|
||||
modelAndView.addObject("exception", ex.getLocalizedMessage());
|
||||
modelAndView.addObject("url", request.getRequestURL());
|
||||
|
||||
modelAndView.setViewName("error");
|
||||
|
||||
return modelAndView;
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import static hirs.attestationca.portal.page.Page.HELP;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Controller for the Help page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/help")
|
||||
public class HelpController extends PageController<NoPageParams> {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private static final String PATH = "/docs";
|
||||
private static final Logger LOGGER = getLogger(HelpController.class);
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*/
|
||||
public HelpController() {
|
||||
super(HELP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
ModelAndView mav = getBaseModelAndView();
|
||||
|
||||
try {
|
||||
File[] documents = new File(
|
||||
applicationContext.getResource(PATH).getFile().getPath()
|
||||
).listFiles();
|
||||
mav.addObject("docs", documents);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("Could not get files from resource.");
|
||||
}
|
||||
|
||||
return mav;
|
||||
}
|
||||
|
||||
}
|
@ -1,16 +1,13 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.portal.enums.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import static hirs.attestationca.portal.page.Page.INDEX;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Controller for the Index page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/index")
|
||||
public class IndexPageController extends PageController<NoPageParams> {
|
||||
@ -19,7 +16,7 @@ public class IndexPageController extends PageController<NoPageParams> {
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*/
|
||||
public IndexPageController() {
|
||||
super(INDEX);
|
||||
super(Page.INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,4 +32,9 @@ public class IndexPageController extends PageController<NoPageParams> {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
// @RequestMapping(value = "/", method = RequestMethod.GET)
|
||||
// public String showIndexPage(ModelMap model) {
|
||||
// model.put("name", "welcome");
|
||||
// return "welcome";
|
||||
// }
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.appraiser.Appraiser;
|
||||
import hirs.appraiser.SupplyChainAppraiser;
|
||||
import hirs.attestationca.portal.model.PolicyPageModel;
|
||||
import hirs.attestationca.portal.entity.userdefined.SupplyChainSettings;
|
||||
import hirs.attestationca.portal.enums.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
import hirs.attestationca.portal.page.PolicyPageModel;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.data.persist.SupplyChainPolicy;
|
||||
import hirs.persist.AppraiserManager;
|
||||
import hirs.persist.PolicyManager;
|
||||
import hirs.persist.PolicyManagerException;
|
||||
import hirs.attestationca.portal.service.SettingsServiceImpl;
|
||||
import hirs.attestationca.portal.utils.exception.PolicyManagerException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
@ -25,9 +25,6 @@ import java.net.URISyntaxException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static hirs.attestationca.portal.page.Page.POLICY;
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* Controller for the Policy page.
|
||||
*/
|
||||
@ -35,7 +32,7 @@ import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
@RequestMapping("/policy")
|
||||
public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
private static final Logger LOGGER = getLogger(PolicyPageController.class);
|
||||
private static final Logger LOGGER = LogManager.getLogger(PolicyPageController.class);
|
||||
|
||||
/**
|
||||
* Represents a web request indicating to enable a setting (based on radio
|
||||
@ -45,8 +42,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
private static final String ENABLED_EXPIRES_PARAMETER_VALUE = "expires";
|
||||
|
||||
private PolicyManager policyManager;
|
||||
private AppraiserManager appraiserManager;
|
||||
private SettingsServiceImpl settingsService;
|
||||
|
||||
/**
|
||||
* Model attribute name used by initPage for the initial data passed to the
|
||||
@ -63,15 +59,16 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param policyManager the policy manager
|
||||
* @param appraiserManager the appraiser manager
|
||||
* @param policyService the policy service
|
||||
*/
|
||||
@Autowired
|
||||
public PolicyPageController(final PolicyManager policyManager,
|
||||
final AppraiserManager appraiserManager) {
|
||||
super(POLICY);
|
||||
this.policyManager = policyManager;
|
||||
this.appraiserManager = appraiserManager;
|
||||
public PolicyPageController(final SettingsServiceImpl policyService) {
|
||||
super(Page.POLICY);
|
||||
this.settingsService = policyService;
|
||||
|
||||
if (this.settingsService.getByName("Default") == null) {
|
||||
this.settingsService.saveSettings(new SupplyChainSettings("Default", "Settings are configured for no validation flags set."));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,11 +82,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
|
||||
// get the basic information to render the page
|
||||
ModelAndView mav = getBaseModelAndView();
|
||||
|
||||
SupplyChainPolicy policy = getDefaultPolicy();
|
||||
SupplyChainSettings policy = getDefaultPolicy();
|
||||
PolicyPageModel pageModel = new PolicyPageModel(policy);
|
||||
mav.addObject(INITIAL_DATA, pageModel);
|
||||
|
||||
@ -106,11 +102,12 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@GetMapping
|
||||
@RequestMapping(value = "update-pc-validation", method = RequestMethod.POST)
|
||||
public RedirectView updatePcVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
@ -119,14 +116,14 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
= ppModel.getPcValidate().equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
// If PC policy setting change results in invalid policy, inform user
|
||||
if (!isPolicyValid(policy.isEcValidationEnabled(), pcValidationOptionEnabled,
|
||||
policy.isPcAttributeValidationEnabled())) {
|
||||
handleUserError(model, messages,
|
||||
"Unable to change Platform Validation setting,"
|
||||
+ " invalid policy configuration.");
|
||||
+ " invalid policy configuration.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
// set the policy option and create display message
|
||||
@ -140,11 +137,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
|
||||
} catch (PolicyManagerException e) {
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
// Log and return any error messages to the user
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA platform validation Policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
@ -157,13 +154,13 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@GetMapping
|
||||
@RequestMapping(value = "update-pc-attribute-validation", method = RequestMethod.POST)
|
||||
public RedirectView updatePcAttributeVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String successMessage;
|
||||
@ -171,7 +168,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
// If PC Attribute Validation is enabled without PC Validation, disallow change
|
||||
if (!isPolicyValid(policy.isEcValidationEnabled(),
|
||||
@ -179,7 +176,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
handleUserError(model, messages,
|
||||
"To enable Platform Attribute Validation, Platform Credential Validation"
|
||||
+ " must also be enabled.");
|
||||
+ " must also be enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
// set the policy option and create display message
|
||||
@ -191,12 +188,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
successMessage = "Platform certificate attribute validation disabled";
|
||||
}
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
|
||||
} catch (PolicyManagerException e) {
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
// Log and return any error messages to the user
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA platform certificate attribute validation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
@ -208,7 +204,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-issue-attestation", method = RequestMethod.POST)
|
||||
public RedirectView updateAttestationVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
@ -224,7 +220,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
if (issuedAttestationOptionEnabled) {
|
||||
successMessage = "Attestation Certificate generation enabled.";
|
||||
@ -235,10 +231,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
policy.setIssueAttestationCertificate(issuedAttestationOptionEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA Attestation Certificate generation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -252,11 +248,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-issue-devid", method = RequestMethod.POST)
|
||||
public RedirectView updateDevIdVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
@ -268,7 +264,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
if (issuedDevIdOptionEnabled) {
|
||||
successMessage = "DevID Certificate generation enabled.";
|
||||
@ -279,10 +275,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
policy.setIssueDevIdCertificate(issuedDevIdOptionEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA DevID Certificate generation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -297,11 +293,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-expire-on", method = RequestMethod.POST)
|
||||
public RedirectView updateExpireOnVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
@ -320,7 +316,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedAttestationOptionEnabled
|
||||
= policy.isIssueAttestationCertificate();
|
||||
|
||||
@ -334,7 +330,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
if (generateCertificateEnabled) {
|
||||
numOfDays = ppModel.getExpirationValue();
|
||||
if (numOfDays == null) {
|
||||
numOfDays = SupplyChainPolicy.TEN_YEARS;
|
||||
numOfDays = SupplyChainSettings.TEN_YEARS;
|
||||
}
|
||||
} else {
|
||||
numOfDays = policy.getValidityDays();
|
||||
@ -349,10 +345,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
policy.setGenerateOnExpiration(generateCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA Attestation Certificate generation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -367,11 +363,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-devid-expire-on", method = RequestMethod.POST)
|
||||
public RedirectView updateDevIdExpireOnVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
@ -390,7 +386,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedDevIdOptionEnabled
|
||||
= policy.isIssueDevIdCertificate();
|
||||
|
||||
@ -404,7 +400,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
if (generateDevIdCertificateEnabled) {
|
||||
numOfDays = ppModel.getDevIdExpirationValue();
|
||||
if (numOfDays == null) {
|
||||
numOfDays = SupplyChainPolicy.TEN_YEARS;
|
||||
numOfDays = SupplyChainSettings.TEN_YEARS;
|
||||
}
|
||||
} else {
|
||||
numOfDays = policy.getDevIdValidityDays();
|
||||
@ -419,10 +415,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
policy.setDevIdExpirationFlag(generateDevIdCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA DevID Certificate generation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -437,11 +433,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-threshold", method = RequestMethod.POST)
|
||||
public RedirectView updateThresholdVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
@ -460,7 +456,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedAttestationOptionEnabled
|
||||
= policy.isIssueAttestationCertificate();
|
||||
|
||||
@ -478,7 +474,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
if (threshold == null || threshold.isEmpty()) {
|
||||
threshold = SupplyChainPolicy.YEAR;
|
||||
threshold = SupplyChainSettings.YEAR;
|
||||
}
|
||||
|
||||
policy.setReissueThreshold(threshold);
|
||||
@ -490,10 +486,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
policy.setGenerateOnExpiration(generateCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA Attestation Certificate generation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -508,11 +504,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param ppModel The data posted by the form mapped into an object.
|
||||
* @param attr RedirectAttributes used to forward data back to the original page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-devid-threshold", method = RequestMethod.POST)
|
||||
public RedirectView updateDevIdThresholdVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr)
|
||||
final RedirectAttributes attr)
|
||||
throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
@ -530,7 +526,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
boolean issuedDevIdOptionEnabled
|
||||
= policy.isIssueDevIdCertificate();
|
||||
|
||||
@ -548,7 +544,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
if (threshold == null || threshold.isEmpty()) {
|
||||
threshold = SupplyChainPolicy.YEAR;
|
||||
threshold = SupplyChainSettings.YEAR;
|
||||
}
|
||||
|
||||
policy.setDevIdReissueThreshold(threshold);
|
||||
@ -560,10 +556,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
policy.setDevIdExpirationFlag(generateDevIdCertificateEnabled);
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA DevID Certificate generation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -578,11 +574,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-ec-validation", method = RequestMethod.POST)
|
||||
public RedirectView updateEcVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
@ -592,14 +588,14 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
= ppModel.getEcValidate().equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If PC Validation is enabled without EC Validation, disallow change
|
||||
if (!isPolicyValid(ecValidationOptionEnabled, policy.isPcValidationEnabled(),
|
||||
policy.isPcAttributeValidationEnabled())) {
|
||||
handleUserError(model, messages,
|
||||
"To disable Endorsement Credential Validation, Platform Validation"
|
||||
+ " must also be disabled.");
|
||||
+ " must also be disabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
// set the policy option and create success message
|
||||
@ -612,10 +608,10 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA endorsement validation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -630,11 +626,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-firmware-validation", method = RequestMethod.POST)
|
||||
public RedirectView updateFirmwareVal(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
@ -644,13 +640,13 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If firmware is enabled without PC attributes, disallow change
|
||||
if (firmwareValidationOptionEnabled && !policy.isPcAttributeValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Firmware validation can not be "
|
||||
+ "enabled without PC Attributes policy enabled.");
|
||||
+ "enabled without PC Attributes policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
@ -661,17 +657,17 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
successMessage = "Firmware validation enabled";
|
||||
} else {
|
||||
policy.setFirmwareValidationEnabled(false);
|
||||
policy.getPcrPolicy().setEnableIgnoreIma(false);
|
||||
policy.getPcrPolicy().setEnableIgnoretBoot(false);
|
||||
policy.setIgnoreImaEnabled(false);
|
||||
policy.setIgnoretBootEnabled(false);
|
||||
policy.setIgnoreOsEvtEnabled(false);
|
||||
successMessage = "Firmware validation disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA firmware validation policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
|
||||
}
|
||||
|
||||
@ -687,11 +683,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-ima-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreIma(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
@ -700,30 +696,30 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore IMA is enabled without firmware, disallow change
|
||||
if (ignoreImaOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Ignore IMA can not be "
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreImaOptionEnabled) {
|
||||
policy.getPcrPolicy().setEnableIgnoreIma(true);
|
||||
policy.setIgnoreImaEnabled(true);
|
||||
successMessage = "Ignore IMA enabled";
|
||||
} else {
|
||||
policy.getPcrPolicy().setEnableIgnoreIma(false);
|
||||
policy.setIgnoreImaEnabled(false);
|
||||
successMessage = "Ignore IMA disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA IMA ignore policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -738,11 +734,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-tboot-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreTboot(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
@ -751,30 +747,30 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore TBoot is enabled without firmware, disallow change
|
||||
if (ignoreTbootOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
handleUserError(model, messages,
|
||||
"Ignore TBoot can not be "
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
+ "enabled without Firmware Validation policy enabled.");
|
||||
return redirectToSelf(new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreTbootOptionEnabled) {
|
||||
policy.getPcrPolicy().setEnableIgnoretBoot(true);
|
||||
policy.setIgnoretBootEnabled(true);
|
||||
successMessage = "Ignore TBoot enabled";
|
||||
} else {
|
||||
policy.getPcrPolicy().setEnableIgnoretBoot(false);
|
||||
policy.setIgnoretBootEnabled(false);
|
||||
successMessage = "Ignore TBoot disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA TBoot ignore policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -789,11 +785,11 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-gpt-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreGptEvents(@ModelAttribute final PolicyPageModel ppModel,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
// set the data received to be populated back into the form
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
@ -802,7 +798,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore TBoot is enabled without firmware, disallow change
|
||||
if (ignoreGptOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
@ -814,18 +810,18 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreGptOptionEnabled) {
|
||||
policy.getPcrPolicy().setEnableIgnoreGpt(true);
|
||||
policy.setIgnoreGptEnabled(true);
|
||||
successMessage = "Ignore GPT enabled";
|
||||
} else {
|
||||
policy.getPcrPolicy().setEnableIgnoreGpt(false);
|
||||
policy.setIgnoreGptEnabled(false);
|
||||
successMessage = "Ignore GPT disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA GPT ignore policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -840,7 +836,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return View containing the url and parameters
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws java.net.URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "update-os-evt-ignore", method = RequestMethod.POST)
|
||||
public RedirectView updateIgnoreOsEvents(
|
||||
@ -855,7 +851,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
.equalsIgnoreCase(ENABLED_CHECKED_PARAMETER_VALUE);
|
||||
|
||||
try {
|
||||
SupplyChainPolicy policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
SupplyChainSettings policy = getDefaultPolicyAndSetInModel(ppModel, model);
|
||||
|
||||
//If Ignore TBoot is enabled without firmware, disallow change
|
||||
if (ignoreOsEvtOptionEnabled && !policy.isFirmwareValidationEnabled()) {
|
||||
@ -867,19 +863,19 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
|
||||
// set the policy option and create success message
|
||||
if (ignoreOsEvtOptionEnabled) {
|
||||
policy.getPcrPolicy().setEnableIgnoreOsEvt(true);
|
||||
policy.getPcrPolicy().setEnableIgnoreGpt(true);
|
||||
policy.setIgnoreOsEvtEnabled(true);
|
||||
policy.setIgnoreGptEnabled(true);
|
||||
successMessage = "Ignore OS Events enabled";
|
||||
} else {
|
||||
policy.getPcrPolicy().setEnableIgnoreOsEvt(false);
|
||||
policy.setIgnoreOsEvtEnabled(false);
|
||||
successMessage = "Ignore OS Events disabled";
|
||||
}
|
||||
|
||||
savePolicyAndApplySuccessMessage(ppModel, model, messages, successMessage, policy);
|
||||
} catch (PolicyManagerException e) {
|
||||
handlePolicyManagerUpdateError(model, messages, e,
|
||||
} catch (PolicyManagerException pmEx) {
|
||||
handlePolicyManagerUpdateError(model, messages, pmEx,
|
||||
"Error changing ACA OS Events ignore policy",
|
||||
"Error updating policy. \n" + e.getMessage());
|
||||
"Error updating policy. \n" + pmEx.getMessage());
|
||||
}
|
||||
|
||||
// return the redirect
|
||||
@ -887,17 +883,17 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
}
|
||||
|
||||
private void handlePolicyManagerUpdateError(final Map<String, Object> model,
|
||||
final PageMessages messages,
|
||||
final PolicyManagerException e,
|
||||
final String message, final String error) {
|
||||
LOGGER.error(message, e);
|
||||
final PageMessages messages,
|
||||
final PolicyManagerException pmEx,
|
||||
final String message, final String error) {
|
||||
LOGGER.error(message, pmEx);
|
||||
messages.addError(error);
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
}
|
||||
|
||||
private void handleUserError(final Map<String, Object> model,
|
||||
final PageMessages messages,
|
||||
final String errorMessage) {
|
||||
final PageMessages messages,
|
||||
final String errorMessage) {
|
||||
messages.addError(errorMessage);
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
}
|
||||
@ -913,8 +909,7 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @return True if policy combination is valid
|
||||
*/
|
||||
private static boolean isPolicyValid(final boolean isEcEnable, final boolean isPcEnable,
|
||||
final boolean isPcAttEnable) {
|
||||
|
||||
final boolean isPcAttEnable) {
|
||||
if (isPcAttEnable && !isPcEnable) {
|
||||
return false;
|
||||
} else {
|
||||
@ -927,11 +922,12 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
*
|
||||
* @return The default Supply Chain Policy
|
||||
*/
|
||||
private SupplyChainPolicy getDefaultPolicy() {
|
||||
final Appraiser supplyChainAppraiser = appraiserManager.getAppraiser(
|
||||
SupplyChainAppraiser.NAME);
|
||||
return (SupplyChainPolicy) policyManager.getDefaultPolicy(
|
||||
supplyChainAppraiser);
|
||||
private SupplyChainSettings getDefaultPolicy() {
|
||||
// final Appraiser supplyChainAppraiser = appraiserService.getAppraiser(
|
||||
// SupplyChainAppraiser.NAME);
|
||||
return new SupplyChainSettings("Default");
|
||||
// return (SupplyChainSettings) policyService.getDefaultPolicy(
|
||||
// supplyChainAppraiser);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -942,23 +938,22 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
* @param model the map of string messages to be displayed on the view
|
||||
* @return The default Supply Chain Policy
|
||||
*/
|
||||
private SupplyChainPolicy getDefaultPolicyAndSetInModel(
|
||||
private SupplyChainSettings getDefaultPolicyAndSetInModel(
|
||||
final PolicyPageModel ppModel, final Map<String, Object> model) {
|
||||
// load the current default policy from the DB
|
||||
SupplyChainPolicy policy = getDefaultPolicy();
|
||||
SupplyChainSettings policy = getDefaultPolicy();
|
||||
|
||||
// set the data received to be populated back into the form
|
||||
model.put(RESULT_DATA, ppModel);
|
||||
return policy;
|
||||
}
|
||||
|
||||
private void savePolicyAndApplySuccessMessage(final PolicyPageModel ppModel,
|
||||
final Map<String, Object> model,
|
||||
final PageMessages messages,
|
||||
final String successMessage,
|
||||
final SupplyChainPolicy policy) {
|
||||
private void savePolicyAndApplySuccessMessage(
|
||||
final PolicyPageModel ppModel, final Map<String, Object> model,
|
||||
final PageMessages messages, final String successMessage,
|
||||
final SupplyChainSettings settings) {
|
||||
// save the policy to the DB
|
||||
policyManager.updatePolicy(policy);
|
||||
settingsService.updateSettings(settings);
|
||||
|
||||
// Log and set the success message
|
||||
messages.addSuccess(successMessage);
|
||||
@ -967,3 +962,4 @@ public class PolicyPageController extends PageController<NoPageParams> {
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,611 +0,0 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.attestationca.portal.page.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
import hirs.attestationca.portal.page.params.ReferenceManifestDetailsPageParams;
|
||||
import hirs.attestationca.service.SupplyChainValidationServiceImpl;
|
||||
import hirs.data.persist.BaseReferenceManifest;
|
||||
import hirs.data.persist.EventLogMeasurements;
|
||||
import hirs.data.persist.ReferenceDigestValue;
|
||||
import hirs.data.persist.ReferenceManifest;
|
||||
import hirs.data.persist.SupportReferenceManifest;
|
||||
import hirs.data.persist.SwidResource;
|
||||
import hirs.data.persist.certificate.CertificateAuthorityCredential;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.DBManagerException;
|
||||
import hirs.persist.ReferenceDigestManager;
|
||||
import hirs.persist.ReferenceEventManager;
|
||||
import hirs.persist.ReferenceManifestManager;
|
||||
import hirs.tpm.eventlog.TCGEventLog;
|
||||
import hirs.tpm.eventlog.TpmPcrEvent;
|
||||
import hirs.utils.ReferenceManifestValidator;
|
||||
import hirs.validation.SupplyChainCredentialValidator;
|
||||
import hirs.validation.SupplyChainValidatorException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Controller for the Reference Manifest Details page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/rim-details")
|
||||
public class ReferenceManifestDetailsPageController
|
||||
extends PageController<ReferenceManifestDetailsPageParams> {
|
||||
|
||||
private final ReferenceManifestManager referenceManifestManager;
|
||||
private final ReferenceDigestManager referenceDigestManager;
|
||||
private final ReferenceEventManager referenceEventManager;
|
||||
private final CertificateManager certificateManager;
|
||||
private static final ReferenceManifestValidator RIM_VALIDATOR
|
||||
= new ReferenceManifestValidator();
|
||||
private static final Logger LOGGER
|
||||
= LogManager.getLogger(ReferenceManifestDetailsPageController.class);
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*
|
||||
* @param referenceManifestManager the reference manifest manager.
|
||||
* @param referenceDigestManager the reference digest manager.
|
||||
* @param referenceEventManager the reference event manager.
|
||||
* @param certificateManager the certificate manager.
|
||||
*/
|
||||
@Autowired
|
||||
public ReferenceManifestDetailsPageController(
|
||||
final ReferenceManifestManager referenceManifestManager,
|
||||
final ReferenceDigestManager referenceDigestManager,
|
||||
final ReferenceEventManager referenceEventManager,
|
||||
final CertificateManager certificateManager) {
|
||||
super(Page.RIM_DETAILS);
|
||||
this.referenceManifestManager = referenceManifestManager;
|
||||
this.referenceDigestManager = referenceDigestManager;
|
||||
this.referenceEventManager = referenceEventManager;
|
||||
this.certificateManager = certificateManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filePath for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from
|
||||
* redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
public ModelAndView initPage(final ReferenceManifestDetailsPageParams params,
|
||||
final Model model) {
|
||||
// get the basic information to render the page
|
||||
ModelAndView mav = getBaseModelAndView();
|
||||
PageMessages messages = new PageMessages();
|
||||
|
||||
// Map with the rim information
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
|
||||
// Check if parameters were set
|
||||
if (params.getId() == null) {
|
||||
String typeError = "ID was not provided";
|
||||
messages.addError(typeError);
|
||||
LOGGER.debug(typeError);
|
||||
mav.addObject(MESSAGES_ATTRIBUTE, messages);
|
||||
} else {
|
||||
try {
|
||||
UUID uuid = UUID.fromString(params.getId());
|
||||
data.putAll(getRimDetailInfo(uuid, referenceManifestManager,
|
||||
referenceDigestManager, referenceEventManager, certificateManager));
|
||||
} catch (IllegalArgumentException iaEx) {
|
||||
String uuidError = "Failed to parse ID from: " + params.getId();
|
||||
messages.addError(uuidError);
|
||||
LOGGER.error(uuidError, iaEx);
|
||||
} catch (Exception ioEx) {
|
||||
LOGGER.error(ioEx);
|
||||
}
|
||||
if (data.isEmpty()) {
|
||||
String notFoundMessage = "Unable to find RIM with ID: " + params.getId();
|
||||
messages.addError(notFoundMessage);
|
||||
LOGGER.warn(notFoundMessage);
|
||||
mav.addObject(MESSAGES_ATTRIBUTE, messages);
|
||||
} else {
|
||||
mav.addObject(INITIAL_DATA, data);
|
||||
}
|
||||
}
|
||||
|
||||
// return the model and view
|
||||
return mav;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the place of an entire class for a string builder.
|
||||
* Gathers all information and returns it for displays.
|
||||
*
|
||||
* @param uuid database reference for the requested RIM.
|
||||
* @param referenceManifestManager the reference manifest manager.
|
||||
* @param referenceDigestManager the reference digest manager.
|
||||
* @param referenceEventManager the reference event manager.
|
||||
* @param certificateManager the certificate manager.
|
||||
* @return mapping of the RIM information from the database.
|
||||
* @throws java.io.IOException error for reading file bytes.
|
||||
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
|
||||
* @throws CertificateException if a certificate doesn't parse.
|
||||
*/
|
||||
public static HashMap<String, Object> getRimDetailInfo(final UUID uuid,
|
||||
final ReferenceManifestManager referenceManifestManager,
|
||||
final ReferenceDigestManager referenceDigestManager,
|
||||
final ReferenceEventManager referenceEventManager,
|
||||
final CertificateManager certificateManager)
|
||||
throws IOException,
|
||||
CertificateException, NoSuchAlgorithmException {
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
|
||||
BaseReferenceManifest bRim = BaseReferenceManifest.select(referenceManifestManager)
|
||||
.byEntityId(uuid).getRIM();
|
||||
|
||||
if (bRim != null) {
|
||||
data.putAll(getBaseRimInfo(bRim, referenceManifestManager, certificateManager));
|
||||
}
|
||||
|
||||
SupportReferenceManifest sRim = SupportReferenceManifest.select(referenceManifestManager)
|
||||
.byEntityId(uuid).getRIM();
|
||||
|
||||
if (sRim != null) {
|
||||
data.putAll(getSupportRimInfo(sRim, referenceManifestManager));
|
||||
}
|
||||
|
||||
EventLogMeasurements bios = EventLogMeasurements.select(referenceManifestManager)
|
||||
.byEntityId(uuid).getRIM();
|
||||
|
||||
if (bios != null) {
|
||||
data.putAll(getMeasurementsRimInfo(bios, referenceManifestManager,
|
||||
referenceDigestManager, referenceEventManager));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the place of an entire class for a string builder.
|
||||
* Gathers all information and returns it for displays.
|
||||
*
|
||||
* @param baseRim established ReferenceManifest Type.
|
||||
* @param referenceManifestManager the reference manifest manager.
|
||||
* @param certificateManager the certificate manager.
|
||||
* @return mapping of the RIM information from the database.
|
||||
* @throws java.io.IOException error for reading file bytes.
|
||||
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
|
||||
* @throws CertificateException if a certificate doesn't parse.
|
||||
*/
|
||||
private static HashMap<String, Object> getBaseRimInfo(
|
||||
final BaseReferenceManifest baseRim,
|
||||
final ReferenceManifestManager referenceManifestManager,
|
||||
final CertificateManager certificateManager)
|
||||
throws IOException, CertificateException, NoSuchAlgorithmException {
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
|
||||
// Software Identity
|
||||
data.put("swidName", baseRim.getSwidName());
|
||||
data.put("swidVersion", baseRim.getSwidVersion());
|
||||
data.put("swidTagVersion", baseRim.getSwidTagVersion());
|
||||
if (baseRim.isSwidCorpus() == 1) {
|
||||
data.put("swidCorpus", "True");
|
||||
} else {
|
||||
data.put("swidCorpus", "False");
|
||||
}
|
||||
if (baseRim.isSwidPatch()) {
|
||||
data.put("swidPatch", "True");
|
||||
} else {
|
||||
data.put("swidPatch", "False");
|
||||
}
|
||||
if (baseRim.isSwidSupplemental()) {
|
||||
data.put("swidSupplemental", "True");
|
||||
} else {
|
||||
data.put("swidSupplemental", "False");
|
||||
}
|
||||
data.put("swidTagId", baseRim.getTagId());
|
||||
// Entity
|
||||
data.put("entityName", baseRim.getEntityName());
|
||||
data.put("entityRegId", baseRim.getEntityRegId());
|
||||
data.put("entityRole", baseRim.getEntityRole());
|
||||
data.put("entityThumbprint", baseRim.getEntityThumbprint());
|
||||
// Link
|
||||
data.put("linkHref", baseRim.getLinkHref());
|
||||
data.put("linkHrefLink", "");
|
||||
for (BaseReferenceManifest bRim : BaseReferenceManifest
|
||||
.select(referenceManifestManager).getRIMs()) {
|
||||
if (baseRim.getLinkHref().contains(bRim.getTagId())) {
|
||||
data.put("linkHrefLink", bRim.getId());
|
||||
}
|
||||
}
|
||||
data.put("linkRel", baseRim.getLinkRel());
|
||||
data.put("platformManufacturer", baseRim.getPlatformManufacturer());
|
||||
data.put("platformManufacturerId", baseRim.getPlatformManufacturerId());
|
||||
data.put("platformModel", baseRim.getPlatformModel());
|
||||
data.put("platformVersion", baseRim.getPlatformVersion());
|
||||
data.put("payloadType", baseRim.getPayloadType());
|
||||
data.put("colloquialVersion", baseRim.getColloquialVersion());
|
||||
data.put("edition", baseRim.getEdition());
|
||||
data.put("product", baseRim.getProduct());
|
||||
data.put("revision", baseRim.getRevision());
|
||||
data.put("bindingSpec", baseRim.getBindingSpec());
|
||||
data.put("bindingSpecVersion", baseRim.getBindingSpecVersion());
|
||||
data.put("pcUriGlobal", baseRim.getPcURIGlobal());
|
||||
data.put("pcUriLocal", baseRim.getPcURILocal());
|
||||
data.put("rimLinkHash", baseRim.getRimLinkHash());
|
||||
if (baseRim.getRimLinkHash() != null) {
|
||||
ReferenceManifest rim = BaseReferenceManifest.select(referenceManifestManager)
|
||||
.byHexDecHash(baseRim.getRimLinkHash()).getRIM();
|
||||
if (rim != null) {
|
||||
data.put("rimLinkId", rim.getId());
|
||||
data.put("linkHashValid", true);
|
||||
} else {
|
||||
data.put("linkHashValid", false);
|
||||
}
|
||||
}
|
||||
data.put("rimType", baseRim.getRimType());
|
||||
|
||||
List<SwidResource> resources = baseRim.parseResource();
|
||||
TCGEventLog logProcessor = null;
|
||||
SupportReferenceManifest support = null;
|
||||
|
||||
if (baseRim.getAssociatedRim() == null) {
|
||||
support = SupportReferenceManifest.select(referenceManifestManager)
|
||||
.byManufacturer(baseRim.getPlatformManufacturer())
|
||||
.getRIM();
|
||||
if (support != null) {
|
||||
baseRim.setAssociatedRim(support.getId());
|
||||
}
|
||||
} else {
|
||||
support = SupportReferenceManifest.select(referenceManifestManager)
|
||||
.byEntityId(baseRim.getAssociatedRim()).getRIM();
|
||||
}
|
||||
// going to have to pull the filename and grab that from the DB
|
||||
// to get the id to make the link
|
||||
RIM_VALIDATOR.setRim(baseRim);
|
||||
for (SwidResource swidRes : resources) {
|
||||
if (support != null && swidRes.getHashValue()
|
||||
.equalsIgnoreCase(support.getHexDecHash())) {
|
||||
RIM_VALIDATOR.validateSupportRimHash(support.getRimBytes(),
|
||||
swidRes.getHashValue());
|
||||
if (RIM_VALIDATOR.isSupportRimValid()) {
|
||||
data.put("supportRimHashValid", true);
|
||||
} else {
|
||||
data.put("supportRimHashValid", false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data.put("associatedRim", baseRim.getAssociatedRim());
|
||||
data.put("swidFiles", resources);
|
||||
if (support != null && (!baseRim.isSwidSupplemental()
|
||||
&& !baseRim.isSwidPatch())) {
|
||||
data.put("pcrList", support.getExpectedPCRList());
|
||||
}
|
||||
|
||||
Set<CertificateAuthorityCredential> certificates =
|
||||
CertificateAuthorityCredential.select(certificateManager)
|
||||
.getCertificates();
|
||||
//Report invalid signature unless RIM_VALIDATOR validates it and cert path is valid
|
||||
data.put("signatureValid", false);
|
||||
for (CertificateAuthorityCredential cert : certificates) {
|
||||
SupplyChainValidationServiceImpl scvsImpl =
|
||||
new SupplyChainValidationServiceImpl(certificateManager);
|
||||
KeyStore keystore = scvsImpl.getCaChain(cert);
|
||||
if (RIM_VALIDATOR.validateXmlSignature(cert)) {
|
||||
try {
|
||||
if (SupplyChainCredentialValidator.verifyCertificate(
|
||||
cert.getX509Certificate(), keystore)) {
|
||||
data.replace("signatureValid", true);
|
||||
break;
|
||||
}
|
||||
} catch (SupplyChainValidatorException e) {
|
||||
LOGGER.error("Error verifying cert chain: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
data.put("skID", RIM_VALIDATOR.getSubjectKeyIdentifier());
|
||||
try {
|
||||
for (CertificateAuthorityCredential cert : certificates) {
|
||||
if (Arrays.equals(cert.getEncodedPublicKey(),
|
||||
RIM_VALIDATOR.getPublicKey().getEncoded())) {
|
||||
data.put("issuerID", cert.getId().toString());
|
||||
}
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
LOGGER.error("Unable to link signing certificate: " + e.getMessage());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the place of an entire class for a string builder.
|
||||
* Gathers all information and returns it for displays.
|
||||
*
|
||||
* @param support established ReferenceManifest Type.
|
||||
* @param referenceManifestManager the reference manifest manager.
|
||||
* @return mapping of the RIM information from the database.
|
||||
* @throws java.io.IOException error for reading file bytes.
|
||||
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
|
||||
* @throws CertificateException if a certificate doesn't parse.
|
||||
*/
|
||||
private static HashMap<String, Object> getSupportRimInfo(
|
||||
final SupportReferenceManifest support,
|
||||
final ReferenceManifestManager referenceManifestManager)
|
||||
throws IOException, CertificateException, NoSuchAlgorithmException {
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
EventLogMeasurements measurements = null;
|
||||
|
||||
if (support.getAssociatedRim() == null) {
|
||||
Set<BaseReferenceManifest> baseRims = BaseReferenceManifest
|
||||
.select(referenceManifestManager)
|
||||
.byRimType(ReferenceManifest.BASE_RIM).getRIMs();
|
||||
for (BaseReferenceManifest baseRim : baseRims) {
|
||||
if (baseRim != null && baseRim.getAssociatedRim() != null
|
||||
&& baseRim.getAssociatedRim().equals(support.getId())) {
|
||||
support.setAssociatedRim(baseRim.getId());
|
||||
try {
|
||||
referenceManifestManager.update(support);
|
||||
} catch (DBManagerException ex) {
|
||||
LOGGER.error("Failed to update Support RIM", ex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// testing this independent of the above if statement because the above
|
||||
// starts off checking if associated rim is null; that is irrelevant for
|
||||
// this statement.
|
||||
measurements = EventLogMeasurements.select(referenceManifestManager)
|
||||
.byHexDecHash(support.getHexDecHash()).getRIM();
|
||||
|
||||
if (support.isSwidPatch()) {
|
||||
data.put("swidPatch", "True");
|
||||
} else {
|
||||
data.put("swidPatch", "False");
|
||||
}
|
||||
if (support.isSwidSupplemental()) {
|
||||
data.put("swidSupplemental", "True");
|
||||
} else {
|
||||
data.put("swidSupplemental", "False");
|
||||
}
|
||||
data.put("swidBase", (!support.isSwidPatch()
|
||||
&& !support.isSwidSupplemental()));
|
||||
data.put("baseRim", support.getTagId());
|
||||
data.put("associatedRim", support.getAssociatedRim());
|
||||
data.put("rimType", support.getRimType());
|
||||
data.put("tagId", support.getTagId());
|
||||
|
||||
TCGEventLog logProcessor = new TCGEventLog(support.getRimBytes());
|
||||
LinkedList<TpmPcrEvent> tpmPcrEvents = new LinkedList<>();
|
||||
TCGEventLog measurementsProcess;
|
||||
if (measurements != null) {
|
||||
measurementsProcess = new TCGEventLog((measurements.getRimBytes()));
|
||||
HashMap<String, TpmPcrEvent> digestMap = new HashMap<>();
|
||||
for (TpmPcrEvent tpe : logProcessor.getEventList()) {
|
||||
digestMap.put(tpe.getEventDigestStr(), tpe);
|
||||
if (!support.isSwidSupplemental()
|
||||
&& !tpe.eventCompare(
|
||||
measurementsProcess.getEventByNumber(
|
||||
tpe.getEventNumber()))) {
|
||||
tpe.setError(true);
|
||||
}
|
||||
tpmPcrEvents.add(tpe);
|
||||
}
|
||||
for (TpmPcrEvent tpe : logProcessor.getEventList()) {
|
||||
tpe.setError(!digestMap.containsKey(tpe.getEventDigestStr()));
|
||||
}
|
||||
data.put("events", tpmPcrEvents);
|
||||
} else {
|
||||
data.put("events", logProcessor.getEventList());
|
||||
}
|
||||
|
||||
getEventSummary(data, logProcessor.getEventList());
|
||||
return data;
|
||||
}
|
||||
|
||||
private static void getEventSummary(final HashMap<String, Object> data,
|
||||
final Collection<TpmPcrEvent> eventList) {
|
||||
boolean crtm = false;
|
||||
boolean bootManager = false;
|
||||
boolean osLoader = false;
|
||||
boolean osKernel = false;
|
||||
boolean acpiTables = false;
|
||||
boolean smbiosTables = false;
|
||||
boolean gptTable = false;
|
||||
boolean bootOrder = false;
|
||||
boolean defaultBootDevice = false;
|
||||
boolean secureBoot = false;
|
||||
boolean pk = false;
|
||||
boolean kek = false;
|
||||
boolean sigDb = false;
|
||||
boolean forbiddenDbx = false;
|
||||
|
||||
String contentStr;
|
||||
for (TpmPcrEvent tpe : eventList) {
|
||||
contentStr = tpe.getEventContentStr();
|
||||
// check for specific events
|
||||
if (contentStr.contains("CRTM")) {
|
||||
crtm = true;
|
||||
} else if (contentStr.contains("shimx64.efi")
|
||||
|| contentStr.contains("bootmgfw.efi")) {
|
||||
bootManager = true;
|
||||
} else if (contentStr.contains("grubx64.efi")
|
||||
|| contentStr.contains("winload.efi")) {
|
||||
osLoader = true;
|
||||
} else if (contentStr.contains("vmlinuz")
|
||||
|| contentStr.contains("ntoskrnl.exe")) {
|
||||
osKernel = true;
|
||||
} else if (contentStr.contains("ACPI")) {
|
||||
acpiTables = true;
|
||||
} else if (contentStr.contains("SMBIOS")) {
|
||||
smbiosTables = true;
|
||||
} else if (contentStr.contains("GPT")) {
|
||||
gptTable = true;
|
||||
} else if (contentStr.contains("BootOrder")) {
|
||||
bootOrder = true;
|
||||
} else if (contentStr.contains("Boot0000")) {
|
||||
defaultBootDevice = true;
|
||||
} else if (contentStr.contains("variable named PK")) {
|
||||
pk = true;
|
||||
} else if (contentStr.contains("variable named KEK")) {
|
||||
kek = true;
|
||||
} else if (contentStr.contains("variable named db")) {
|
||||
if (contentStr.contains("dbx")) {
|
||||
forbiddenDbx = true;
|
||||
} else {
|
||||
sigDb = true;
|
||||
}
|
||||
} else if (contentStr.contains("Secure Boot is enabled")) {
|
||||
secureBoot = true;
|
||||
}
|
||||
}
|
||||
|
||||
data.put("crtm", crtm);
|
||||
data.put("bootManager", bootManager);
|
||||
data.put("osLoader", osLoader);
|
||||
data.put("osKernel", osKernel);
|
||||
data.put("acpiTables", acpiTables);
|
||||
data.put("smbiosTables", smbiosTables);
|
||||
data.put("gptTable", gptTable);
|
||||
data.put("bootOrder", bootOrder);
|
||||
data.put("defaultBootDevice", defaultBootDevice);
|
||||
data.put("secureBoot", secureBoot);
|
||||
data.put("pk", pk);
|
||||
data.put("kek", kek);
|
||||
data.put("sigDb", sigDb);
|
||||
data.put("forbiddenDbx", forbiddenDbx);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the place of an entire class for a string builder.
|
||||
* Gathers all information and returns it for displays.
|
||||
*
|
||||
* @param measurements established ReferenceManifest Type.
|
||||
* @param referenceManifestManager the reference manifest manager.
|
||||
* @param referenceDigestManager the reference digest manager.
|
||||
* @param referenceEventManager the reference event manager.
|
||||
* @return mapping of the RIM information from the database.
|
||||
* @throws java.io.IOException error for reading file bytes.
|
||||
* @throws NoSuchAlgorithmException If an unknown Algorithm is encountered.
|
||||
* @throws CertificateException if a certificate doesn't parse.
|
||||
*/
|
||||
private static HashMap<String, Object> getMeasurementsRimInfo(
|
||||
final EventLogMeasurements measurements,
|
||||
final ReferenceManifestManager referenceManifestManager,
|
||||
final ReferenceDigestManager referenceDigestManager,
|
||||
final ReferenceEventManager referenceEventManager)
|
||||
throws IOException, CertificateException, NoSuchAlgorithmException {
|
||||
HashMap<String, Object> data = new HashMap<>();
|
||||
LinkedList<TpmPcrEvent> livelogEvents = new LinkedList<>();
|
||||
BaseReferenceManifest base = null;
|
||||
List<SupportReferenceManifest> supports = new ArrayList<>();
|
||||
SupportReferenceManifest baseSupport = null;
|
||||
|
||||
data.put("supportFilename", "Blank");
|
||||
data.put("supportId", "");
|
||||
data.put("associatedRim", "");
|
||||
data.put("rimType", measurements.getRimType());
|
||||
data.put("hostName", measurements.getDeviceName());
|
||||
data.put("validationResult", measurements.getOverallValidationResult());
|
||||
data.put("swidBase", true);
|
||||
|
||||
List<ReferenceDigestValue> eventValues = new ArrayList<>();
|
||||
if (measurements.getDeviceName() != null) {
|
||||
supports.addAll(SupportReferenceManifest
|
||||
.select(referenceManifestManager)
|
||||
.byDeviceName(measurements
|
||||
.getDeviceName()).getRIMs());
|
||||
for (SupportReferenceManifest support : supports) {
|
||||
if (support.isBaseSupport()) {
|
||||
baseSupport = support;
|
||||
}
|
||||
}
|
||||
|
||||
if (baseSupport != null) {
|
||||
data.put("supportFilename", baseSupport.getFileName());
|
||||
data.put("supportId", baseSupport.getId());
|
||||
|
||||
base = BaseReferenceManifest
|
||||
.select(referenceManifestManager)
|
||||
.byEntityId(baseSupport.getAssociatedRim())
|
||||
.getRIM();
|
||||
data.put("tagId", baseSupport.getTagId());
|
||||
|
||||
if (base != null) {
|
||||
data.put("associatedRim", base.getId());
|
||||
}
|
||||
|
||||
eventValues.addAll(referenceEventManager.getValuesByRimId(base));
|
||||
}
|
||||
}
|
||||
|
||||
TCGEventLog measurementLog = new TCGEventLog(measurements.getRimBytes());
|
||||
Map<String, ReferenceDigestValue> eventValueMap = new HashMap<>();
|
||||
|
||||
for (ReferenceDigestValue rdv : eventValues) {
|
||||
eventValueMap.put(rdv.getDigestValue(), rdv);
|
||||
}
|
||||
for (TpmPcrEvent measurementEvent : measurementLog.getEventList()) {
|
||||
if (!eventValueMap.containsKey(measurementEvent.getEventDigestStr())) {
|
||||
livelogEvents.add(measurementEvent);
|
||||
}
|
||||
}
|
||||
|
||||
if (!supports.isEmpty()) {
|
||||
Map<String, List<TpmPcrEvent>> baselineLogEvents = new HashMap<>();
|
||||
List<TpmPcrEvent> matchedEvents = null;
|
||||
List<TpmPcrEvent> combinedBaselines = new LinkedList<>();
|
||||
for (SupportReferenceManifest support : supports) {
|
||||
combinedBaselines.addAll(support.getEventLog());
|
||||
}
|
||||
String bootVariable;
|
||||
String variablePrefix = "Variable Name:";
|
||||
String variableSuffix = "UEFI_GUID";
|
||||
for (TpmPcrEvent tpe : livelogEvents) {
|
||||
matchedEvents = new ArrayList<>();
|
||||
for (TpmPcrEvent tpmPcrEvent : combinedBaselines) {
|
||||
if (tpmPcrEvent.getEventType() == tpe.getEventType()) {
|
||||
if (tpe.getEventContentStr().contains(variablePrefix)) {
|
||||
bootVariable = tpe.getEventContentStr().substring((
|
||||
tpe.getEventContentStr().indexOf(variablePrefix)
|
||||
+ variablePrefix.length()),
|
||||
tpe.getEventContentStr().indexOf(variableSuffix));
|
||||
if (tpmPcrEvent.getEventContentStr().contains(bootVariable)) {
|
||||
matchedEvents.add(tpmPcrEvent);
|
||||
}
|
||||
} else {
|
||||
matchedEvents.add(tpmPcrEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
baselineLogEvents.put(tpe.getEventDigestStr(), matchedEvents);
|
||||
}
|
||||
data.put("eventTypeMap", baselineLogEvents);
|
||||
}
|
||||
|
||||
TCGEventLog logProcessor = new TCGEventLog(measurements.getRimBytes());
|
||||
data.put("livelogEvents", livelogEvents);
|
||||
data.put("events", logProcessor.getEventList());
|
||||
getEventSummary(data, logProcessor.getEventList());
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
@ -1,685 +0,0 @@
|
||||
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.attestationca.portal.datatables.DataTableInput;
|
||||
import hirs.attestationca.portal.datatables.DataTableResponse;
|
||||
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
|
||||
import hirs.attestationca.portal.page.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.PageMessages;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.data.persist.BaseReferenceManifest;
|
||||
import hirs.data.persist.EventLogMeasurements;
|
||||
import hirs.data.persist.ReferenceDigestValue;
|
||||
import hirs.data.persist.ReferenceManifest;
|
||||
import hirs.data.persist.SupportReferenceManifest;
|
||||
import hirs.data.persist.SwidResource;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.persist.CriteriaModifier;
|
||||
import hirs.persist.DBManagerException;
|
||||
import hirs.persist.ReferenceEventManager;
|
||||
import hirs.persist.ReferenceManifestManager;
|
||||
import hirs.tpm.eventlog.TCGEventLog;
|
||||
import hirs.tpm.eventlog.TpmPcrEvent;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
/**
|
||||
* Controller for the Reference Manifest page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/reference-manifests")
|
||||
public class ReferenceManifestPageController
|
||||
extends PageController<NoPageParams> {
|
||||
|
||||
private static final String BIOS_RELEASE_DATE_FORMAT = "yyyy-MM-dd";
|
||||
private static final String LOG_FILE_PATTERN = "([^\\s]+(\\.(?i)(rimpcr|rimel|bin|log))$)";
|
||||
|
||||
private final BiosDateValidator biosValidator;
|
||||
private final ReferenceManifestManager referenceManifestManager;
|
||||
private final ReferenceEventManager referenceEventManager;
|
||||
private static final Logger LOGGER
|
||||
= LogManager.getLogger(ReferenceManifestPageController.class);
|
||||
|
||||
/**
|
||||
* This class was created for the purposes of avoiding findbugs message: As
|
||||
* the JavaDoc states, DateFormats are inherently unsafe for multi-threaded
|
||||
* use. The detector has found a call to an instance of DateFormat that has
|
||||
* been obtained via a static field. This looks suspicious.
|
||||
*
|
||||
* This class can have uses elsewhere but for now it will remain here.
|
||||
*/
|
||||
private static final class BiosDateValidator {
|
||||
|
||||
private final String dateFormat;
|
||||
|
||||
/**
|
||||
* Default constructor that sets the format to parse against.
|
||||
*
|
||||
* @param dateFormat
|
||||
*/
|
||||
BiosDateValidator(final String dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a date by attempting to parse based on format provided.
|
||||
*
|
||||
* @param date string of the given date
|
||||
* @return true if the format matches
|
||||
*/
|
||||
public boolean isValid(final String date) {
|
||||
DateFormat validFormat = new SimpleDateFormat(this.dateFormat);
|
||||
boolean result = true;
|
||||
validFormat.setLenient(false);
|
||||
|
||||
try {
|
||||
validFormat.parse(date);
|
||||
} catch (ParseException pEx) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*
|
||||
* @param referenceManifestManager the reference manifest manager
|
||||
* @param referenceEventManager this is the reference event manager
|
||||
*/
|
||||
@Autowired
|
||||
public ReferenceManifestPageController(
|
||||
final ReferenceManifestManager referenceManifestManager,
|
||||
final ReferenceEventManager referenceEventManager) {
|
||||
super(Page.REFERENCE_MANIFESTS);
|
||||
this.referenceManifestManager = referenceManifestManager;
|
||||
this.referenceEventManager = referenceEventManager;
|
||||
this.biosValidator = new BiosDateValidator(BIOS_RELEASE_DATE_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filePath for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from
|
||||
* redirect.
|
||||
* @return the filePath for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
public ModelAndView initPage(final NoPageParams params,
|
||||
final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of RIMs using the data table input for paging, ordering,
|
||||
* and filtering.
|
||||
*
|
||||
* @param input the data tables input
|
||||
* @return the data tables response, including the result set and paging
|
||||
* information
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/list",
|
||||
produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
method = RequestMethod.GET)
|
||||
public DataTableResponse<ReferenceManifest> getTableData(
|
||||
final DataTableInput input) {
|
||||
LOGGER.debug("Handling request for summary list: " + input);
|
||||
|
||||
String orderColumnName = input.getOrderColumnName();
|
||||
LOGGER.debug("Ordering on column: " + orderColumnName);
|
||||
|
||||
// check that the alert is not archived and that it is in the specified report
|
||||
CriteriaModifier criteriaModifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
criteria.add(Restrictions.isNull(Certificate.ARCHIVE_FIELD));
|
||||
}
|
||||
};
|
||||
FilteredRecordsList<ReferenceManifest> records
|
||||
= OrderedListQueryDataTableAdapter.getOrderedList(
|
||||
ReferenceManifest.class,
|
||||
referenceManifestManager,
|
||||
input, orderColumnName, criteriaModifier);
|
||||
|
||||
LOGGER.debug("Returning list of size: " + records.size());
|
||||
return new DataTableResponse<>(records, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload and processes a reference manifest(s).
|
||||
*
|
||||
* @param files the files to process
|
||||
* @param attr the redirection attributes
|
||||
* @return the redirection view
|
||||
* @throws URISyntaxException if malformed URI
|
||||
* @throws Exception if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "/upload", method = RequestMethod.POST)
|
||||
protected RedirectView upload(
|
||||
@RequestParam("file") final MultipartFile[] files,
|
||||
final RedirectAttributes attr) throws URISyntaxException, Exception {
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
String fileName;
|
||||
Pattern logPattern = Pattern.compile(LOG_FILE_PATTERN);
|
||||
Matcher matcher;
|
||||
boolean supportRIM = false;
|
||||
List<BaseReferenceManifest> baseRims = new ArrayList<>();
|
||||
List<SupportReferenceManifest> supportRims = new ArrayList<>();
|
||||
|
||||
// loop through the files
|
||||
for (MultipartFile file : files) {
|
||||
fileName = file.getOriginalFilename();
|
||||
matcher = logPattern.matcher(fileName);
|
||||
supportRIM = matcher.matches();
|
||||
|
||||
//Parse reference manifests
|
||||
parseRIM(file, supportRIM, messages, baseRims, supportRims);
|
||||
}
|
||||
baseRims.stream().forEach((rim) -> {
|
||||
LOGGER.info(String.format("Storing swidtag %s", rim.getFileName()));
|
||||
storeManifest(messages, rim, false);
|
||||
});
|
||||
supportRims.stream().forEach((rim) -> {
|
||||
LOGGER.info(String.format("Storing event log %s", rim.getFileName()));
|
||||
storeManifest(messages, rim, true);
|
||||
});
|
||||
|
||||
// Prep a map to associated the swidtag payload hash to the swidtag.
|
||||
// pass it in to update support rims that either were uploaded
|
||||
// or already exist
|
||||
// create a map of the supports rims in case an uploaded swidtag
|
||||
// isn't one to one with the uploaded support rims.
|
||||
Map<String, SupportReferenceManifest> updatedSupportRims
|
||||
= updateSupportRimInfo(generatePayloadHashMap(baseRims));
|
||||
|
||||
// look for missing uploaded support rims
|
||||
for (SupportReferenceManifest support : supportRims) {
|
||||
if (!updatedSupportRims.containsKey(support.getHexDecHash())) {
|
||||
// Make sure we are getting the db version of the file
|
||||
updatedSupportRims.put(support.getHexDecHash(),
|
||||
SupportReferenceManifest
|
||||
.select(referenceManifestManager)
|
||||
.byHexDecHash(support.getHexDecHash())
|
||||
.getRIM());
|
||||
}
|
||||
}
|
||||
|
||||
// pass in the updated support rims
|
||||
// and either update or add the events
|
||||
processTpmEvents(new ArrayList<SupportReferenceManifest>(updatedSupportRims.values()));
|
||||
|
||||
//Add messages to the model
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
|
||||
return redirectTo(Page.REFERENCE_MANIFESTS,
|
||||
new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Archives (soft delete) the Reference Integrity Manifest entry.
|
||||
*
|
||||
* @param id the UUID of the rim to delete
|
||||
* @param attr RedirectAttributes used to forward data back to the original
|
||||
* page.
|
||||
* @return redirect to this page
|
||||
* @throws URISyntaxException if malformed URI
|
||||
*/
|
||||
@RequestMapping(value = "/delete", method = RequestMethod.POST)
|
||||
public RedirectView delete(@RequestParam final String id,
|
||||
final RedirectAttributes attr) throws URISyntaxException {
|
||||
LOGGER.info("Handling request to delete " + id);
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
PageMessages messages = new PageMessages();
|
||||
|
||||
try {
|
||||
ReferenceManifest referenceManifest = getRimFromDb(id);
|
||||
|
||||
if (referenceManifest == null) {
|
||||
String notFoundMessage = "Unable to locate RIM with ID: " + id;
|
||||
messages.addError(notFoundMessage);
|
||||
LOGGER.warn(notFoundMessage);
|
||||
} else {
|
||||
referenceManifest.archive();
|
||||
referenceManifestManager.update(referenceManifest);
|
||||
|
||||
String deleteCompletedMessage = "RIM successfully deleted";
|
||||
messages.addInfo(deleteCompletedMessage);
|
||||
LOGGER.info(deleteCompletedMessage);
|
||||
|
||||
// if support rim, update associated events
|
||||
if (referenceManifest instanceof SupportReferenceManifest) {
|
||||
List<ReferenceDigestValue> rdvs = referenceEventManager
|
||||
.getValuesByRimId(referenceManifest);
|
||||
|
||||
for (ReferenceDigestValue rdv : rdvs) {
|
||||
rdv.archive("Support RIM was deleted");
|
||||
referenceEventManager.updateEvent(rdv);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: " + id;
|
||||
messages.addError(uuidError);
|
||||
LOGGER.error(uuidError, ex);
|
||||
} catch (DBManagerException ex) {
|
||||
String dbError = "Failed to archive cert: " + id;
|
||||
messages.addError(dbError);
|
||||
LOGGER.error(dbError, ex);
|
||||
}
|
||||
|
||||
model.put(MESSAGES_ATTRIBUTE, messages);
|
||||
return redirectTo(Page.REFERENCE_MANIFESTS, new NoPageParams(), model, attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download the rim by writing it to the response stream
|
||||
* for download.
|
||||
*
|
||||
* @param id the UUID of the rim to download
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@RequestMapping(value = "/download", method = RequestMethod.GET)
|
||||
public void download(@RequestParam final String id,
|
||||
final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOGGER.info("Handling RIM request to download " + id);
|
||||
|
||||
try {
|
||||
ReferenceManifest referenceManifest = getRimFromDb(id);
|
||||
|
||||
if (referenceManifest == null) {
|
||||
String notFoundMessage = "Unable to locate RIM with ID: " + id;
|
||||
LOGGER.warn(notFoundMessage);
|
||||
// send a 404 error when invalid Reference Manifest
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
} else {
|
||||
StringBuilder fileName = new StringBuilder("filename=\"");
|
||||
fileName.append(referenceManifest.getFileName());
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment;" + fileName);
|
||||
response.setContentType("application/octet-stream");
|
||||
|
||||
// write cert to output stream
|
||||
response.getOutputStream().write(referenceManifest.getRimBytes());
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: " + id;
|
||||
LOGGER.error(uuidError, ex);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles request to download bulk of RIMs by writing it to the response stream
|
||||
* for download in bulk.
|
||||
*
|
||||
* @param response the response object (needed to update the header with the
|
||||
* file name)
|
||||
* @throws java.io.IOException when writing to response output stream
|
||||
*/
|
||||
@RequestMapping(value = "/bulk", method = RequestMethod.GET)
|
||||
public void bulk(final HttpServletResponse response)
|
||||
throws IOException {
|
||||
LOGGER.info("Handling request to download all Reference Integrity Manifests");
|
||||
String fileName = "rims.zip";
|
||||
String zipFileName;
|
||||
|
||||
// Set filename for download.
|
||||
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
|
||||
response.setContentType("application/zip");
|
||||
|
||||
List<ReferenceManifest> referenceManifestList = new LinkedList<>();
|
||||
referenceManifestList.addAll(BaseReferenceManifest
|
||||
.select(referenceManifestManager).getRIMs());
|
||||
referenceManifestList.addAll(SupportReferenceManifest
|
||||
.select(referenceManifestManager).getRIMs());
|
||||
|
||||
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
|
||||
// get all files
|
||||
for (ReferenceManifest rim : referenceManifestList) {
|
||||
if (rim.getFileName().isEmpty()) {
|
||||
zipFileName = "";
|
||||
} else {
|
||||
// configure the zip entry, the properties of the 'file'
|
||||
zipFileName = rim.getFileName();
|
||||
}
|
||||
ZipEntry zipEntry = new ZipEntry(zipFileName);
|
||||
zipEntry.setSize((long) rim.getRimBytes().length * Byte.SIZE);
|
||||
zipEntry.setTime(System.currentTimeMillis());
|
||||
zipOut.putNextEntry(zipEntry);
|
||||
// the content of the resource
|
||||
StreamUtils.copy(rim.getRimBytes(), zipOut);
|
||||
zipOut.closeEntry();
|
||||
}
|
||||
zipOut.finish();
|
||||
// write cert to output stream
|
||||
} catch (IllegalArgumentException ex) {
|
||||
String uuidError = "Failed to parse ID from: ";
|
||||
LOGGER.error(uuidError, ex);
|
||||
// send a 404 error when invalid certificate
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the parameter and looks for this information in the
|
||||
* Database.
|
||||
*
|
||||
* @param id of the RIM
|
||||
* @return the associated RIM from the DB
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private ReferenceManifest getRimFromDb(final String id) throws IllegalArgumentException {
|
||||
UUID uuid = UUID.fromString(id);
|
||||
ReferenceManifest rim = BaseReferenceManifest.select(referenceManifestManager)
|
||||
.byEntityId(uuid).getRIM();
|
||||
|
||||
if (rim == null) {
|
||||
rim = SupportReferenceManifest.select(referenceManifestManager)
|
||||
.byEntityId(uuid).getRIM();
|
||||
}
|
||||
|
||||
if (rim == null) {
|
||||
rim = EventLogMeasurements.select(referenceManifestManager)
|
||||
.byEntityId(uuid).getRIM();
|
||||
}
|
||||
|
||||
return rim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the rim files provided and returns a {@link ReferenceManifest}
|
||||
* object.
|
||||
*
|
||||
* @param file the provide user file via browser.
|
||||
* @param supportRIM matcher result
|
||||
* @param messages the object that handles displaying information to the
|
||||
* user.
|
||||
* @param baseRims object to store multiple files
|
||||
* @param supportRims object to store multiple files
|
||||
* @return a single or collection of reference manifest files.
|
||||
*/
|
||||
private void parseRIM(
|
||||
final MultipartFile file, final boolean supportRIM,
|
||||
final PageMessages messages, final List<BaseReferenceManifest> baseRims,
|
||||
final List<SupportReferenceManifest> supportRims) {
|
||||
|
||||
byte[] fileBytes = new byte[0];
|
||||
String fileName = file.getOriginalFilename();
|
||||
|
||||
// build the manifest from the uploaded bytes
|
||||
try {
|
||||
fileBytes = file.getBytes();
|
||||
} catch (IOException e) {
|
||||
final String failMessage
|
||||
= String.format("Failed to read uploaded file (%s): ", fileName);
|
||||
LOGGER.error(failMessage, e);
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
if (supportRIM) {
|
||||
supportRims.add(new SupportReferenceManifest(fileName, fileBytes));
|
||||
} else {
|
||||
baseRims.add(new BaseReferenceManifest(fileName, fileBytes));
|
||||
}
|
||||
} catch (IOException ioEx) {
|
||||
final String failMessage
|
||||
= String.format("Failed to parse uploaded file (%s): ", fileName);
|
||||
LOGGER.error(failMessage, ioEx);
|
||||
messages.addError(failMessage + ioEx.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the {@link ReferenceManifest} objects.
|
||||
*
|
||||
* @param messages message object for user display of statuses
|
||||
* @param referenceManifest the object to store
|
||||
* @param supportRim boolean flag indicating if this is a support RIM
|
||||
* process.
|
||||
*/
|
||||
private void storeManifest(
|
||||
final PageMessages messages,
|
||||
final ReferenceManifest referenceManifest,
|
||||
final boolean supportRim) {
|
||||
|
||||
ReferenceManifest existingManifest = null;
|
||||
String fileName = referenceManifest.getFileName();
|
||||
MessageDigest digest = null;
|
||||
String rimHash = "";
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException noSaEx) {
|
||||
LOGGER.error(noSaEx);
|
||||
}
|
||||
|
||||
// look for existing manifest in the database
|
||||
try {
|
||||
if (supportRim) {
|
||||
if (digest != null) {
|
||||
rimHash = Hex.encodeHexString(
|
||||
digest.digest(referenceManifest.getRimBytes()));
|
||||
}
|
||||
existingManifest = SupportReferenceManifest
|
||||
.select(referenceManifestManager)
|
||||
.byHexDecHash(rimHash)
|
||||
.includeArchived()
|
||||
.getRIM();
|
||||
} else {
|
||||
if (digest != null) {
|
||||
rimHash = Base64.encodeBase64String(
|
||||
digest.digest(referenceManifest.getRimBytes()));
|
||||
}
|
||||
existingManifest = BaseReferenceManifest
|
||||
.select(referenceManifestManager).byBase64Hash(rimHash)
|
||||
.includeArchived()
|
||||
.getRIM();
|
||||
}
|
||||
} catch (DBManagerException e) {
|
||||
final String failMessage = String.format("Querying for existing certificate "
|
||||
+ "failed (%s): ", fileName);
|
||||
messages.addError(failMessage + e.getMessage());
|
||||
LOGGER.error(failMessage, e);
|
||||
}
|
||||
|
||||
try {
|
||||
// save the new certificate if no match is found
|
||||
if (existingManifest == null) {
|
||||
referenceManifestManager.save(referenceManifest);
|
||||
|
||||
final String successMsg = String.format("RIM successfully uploaded (%s): ",
|
||||
fileName);
|
||||
messages.addSuccess(successMsg);
|
||||
LOGGER.info(successMsg);
|
||||
}
|
||||
} catch (DBManagerException dbmEx) {
|
||||
final String failMessage = String.format("Storing RIM failed (%s): ",
|
||||
fileName);
|
||||
messages.addError(failMessage + dbmEx.getMessage());
|
||||
LOGGER.error(failMessage, dbmEx);
|
||||
}
|
||||
|
||||
try {
|
||||
// if an identical RIM is archived, update the existing RIM to
|
||||
// unarchive it and change the creation date
|
||||
if (existingManifest != null && existingManifest.isArchived()) {
|
||||
existingManifest.restore();
|
||||
existingManifest.resetCreateTime();
|
||||
referenceManifestManager.update(existingManifest);
|
||||
|
||||
final String successMsg
|
||||
= String.format("Pre-existing RIM found and unarchived (%s): ", fileName);
|
||||
messages.addSuccess(successMsg);
|
||||
LOGGER.info(successMsg);
|
||||
}
|
||||
} catch (DBManagerException dbmEx) {
|
||||
final String failMessage = String.format("Found an identical pre-existing RIM in the "
|
||||
+ "archive, but failed to unarchive it (%s): ", fileName);
|
||||
messages.addError(failMessage + dbmEx.getMessage());
|
||||
LOGGER.error(failMessage, dbmEx);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, BaseReferenceManifest> generatePayloadHashMap(
|
||||
final List<BaseReferenceManifest> uploadedBaseRims) {
|
||||
BaseReferenceManifest dbBaseRim;
|
||||
HashMap<String, BaseReferenceManifest> tempMap = new HashMap<>();
|
||||
for (BaseReferenceManifest base : uploadedBaseRims) {
|
||||
// this is done to make sure we have the version with the UUID
|
||||
dbBaseRim = BaseReferenceManifest.select(referenceManifestManager)
|
||||
.byBase64Hash(base.getBase64Hash()).getRIM();
|
||||
if (dbBaseRim != null) {
|
||||
for (SwidResource swid : dbBaseRim.parseResource()) {
|
||||
tempMap.put(swid.getHashValue(), dbBaseRim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempMap;
|
||||
}
|
||||
|
||||
private Map<String, SupportReferenceManifest> updateSupportRimInfo(
|
||||
final Map<String, BaseReferenceManifest> dbBaseRims) {
|
||||
BaseReferenceManifest dbBaseRim;
|
||||
SupportReferenceManifest supportRim;
|
||||
Map<String, SupportReferenceManifest> updatedSupportRims = new HashMap<>();
|
||||
List<String> hashValues = new LinkedList<>(dbBaseRims.keySet());
|
||||
for (String supportHash : hashValues) {
|
||||
supportRim = SupportReferenceManifest.select(referenceManifestManager)
|
||||
.byHexDecHash(supportHash).getRIM();
|
||||
// I have to assume the baseRim is from the database
|
||||
// Updating the id values, manufacturer, model
|
||||
if (supportRim != null && !supportRim.isUpdated()) {
|
||||
dbBaseRim = dbBaseRims.get(supportHash);
|
||||
supportRim.setSwidTagVersion(dbBaseRim.getSwidTagVersion());
|
||||
supportRim.setPlatformManufacturer(dbBaseRim.getPlatformManufacturer());
|
||||
supportRim.setPlatformModel(dbBaseRim.getPlatformModel());
|
||||
supportRim.setTagId(dbBaseRim.getTagId());
|
||||
supportRim.setAssociatedRim(dbBaseRim.getId());
|
||||
supportRim.setUpdated(true);
|
||||
referenceManifestManager.update(supportRim);
|
||||
updatedSupportRims.put(supportHash, supportRim);
|
||||
}
|
||||
}
|
||||
|
||||
return updatedSupportRims;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the support rim is a supplemental or base, this method looks for the
|
||||
* original oem base rim to associate with each event.
|
||||
* @param supportRim assumed db object
|
||||
* @return reference to the base rim
|
||||
*/
|
||||
private ReferenceManifest findBaseRim(final SupportReferenceManifest supportRim) {
|
||||
if (supportRim != null && (supportRim.getId() != null
|
||||
&& !supportRim.getId().toString().equals(""))) {
|
||||
Set<BaseReferenceManifest> baseRims = BaseReferenceManifest
|
||||
.select(referenceManifestManager)
|
||||
.byManufacturerModel(supportRim.getPlatformManufacturer(),
|
||||
supportRim.getPlatformModel()).getRIMs();
|
||||
|
||||
for (BaseReferenceManifest base : baseRims) {
|
||||
if (base.isBase()) {
|
||||
// there should be only one
|
||||
return base;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void processTpmEvents(final List<SupportReferenceManifest> dbSupportRims) {
|
||||
boolean updated = true;
|
||||
List<ReferenceDigestValue> tpmEvents;
|
||||
TCGEventLog logProcessor = null;
|
||||
ReferenceManifest baseRim;
|
||||
|
||||
for (SupportReferenceManifest dbSupport : dbSupportRims) {
|
||||
// So first we'll have to pull values based on support rim
|
||||
// get by support rim id NEXT
|
||||
|
||||
if (dbSupport.getPlatformManufacturer() != null) {
|
||||
tpmEvents = referenceEventManager.getValuesByRimId(dbSupport);
|
||||
baseRim = findBaseRim(dbSupport);
|
||||
if (tpmEvents.isEmpty()) {
|
||||
ReferenceDigestValue rdv;
|
||||
try {
|
||||
logProcessor = new TCGEventLog(dbSupport.getRimBytes());
|
||||
for (TpmPcrEvent tpe : logProcessor.getEventList()) {
|
||||
rdv = new ReferenceDigestValue(baseRim.getId(),
|
||||
dbSupport.getId(), dbSupport.getPlatformManufacturer(),
|
||||
dbSupport.getPlatformModel(), tpe.getPcrIndex(),
|
||||
tpe.getEventDigestStr(), tpe.getEventTypeStr(),
|
||||
false, false, updated, tpe.getEventContent());
|
||||
|
||||
this.referenceEventManager.saveValue(rdv);
|
||||
}
|
||||
} catch (CertificateException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
for (ReferenceDigestValue rdv : tpmEvents) {
|
||||
if (!rdv.isUpdated()) {
|
||||
rdv.updateInfo(dbSupport, baseRim.getId());
|
||||
this.referenceEventManager.updateEvent(rdv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,186 +0,0 @@
|
||||
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.attestationca.portal.datatables.DataTableInput;
|
||||
import hirs.attestationca.portal.datatables.DataTableResponse;
|
||||
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
|
||||
import hirs.attestationca.portal.page.Page;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.data.persist.ReferenceDigestValue;
|
||||
import hirs.data.persist.SupportReferenceManifest;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.persist.CriteriaModifier;
|
||||
import hirs.persist.DBManagerException;
|
||||
import hirs.persist.DBReferenceDigestManager;
|
||||
import hirs.persist.DBReferenceEventManager;
|
||||
import hirs.persist.DBReferenceManifestManager;
|
||||
import hirs.persist.ReferenceDigestManager;
|
||||
import hirs.persist.ReferenceEventManager;
|
||||
import hirs.persist.ReferenceManifestManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* Controller for the TPM Events page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/rim-database")
|
||||
public class RimDatabasePageController
|
||||
extends PageController<NoPageParams> {
|
||||
|
||||
private static final String BIOS_RELEASE_DATE_FORMAT = "yyyy-MM-dd";
|
||||
|
||||
private final BiosDateValidator biosValidator;
|
||||
private final ReferenceManifestManager referenceManifestManager;
|
||||
private final ReferenceDigestManager referenceDigestManager;
|
||||
private final ReferenceEventManager referenceEventManager;
|
||||
private static final Logger LOGGER
|
||||
= LogManager.getLogger(RimDatabasePageController.class);
|
||||
|
||||
/**
|
||||
* This class was created for the purposes of avoiding findbugs message: As
|
||||
* the JavaDoc states, DateFormats are inherently unsafe for multi-threaded
|
||||
* use. The detector has found a call to an instance of DateFormat that has
|
||||
* been obtained via a static field. This looks suspicious.
|
||||
* <p>
|
||||
* This class can have uses elsewhere but for now it will remain here.
|
||||
*/
|
||||
private static final class BiosDateValidator {
|
||||
|
||||
private final String dateFormat;
|
||||
|
||||
/**
|
||||
* Default constructor that sets the format to parse against.
|
||||
*
|
||||
* @param dateFormat
|
||||
*/
|
||||
BiosDateValidator(final String dateFormat) {
|
||||
this.dateFormat = dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a date by attempting to parse based on format provided.
|
||||
*
|
||||
* @param date string of the given date
|
||||
* @return true if the format matches
|
||||
*/
|
||||
public boolean isValid(final String date) {
|
||||
DateFormat validFormat = new SimpleDateFormat(this.dateFormat);
|
||||
boolean result = true;
|
||||
validFormat.setLenient(false);
|
||||
|
||||
try {
|
||||
validFormat.parse(date);
|
||||
} catch (ParseException pEx) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
*
|
||||
* @param referenceManifestManager the ReferenceManifestManager object
|
||||
* @param referenceDigestManager the ReferenceDigestManager object
|
||||
* @param referenceEventManager the referenceEventManager object
|
||||
*/
|
||||
@Autowired
|
||||
public RimDatabasePageController(
|
||||
final DBReferenceManifestManager referenceManifestManager,
|
||||
final DBReferenceDigestManager referenceDigestManager,
|
||||
final DBReferenceEventManager referenceEventManager) {
|
||||
super(Page.RIM_DATABASE);
|
||||
this.referenceManifestManager = referenceManifestManager;
|
||||
this.referenceDigestManager = referenceDigestManager;
|
||||
this.referenceEventManager = referenceEventManager;
|
||||
this.biosValidator = new BiosDateValidator(BIOS_RELEASE_DATE_FORMAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filePath for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from
|
||||
* redirect.
|
||||
* @return the filePath for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
public ModelAndView initPage(final NoPageParams params,
|
||||
final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of TPM Events using the data table input for paging, ordering,
|
||||
* and filtering.
|
||||
*
|
||||
* @param input the data tables input
|
||||
* @return the data tables response, including the result set and paging
|
||||
* information
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "/list",
|
||||
produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
method = RequestMethod.GET)
|
||||
public DataTableResponse<ReferenceDigestValue> getTableData(
|
||||
final DataTableInput input) {
|
||||
LOGGER.info("Handling request for summary list: " + input);
|
||||
|
||||
String orderColumnName = input.getOrderColumnName();
|
||||
LOGGER.info("Ordering on column: " + orderColumnName);
|
||||
|
||||
// check that the alert is not archived and that it is in the specified report
|
||||
CriteriaModifier criteriaModifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
criteria.add(Restrictions.isNull(Certificate.ARCHIVE_FIELD));
|
||||
}
|
||||
};
|
||||
|
||||
LOGGER.info("Querying with the following datatableinput: " + input.toString());
|
||||
|
||||
FilteredRecordsList<ReferenceDigestValue> referenceDigestValues =
|
||||
OrderedListQueryDataTableAdapter.getOrderedList(
|
||||
ReferenceDigestValue.class,
|
||||
referenceEventManager,
|
||||
input, orderColumnName, criteriaModifier);
|
||||
|
||||
SupportReferenceManifest support;
|
||||
for (ReferenceDigestValue rdv : referenceDigestValues) {
|
||||
// We are updating the base rim ID field if necessary and
|
||||
if (rdv.getBaseRimId() == null) {
|
||||
support = SupportReferenceManifest.select(referenceManifestManager)
|
||||
.byEntityId(rdv.getSupportRimId()).getRIM();
|
||||
if (support != null) {
|
||||
rdv.setBaseRimId(support.getAssociatedRim());
|
||||
try {
|
||||
referenceEventManager.updateEvent(rdv);
|
||||
} catch (DBManagerException e) {
|
||||
LOGGER.error("Failed to update TPM Event with Base RIM ID");
|
||||
LOGGER.error(rdv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new DataTableResponse<>(referenceDigestValues, input);
|
||||
}
|
||||
}
|
@ -1,446 +0,0 @@
|
||||
package hirs.attestationca.portal.page.controllers;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import hirs.FilteredRecordsList;
|
||||
import hirs.attestationca.portal.datatables.DataTableInput;
|
||||
import hirs.attestationca.portal.datatables.DataTableResponse;
|
||||
import hirs.attestationca.portal.datatables.OrderedListQueryDataTableAdapter;
|
||||
import hirs.attestationca.portal.page.PageController;
|
||||
import hirs.attestationca.portal.page.params.NoPageParams;
|
||||
import hirs.data.persist.SupplyChainValidationSummary;
|
||||
import hirs.data.persist.certificate.Certificate;
|
||||
import hirs.data.persist.certificate.PlatformCredential;
|
||||
import hirs.data.persist.certificate.attributes.ComponentIdentifier;
|
||||
import hirs.data.persist.certificate.attributes.V2.ComponentIdentifierV2;
|
||||
import hirs.persist.CertificateManager;
|
||||
import hirs.persist.CriteriaModifier;
|
||||
import hirs.persist.CrudManager;
|
||||
import hirs.persist.DeviceManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static hirs.attestationca.portal.page.Page.VALIDATION_REPORTS;
|
||||
import static org.apache.logging.log4j.LogManager.getLogger;
|
||||
|
||||
/**
|
||||
* Controller for the Validation Reports page.
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/validation-reports")
|
||||
public class ValidationReportsPageController extends PageController<NoPageParams> {
|
||||
|
||||
private final CrudManager<SupplyChainValidationSummary> supplyChainValidatorSummaryManager;
|
||||
private final CertificateManager certificateManager;
|
||||
private final DeviceManager deviceManager;
|
||||
|
||||
private static String systemColumnHeaders = "Verified Manufacturer,"
|
||||
+ "Model,SN,Verification Date,Device Status";
|
||||
private static String componentColumnHeaders = "Component name,Component manufacturer,"
|
||||
+ "Component model,Component SN,Issuer,Component status";
|
||||
private static final String DEFAULT_COMPANY = "AllDevices";
|
||||
private static final String UNDEFINED = "undefined";
|
||||
private static final String TRUE = "true";
|
||||
private static final Logger LOGGER = getLogger(ValidationReportsPageController.class);
|
||||
|
||||
/**
|
||||
* Constructor providing the Page's display and routing specification.
|
||||
* @param supplyChainValidatorSummaryManager the manager
|
||||
* @param certificateManager the certificate manager
|
||||
* @param deviceManager the device manager
|
||||
*/
|
||||
@Autowired
|
||||
public ValidationReportsPageController(
|
||||
final CrudManager<SupplyChainValidationSummary> supplyChainValidatorSummaryManager,
|
||||
final CertificateManager certificateManager,
|
||||
final DeviceManager deviceManager) {
|
||||
super(VALIDATION_REPORTS);
|
||||
this.supplyChainValidatorSummaryManager = supplyChainValidatorSummaryManager;
|
||||
this.certificateManager = certificateManager;
|
||||
this.deviceManager = deviceManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path for the view and the data model for the page.
|
||||
*
|
||||
* @param params The object to map url parameters into.
|
||||
* @param model The data model for the request. Can contain data from redirect.
|
||||
* @return the path for the view and data model for the page.
|
||||
*/
|
||||
@Override
|
||||
@RequestMapping
|
||||
public ModelAndView initPage(final NoPageParams params, final Model model) {
|
||||
return getBaseModelAndView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of validation summaries per the data table input query.
|
||||
* @param input the data table query.
|
||||
* @return the data table response containing the supply chain summary records
|
||||
*/
|
||||
@ResponseBody
|
||||
@RequestMapping(value = "list", produces = MediaType.APPLICATION_JSON_VALUE,
|
||||
method = RequestMethod.GET)
|
||||
public DataTableResponse<SupplyChainValidationSummary> getTableData(
|
||||
final DataTableInput input) {
|
||||
|
||||
LOGGER.debug("Handling request for summary list: " + input);
|
||||
|
||||
// attempt to get the column property based on the order index.
|
||||
String orderColumnName = input.getOrderColumnName();
|
||||
|
||||
LOGGER.debug("Ordering on column: " + orderColumnName);
|
||||
|
||||
// define an alias so the composite object, device, can be used by the
|
||||
// datatables / query. This is necessary so the device.name property can
|
||||
// be used.
|
||||
CriteriaModifier criteriaModifier = new CriteriaModifier() {
|
||||
@Override
|
||||
public void modify(final Criteria criteria) {
|
||||
criteria.add(Restrictions.isNull(Certificate.ARCHIVE_FIELD));
|
||||
criteria.createAlias("device", "device");
|
||||
}
|
||||
};
|
||||
|
||||
FilteredRecordsList<SupplyChainValidationSummary> records =
|
||||
OrderedListQueryDataTableAdapter.getOrderedList(
|
||||
SupplyChainValidationSummary.class,
|
||||
supplyChainValidatorSummaryManager, input, orderColumnName,
|
||||
criteriaModifier);
|
||||
|
||||
return new DataTableResponse<>(records, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method handles downloading a validation report.
|
||||
* @param request object
|
||||
* @param response object
|
||||
* @throws IOException thrown by BufferedWriter object
|
||||
*/
|
||||
@SuppressWarnings({"checkstyle:magicnumber", "checkstyle:methodlength" })
|
||||
@RequestMapping(value = "download", method = RequestMethod.POST)
|
||||
public void download(final HttpServletRequest request,
|
||||
final HttpServletResponse response) throws IOException {
|
||||
|
||||
LOGGER.info("Downloading validation report");
|
||||
String company = "";
|
||||
String contractNumber = "";
|
||||
Pattern pattern = Pattern.compile("^\\w*$");
|
||||
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd");
|
||||
DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
|
||||
LocalDate startDate = null;
|
||||
LocalDate endDate = null;
|
||||
ArrayList<LocalDate> createTimes = new ArrayList<LocalDate>();
|
||||
String[] deviceNames = new String[]{};
|
||||
String columnHeaders = "";
|
||||
boolean systemOnly = false;
|
||||
boolean componentOnly = false;
|
||||
String filterManufacturer = "";
|
||||
String filterSerial = "";
|
||||
boolean jsonVersion = false;
|
||||
|
||||
Enumeration parameters = request.getParameterNames();
|
||||
while (parameters.hasMoreElements()) {
|
||||
String parameter = (String) parameters.nextElement();
|
||||
String parameterValue = request.getParameter(parameter);
|
||||
LOGGER.info(parameter + ": " + parameterValue);
|
||||
switch (parameter) {
|
||||
case "company":
|
||||
Matcher companyMatcher = pattern.matcher(parameterValue);
|
||||
if (companyMatcher.matches()) {
|
||||
company = parameterValue;
|
||||
} else {
|
||||
company = DEFAULT_COMPANY;
|
||||
}
|
||||
break;
|
||||
case "contract":
|
||||
Matcher contractMatcher = pattern.matcher(parameterValue);
|
||||
if (contractMatcher.matches()) {
|
||||
contractNumber = parameterValue;
|
||||
} else {
|
||||
contractNumber = "none";
|
||||
}
|
||||
break;
|
||||
case "dateStart":
|
||||
if (parameterValue != null && !parameterValue.isEmpty()) {
|
||||
startDate = LocalDate.parse(parameterValue, dateFormat);
|
||||
} else {
|
||||
startDate = LocalDate.ofEpochDay(0);
|
||||
}
|
||||
break;
|
||||
case "dateEnd":
|
||||
if (parameterValue != null && !parameterValue.isEmpty()) {
|
||||
endDate = LocalDate.parse(parameterValue, dateFormat);
|
||||
} else {
|
||||
endDate = LocalDate.now();
|
||||
}
|
||||
break;
|
||||
case "createTimes":
|
||||
if (!parameterValue.equals(UNDEFINED)
|
||||
&& !parameterValue.isEmpty()) {
|
||||
String[] timestamps = parameterValue.split(",");
|
||||
for (String timestamp : timestamps) {
|
||||
createTimes.add(LocalDateTime.parse(timestamp,
|
||||
dateTimeFormat).toLocalDate());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "deviceNames":
|
||||
if (!parameterValue.equals(UNDEFINED)
|
||||
&& !parameterValue.isEmpty()) {
|
||||
deviceNames = parameterValue.split(",");
|
||||
}
|
||||
break;
|
||||
case "system":
|
||||
if (parameterValue.equals(TRUE)) {
|
||||
systemOnly = true;
|
||||
if (!columnHeaders.isEmpty()) {
|
||||
columnHeaders = "," + columnHeaders;
|
||||
}
|
||||
columnHeaders = systemColumnHeaders + columnHeaders;
|
||||
}
|
||||
break;
|
||||
case "component":
|
||||
if (parameterValue.equals(TRUE)) {
|
||||
componentOnly = true;
|
||||
if (!columnHeaders.isEmpty()) {
|
||||
columnHeaders += ",";
|
||||
}
|
||||
columnHeaders += componentColumnHeaders;
|
||||
}
|
||||
break;
|
||||
case "manufacturer":
|
||||
if (parameterValue != null && !parameterValue.isEmpty()) {
|
||||
filterManufacturer = parameterValue;
|
||||
}
|
||||
break;
|
||||
case "serial":
|
||||
if (parameterValue != null && !parameterValue.isEmpty()) {
|
||||
filterSerial = parameterValue;
|
||||
}
|
||||
break;
|
||||
case "json":
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
jsonVersion = true;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
if (!jsonVersion) {
|
||||
response.setHeader("Content-Type", "text/csv");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment;filename=validation_report.csv");
|
||||
}
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(
|
||||
new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8));
|
||||
StringBuilder reportData = new StringBuilder();
|
||||
JsonArray jsonReportData = new JsonArray();
|
||||
for (int i = 0; i < deviceNames.length; i++) {
|
||||
if ((createTimes.get(i).isAfter(startDate) || createTimes.get(i).isEqual(startDate))
|
||||
&& (createTimes.get(i).isBefore(endDate)
|
||||
|| createTimes.get(i).isEqual(endDate))) {
|
||||
UUID deviceId = deviceManager.getDevice(deviceNames[i]).getId();
|
||||
PlatformCredential pc = PlatformCredential.select(certificateManager)
|
||||
.byDeviceId(deviceId).getCertificate();
|
||||
if (jsonVersion) {
|
||||
jsonReportData.add(assembleJsonContent(pc, parseComponents(pc),
|
||||
company, contractNumber));
|
||||
} else {
|
||||
if (i == 0) {
|
||||
bufferedWriter.append("Company: " + company + "\n");
|
||||
bufferedWriter.append("Contract number: " + contractNumber + "\n");
|
||||
}
|
||||
if (systemOnly && componentOnly) {
|
||||
systemOnly = false;
|
||||
componentOnly = false;
|
||||
}
|
||||
if ((filterManufacturer.isEmpty() || filterManufacturer.equals(
|
||||
pc.getManufacturer()))
|
||||
&& (filterSerial.isEmpty() || filterSerial.equals(
|
||||
pc.getPlatformSerial()))) {
|
||||
if (!componentOnly) {
|
||||
reportData.append(pc.getManufacturer() + ","
|
||||
+ pc.getModel() + ","
|
||||
+ pc.getPlatformSerial() + ","
|
||||
+ LocalDateTime.now().toString() + ","
|
||||
+ pc.getDevice().getSupplyChainStatus() + ",");
|
||||
}
|
||||
if (!systemOnly) {
|
||||
ArrayList<ArrayList<String>> parsedComponents = parseComponents(pc);
|
||||
for (ArrayList<String> component : parsedComponents) {
|
||||
for (String data : component) {
|
||||
reportData.append(data + ",");
|
||||
}
|
||||
reportData.deleteCharAt(reportData.length() - 1);
|
||||
reportData.append(System.lineSeparator());
|
||||
if (!componentOnly) {
|
||||
reportData.append(",,,,,");
|
||||
}
|
||||
}
|
||||
reportData = reportData.delete(
|
||||
reportData.lastIndexOf(System.lineSeparator()) + 1,
|
||||
reportData.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!jsonVersion) {
|
||||
if (columnHeaders.isEmpty()) {
|
||||
columnHeaders = systemColumnHeaders + "," + componentColumnHeaders;
|
||||
}
|
||||
bufferedWriter.append(columnHeaders + System.lineSeparator());
|
||||
bufferedWriter.append(reportData.toString());
|
||||
} else {
|
||||
bufferedWriter.append(jsonReportData.toString());
|
||||
}
|
||||
bufferedWriter.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds a JSON object from the system and component data in a
|
||||
* validation report.
|
||||
* @param pc the platform credential used to validate.
|
||||
* @param parsedComponents component data parsed from the platform credential.
|
||||
* @param company company name.
|
||||
* @param contractNumber contract number.
|
||||
* @return the JSON object in String format.
|
||||
*/
|
||||
@SuppressWarnings({"checkstyle:magicnumber" })
|
||||
private JsonObject assembleJsonContent(final PlatformCredential pc,
|
||||
final ArrayList<ArrayList<String>> parsedComponents,
|
||||
final String company,
|
||||
final String contractNumber) {
|
||||
JsonObject systemData = new JsonObject();
|
||||
|
||||
systemData.addProperty("Company", company);
|
||||
systemData.addProperty("Contract number", contractNumber);
|
||||
systemData.addProperty("Verified Manufacturer", pc.getManufacturer());
|
||||
systemData.addProperty("Model", pc.getModel());
|
||||
systemData.addProperty("SN", pc.getPlatformSerial());
|
||||
systemData.addProperty("Verification Date", LocalDateTime.now().toString());
|
||||
systemData.addProperty("Device Status", pc.getDevice().getSupplyChainStatus().toString());
|
||||
|
||||
JsonArray components = new JsonArray();
|
||||
for (ArrayList<String> componentData : parsedComponents) {
|
||||
JsonObject component = new JsonObject();
|
||||
component.addProperty("Component name", componentData.get(0));
|
||||
component.addProperty("Component manufacturer", componentData.get(1));
|
||||
component.addProperty("Component model", componentData.get(2));
|
||||
component.addProperty("Component SN", componentData.get(3));
|
||||
component.addProperty("Issuer", componentData.get(4));
|
||||
component.addProperty("Component status", componentData.get(5));
|
||||
components.add(component);
|
||||
}
|
||||
systemData.add("Components", components);
|
||||
|
||||
return systemData;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method parses the following ComponentIdentifier fields into an ArrayList of ArrayLists.
|
||||
* - ComponentClass
|
||||
* - Manufacturer
|
||||
* - Model
|
||||
* - Serial number
|
||||
* - Pass/fail status (based on componentFailures string)
|
||||
* @param pc the platform credential.
|
||||
* @return the ArrayList of ArrayLists containing the parsed component data.
|
||||
*/
|
||||
private ArrayList<ArrayList<String>> parseComponents(final PlatformCredential pc) {
|
||||
ArrayList<ArrayList<String>> parsedComponents = new ArrayList<ArrayList<String>>();
|
||||
ArrayList<ArrayList<Object>> chainComponents = new ArrayList<>();
|
||||
|
||||
StringBuilder componentFailureString = new StringBuilder();
|
||||
if (pc.getComponentIdentifiers() != null
|
||||
&& pc.getComponentIdentifiers().size() > 0) {
|
||||
componentFailureString.append(pc.getComponentFailures());
|
||||
// get all the certificates associated with the platform serial
|
||||
List<PlatformCredential> chainCertificates = PlatformCredential
|
||||
.select(certificateManager)
|
||||
.byBoardSerialNumber(pc.getPlatformSerial())
|
||||
.getCertificates().stream().collect(Collectors.toList());
|
||||
// combine all components in each certificate
|
||||
for (ComponentIdentifier ci : pc.getComponentIdentifiers()) {
|
||||
ArrayList<Object> issuerAndComponent = new ArrayList<Object>();
|
||||
issuerAndComponent.add(pc.getIssuer());
|
||||
issuerAndComponent.add(ci);
|
||||
chainComponents.add(issuerAndComponent);
|
||||
}
|
||||
|
||||
for (PlatformCredential cert : chainCertificates) {
|
||||
componentFailureString.append(cert.getComponentFailures());
|
||||
if (!cert.isBase()) {
|
||||
for (ComponentIdentifier ci : cert.getComponentIdentifiers()) {
|
||||
ArrayList<Object> issuerAndComponent = new ArrayList<Object>();
|
||||
issuerAndComponent.add(cert.getIssuer());
|
||||
issuerAndComponent.add(ci);
|
||||
chainComponents.add(issuerAndComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGGER.info("Component failures: " + componentFailureString.toString());
|
||||
for (ArrayList<Object> issuerAndComponent : chainComponents) {
|
||||
ArrayList<String> componentData = new ArrayList<String>();
|
||||
String issuer = (String) issuerAndComponent.get(0);
|
||||
issuer = issuer.replaceAll(",", " ");
|
||||
ComponentIdentifier ci = (ComponentIdentifier) issuerAndComponent.get(1);
|
||||
if (ci instanceof ComponentIdentifierV2) {
|
||||
String componentClass =
|
||||
((ComponentIdentifierV2) ci).getComponentClass().toString();
|
||||
String[] splitStrings = componentClass.split("\r\n|\n|\r");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String s : splitStrings) {
|
||||
sb.append(s);
|
||||
sb.append(" ");
|
||||
}
|
||||
sb = sb.deleteCharAt(sb.length() - 1);
|
||||
componentData.add(sb.toString());
|
||||
} else {
|
||||
componentData.add("Platform Component");
|
||||
}
|
||||
componentData.add(ci.getComponentManufacturer().getString());
|
||||
componentData.add(ci.getComponentModel().getString());
|
||||
componentData.add(ci.getComponentSerial().getString());
|
||||
componentData.add(issuer);
|
||||
//Failing components are identified by hashcode
|
||||
if (componentFailureString.toString().contains(String.valueOf(ci.hashCode()))) {
|
||||
componentData.add("Fail");
|
||||
} else {
|
||||
componentData.add("Pass");
|
||||
}
|
||||
parsedComponents.add(componentData);
|
||||
LOGGER.info(String.join(",", componentData));
|
||||
}
|
||||
}
|
||||
|
||||
return parsedComponents;
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package contains PageController implementations.
|
||||
*/
|
||||
package hirs.attestationca.portal.page.controllers;
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package provides interfaces and superclasses for PageController and associated objects.
|
||||
*/
|
||||
package hirs.attestationca.portal.page;
|
@ -1,99 +0,0 @@
|
||||
package hirs.attestationca.portal.page.params;
|
||||
|
||||
import hirs.attestationca.portal.page.PageParams;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* URL parameters object for the CertificateDetails page and controller.
|
||||
*/
|
||||
public class CertificateDetailsPageParams implements PageParams {
|
||||
|
||||
private String id;
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Constructor to set all Certificate Details URL parameters.
|
||||
*
|
||||
* @param id the String parameter to set
|
||||
* @param type the Integer parameter to set
|
||||
*/
|
||||
public CertificateDetailsPageParams(final String id, final String type) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to set ID Certificate Details URL parameters.
|
||||
*
|
||||
* @param id the String parameter to set
|
||||
*/
|
||||
public CertificateDetailsPageParams(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor for Spring.
|
||||
*/
|
||||
public CertificateDetailsPageParams() {
|
||||
id = null;
|
||||
type = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String id parameter.
|
||||
*
|
||||
* @return the String id parameter.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the String id parameter.
|
||||
*
|
||||
* @param id the String id parameter.
|
||||
*/
|
||||
public void setId(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String type parameter.
|
||||
*
|
||||
* @return the String type parameter.
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the String type parameter.
|
||||
*
|
||||
* @param type the String type parameter.
|
||||
*/
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows PageController to iterate over the url parameters.
|
||||
*
|
||||
* @return map containing the object's URL parameters.
|
||||
*/
|
||||
@Override
|
||||
public LinkedHashMap<String, ?> asMap() {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("id", id);
|
||||
map.put("type", type);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CertificateDetailsPageParams{"
|
||||
+ "id:' " + id + "',"
|
||||
+ "type: " + type
|
||||
+ "}";
|
||||
}
|
||||
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
|
||||
package hirs.attestationca.portal.page.params;
|
||||
|
||||
import hirs.attestationca.portal.page.PageParams;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* URL parameters object for the Reference Manifest Details page and controller.
|
||||
*/
|
||||
public class ReferenceManifestDetailsPageParams implements PageParams {
|
||||
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Constructor to set all RIM Details URL parameters.
|
||||
*
|
||||
* @param id the String parameter to set
|
||||
*/
|
||||
public ReferenceManifestDetailsPageParams(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor for Spring.
|
||||
*
|
||||
*/
|
||||
public ReferenceManifestDetailsPageParams() {
|
||||
this.id = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String id parameter.
|
||||
*
|
||||
* @return the String id parameter.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the String id parameter.
|
||||
*
|
||||
* @param id the String id parameter.
|
||||
*/
|
||||
public void setId(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows PageController to iterate over the url parameters.
|
||||
*
|
||||
* @return map containing the object's URL parameters.
|
||||
*/
|
||||
@Override
|
||||
public LinkedHashMap<String, ?> asMap() {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("id", id);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ReferenceManifestDetailsPageParams{"
|
||||
+ "id:' " + id
|
||||
+ "}";
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
|
||||
package hirs.attestationca.portal.page.params;
|
||||
|
||||
import hirs.attestationca.portal.page.PageParams;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* URL parameters object for the ReferenceManifest page and controller.
|
||||
*/
|
||||
public class ReferenceManifestPageParams implements PageParams {
|
||||
|
||||
private String id;
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Constructor to set all Reference Integrity Manifest URL parameters.
|
||||
*
|
||||
* @param id the String parameter to set
|
||||
* @param type the Integer parameter to set
|
||||
*/
|
||||
public ReferenceManifestPageParams(final String id, final String type) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
*Constructor to set all Reference Integrity Manifest URL parameters.
|
||||
*
|
||||
* @param id the String parameter to set
|
||||
*/
|
||||
public ReferenceManifestPageParams(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor for Spring.
|
||||
*/
|
||||
public ReferenceManifestPageParams() {
|
||||
id = null;
|
||||
type = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String id parameter.
|
||||
*
|
||||
* @return the String id parameter.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the String id parameter.
|
||||
*
|
||||
* @param id the String id parameter.
|
||||
*/
|
||||
public void setId(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the String type parameter.
|
||||
*
|
||||
* @return the String type parameter.
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the String type parameter.
|
||||
*
|
||||
* @param type the String type parameter.
|
||||
*/
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows PageController to iterate over the url parameters.
|
||||
*
|
||||
* @return map containing the object's URL parameters.
|
||||
*/
|
||||
@Override
|
||||
public LinkedHashMap<String, ?> asMap() {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("id", id);
|
||||
map.put("type", type);
|
||||
return map;
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* This package contains url parameter classes for portal pages.
|
||||
*/
|
||||
package hirs.attestationca.portal.page.params;
|
@ -1,125 +0,0 @@
|
||||
package hirs.attestationca.portal.persistence;
|
||||
|
||||
import hirs.data.persist.SupplyChainValidationSummary;
|
||||
import hirs.persist.AppraiserManager;
|
||||
import hirs.persist.CrudManager;
|
||||
import hirs.persist.DBAppraiserManager;
|
||||
import hirs.persist.DBCertificateManager;
|
||||
import hirs.persist.DBDeviceGroupManager;
|
||||
import hirs.persist.DBDeviceManager;
|
||||
import hirs.persist.DBManager;
|
||||
import hirs.persist.DBPolicyManager;
|
||||
import hirs.persist.DBReferenceDigestManager;
|
||||
import hirs.persist.DBReferenceEventManager;
|
||||
import hirs.persist.DBReferenceManifestManager;
|
||||
import hirs.persist.DeviceGroupManager;
|
||||
import hirs.persist.DeviceManager;
|
||||
import hirs.persist.HibernateConfiguration;
|
||||
import hirs.persist.PolicyManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
|
||||
|
||||
/**
|
||||
* Spring configuration class for persistence beans used by the Attestation CA Portal.
|
||||
*/
|
||||
@Configuration
|
||||
@Import({ HibernateConfiguration.class })
|
||||
public class PersistenceConfiguration {
|
||||
|
||||
@Autowired
|
||||
private LocalSessionFactoryBean sessionFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a {@link PolicyManager} ready to use.
|
||||
*
|
||||
* @return {@link PolicyManager}
|
||||
*/
|
||||
@Bean
|
||||
public PolicyManager policyManager() {
|
||||
return new DBPolicyManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DeviceManager} ready to use.
|
||||
*
|
||||
* @return {@link DeviceManager}
|
||||
*/
|
||||
@Bean
|
||||
public DeviceManager deviceManager() {
|
||||
return new DBDeviceManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DBCertificateManager} ready to use.
|
||||
*
|
||||
* @return {@link DBCertificateManager}
|
||||
*/
|
||||
@Bean
|
||||
public DBCertificateManager certificateManager() {
|
||||
return new DBCertificateManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DBReferenceManifestManager} ready to use.
|
||||
*
|
||||
* @return {@link DBReferenceManifestManager}
|
||||
*/
|
||||
@Bean
|
||||
public DBReferenceManifestManager referenceManifestManager() {
|
||||
return new DBReferenceManifestManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DBReferenceDigestManager} ready to use.
|
||||
*
|
||||
* @return {@link DBReferenceDigestManager}
|
||||
*/
|
||||
@Bean
|
||||
public DBReferenceDigestManager referenceDigestManager() {
|
||||
return new DBReferenceDigestManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DBReferenceEventManager} ready to use.
|
||||
*
|
||||
* @return {@link DBReferenceEventManager}
|
||||
*/
|
||||
@Bean
|
||||
public DBReferenceEventManager referenceEventManager() {
|
||||
return new DBReferenceEventManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link AppraiserManager} ready to use.
|
||||
*
|
||||
* @return {@link AppraiserManager}
|
||||
*/
|
||||
@Bean
|
||||
public AppraiserManager appraiserManager() {
|
||||
return new DBAppraiserManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DeviceGroupManager} ready to use.
|
||||
*
|
||||
* @return {@link DeviceGroupManager}
|
||||
*/
|
||||
@Bean
|
||||
public DeviceGroupManager deviceGroupManager() {
|
||||
return new DBDeviceGroupManager(sessionFactory.getObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DBManager} for SupplyChainValidationSummary persistence, ready for use.
|
||||
*
|
||||
* @return {@link DBManager}
|
||||
*/
|
||||
@Bean
|
||||
public CrudManager<SupplyChainValidationSummary> supplyChainValidationSummaryManager() {
|
||||
return new DBManager<>(SupplyChainValidationSummary.class, sessionFactory.getObject());
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Persistence related classes for Attestation CA Portal.
|
||||
*/
|
||||
package hirs.attestationca.portal.persistence;
|
@ -0,0 +1,15 @@
|
||||
package hirs.attestationca.portal.service;
|
||||
|
||||
public class DbServiceImpl {
|
||||
/**
|
||||
* The default maximum number of retries to attempt a database transaction.
|
||||
*/
|
||||
public static final int DEFAULT_MAX_RETRY_ATTEMPTS = 10;
|
||||
/*
|
||||
* The default number of milliseconds to wait before retrying a database transaction.
|
||||
*/
|
||||
private static final long DEFAULT_RETRY_WAIT_TIME_MS = 3000;
|
||||
|
||||
// structure for retrying methods in the database
|
||||
// private RetryTemplate retryTemplate;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package hirs.attestationca.portal.service;
|
||||
|
||||
public interface DefaultService {
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user