diff options
author | Guo Ruijing <ruijing.guo@intel.com> | 2017-07-28 08:21:14 +0000 |
---|---|---|
committer | Pamela Dragosh <pdragosh@research.att.com> | 2017-07-31 08:31:07 -0400 |
commit | f8a620d1ff2b0d33b08a22279058f3e0253bdde1 (patch) | |
tree | 9092df7a6c57a46d36988245f60db0c29a7b1404 /integrity-audit/src/main/java/org/onap | |
parent | e7bd0934d383c811b0b7302c42991aa1d61941c4 (diff) |
[POLICY-71] replace openecomp for policy-common
Change-Id: I3241f5d1f0234043b4dff718eda1ffdc48052276
Signed-off-by: Guo Ruijing <ruijing.guo@intel.com>
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
Diffstat (limited to 'integrity-audit/src/main/java/org/onap')
9 files changed, 2579 insertions, 0 deletions
diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java new file mode 100644 index 00000000..e7e16a64 --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/AuditThread.java @@ -0,0 +1,769 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Properties; +//import org.apache.log4j.Logger; + + +import org.onap.policy.common.ia.jpa.IntegrityAuditEntity; +import org.onap.policy.common.logging.eelf.MessageCodes; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +/** + * AuditThread is the main thread for the IntegrityAudit + * + */ +public class AuditThread extends Thread { + + private static final Logger logger = FlexLogger.getLogger(AuditThread.class); + + /* + * Number of milliseconds that must elapse for audit to be considered + * complete. It's public for access by JUnit test logic. + */ + public static final long AUDIT_COMPLETION_INTERVAL = 30000; + + /* + * Number of iterations for audit simulation. + */ + public static final long AUDIT_SIMULATION_ITERATIONS = 3; + + /* + * Number of milliseconds to sleep between audit simulation iterations. It's + * public for access by JUnit test logic. + */ + public static final long AUDIT_SIMULATION_SLEEP_INTERVAL = 5000; + + /* + * Unless audit has already been run on this entity, number of milliseconds + * to sleep between audit thread iterations. If audit has already been run, + * we sleep integrityAuditPeriodMillis. + */ + private static final long AUDIT_THREAD_SLEEP_INTERVAL = 5000; + + /* + * DB access class. + */ + private DbDAO dbDAO; + + /* + * E.g. pdp_xacml + */ + private String nodeType; + + /* + * Persistence unit for which this audit is being run. + */ + private String persistenceUnit; + + /* + * Name of this resource + */ + private String resourceName; + + /* + * E.g. DB_DRIVER, SITE_NAME, NODE_TYPE + */ + private Properties properties; + + /* + * See IntegrityAudit class for usage. + */ + private int integrityAuditPeriodMillis; + + /* + * The containing IntegrityAudit instance + */ + private IntegrityAudit integrityAudit; + + /** + * AuditThread constructor + * @param resourceName + * @param persistenceUnit + * @param properties + * @param integrityAuditPeriodSeconds + * @param integrityAudit + * @throws Exception + */ + public AuditThread(String resourceName, String persistenceUnit, + Properties properties, int integrityAuditPeriodSeconds, IntegrityAudit integrityAudit) + throws Exception { + this.resourceName = resourceName; + this.persistenceUnit = persistenceUnit; + this.properties = properties; + this.integrityAuditPeriodMillis = integrityAuditPeriodSeconds * 1000; + this.integrityAudit = integrityAudit; + + /* + * The DbDAO Constructor registers this node in the IntegrityAuditEntity + * table. Each resource (node) inserts its own name, persistenceUnit, DB + * access properties and other pertinent properties in the table. This + * allows the audit on each node to compare its own version of the + * entities for the persistenceUnit in question with the versions from + * all other nodes of similar type. + */ + dbDAO = new DbDAO(this.resourceName, this.persistenceUnit, + this.properties); + this.nodeType = properties.getProperty(IntegrityAuditProperties.NODE_TYPE); + + } + + public void run() { + + logger.info("AuditThread.run: Entering"); + + try { + + /* + * Triggers change in designation, unless no other viable candidate. + */ + boolean auditCompleted = false; + + DbAudit dbAudit = new DbAudit(dbDAO); + + IntegrityAuditEntity entityCurrentlyDesignated = null; + IntegrityAuditEntity thisEntity = null; + integrityAudit.setThreadInitialized(true); // An exception will set + // it to false + + while (true) { + try{ + + /* + * It may have been awhile since we last cycled through this + * loop, so refresh the list of IntegrityAuditEntities. + */ + List<IntegrityAuditEntity> integrityAuditEntityList = getIntegrityAuditEntityList(); + + /* + * We could've set entityCurrentlyDesignated as a side effect of + * getIntegrityAuditEntityList(), but then we would've had to + * make entityCurrentlyDesignated a class level attribute. Using + * this approach, we can keep it local to the run() method. + */ + entityCurrentlyDesignated = getEntityCurrentlyDesignated(integrityAuditEntityList); + + /* + * Need to refresh thisEntity each time through loop, because we + * need a fresh version of lastUpdated. + */ + thisEntity = getThisEntity(integrityAuditEntityList); + + /* + * If we haven't done the audit yet, note that we're current and + * see if we're designated. + */ + if (!auditCompleted) { + dbDAO.setLastUpdated(); + + /* + * If no current designation or currently designated node is + * stale, see if we're the next node to be designated. + */ + if (entityCurrentlyDesignated == null + || isStale(entityCurrentlyDesignated)) { + IntegrityAuditEntity designationCandidate = getDesignationCandidate(integrityAuditEntityList); + + /* + * If we're the next node to be designated, run the + * audit. + */ + if (designationCandidate.getResourceName().equals( + this.resourceName)) { + runAudit(dbAudit); + auditCompleted = true; + } else { + if (logger.isDebugEnabled()) { + logger.debug("AuditThread.run: designationCandidate, " + + designationCandidate + .getResourceName() + + ", not this entity, " + + thisEntity.getResourceName()); + } + } + + /* + * Application may have been stopped and restarted, in + * which case we might be designated but auditCompleted + * will have been reset to false, so account for this. + */ + } else if (thisEntity.getResourceName().equals( + entityCurrentlyDesignated.getResourceName())) { + + if (logger.isDebugEnabled()) { + logger.debug("AuditThread.run: Re-running audit for " + + thisEntity.getResourceName()); + } + runAudit(dbAudit); + auditCompleted = true; + + } else { + if (logger.isDebugEnabled()) { + logger.debug("AuditThread.run: Currently designated node, " + + entityCurrentlyDesignated + .getResourceName() + + ", not yet stale and not this node"); + } + } + + + /* + * Audit already completed on this node, so allow the node + * to go stale until twice the AUDIT_COMPLETION_PERIOD has + * elapsed. This should give plenty of time for another node + * (if another node is out there) to pick up designation. + */ + } else { + + auditCompleted = resetAuditCompleted(auditCompleted, + thisEntity); + + } + + /* + * If we've just run audit, sleep per the + * integrity_audit_period_seconds property, otherwise just sleep + * the normal interval. + */ + if (auditCompleted) { + + if (logger.isDebugEnabled()) { + logger.debug("AuditThread.run: Audit completed; resourceName=" + + this.resourceName + + " sleeping " + + integrityAuditPeriodMillis + "ms"); + } + Thread.sleep(integrityAuditPeriodMillis); + if (logger.isDebugEnabled()) { + logger.debug("AuditThread.run: resourceName=" + + this.resourceName + " awaking from " + + integrityAuditPeriodMillis + "ms sleep"); + } + + } else { + + if (logger.isDebugEnabled()) { + logger.debug("AuditThread.run: resourceName=" + + this.resourceName + ": Sleeping " + + AuditThread.AUDIT_THREAD_SLEEP_INTERVAL + + "ms"); + } + Thread.sleep(AuditThread.AUDIT_THREAD_SLEEP_INTERVAL); + if (logger.isDebugEnabled()) { + logger.debug("AuditThread.run: resourceName=" + + this.resourceName + ": Awaking from " + + AuditThread.AUDIT_THREAD_SLEEP_INTERVAL + + "ms sleep"); + } + + } + } catch (Exception e){ + String msg = "AuditThread.run loop - Exception thrown: " + e.getMessage() + + "; Will try audit again in " + (integrityAuditPeriodMillis/1000) + " seconds"; + logger.error(MessageCodes.EXCEPTION_ERROR, e, msg); + // Sleep and try again later + Thread.sleep(integrityAuditPeriodMillis); + continue; + } + + } + + } catch (Exception e) { + String msg = "AuditThread.run: Could not start audit loop. Exception thrown; message="+ e.getMessage(); + logger.error(MessageCodes.EXCEPTION_ERROR, e, msg); + integrityAudit.setThreadInitialized(false); + } + + logger.info("AuditThread.run: Exiting"); + } + + /* + * Used to create a list that is sorted lexicographically by resourceName. + */ + Comparator<IntegrityAuditEntity> comparator = new Comparator<IntegrityAuditEntity>() { + @Override + public int compare(final IntegrityAuditEntity r1, + final IntegrityAuditEntity r2) { + return r1.getResourceName().compareTo(r2.getResourceName()); + } + }; + + /** + * getDesignationCandidate() + * Using round robin algorithm, gets next candidate to be designated. Assumes + * list is sorted lexicographically by resourceName. + */ + private IntegrityAuditEntity getDesignationCandidate( + List<IntegrityAuditEntity> integrityAuditEntityList) { + + //Note: assumes integrityAuditEntityList is already lexicographically sorted by resourceName + + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Entering, integrityAuditEntityList.size()=" + + integrityAuditEntityList.size()); + } + + IntegrityAuditEntity designationCandidate = null; + IntegrityAuditEntity thisEntity = null; + + int designatedEntityIndex = -1; + int entityIndex = 0; + int priorCandidateIndex = -1; + int subsequentCandidateIndex = -1; + + for (IntegrityAuditEntity integrityAuditEntity : integrityAuditEntityList) { + + if (logger.isDebugEnabled()) { + logIntegrityAuditEntity(integrityAuditEntity); + } + + if (integrityAuditEntity.getResourceName() + .equals(this.resourceName)) { + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: thisEntity=" + + integrityAuditEntity.getResourceName()); + } + thisEntity = integrityAuditEntity; + } + + if (integrityAuditEntity.isDesignated()) { + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Currently designated entity resourceName=" + + integrityAuditEntity.getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity.getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated() + + ", entityIndex=" + entityIndex); + } + designatedEntityIndex = entityIndex; + + /* + * Entity not currently designated + */ + } else { + + /* + * See if non-designated entity is stale. + */ + if (isStale(integrityAuditEntity)) { + + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Entity is stale; resourceName=" + + integrityAuditEntity.getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity.getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated() + + ", entityIndex=" + entityIndex); + } + + /* + * Entity is current. + */ + } else { + + if (designatedEntityIndex == -1) { + + if (priorCandidateIndex == -1) { + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Prior candidate found, resourceName=" + + integrityAuditEntity + .getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity + .getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated() + + ", entityIndex=" + entityIndex); + } + priorCandidateIndex = entityIndex; + } else { + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Prior entity current but prior candidate already found; resourceName=" + + integrityAuditEntity + .getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity + .getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated() + + ", entityIndex=" + entityIndex); + } + } + } else { + if (subsequentCandidateIndex == -1) { + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Subsequent candidate found, resourceName=" + + integrityAuditEntity + .getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity + .getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated() + + ", entityIndex=" + entityIndex); + } + subsequentCandidateIndex = entityIndex; + } else { + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Subsequent entity current but subsequent candidate already found; resourceName=" + + integrityAuditEntity + .getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity + .getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated() + + ", entityIndex=" + entityIndex); + } + } + } + + } // end entity is current + + } // end entity not currently designated + + entityIndex++; + + } // end for loop + + /* + * Per round robin algorithm, if a current entity is found that is + * lexicographically after the currently designated entity, this entity + * becomes the designation candidate. If no current entity is found that + * is lexicographically after currently designated entity, we cycle back + * to beginning of list and pick the first current entity as the + * designation candidate. + */ + if (subsequentCandidateIndex != -1) { + designationCandidate = integrityAuditEntityList + .get(subsequentCandidateIndex); + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Exiting and returning subsequent designationCandidate=" + + designationCandidate.getResourceName()); + } + } else { + if (priorCandidateIndex != -1) { + designationCandidate = integrityAuditEntityList + .get(priorCandidateIndex); + if (logger.isDebugEnabled()) { + logger.debug("getDesignationCandidate: Exiting and returning prior designationCandidate=" + + designationCandidate.getResourceName()); + } + } else { + logger.debug("getDesignationCandidate: No subsequent or prior candidate found; designating thisEntity, resourceName=" + + thisEntity.getResourceName()); + designationCandidate = thisEntity; + } + } + + return designationCandidate; + + } + + /** + * getEntityCurrentlyDesignated() + * Returns entity that is currently designated. + * @param integrityAuditEntityList + * @return + */ + private IntegrityAuditEntity getEntityCurrentlyDesignated( + List<IntegrityAuditEntity> integrityAuditEntityList) { + + if (logger.isDebugEnabled()) { + logger.debug("getEntityCurrentlyDesignated: Entering, integrityAuditEntityList.size=" + + integrityAuditEntityList.size()); + } + + IntegrityAuditEntity entityCurrentlyDesignated = null; + + for (IntegrityAuditEntity integrityAuditEntity : integrityAuditEntityList) { + + if (integrityAuditEntity.isDesignated()) { + if (logger.isDebugEnabled()) { + logger.debug("getEntityCurrentlyDesignated: Currently designated entity resourceName=" + + integrityAuditEntity.getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity.getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated()); + } + entityCurrentlyDesignated = integrityAuditEntity; + } + + } // end for loop + + if (logger.isDebugEnabled()) { + if (entityCurrentlyDesignated != null) { + logger.debug("getEntityCurrentlyDesignated: Exiting and returning entityCurrentlyDesignated=" + + entityCurrentlyDesignated.getResourceName()); + } else { + logger.debug("getEntityCurrentlyDesignated: Exiting and returning entityCurrentlyDesignated=" + + entityCurrentlyDesignated); + } + } + return entityCurrentlyDesignated; + + } + + /** + * getIntegrityAuditEnityList gets the list of IntegrityAuditEntity + * @return + * @throws DbDaoTransactionException + */ + private List<IntegrityAuditEntity> getIntegrityAuditEntityList() + throws DbDaoTransactionException { + + if (logger.isDebugEnabled()) { + logger.debug("getIntegrityAuditEntityList: Entering"); + } + + /* + * Get all records for this nodeType and persistenceUnit and then sort + * them lexicographically by resourceName. Get index of designated + * entity, if any. + */ + /* + * Sorted list of entities for a particular nodeType and + * persistenceUnit. + */ + List<IntegrityAuditEntity> integrityAuditEntityList = new ArrayList<IntegrityAuditEntity>(); + integrityAuditEntityList = dbDAO.getIntegrityAuditEntities( + this.persistenceUnit, this.nodeType); + int listSize = integrityAuditEntityList.size(); + if (logger.isDebugEnabled()) { + logger.debug("getIntegrityAuditEntityList: Got " + listSize + + " IntegrityAuditEntity records"); + } + Collections.sort((List<IntegrityAuditEntity>) integrityAuditEntityList, + comparator); + + if (logger.isDebugEnabled()) { + logger.debug("getIntegrityAuditEntityList: Exiting and returning integrityAuditEntityList, size=" + + listSize); + } + return integrityAuditEntityList; + + } + + + /** + * Returns the IntegrityAuditEntity for this entity. + * @param integrityAuditEntityList + * @return + */ + private IntegrityAuditEntity getThisEntity( + List<IntegrityAuditEntity> integrityAuditEntityList) { + + if (logger.isDebugEnabled()) { + logger.debug("getThisEntity: Entering, integrityAuditEntityList.size=" + + integrityAuditEntityList.size()); + } + + IntegrityAuditEntity thisEntity = null; + + for (IntegrityAuditEntity integrityAuditEntity : integrityAuditEntityList) { + + if (integrityAuditEntity.getResourceName().equals(this.resourceName)) { + if (logger.isDebugEnabled()) { + logger.debug("getThisEntity: For this entity, resourceName=" + + integrityAuditEntity.getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity.getPersistenceUnit() + + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated()); + } + thisEntity = integrityAuditEntity; + } + + } // end for loop + + if (logger.isDebugEnabled()) { + if (thisEntity != null) { + logger.debug("getThisEntity: Exiting and returning thisEntity=" + + thisEntity.getResourceName()); + } else { + logger.debug("getThisEntity: Exiting and returning thisEntity=" + + thisEntity); + } + } + return thisEntity; + + } + + + /** + * Returns false if the lastUpdated time for the record in question is more + * than AUDIT_COMPLETION_INTERVAL seconds ago. During an audit, lastUpdated is updated every five + * seconds or so, but when an audit finishes, the node doing the audit stops + * updating lastUpdated. + * @param integrityAuditEntity + * @return + */ + private boolean isStale(IntegrityAuditEntity integrityAuditEntity) { + + if (logger.isDebugEnabled()) { + logger.debug("isStale: Entering, resourceName=" + + integrityAuditEntity.getResourceName() + + ", persistenceUnit=" + + integrityAuditEntity.getPersistenceUnit() + + ", lastUpdated=" + integrityAuditEntity.getLastUpdated()); + } + + boolean stale = false; + + Date currentTime = new Date(); + Date lastUpdated = integrityAuditEntity.getLastUpdated(); + + /* + * If lastUpdated is null, we assume that the audit never ran for that + * node. + */ + long lastUpdatedTime = 0; + if (lastUpdated != null) { + lastUpdatedTime = lastUpdated.getTime(); + } + long timeDifference = currentTime.getTime() - lastUpdatedTime; + if (timeDifference > AUDIT_COMPLETION_INTERVAL) { + stale = true; + } + + if (logger.isDebugEnabled()) { + logger.debug("isStale: Exiting and returning stale=" + stale + + ", timeDifference=" + timeDifference); + } + + return stale; + } + + private void logIntegrityAuditEntity( + IntegrityAuditEntity integrityAuditEntity) { + + logger.debug("logIntegrityAuditEntity: id=" + + integrityAuditEntity.getId() + ", jdbcDriver=" + + integrityAuditEntity.getJdbcDriver() + ", jdbcPassword=" + + integrityAuditEntity.getJdbcPassword() + ", jdbcUrl=" + + integrityAuditEntity.getJdbcUrl() + ", jdbcUser=" + + integrityAuditEntity.getJdbcUser() + ", nodeType=" + + integrityAuditEntity.getNodeType() + ", persistenceUnit=" + + integrityAuditEntity.getPersistenceUnit() + ", resourceName=" + + integrityAuditEntity.getResourceName() + ", site=" + + integrityAuditEntity.getSite() + ", createdDate=" + + integrityAuditEntity.getCreatedDate() + ", lastUpdated=" + + integrityAuditEntity.getLastUpdated() + ", designated=" + + integrityAuditEntity.isDesignated()); + } + + /* + * If more than (AUDIT_COMPLETION_INTERVAL * 2) milliseconds have elapsed + * since we last ran the audit, reset auditCompleted, so + * + * 1) we'll eventually re-run the audit, if no other node picks up the + * designation. + * + * or + * + * 2) We'll run the audit when the round robin comes back to us. + */ + private boolean resetAuditCompleted(boolean auditCompleted, + IntegrityAuditEntity thisEntity) { + + if (logger.isDebugEnabled()) { + logger.debug("resetAuditCompleted: auditCompleted=" + + auditCompleted + "; for thisEntity, resourceName=" + + thisEntity.getResourceName() + ", persistenceUnit=" + + thisEntity.getPersistenceUnit() + ", lastUpdated=" + + thisEntity.getLastUpdated()); + } + + long timeDifference = -1; + + Date currentTime = new Date(); + Date lastUpdated = thisEntity.getLastUpdated(); + + long lastUpdatedTime = lastUpdated.getTime(); + timeDifference = currentTime.getTime() - lastUpdatedTime; + + if (timeDifference > (AUDIT_COMPLETION_INTERVAL * 2)) { + if (logger.isDebugEnabled()) { + logger.debug("resetAuditCompleted: Resetting auditCompleted for resourceName=" + + this.resourceName); + } + auditCompleted = false; + } else { + if (logger.isDebugEnabled()) { + logger.debug("resetAuditCompleted: For resourceName=" + + resourceName + + ", time since last update is only " + + timeDifference + "; retaining current value for auditCompleted"); + } + } + + if (logger.isDebugEnabled()) { + logger.debug("resetAuditCompleted: Exiting and returning auditCompleted=" + + auditCompleted + ", timeDifference=" + timeDifference); + } + return auditCompleted; + } + + private void runAudit(DbAudit dbAudit) throws Exception { + + if (logger.isDebugEnabled()) { + logger.debug("runAudit: Entering, dbAudit=" + dbAudit + + "; notifying other resources that resourceName=" + + this.resourceName + " is current"); + } + + /* + * changeDesignated marks all other nodes as non-designated and this + * node as designated. + */ + dbDAO.changeDesignated(this.resourceName, this.persistenceUnit, + this.nodeType); + + if (logger.isDebugEnabled()) { + logger.debug("runAudit: Running audit for persistenceUnit=" + + this.persistenceUnit + " on resourceName=" + + this.resourceName); + } + if (IntegrityAudit.isUnitTesting) { + dbAudit.dbAuditSimulate(this.resourceName, this.persistenceUnit, + this.nodeType); + } else { + dbAudit.dbAudit(this.resourceName, this.persistenceUnit, + this.nodeType); + } + + if (logger.isDebugEnabled()) { + logger.debug("runAudit: Exiting"); + } + + } + +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAudit.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAudit.java new file mode 100644 index 00000000..8312daa3 --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAudit.java @@ -0,0 +1,462 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; + +import javax.persistence.Table; + +import org.apache.commons.lang3.SerializationUtils; +import org.apache.commons.lang3.builder.RecursiveToStringStyle; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +//import org.apache.log4j.Logger; + + + + + +import org.onap.policy.common.ia.jpa.IntegrityAuditEntity; +import org.onap.policy.common.logging.eelf.MessageCodes; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +/** + * class DbAudit does actual auditing of DB tables. + */ +public class DbAudit { + + private static final Logger logger = FlexLogger.getLogger(DbAudit.class); + + DbDAO dbDAO = null; + + public DbAudit(DbDAO dbDAO) { + + if (logger.isDebugEnabled()) { + logger.debug("Constructor: Entering"); + } + + this.dbDAO = dbDAO; + + if (logger.isDebugEnabled()) { + logger.debug("Constructor: Exiting"); + } + + } + + /** + * dbAudit actually does the audit + * @param resourceName + * @param persistenceUnit + * @param nodeType + * @throws Exception + */ + public void dbAudit(String resourceName, String persistenceUnit, String nodeType) throws Exception { + + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Entering, resourceName=" + resourceName + + ", persistenceUnit=" + persistenceUnit + ", nodeType=" + + nodeType); + } + + // Get all IntegrityAudit entries so we can get the DB access info + List<IntegrityAuditEntity> iaeList = dbDAO.getIntegrityAuditEntities(persistenceUnit, nodeType); + if(iaeList == null || iaeList.isEmpty()){ + + String msg = "DbAudit: for node " + resourceName + " Found no IntegrityAuditEntity entries"; + logger.error(MessageCodes.ERROR_AUDIT, msg); + throw new DbAuditException(msg); + + }else if(iaeList.size() == 1){ + + Long iaeId = null; + String iaeRN = null; + String iaeNT = null; + String iaeS = null; + for (IntegrityAuditEntity iae : iaeList){ + iaeId = iae.getId(); + iaeRN = iae.getResourceName(); + iaeNT = iae.getNodeType(); + iaeS = iae.getSite(); + } + String msg = "DbAudit: Found only one IntegrityAuditEntity entry:" + + " ID = " + iaeId + + " ResourceName = " + iaeRN + + " NodeType = " + iaeNT + + " Site = " + iaeS; + logger.warn(msg); + return; + } + + // Obtain all persistence class names for the PU we are auditing + HashSet<String> classNameSet = dbDAO.getPersistenceClassNames(); + if(classNameSet == null || classNameSet.isEmpty()){ + + String msg = "DbAudit: For node " + resourceName + " Found no persistence class names"; + logger.error(MessageCodes.ERROR_AUDIT, msg); + throw new DbAuditException(msg); + + } + + /* + * Retrieve myIae. We are going to compare the local class entries against + * all other DB nodes. Since the audit is run in a round-robin, every instance + * will be compared against every other instance. + */ + IntegrityAuditEntity myIae = dbDAO.getMyIntegrityAuditEntity(); + + if(myIae == null){ + + String msg = "DbAudit: Found no IntegrityAuditEntity entry for resourceName: " + resourceName + + " persistenceUnit: " + persistenceUnit; + logger.error(MessageCodes.ERROR_AUDIT, msg); + throw new DbAuditException(msg); + + } + /* + * This is the map of mismatched entries indexed by className. For + * each class name there is a list of mismatched entries + */ + HashMap<String,HashSet<Object>> misMatchedMap = new HashMap<String,HashSet<Object>>(); + + // We need to keep track of how long the audit is taking + long startTime = System.currentTimeMillis(); + + // Retrieve all instances of the class for each node + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Traversing classNameSet, size=" + classNameSet.size()); + } + for(String clazzName: classNameSet){ + + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: clazzName=" + clazzName); + } + + // all instances of the class for myIae + HashMap<Object,Object> myEntries = dbDAO.getAllMyEntries(clazzName); + //get a map of the objects indexed by id. Does not necessarily have any entries + + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Traversing iaeList, size=" + iaeList.size()); + } + for (IntegrityAuditEntity iae : iaeList){ + if(iae.getId() == myIae.getId()){ + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: My Id=" + iae.getId() + + ", resourceName=" + iae.getResourceName()); + } + continue; //no need to compare with self + } else { + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Id=" + iae.getId() + + ", resourceName=" + iae.getResourceName()); + } + } + // Create properties for the other db node + Properties theirProperties = new Properties(); + theirProperties.put(IntegrityAuditProperties.DB_DRIVER, iae.getJdbcDriver()); + theirProperties.put(IntegrityAuditProperties.DB_URL, iae.getJdbcUrl()); + theirProperties.put(IntegrityAuditProperties.DB_USER, iae.getJdbcUser()); + theirProperties.put(IntegrityAuditProperties.DB_PWD, iae.getJdbcPassword()); + theirProperties.put(IntegrityAuditProperties.SITE_NAME, iae.getSite()); + theirProperties.put(IntegrityAuditProperties.NODE_TYPE, iae.getNodeType()); + + //get a map of the instances for their iae indexed by id + HashMap<Object,Object> theirEntries = dbDAO.getAllEntries(persistenceUnit, theirProperties, clazzName); + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: For persistenceUnit=" + + persistenceUnit + ", clazzName=" + clazzName + + ", theirEntries.size()=" + + theirEntries.size()); + } + + /* + * Compare myEntries with theirEntries and get back a set of mismatched IDs. + * Collect the IDs for the class where a mismatch occurred. We will check + * them again for all nodes later. + */ + HashSet<Object> misMatchedKeySet = compareEntries(myEntries, theirEntries); + if(!misMatchedKeySet.isEmpty()){ + HashSet<Object> misMatchedEntry = misMatchedMap.get(clazzName); + if(misMatchedEntry == null){ + misMatchedMap.put(clazzName, misMatchedKeySet); + }else{ + misMatchedEntry.addAll(misMatchedKeySet); + misMatchedMap.put(clazzName, misMatchedEntry); + } + } + } //end for (IntegrityAuditEntity iae : iaeList) + //Time check + if((System.currentTimeMillis() - startTime) >= 5000){ //5 seconds + //update the timestamp + dbDAO.setLastUpdated(); + //reset the startTime + startTime=System.currentTimeMillis(); + }else{ + //sleep a couple seconds to break up the activity + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Sleeping 2 seconds"); + } + Thread.sleep(2000); + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Waking from sleep"); + } + } + }//end: for(String clazzName: classNameList) + + //check if misMatchedMap is empty + if(misMatchedMap.isEmpty()){ + + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Exiting, misMatchedMap is empty"); + } + //we are done + return; + } else { + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Doing another comparison; misMatchedMap.size()=" + misMatchedMap.size()); + } + } + + // If misMatchedMap is not empty, retrieve the entries in each misMatched list and compare again + classNameSet = new HashSet<String>(misMatchedMap.keySet()); + // We need to keep track of how long the audit is taking + startTime = System.currentTimeMillis(); + + // Retrieve all instances of the class for each node + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Second comparison; traversing classNameSet, size=" + classNameSet.size()); + } + + int errorCount = 0; + + for(String clazzName: classNameSet){ + + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Second comparison; clazzName=" + clazzName); + } + + // all instances of the class for myIae + HashSet<Object> keySet = misMatchedMap.get(clazzName); + HashMap<Object,Object> myEntries = dbDAO.getAllMyEntries(clazzName, keySet); + //get a map of the objects indexed by id + + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Second comparison; traversing iaeList, size=" + iaeList.size()); + } + for (IntegrityAuditEntity iae : iaeList){ + if(iae.getId() == myIae.getId()){ + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Second comparison; My Id=" + iae.getId() + + ", resourceName=" + iae.getResourceName()); + } + continue; //no need to compare with self + } else { + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Second comparison; Id=" + iae.getId() + + ", resourceName=" + iae.getResourceName()); + } + } + // Create properties for the other db node + Properties theirProperties = new Properties(); + theirProperties.put(IntegrityAuditProperties.DB_DRIVER, iae.getJdbcDriver()); + theirProperties.put(IntegrityAuditProperties.DB_URL, iae.getJdbcUrl()); + theirProperties.put(IntegrityAuditProperties.DB_USER, iae.getJdbcUser()); + theirProperties.put(IntegrityAuditProperties.DB_PWD, iae.getJdbcPassword()); + theirProperties.put(IntegrityAuditProperties.SITE_NAME, iae.getSite()); + theirProperties.put(IntegrityAuditProperties.NODE_TYPE, iae.getNodeType()); + + //get a map of the instances for their iae indexed by id + HashMap<Object,Object> theirEntries = dbDAO.getAllEntries(persistenceUnit, theirProperties, clazzName, keySet); + + /* + * Compare myEntries with theirEntries and get back a set of mismatched IDs. + * Collect the IDs for the class where a mismatch occurred. We will now + * write an error log for each. + */ + HashSet<Object> misMatchedKeySet = compareEntries(myEntries, theirEntries); + if(!misMatchedKeySet.isEmpty()){ + String keysString = ""; + for(Object key: misMatchedKeySet){ + keysString = keysString.concat(key.toString() + ", "); + errorCount ++; + } + writeAuditSummaryLog(clazzName, resourceName, iae.getResourceName(), keysString); + if(logger.isDebugEnabled()){ + for(Object key : misMatchedKeySet){ + writeAuditDebugLog(clazzName, resourceName, iae.getResourceName(), myEntries.get(key), theirEntries.get(key)); + } + } + } + } + //Time check + if((System.currentTimeMillis() - startTime) >= 5000){ //5 seconds + //update the timestamp + dbDAO.setLastUpdated(); + //reset the startTime + startTime=System.currentTimeMillis(); + }else{ + //sleep a couple seconds to break up the activity + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Second comparison; sleeping 2 seconds"); + } + Thread.sleep(2000); + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Second comparison; waking from sleep"); + } + } + }//end: for(String clazzName: classNameList) + + if(errorCount != 0){ + String msg = " DB Audit: " + errorCount + " errors found. A large number of errors may indicate DB replication has stopped"; + logger.error(MessageCodes.ERROR_AUDIT, msg); + } + + if (logger.isDebugEnabled()) { + logger.debug("dbAudit: Exiting"); + } + + return; //all done + } + + /** + * dbAuditSimulate simulates the DB audit + * @param resourceName + * @param persistenceUnit + * @param nodeType + * @throws InterruptedException + * @throws DbDaoTransactionException + */ + public void dbAuditSimulate(String resourceName, String persistenceUnit, + String nodeType) throws InterruptedException, + DbDaoTransactionException { + + logger.info("dbAuditSimulate: Starting audit simulation for resourceName=" + + resourceName + ", persistenceUnit=" + persistenceUnit); + + for (int i = 0; i < AuditThread.AUDIT_SIMULATION_ITERATIONS; i++) { + dbDAO.setLastUpdated(); + logger.info("dbAuditSimulate: i=" + i + ", sleeping " + + AuditThread.AUDIT_SIMULATION_SLEEP_INTERVAL + "ms"); + Thread.sleep(AuditThread.AUDIT_SIMULATION_SLEEP_INTERVAL); + } + + logger.info("dbAuditSimulate: Finished audit simulation for resourceName=" + + resourceName + ", persistenceUnit=" + persistenceUnit); + + } + + /** + * compareEntries() will compare the lists of entries from the DB + * @param myEntries + * @param theirEntries + * @return + */ + public HashSet<Object> compareEntries(HashMap<Object,Object> myEntries, HashMap<Object,Object> theirEntries){ + /* + * Compare the entries for the same key in each of the hashmaps. The comparison will be done by serializing the objects + * (create a byte array) and then do a byte array comparison. The audit will walk the local repository hash map comparing + * to the remote cluster hashmap and then turn it around and walk the remote hashmap and look for any entries that are not + * present in the local cluster hashmap. + * + * If the objects are not identical, the audit will put the object IDs on a list to try after completing the audit of the table + * it is currently working on. + * + */ + HashSet<Object> misMatchedKeySet = new HashSet<Object>(); + for(Object key: myEntries.keySet()){ + byte[] mySerializedEntry = SerializationUtils.serialize((Serializable) myEntries.get(key)); + byte[] theirSerializedEntry = SerializationUtils.serialize((Serializable) theirEntries.get(key)); + if(!Arrays.equals(mySerializedEntry, theirSerializedEntry)){ + logger.debug("compareEntries: For myEntries.key=" + key + ", entries do not match"); + misMatchedKeySet.add(key); + } else { + logger.debug("compareEntries: For myEntries.key=" + key + ", entries match"); + } + } + //now compare it in the other direction to catch entries in their set that is not in my set + for(Object key: theirEntries.keySet()){ + byte[] mySerializedEntry = SerializationUtils.serialize((Serializable) myEntries.get(key)); + byte[] theirSerializedEntry = SerializationUtils.serialize((Serializable) theirEntries.get(key)); + if(!Arrays.equals(mySerializedEntry, theirSerializedEntry)){ + logger.debug("compareEntries: For theirEntries.key=" + key + ", entries do not match"); + misMatchedKeySet.add(key); + } else { + logger.debug("compareEntries: For theirEntries.key=" + key + ", entries match"); + } + } + + //return a Set of the object IDs + logger.debug("compareEntries: misMatchedKeySet.size()=" + misMatchedKeySet.size()); + return misMatchedKeySet; + } + + /** + * writeAuditDebugLog() writes the mismatched entry details to the debug log + * @param clazzName + * @param resourceName1 + * @param resourceName2 + * @param entry1 + * @param entry2 + * @throws ClassNotFoundException + */ + public void writeAuditDebugLog(String clazzName, String resourceName1, + String resourceName2, Object entry1, Object entry2) throws ClassNotFoundException{ + Class<?> entityClass = Class.forName(clazzName); + String tableName = entityClass.getAnnotation(Table.class).name(); + String msg = "\nDB Audit Error: " + + "\n Table Name: " + tableName + + "\n Entry 1 (short prefix style): " + resourceName1 + ": " + new ReflectionToStringBuilder(entry1,ToStringStyle.SHORT_PREFIX_STYLE).toString() + + "\n Entry 2 (short prefix style): " + resourceName2 + ": " + new ReflectionToStringBuilder(entry2,ToStringStyle.SHORT_PREFIX_STYLE).toString() + + "\n Entry 1 (recursive style): " + resourceName1 + ": " + new ReflectionToStringBuilder(entry1, new RecursiveToStringStyle()).toString() + + "\n Entry 2 (recursive style): " + resourceName2 + ": " + new ReflectionToStringBuilder(entry2, new RecursiveToStringStyle()).toString(); + logger.debug(msg); + + } + + /** + * writeAuditSummaryLog() writes a summary of the DB mismatches to the error log + * @param clazzName + * @param resourceName1 + * @param resourceName2 + * @param keys + * @throws ClassNotFoundException + */ + public void writeAuditSummaryLog(String clazzName, String resourceName1, + String resourceName2, String keys) throws ClassNotFoundException{ + Class<?> entityClass = Class.forName(clazzName); + String tableName = entityClass.getAnnotation(Table.class).name(); + String msg = " DB Audit Error: Table Name: " + tableName + + "; Mismatch between nodes: " + resourceName1 +" and " + resourceName2 + + "; Mismatched entries (keys): " + keys; + logger.info(msg); + } + + + + + +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAuditException.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAuditException.java new file mode 100644 index 00000000..f5cd183f --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbAuditException.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +public class DbAuditException extends Exception{ + private static final long serialVersionUID = 1L; + public DbAuditException() { + } + public DbAuditException(String message) { + super(message); + } + + public DbAuditException(Throwable cause) { + super(cause); + } + public DbAuditException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDAO.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDAO.java new file mode 100644 index 00000000..64c01931 --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDAO.java @@ -0,0 +1,739 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.LockTimeoutException; +import javax.persistence.Persistence; +import javax.persistence.PersistenceUnitUtil; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import javax.persistence.metamodel.ManagedType; +import javax.persistence.metamodel.Metamodel; + +//import org.apache.log4j.Logger; + +import org.onap.policy.common.ia.jpa.IntegrityAuditEntity; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +/** + * class DbDAO provides the inteface to the DBs for the purpose of audits. + * + */ +public class DbDAO { + private static final Logger logger = FlexLogger.getLogger(DbDAO.class.getName()); + private String resourceName; + private String persistenceUnit; + private String dbDriver; + private String dbUrl; + private String dbUser; + private String dbPwd; + private String siteName; + private String nodeType; + private Properties properties=null; + + private EntityManagerFactory emf; + + /* + * Supports designation serialization. + */ + private static final Object lock = new Object(); + + + /** + * DbDAO Constructor + * @param resourceName + * @param persistenceUnit + * @param properties + * @throws Exception + */ + public DbDAO(String resourceName, String persistenceUnit, Properties properties) throws Exception { + logger.debug("DbDAO contructor: enter"); + + validateProperties(resourceName, persistenceUnit, properties); + + emf = Persistence.createEntityManagerFactory(persistenceUnit, properties); + + register(); + + logger.debug("DbDAO contructor: exit"); + } + + /** + * validateProperties will validate the properties + * @param resourceName + * @param persistenceUnit + * @param properties + * @throws IntegrityAuditPropertiesException + */ + private void validateProperties(String resourceName, String persistenceUnit, Properties properties) throws IntegrityAuditPropertiesException{ + String badparams=""; + if(IntegrityAudit.parmsAreBad(resourceName, persistenceUnit, properties, badparams)){ + String msg = "DbDAO: Bad parameters: badparams" + badparams; + throw new IntegrityAuditPropertiesException(msg); + } + this.resourceName = resourceName; + this.persistenceUnit = persistenceUnit; + this.dbDriver = properties.getProperty(IntegrityAuditProperties.DB_DRIVER).trim(); + this.dbUrl = properties.getProperty(IntegrityAuditProperties.DB_URL).trim(); + this.dbUser = properties.getProperty(IntegrityAuditProperties.DB_USER).trim(); + this.dbPwd = properties.getProperty(IntegrityAuditProperties.DB_PWD).trim(); + this.siteName = properties.getProperty(IntegrityAuditProperties.SITE_NAME).trim(); + this.nodeType = properties.getProperty(IntegrityAuditProperties.NODE_TYPE).trim(); + this.properties = properties; + logger.debug("DbDAO.assignProperties: exit:" + + "\nresourceName: " + this.resourceName + + "\npersistenceUnit: " + this.persistenceUnit + + "\nproperties: " + this.properties); + } + + /** + * getAllMyEntries gets all the DB entries for a particular class + * @param className + * @return + */ + public HashMap<Object, Object> getAllMyEntries(String className) { + logger.debug("getAllMyEntries: Entering, className=" + + className); + HashMap<Object, Object> resultMap = new HashMap<Object,Object>(); + EntityManager em = emf.createEntityManager(); + try{ + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery<Object> cq = cb.createQuery(); + Root<?> rootEntry = cq.from(Class.forName(className)); + CriteriaQuery<Object> all = cq.select(rootEntry); + TypedQuery<Object> allQuery = em.createQuery(all); + List<Object> objectList = allQuery.getResultList(); + //Now create the map + + PersistenceUnitUtil util = emf.getPersistenceUnitUtil(); + for (Object o: objectList){ + Object key = util.getIdentifier(o); + resultMap.put(key, o); + } + }catch(Exception e){ + String msg = "getAllEntries encountered exception: " + e; + logger.error(msg); + System.out.println(new Date()); + e.printStackTrace(); + } + em.close(); + logger.debug("getAllMyEntries: Exit, resultMap.keySet()=" + resultMap.keySet()); + return resultMap; + } + + /** + * getAllMyEntries gets all entries for a class + * @param className + * @param keySet + * @return + */ + public HashMap<Object, Object> getAllMyEntries(String className, HashSet<Object> keySet){ + logger.debug("getAllMyEntries: Entering, className=" + + className + ",\n keySet=" + keySet); + + HashMap<Object, Object> resultMap = new HashMap<Object,Object>(); + EntityManager em = emf.createEntityManager(); + try{ + Class<?> clazz = Class.forName(className); + for(Object key : keySet){ + Object entry = em.find(clazz, key); + resultMap.put(key, entry); + } + }catch(Exception e){ + String msg = "getAllMyEntries encountered exception: " + e; + logger.error(msg); + System.out.println(new Date()); + e.printStackTrace(); + } + em.close(); + + logger.debug("getAllMyEntries: Returning resultMap, size=" + resultMap.size()); + return resultMap; + } + + /** + * getAllEntries gets all entriesfor a particular persistence unit adn className + * @param persistenceUnit + * @param properties + * @param className + * @return + */ + public HashMap<Object,Object> getAllEntries(String persistenceUnit, Properties properties, String className){ + + logger.debug("getAllEntries: Entering, persistenceUnit=" + + persistenceUnit + ",\n className=" + className); + HashMap<Object, Object> resultMap = new HashMap<Object,Object>(); + + EntityManagerFactory theEmf = Persistence.createEntityManagerFactory(persistenceUnit, properties); + EntityManager em = theEmf.createEntityManager(); + try{ + CriteriaBuilder cb = em.getCriteriaBuilder(); + CriteriaQuery<Object> cq = cb.createQuery(); + Root<?> rootEntry = cq.from(Class.forName(className)); + CriteriaQuery<Object> all = cq.select(rootEntry); + TypedQuery<Object> allQuery = em.createQuery(all); + List<Object> objectList = allQuery.getResultList(); + + PersistenceUnitUtil util = theEmf.getPersistenceUnitUtil(); + for (Object o: objectList){ + Object key = util.getIdentifier(o); + resultMap.put(key, o); + } + }catch(Exception e){ + String msg = "getAllEntries encountered exception:" + e; + logger.error(msg); + System.out.println(new Date()); + e.printStackTrace(); + } + em.close(); + + logger.debug("getAllEntries: Returning resultMap, size=" + resultMap.size()); + + return resultMap; + } + + + /** + * getAllEntries gest all entries for a persistence unit + * @param persistenceUnit + * @param properties + * @param className + * @param keySet + * @return + */ + + public HashMap<Object,Object> getAllEntries(String persistenceUnit, Properties properties, String className, HashSet<Object> keySet){ + logger.debug("getAllEntries: Entering, persistenceUnit=" + + persistenceUnit + ",\n properties= " + properties + ",\n className=" + className + ",\n keySet= " + keySet); + EntityManagerFactory theEmf = Persistence.createEntityManagerFactory(persistenceUnit, properties); + EntityManager em = theEmf.createEntityManager(); + HashMap<Object, Object> resultMap = new HashMap<Object,Object>(); + try{ + Class<?> clazz = Class.forName(className); + for(Object key : keySet){ + Object entry = em.find(clazz, key); + resultMap.put(key, entry); + } + }catch(Exception e){ + String msg = "getAllEntries encountered exception: " + e; + logger.error(msg); + System.out.println(new Date()); + e.printStackTrace(); + } + em.close(); + logger.debug("getAllEntries: Exit, resultMap, size=" + resultMap.size()); + return resultMap; + } + + /** + * getIntegrityAuditEntities() Get all the IntegrityAuditEntities for a particular persistence unit + * and node type + * @param persistenceUnit + * @param nodeType + * @return + * @throws DbDaoTransactionException + */ + @SuppressWarnings("unchecked") + public List<IntegrityAuditEntity> getIntegrityAuditEntities(String persistenceUnit, String nodeType) throws DbDaoTransactionException { + logger.debug("getIntegrityAuditEntities: Entering, persistenceUnit=" + + persistenceUnit + ",\n nodeType= " + nodeType); + try{ + EntityManager em = emf.createEntityManager(); + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry + Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.persistenceUnit=:pu and i.nodeType=:nt"); + iaequery.setParameter("pu", persistenceUnit); + iaequery.setParameter("nt", nodeType); + + List<IntegrityAuditEntity> iaeList = iaequery.getResultList(); + + // commit transaction + et.commit(); + em.close(); + logger.debug("getIntegrityAuditEntities: Exit, iaeList=" + iaeList); + return iaeList; + }catch (Exception e){ + String msg = "DbDAO: " + "getIntegrityAuditEntities() " + "ecountered a problem in execution: "; + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(e); + } + + } + + /** + * getMyIntegrityAuditEntity() gets my IntegrityAuditEntity + * @return + * @throws DbDaoTransactionException + */ + public IntegrityAuditEntity getMyIntegrityAuditEntity() throws DbDaoTransactionException{ + try{ + EntityManager em = emf.createEntityManager(); + + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + // if IntegrityAuditEntity entry exists for resourceName and PU, retrieve it + Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu"); + iaequery.setParameter("rn", this.resourceName); + iaequery.setParameter("pu", this.persistenceUnit); + + @SuppressWarnings("rawtypes") + List iaeList = iaequery.getResultList(); + IntegrityAuditEntity iae = null; + + if(!iaeList.isEmpty()){ + //ignores multiple results + iae = (IntegrityAuditEntity) iaeList.get(0); + // refresh the object from DB in case cached data was returned + em.refresh(iae); + logger.info("Resource: " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit + + " exists"); + }else{ + // If it does not exist, log an error + logger.error("Attempting to setLastUpdated" + + " on an entry that does not exist:" + +" resource " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit); + } + + // close the transaction + et.commit(); + // close the EntityManager + em.close(); + + return iae; + }catch (Exception e){ + String msg = "DbDAO: " + "setLastUpdated() " + "ecountered a problem in execution: "; + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(e); + } + } + + + /** + * getIntegrityAuditEntity() gets the IntegrityAuditEntity with a particular ID + * @param id + * @return + * @throws DbDaoTransactionException + */ + public IntegrityAuditEntity getIntegrityAuditEntity(long id) throws DbDaoTransactionException{ + try{ + EntityManager em = emf.createEntityManager(); + + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + IntegrityAuditEntity iae = em.find(IntegrityAuditEntity.class, id); + + et.commit(); + em.close(); + + return iae; + }catch (Exception e){ + String msg = "DbDAO: " + "getIntegrityAuditEntity() " + "ecountered a problem in execution: "; + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(e); + } + } + + /** + * getPersistenceClassNames() gets all the persistence class names. + * @return + */ + public HashSet<String> getPersistenceClassNames(){ + logger.debug("DbDAO: getPersistenceClassNames() entry"); + HashSet<String> returnList = new HashSet<String>(); + final Metamodel mm = emf.getMetamodel(); + logger.debug("\n" + persistenceUnit +" persistence unit classes:"); + for (final ManagedType<?> managedType : mm.getManagedTypes()) { + Class<?> c = managedType.getJavaType(); + logger.debug(" " + c.getSimpleName()); + returnList.add(c.getName()); //the full class name needed to make a query using jpa + } + logger.debug("DbDAO: getPersistenceClassNames() exit"); + return returnList; + } + + /** + * Register the IntegrityAudit instance + */ + private void register() throws DbDaoTransactionException { + try{ + EntityManager em = emf.createEntityManager(); + + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry + Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu"); + iaequery.setParameter("rn", this.resourceName); + iaequery.setParameter("pu", this.persistenceUnit); + + @SuppressWarnings("rawtypes") + List iaeList = iaequery.getResultList(); + IntegrityAuditEntity iae = null; + + //If it already exists, we just want to update the properties and lastUpdated date + if(!iaeList.isEmpty()){ + //ignores multiple results + iae = (IntegrityAuditEntity) iaeList.get(0); + // refresh the object from DB in case cached data was returned + em.refresh(iae); + logger.info("Resource: " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit + + " exists and entry be updated"); + }else{ + // If it does not exist, we also must add teh resourceName, persistenceUnit and designated values + logger.info("Adding resource " + resourceName + " with PersistenceUnit: " + this.persistenceUnit + + " to IntegrityAuditEntity table"); + iae = new IntegrityAuditEntity(); + iae.setResourceName(this.resourceName); + iae.setPersistenceUnit(this.persistenceUnit); + iae.setDesignated(false); + } + //update/set properties in entry + iae.setSite(this.siteName); + iae.setNodeType(this.nodeType); + iae.setLastUpdated(new Date()); + iae.setJdbcDriver(this.dbDriver); + iae.setJdbcPassword(this.dbPwd); + iae.setJdbcUrl(dbUrl); + iae.setJdbcUser(dbUser); + + em.persist(iae); + // flush to the DB + em.flush(); + + // commit transaction + et.commit(); + em.close(); + }catch (Exception e){ + String msg = "DbDAO: " + "register() " + "ecountered a problem in execution: "; + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(e); + } + + } + + public void setDesignated(boolean designated) throws DbDaoTransactionException{ + setDesignated(this.resourceName, this.persistenceUnit, designated); + } + + + public void setDesignated(String rName, String pUnit, boolean desig) throws DbDaoTransactionException{ + logger.debug("setDesignated: enter, resourceName: " + rName + ", persistenceUnit: " + + pUnit + ", designated: " + desig); + try{ + + EntityManager em = emf.createEntityManager(); + + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry + Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu"); + iaequery.setParameter("rn", rName); + iaequery.setParameter("pu", pUnit); + + @SuppressWarnings("rawtypes") + List iaeList = iaequery.getResultList(); + IntegrityAuditEntity iae = null; + + if(!iaeList.isEmpty()){ + //ignores multiple results + iae = (IntegrityAuditEntity) iaeList.get(0); + // refresh the object from DB in case cached data was returned + em.refresh(iae); + logger.info("Resource: " + rName + " with PersistenceUnit: " + pUnit + + " exists and designated be updated"); + iae.setDesignated(desig); + + em.persist(iae); + // flush to the DB + em.flush(); + }else{ + // If it does not exist, log an error + logger.error("Attempting to setDesignated(" + + desig + ") on an entry that does not exist:" + +" resource " + rName + " with PersistenceUnit: " + pUnit); + } + + // close the transaction + et.commit(); + // close the EntityManager + em.close(); + }catch (Exception e){ + String msg = "DbDAO: " + "setDesignated() " + "ecountered a problem in execution: "; + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(e); + } + + } + + public void setLastUpdated() throws DbDaoTransactionException{ + logger.debug("setLastUpdated: enter, resourceName: " + this.resourceName + ", persistenceUnit: " + + this.persistenceUnit); + try{ + EntityManager em = emf.createEntityManager(); + + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry + Query iaequery = em.createQuery("Select i from IntegrityAuditEntity i where i.resourceName=:rn and i.persistenceUnit=:pu"); + iaequery.setParameter("rn", this.resourceName); + iaequery.setParameter("pu", this.persistenceUnit); + + @SuppressWarnings("rawtypes") + List iaeList = iaequery.getResultList(); + IntegrityAuditEntity iae = null; + + if(!iaeList.isEmpty()){ + //ignores multiple results + iae = (IntegrityAuditEntity) iaeList.get(0); + // refresh the object from DB in case cached data was returned + em.refresh(iae); + logger.info("Resource: " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit + + " exists and lastUpdated be updated"); + iae.setLastUpdated(new Date()); + + em.persist(iae); + // flush to the DB + em.flush(); + }else{ + // If it does not exist, log an error + logger.error("Attempting to setLastUpdated" + + " on an entry that does not exist:" + +" resource " + this.resourceName + " with PersistenceUnit: " + this.persistenceUnit); + } + + // close the transaction + et.commit(); + // close the EntityManager + em.close(); + }catch (Exception e){ + String msg = "DbDAO: " + "setLastUpdated() " + "ecountered a problem in execution: "; + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(e); + } + + } + + /** + * Normally this method should only be used in a JUnit test environment. + * Manually deletes all PDP records in droolspdpentity table. + */ + public int deleteAllIntegrityAuditEntities() throws DbDaoTransactionException { + + try{ + + if (!IntegrityAudit.isUnitTesting) { + String msg = "DbDAO: " + "deleteAllIntegrityAuditEntities() " + "should only be invoked during JUnit testing"; + logger.error(msg); + throw new DbDaoTransactionException(msg); + } + + EntityManager em = emf.createEntityManager(); + // Start a transaction + EntityTransaction et = em.getTransaction(); + + et.begin(); + + // if IntegrityAuditEntity entry exists for resourceName and PU, update it. If not found, create a new entry + Query iaequery = em.createQuery("Delete from IntegrityAuditEntity"); + + int returnCode = iaequery.executeUpdate(); + + // commit transaction + et.commit(); + em.close(); + + logger.info("deleteAllIntegrityAuditEntities: returnCode=" + returnCode); + + return returnCode; + + }catch (Exception e){ + String msg = "DbDAO: " + "deleteAllIntegrityAuditEntities() " + "encountered a problem in execution: "; + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(e); + } + + } + + /** + * Changes designation to specified resourceName + * + * static lock object in conjunction with synchronized keyword ensures that + * designation changes are done serially within a resource. I.e. static lock + * ensures that multiple instantiations of DbDAO don't interleave + * changeDesignated() invocations and potentially produce simultaneous + * designations. + * + * Optimistic locking (the default, versus pessimistic) is sufficient to + * avoid simultaneous designations from interleaved changeDesignated() + * invocations from different resources (entities), because it prevents + * "dirty" and "non-repeatable" reads. + * + * See http://www.objectdb.com/api/java/jpa/LockModeType + * + * and + * + * http://stackoverflow.com/questions/2120248/how-to-synchronize-a-static- + * variable-among-threads-running-different-instances-o + */ + public void changeDesignated(String resourceName, String persistenceUnit, + String nodeType) throws DbDaoTransactionException { + + if (logger.isDebugEnabled()) { + logger.debug("changeDesignated: Entering, resourceName=" + + resourceName + ", persistenceUnit=" + persistenceUnit + + ", nodeType=" + nodeType); + } + + long startTime = System.currentTimeMillis(); + + synchronized (lock) { + + EntityManager em = null; + try { + + em = emf.createEntityManager(); + em.getTransaction().begin(); + + /* + * Define query + */ + Query query = em + .createQuery("Select i from IntegrityAuditEntity i where i.persistenceUnit=:pu and i.nodeType=:nt"); + query.setParameter("pu", persistenceUnit); + query.setParameter("nt", nodeType); + + /* + * Execute query using pessimistic write lock. This ensures that if anyone else is currently reading + * the records we'll throw a LockTimeoutException. + */ + @SuppressWarnings("unchecked") + List<IntegrityAuditEntity> integrityAuditEntityList = (List<IntegrityAuditEntity>) query + .getResultList(); + for (Object o : integrityAuditEntityList) { + if (o instanceof IntegrityAuditEntity) { + IntegrityAuditEntity integrityAuditEntity = (IntegrityAuditEntity) o; + if (integrityAuditEntity.getResourceName().equals( + resourceName)) { + if (logger.isDebugEnabled()) { + logger.debug("changeDesignated: Designating resourceName=" + + integrityAuditEntity + .getResourceName()); + } + integrityAuditEntity.setDesignated(true); + } else { + if (logger.isDebugEnabled()) { + logger.debug("changeDesignated: Removing designation from resourceName=" + + integrityAuditEntity + .getResourceName()); + } + integrityAuditEntity.setDesignated(false); + } + } + } + + if (logger.isDebugEnabled()) { + logger.debug("changeDesignated: Committing designation to resourceName=" + + resourceName); + } + em.getTransaction().commit(); + + /* + * If we get a LockTimeoutException, no harm done really. We'll + * probably be successful on the next attempt. The odds of + * another DbDAO instance on this entity or another entity + * attempting a simultaneous IntegrityAuditEntity table + * read/update are pretty slim (we're only in this method for + * two or three milliseconds) + */ + } catch (LockTimeoutException e) { + em.getTransaction().rollback(); + String msg = "DbDAO: " + "changeDesignated() " + + "caught LockTimeoutException, message=" + e.getMessage(); + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(msg, e); + } catch (Exception e) { + em.getTransaction().rollback(); + String msg = "DbDAO: " + "changeDesignated() " + + "caught Exception, message=" + e.getMessage(); + logger.error(msg + e); + System.out.println(new Date()); + e.printStackTrace(); + throw new DbDaoTransactionException(msg, e); + } + + } // end synchronized block + + if (logger.isDebugEnabled()) { + logger.debug("changeDesignated: Exiting; time expended=" + + (System.currentTimeMillis() - startTime) + "ms"); + } + + } + + +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDaoTransactionException.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDaoTransactionException.java new file mode 100644 index 00000000..4ad8521a --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/DbDaoTransactionException.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +public class DbDaoTransactionException extends Exception{ + private static final long serialVersionUID = 1L; + public DbDaoTransactionException() { + } + public DbDaoTransactionException(String message) { + super(message); + } + + public DbDaoTransactionException(Throwable cause) { + super(cause); + } + public DbDaoTransactionException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java new file mode 100644 index 00000000..5ec6229c --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAudit.java @@ -0,0 +1,241 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +import java.util.Properties; + +//import org.apache.log4j.Logger; + +import org.onap.policy.common.ia.IntegrityAuditProperties.NodeTypeEnum; +import org.onap.policy.common.logging.flexlogger.FlexLogger; +import org.onap.policy.common.logging.flexlogger.Logger; + +/** + * class IntegrityAudit + * Audits all persisted entities for all resource clusters for all sites and logs any anomalies. + */ +public class IntegrityAudit { + + private static final Logger logger = FlexLogger.getLogger(IntegrityAudit.class); + + public static boolean isUnitTesting; + private boolean isThreadInitialized = false; + + AuditThread auditThread = null; + + private String persistenceUnit; + private Properties properties; + private String resourceName; + + + /* + * This is the audit period in seconds. For example, if it had a value of 3600, the audit + * can only run once per hour. If it has a value of 60, it can run once per minute. + * + * Values: + * integrityAuditPeriodSeconds < 0 (negative number) indicates the audit is off + * integrityAuditPeriodSecconds == 0 indicates the audit is to run continuously + * integrityAuditPeriodSeconds > 0 indicates the audit is to run at most once during the indicated period + * + */ + private int integrityAuditPeriodSeconds; + + /** + * IntegrityAudit constructor + * @param resourceName + * @param persistenceUnit + * @param properties + * @throws Exception + */ + public IntegrityAudit(String resourceName, String persistenceUnit, Properties properties) throws Exception { + + logger.info("Constructor: Entering and checking for nulls"); + String parmList = ""; + if (parmsAreBad(resourceName, persistenceUnit, properties, parmList)) { + logger.error("Constructor: Parms contain nulls; cannot run audit for resourceName=" + + resourceName + ", persistenceUnit=" + persistenceUnit + + ", bad parameters: " + parmList); + throw new Exception( + "Constructor: Parms contain nulls; cannot run audit for resourceName=" + + resourceName + ", persistenceUnit=" + + persistenceUnit + + ", bad parameters: " + parmList); + } + + this.persistenceUnit = persistenceUnit; + this.properties = properties; + this.resourceName = resourceName; + + if(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS) != null){ //It is allowed to be null + this.integrityAuditPeriodSeconds= Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim()); + } else{ + //If it is null, set it to the default value + this.integrityAuditPeriodSeconds = IntegrityAuditProperties.DEFAULT_AUDIT_PERIOD_SECONDS; + } + logger.info("Constructor: Exiting"); + + } + + /** + * Used during JUnit testing by AuditPeriodTest.java + */ + public int getIntegrityAuditPeriodSeconds() { + return integrityAuditPeriodSeconds; + } + + /** + * Determine if the nodeType conforms to the required node types + */ + public static boolean isNodeTypeEnum(String nt) { + for (NodeTypeEnum n : NodeTypeEnum.values()) { + if (n.toString().equals(nt)) { + return true; + } + } + return false; + } + + + /** + * Makes sure we don't try to run the audit with bad parameters. + */ + public static boolean parmsAreBad(String resourceName, String persistenceUnit, + Properties properties, String badparams) { + + boolean parmsAreBad = false; + + if(resourceName == null || resourceName.isEmpty()){ + badparams = badparams.concat("resourceName "); + parmsAreBad = true; + } + + if(persistenceUnit == null || persistenceUnit.isEmpty()){ + badparams = badparams.concat("persistenceUnit "); + parmsAreBad = true; + } + + String dbDriver = properties.getProperty(IntegrityAuditProperties.DB_DRIVER).trim(); + if(dbDriver == null || dbDriver.isEmpty()){ + badparams = badparams.concat("dbDriver "); + parmsAreBad = true; + } + + String dbUrl = properties.getProperty(IntegrityAuditProperties.DB_URL).trim(); + if(dbUrl == null || dbUrl.isEmpty()){ + badparams = badparams.concat("dbUrl "); + parmsAreBad = true; + } + + String dbUser = properties.getProperty(IntegrityAuditProperties.DB_USER).trim(); + if(dbUser == null || dbUser.isEmpty()){ + badparams = badparams.concat("dbUser "); + parmsAreBad = true; + } + + String dbPwd = properties.getProperty(IntegrityAuditProperties.DB_PWD).trim(); + if(dbPwd == null){ //may be empty + badparams = badparams.concat("dbPwd "); + parmsAreBad = true; + } + + String siteName = properties.getProperty(IntegrityAuditProperties.SITE_NAME).trim(); + if(siteName == null || siteName.isEmpty()){ + badparams = badparams.concat("siteName "); + parmsAreBad = true; + } + + String nodeType = properties.getProperty(IntegrityAuditProperties.NODE_TYPE).trim(); + if(nodeType == null || nodeType.isEmpty()){ + badparams = badparams.concat("nodeType "); + parmsAreBad = true; + } else { + if (!isNodeTypeEnum(nodeType)) { + String nodetypes = "nodeType must be one of["; + for (NodeTypeEnum n : NodeTypeEnum.values()) { + nodetypes = nodetypes.concat(n.toString() + " "); + } + badparams = badparams.concat(nodetypes + "] "); + parmsAreBad = true; + } + } + if(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS) != null){ //It is allowed to be null + try{ + Integer.parseInt(properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim()); + }catch(NumberFormatException nfe){ + badparams = badparams.concat(", auditPeriodSeconds=" + + properties.getProperty(IntegrityAuditProperties.AUDIT_PERIOD_SECONDS).trim()); + parmsAreBad = true; + } + } + logger.debug("parmsAreBad: exit:" + + "\nresourceName: " + resourceName + + "\npersistenceUnit: " + persistenceUnit + + "\nproperties: " + properties); + + return parmsAreBad; + } + /** + * Starts the audit thread + * @throws Exception + */ + public void startAuditThread() throws Exception { + + logger.info("startAuditThread: Entering"); + + if (integrityAuditPeriodSeconds >= 0) { + this.auditThread = new AuditThread(this.resourceName, + this.persistenceUnit, this.properties, + integrityAuditPeriodSeconds, this); + logger.info("startAuditThread: Audit started and will run every " + + integrityAuditPeriodSeconds + " seconds"); + this.auditThread.start(); + } else { + logger.info("startAuditThread: Suppressing integrity audit, integrityAuditPeriodSeconds=" + + integrityAuditPeriodSeconds); + } + + logger.info("startAuditThread: Exiting"); + } + /** + * Stops the audit thread + */ + public void stopAuditThread() { + + logger.info("stopAuditThread: Entering"); + + if (this.auditThread != null) { + this.auditThread.interrupt(); + } else { + logger.info("stopAuditThread: auditThread never instantiated; no need to interrupt"); + } + + logger.info("stopAuditThread: Exiting"); + } + + public boolean isThreadInitialized() { + return isThreadInitialized; + } + + public void setThreadInitialized(boolean isThreadInitialized) { + logger.info("setThreadInitialized: Setting isThreadInitialized=" + isThreadInitialized); + this.isThreadInitialized = isThreadInitialized; + } +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditProperties.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditProperties.java new file mode 100644 index 00000000..3f87cf26 --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditProperties.java @@ -0,0 +1,54 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +public class IntegrityAuditProperties { + + public static final String DEFAULT_DB_DRIVER = "org.h2.Driver"; + public static final String DEFAULT_DB_URL = "jdbc:h2:file:./sql/iaTest"; + public static final String DEFAULT_DB_USER = "sa"; + public static final String DEFAULT_DB_PWD = ""; + public static final int DEFAULT_AUDIT_PERIOD_SECONDS = -1; // Audit does not run + + public static final String DB_DRIVER = "javax.persistence.jdbc.driver"; + public static final String DB_URL = "javax.persistence.jdbc.url"; + public static final String DB_USER = "javax.persistence.jdbc.user"; + public static final String DB_PWD = "javax.persistence.jdbc.password"; + public static final String AUDIT_PERIOD_SECONDS = "integrity_audit_period_seconds"; + + + public static final String SITE_NAME = "site_name"; + public static final String NODE_TYPE = "node_type"; + + public static enum NodeTypeEnum { + pdp_xacml, + pdp_drools, + pap, + pap_admin, + logparser, + brms_gateway, + astra_gateway, + elk_server, + pypdp + + } + +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditPropertiesException.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditPropertiesException.java new file mode 100644 index 00000000..b62e9064 --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/IntegrityAuditPropertiesException.java @@ -0,0 +1,37 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia; + +public class IntegrityAuditPropertiesException extends Exception{ + private static final long serialVersionUID = 1L; + public IntegrityAuditPropertiesException() { + } + public IntegrityAuditPropertiesException(String message) { + super(message); + } + + public IntegrityAuditPropertiesException(Throwable cause) { + super(cause); + } + public IntegrityAuditPropertiesException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/integrity-audit/src/main/java/org/onap/policy/common/ia/jpa/IntegrityAuditEntity.java b/integrity-audit/src/main/java/org/onap/policy/common/ia/jpa/IntegrityAuditEntity.java new file mode 100644 index 00000000..2b68a51d --- /dev/null +++ b/integrity-audit/src/main/java/org/onap/policy/common/ia/jpa/IntegrityAuditEntity.java @@ -0,0 +1,203 @@ +/*- + * ============LICENSE_START======================================================= + * Integrity Audit + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.ia.jpa; + +import java.io.Serializable; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +/* + * The Entity class to for management of IntegrityAudits + */ + +@Entity +@Table(name="IntegrityAuditEntity") +@NamedQueries({ + @NamedQuery(name=" IntegrityAuditEntity.findAll", query="SELECT e FROM IntegrityAuditEntity e "), + @NamedQuery(name="IntegrityAuditEntity.deleteAll", query="DELETE FROM IntegrityAuditEntity WHERE 1=1") +}) + +public class IntegrityAuditEntity implements Serializable { + private static final long serialVersionUID = 1L; + + public static boolean isUnitTesting; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name="id") + private long id; + + @Column(name="persistenceUnit", nullable=false) + private String persistenceUnit; + + @Column(name="site", nullable=true) + private String site; + + @Column(name="nodeType", nullable=true) + private String nodeType; + + @Column(name="resourceName", nullable=false, unique=true) + private String resourceName; + + @Column(name="designated", nullable=true) + private boolean designated = false; + + @Column(name="jdbcDriver", nullable=false) + private String jdbcDriver; + + @Column(name="jdbcUrl", nullable=false) + private String jdbcUrl; + + @Column(name="jdbcUser", nullable=false) + private String jdbcUser; + + @Column(name="jdbcPassword", nullable=false) + private String jdbcPassword; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="createdDate", updatable=true) + private Date createdDate; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="lastUpdated") + private Date lastUpdated; + + + public IntegrityAuditEntity() { + } + + @PrePersist + public void prePersist() { + Date date = new Date(); + this.createdDate = date; + this.lastUpdated = date; + } + + @PreUpdate + public void preUpdate() { + if (!isUnitTesting) { + this.lastUpdated = new Date(); + } + } + + public long getId() { + return id; + } + + public String getPersistenceUnit() { + return persistenceUnit; + } + + public void setPersistenceUnit(String persistenceUnit) { + this.persistenceUnit = persistenceUnit; + } + + public String getSite() { + return site; + } + + public void setSite(String site) { + this.site = site; + } + + public String getNodeType() { + return nodeType; + } + + public void setNodeType(String nodeType) { + this.nodeType = nodeType; + } + + public String getResourceName() { + return resourceName; + } + + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + + public boolean isDesignated() { + return designated; + } + + public void setDesignated(boolean designated) { + this.designated = designated; + } + + public String getJdbcDriver() { + return jdbcDriver; + } + + public void setJdbcDriver(String jdbcDriver) { + this.jdbcDriver = jdbcDriver; + } + + public String getJdbcUrl() { + return jdbcUrl; + } + + public void setJdbcUrl(String jdbcUrl) { + this.jdbcUrl = jdbcUrl; + } + + public String getJdbcUser() { + return jdbcUser; + } + + public void setJdbcUser(String jdbcUser) { + this.jdbcUser = jdbcUser; + } + + public String getJdbcPassword() { + return jdbcPassword; + } + + public void setJdbcPassword(String jdbcPassword) { + this.jdbcPassword = jdbcPassword; + } + + public Date getLastUpdated() { + return lastUpdated; + } + + public void setLastUpdated(Date lastUpdated) { + this.lastUpdated = lastUpdated; + } + + public Date getCreatedDate() { + return createdDate; + } + + public void setCreatedDate(Date created) { + this.createdDate = created; + } +} |