From faf283066f186838665ed5c38c1ba8319041bc1c Mon Sep 17 00:00:00 2001 From: Joshua Reich Date: Fri, 14 Sep 2018 11:38:01 -0700 Subject: Add demo for Control Loop Coordination. New PipEngine and Junit test added to guard. Also bug in existing Junit test fixed. All other code added to new directory template.demo.clc Change-Id: Ida2267528bcb9404dc59ff391d45797b591814cc Issue-ID: POLICY-1109 Signed-off-by: Joshua Reich --- .../org/onap/policy/guard/PIPEngineGetHistory.java | 405 -------------------- .../org/onap/policy/guard/PipEngineGetHistory.java | 405 ++++++++++++++++++++ .../org/onap/policy/guard/PipEngineGetStatus.java | 311 ++++++++++++++++ .../onap/policy/guard/PipEngineGetHistoryTest.java | 23 +- .../onap/policy/guard/PipEngineGetStatusTest.java | 411 +++++++++++++++++++++ 5 files changed, 1143 insertions(+), 412 deletions(-) delete mode 100644 controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java create mode 100644 controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetHistory.java create mode 100644 controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetStatus.java create mode 100644 controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetStatusTest.java (limited to 'controlloop/common/guard') diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java deleted file mode 100644 index a9a984ade..000000000 --- a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PIPEngineGetHistory.java +++ /dev/null @@ -1,405 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * guard - * ================================================================================ - * Copyright (C) 2017-2018 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.guard; - -import com.att.research.xacml.api.Attribute; -import com.att.research.xacml.api.AttributeValue; -import com.att.research.xacml.api.Identifier; -import com.att.research.xacml.api.pip.PIPException; -import com.att.research.xacml.api.pip.PIPFinder; -import com.att.research.xacml.api.pip.PIPRequest; -import com.att.research.xacml.api.pip.PIPResponse; -import com.att.research.xacml.std.IdentifierImpl; -import com.att.research.xacml.std.StdMutableAttribute; -import com.att.research.xacml.std.datatypes.DataTypes; -import com.att.research.xacml.std.pip.StdMutablePIPResponse; -import com.att.research.xacml.std.pip.StdPIPRequest; -import com.att.research.xacml.std.pip.StdPIPResponse; -import com.att.research.xacml.std.pip.engines.StdConfigurableEngine; - -import java.math.BigInteger; -import java.sql.Timestamp; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Properties; -import java.util.Set; - -import javax.persistence.EntityManager; -import javax.persistence.NoResultException; -import javax.persistence.NonUniqueResultException; -import javax.persistence.Persistence; -import javax.persistence.Query; - -import org.onap.policy.drools.system.PolicyEngine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PIPEngineGetHistory extends StdConfigurableEngine { - private static final Logger logger = LoggerFactory.getLogger(PIPEngineGetHistory.class); - - // - // Base issuer string. The issuer in the policy will also contain time window information - // E.g., "com:att:research:xacml:guard:historydb:tw:10:min" - // - public static final String DEFAULT_ISSUER = "com:att:research:xacml:guard:historydb"; - public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB"; - - private static final String XML_SCHEMA_STRING = "http://www.w3.org/2001/XMLSchema#string"; - - private static final String XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT = - "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"; - private static final String XACML_ACTOR_ACTOR_ID = "urn:oasis:names:tc:xacml:1.0:actor:actor-id"; - private static final String XACML_ATTRIBUTE_CATEGORY_ACTION = - "urn:oasis:names:tc:xacml:3.0:attribute-category:action"; - private static final String XACML_OPERATION_OPERATION_ID = "urn:oasis:names:tc:xacml:1.0:operation:operation-id"; - private static final String XACML_ATTRIBUTE_CATEGORY_RESOURCE = - "urn:oasis:names:tc:xacml:3.0:attribute-category:resource"; - private static final String XACML_TARGET_TARGET_ID = "urn:oasis:names:tc:xacml:1.0:target:target-id"; - private static final String XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT = - "com:att:research:xacml:test:sql:resource:operations:count"; - - private static final PIPRequest PIP_REQUEST_ACTOR = - new StdPIPRequest(new IdentifierImpl(XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT), - new IdentifierImpl(XACML_ACTOR_ACTOR_ID), new IdentifierImpl(XML_SCHEMA_STRING)); - - private static final PIPRequest PIP_REQUEST_RECIPE = - new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_ACTION), - new IdentifierImpl(XACML_OPERATION_OPERATION_ID), new IdentifierImpl(XML_SCHEMA_STRING)); - - private static final PIPRequest PIP_REQUEST_TARGET = - new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE), - new IdentifierImpl(XACML_TARGET_TARGET_ID), new IdentifierImpl(XML_SCHEMA_STRING)); - - public PIPEngineGetHistory() { - super(); - } - - @Override - public Collection attributesRequired() { - return Collections.emptySet(); - } - - @Override - public Collection attributesProvided() { - return Collections.emptySet(); - } - - @Override - public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { - logger.debug("Entering FeqLimiter PIP"); - - /* - * First check to see if the issuer is set and then match it - */ - String string; - if ((string = pipRequest.getIssuer()) == null) { - - logger.debug("No issuer in the request..."); - logger.debug("FeqLimiter PIP - No issuer in the request!"); - return StdPIPResponse.PIP_RESPONSE_EMPTY; - } else { - // Notice, we are checking here for the base issuer prefix. - if (!string.contains(this.getIssuer())) { - logger.debug("Requested issuer '{}' does not match {}", string, getIssuer()); - logger.debug("FeqLimiter PIP - Issuer {} does not match with: ", string, this.getIssuer()); - return StdPIPResponse.PIP_RESPONSE_EMPTY; - } - } - - String[] s1 = string.split("tw:"); - String[] s2 = s1[1].split(":"); - String timeWindowVal = s2[0];// number [of minutes, hours, days...] - String timeWindowScale = s2[1];// e.g., minute, hour, day, week, month, year - - String actor = null; - String operation = null; - String target = null; - try { - actor = getActor(pipFinder).iterator().next(); - operation = getRecipe(pipFinder).iterator().next(); - target = getTarget(pipFinder).iterator().next(); - } catch (Exception e) { - logger.debug("could not retrieve actor, operation, or target from PIP finder", e); - return StdPIPResponse.PIP_RESPONSE_EMPTY; - } - - String timeWindow = timeWindowVal + " " + timeWindowScale; - - logger.debug("Going to query DB about: {} {} {} {}", actor, operation, target, timeWindow); - int countFromDb = getCountFromDb(actor, operation, target, timeWindow); - - StdMutablePIPResponse stdPipResponse = new StdMutablePIPResponse(); - - this.addIntegerAttribute(stdPipResponse, new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE), - new IdentifierImpl(XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT), countFromDb, pipRequest); - - return new StdPIPResponse(stdPipResponse); - } - - @Override - public void configure(String id, Properties properties) throws PIPException { - super.configure(id, properties); - - if (this.getDescription() == null) { - this.setDescription(DEFAULT_DESCRIPTION); - } - if (this.getIssuer() == null) { - this.setIssuer(DEFAULT_ISSUER); - } - } - - private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) { - PIPResponse pipResponse = null; - - try { - pipResponse = pipFinder.getMatchingAttributes(pipRequest, this); - } catch (PIPException ex) { - logger.error("getAttribute threw:", ex); - return null; - } - if (pipResponse == null) { - return null; - } - if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) { - if (logger.isWarnEnabled()) { - logger.warn("PIP response error {}: {}", pipRequest.getAttributeId().stringValue(), - pipResponse.getStatus().toString()); - } - return null; - } - if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) { - if (logger.isWarnEnabled()) { - logger.warn("No attributes in POP response {}: {}", pipRequest.getAttributeId().stringValue(), - pipResponse.getStatus().toString()); - } - return null; - } - return pipResponse; - } - - private Set getActor(PIPFinder pipFinder) { - /* - * Get the AT&T UID from either the subject id or the attuid property - */ - PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_ACTOR, pipFinder); - if (pipResponseAttUid == null) { - return new HashSet<>(); - } - - /* - * Iterate over all of the returned results and do the LDAP requests - */ - Collection listAttUids = pipResponseAttUid.getAttributes(); - Set setAttUids = new HashSet<>(); - for (Attribute attributeAttUid : listAttUids) { - Iterator> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING); - if (iterAttributeValues != null) { - while (iterAttributeValues.hasNext()) { - String attuid = iterAttributeValues.next().getValue(); - if (attuid != null) { - setAttUids.add(attuid); - } - } - } - } - - return setAttUids; - } - - private Set getRecipe(PIPFinder pipFinder) { - /* - * Get the AT&T UID from either the subject id or the attuid property - */ - PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_RECIPE, pipFinder); - if (pipResponseAttUid == null) { - return new HashSet<>(); - } - - /* - * Iterate over all of the returned results and do the LDAP requests - */ - Collection listAttUids = pipResponseAttUid.getAttributes(); - Set setAttUids = new HashSet<>(); - for (Attribute attributeAttUid : listAttUids) { - Iterator> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING); - if (iterAttributeValues != null) { - while (iterAttributeValues.hasNext()) { - String attuid = iterAttributeValues.next().getValue(); - if (attuid != null) { - setAttUids.add(attuid); - } - } - } - } - - return setAttUids; - } - - private void addIntegerAttribute(StdMutablePIPResponse stdPipResponse, Identifier category, Identifier attributeId, - int value, PIPRequest pipRequest) { - AttributeValue attributeValue = null; - try { - attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value); - } catch (Exception ex) { - logger.error("Failed to convert {} to an AttributeValue", value, ex); - } - if (attributeValue != null) { - stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, - pipRequest.getIssuer()/* this.getIssuer() */, false)); - } - } - - private Set getTarget(PIPFinder pipFinder) { - /* - * Get the AT&T UID from either the subject id or the attuid property - */ - PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_TARGET, pipFinder); - if (pipResponseAttUid == null) { - return new HashSet<>(); - } - - /* - * Iterate over all of the returned results and do the LDAP requests - */ - Collection listAttUids = pipResponseAttUid.getAttributes(); - Set setAttUids = new HashSet<>(); - for (Attribute attributeAttUid : listAttUids) { - Iterator> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING); - if (iterAttributeValues != null) { - while (iterAttributeValues.hasNext()) { - String attuid = iterAttributeValues.next().getValue(); - if (attuid != null) { - setAttUids.add(attuid); - } - } - } - } - - return setAttUids; - } - - private static int getCountFromDb(String actor, String operation, String target, String timeWindow) { - // DB Properties - Properties props = new Properties(); - props.put(Util.ECLIPSE_LINK_KEY_URL, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL)); - props.put(Util.ECLIPSE_LINK_KEY_USER, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER)); - props.put(Util.ECLIPSE_LINK_KEY_PASS, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS)); - - - EntityManager em = null; - String opsHistPu = System.getProperty("OperationsHistoryPU"); - if (opsHistPu == null || !opsHistPu.equals("TestOperationsHistoryPU")) { - opsHistPu = "OperationsHistoryPU"; - } else { - props.clear(); - } - - try { - em = Persistence.createEntityManagerFactory(opsHistPu, props).createEntityManager(); - } catch (Exception ex) { - logger.error("PIP thread got Exception. Can't connect to Operations History DB -- {}", opsHistPu); - logger.error("getCountFromDb threw: ", ex); - return -1; - } - - long now = new Date().getTime(); - long diff; - try { - diff = now - getMsFromTimeWindow(timeWindow); - } catch (Exception ex) { - logger.error("PIP thread got Exception " + ex); - return -1; - } - - StringBuilder sqlBuilder = new StringBuilder(); - sqlBuilder.append("select count(*) as count from operationshistory10 where outcome<>'Failure_Guard'"); - sqlBuilder.append(" and actor= ?"); - sqlBuilder.append(" and operation= ?"); - sqlBuilder.append(" and target= ?"); - sqlBuilder.append(" and endtime between '"); - sqlBuilder.append(new Timestamp(diff)); - sqlBuilder.append("' and '"); - sqlBuilder.append(new Timestamp(now)); - sqlBuilder.append('\''); - - Query nq = em.createNativeQuery(sqlBuilder.toString()); - nq.setParameter(1, actor); - nq.setParameter(2, operation); - nq.setParameter(3, target); - - int ret = -1; - try { - ret = ((Number) nq.getSingleResult()).intValue(); - } catch (NoResultException | NonUniqueResultException ex) { - logger.error("getCountFromDb threw: ", ex); - return -1; - } - - em.close(); - - return ret; - } - - /** - * Get the Millisecond time from a time window string. - * - * @param timeWindow the time window string to parse - * @return the millisecond time from the time window string - * @throws PIPException On invalid time window strings - */ - private static long getMsFromTimeWindow(String timeWindowString) throws PIPException { - long ms = 0; - double multiplier = 0; - - String[] split = timeWindowString.split(" "); - if (split.length != 2) { - throw new PIPException("Invalid Value Unit pair for SQL"); - } - - ms = Long.parseLong(split[0]); - - if ("SECOND".compareToIgnoreCase(split[1]) == 0) { - multiplier = 1000; - } else if ("MINUTE".compareToIgnoreCase(split[1]) == 0) { - multiplier = 60000; - } else if ("HOUR".compareToIgnoreCase(split[1]) == 0) { - multiplier = 3.6e+6; - } else if ("DAY".compareToIgnoreCase(split[1]) == 0) { - multiplier = 8.64e+7; - } else if ("WEEK".compareToIgnoreCase(split[1]) == 0) { - multiplier = 6.048e+8; - } else if ("MONTH".compareToIgnoreCase(split[1]) == 0) { - multiplier = 2.628e+9; - } else if ("QUARTER".compareToIgnoreCase(split[1]) == 0) { - multiplier = 2.628e+9 * 3; - } else if ("YEAR".compareToIgnoreCase(split[1]) == 0) { - multiplier = 3.154e+10; - } else { - logger.error("{} not supported", split[1]); - } - - ms *= multiplier; - return ms; - } -} diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetHistory.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetHistory.java new file mode 100644 index 000000000..2a1ef2fc6 --- /dev/null +++ b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetHistory.java @@ -0,0 +1,405 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2017-2018 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.guard; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPRequest; +import com.att.research.xacml.api.pip.PIPResponse; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.pip.StdMutablePIPResponse; +import com.att.research.xacml.std.pip.StdPIPRequest; +import com.att.research.xacml.std.pip.StdPIPResponse; +import com.att.research.xacml.std.pip.engines.StdConfigurableEngine; + +import java.math.BigInteger; +import java.sql.Timestamp; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; + +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; +import javax.persistence.NonUniqueResultException; +import javax.persistence.Persistence; +import javax.persistence.Query; + +import org.onap.policy.drools.system.PolicyEngine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PipEngineGetHistory extends StdConfigurableEngine { + private static final Logger logger = LoggerFactory.getLogger(PipEngineGetHistory.class); + + // + // Base issuer string. The issuer in the policy will also contain time window information + // E.g., "com:att:research:xacml:guard:historydb:tw:10:min" + // + public static final String DEFAULT_ISSUER = "com:att:research:xacml:guard:historydb"; + public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB"; + + private static final String XML_SCHEMA_STRING = "http://www.w3.org/2001/XMLSchema#string"; + + private static final String XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT = + "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"; + private static final String XACML_ACTOR_ACTOR_ID = "urn:oasis:names:tc:xacml:1.0:actor:actor-id"; + private static final String XACML_ATTRIBUTE_CATEGORY_ACTION = + "urn:oasis:names:tc:xacml:3.0:attribute-category:action"; + private static final String XACML_OPERATION_OPERATION_ID = "urn:oasis:names:tc:xacml:1.0:operation:operation-id"; + private static final String XACML_ATTRIBUTE_CATEGORY_RESOURCE = + "urn:oasis:names:tc:xacml:3.0:attribute-category:resource"; + private static final String XACML_TARGET_TARGET_ID = "urn:oasis:names:tc:xacml:1.0:target:target-id"; + private static final String XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT = + "com:att:research:xacml:test:sql:resource:operations:count"; + + private static final PIPRequest PIP_REQUEST_ACTOR = + new StdPIPRequest(new IdentifierImpl(XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT), + new IdentifierImpl(XACML_ACTOR_ACTOR_ID), new IdentifierImpl(XML_SCHEMA_STRING)); + + private static final PIPRequest PIP_REQUEST_RECIPE = + new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_ACTION), + new IdentifierImpl(XACML_OPERATION_OPERATION_ID), new IdentifierImpl(XML_SCHEMA_STRING)); + + private static final PIPRequest PIP_REQUEST_TARGET = + new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE), + new IdentifierImpl(XACML_TARGET_TARGET_ID), new IdentifierImpl(XML_SCHEMA_STRING)); + + public PipEngineGetHistory() { + super(); + } + + @Override + public Collection attributesRequired() { + return Collections.emptySet(); + } + + @Override + public Collection attributesProvided() { + return Collections.emptySet(); + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { + logger.debug("Entering FeqLimiter PIP"); + + /* + * First check to see if the issuer is set and then match it + */ + String string; + if ((string = pipRequest.getIssuer()) == null) { + + logger.debug("No issuer in the request..."); + logger.debug("FeqLimiter PIP - No issuer in the request!"); + return StdPIPResponse.PIP_RESPONSE_EMPTY; + } else { + // Notice, we are checking here for the base issuer prefix. + if (!string.contains(this.getIssuer())) { + logger.debug("Requested issuer '{}' does not match {}", string, getIssuer()); + logger.debug("FeqLimiter PIP - Issuer {} does not match with: ", string, this.getIssuer()); + return StdPIPResponse.PIP_RESPONSE_EMPTY; + } + } + + String[] s1 = string.split("tw:"); + String[] s2 = s1[1].split(":"); + String timeWindowVal = s2[0];// number [of minutes, hours, days...] + String timeWindowScale = s2[1];// e.g., minute, hour, day, week, month, year + + String actor = null; + String operation = null; + String target = null; + try { + actor = getActor(pipFinder).iterator().next(); + operation = getRecipe(pipFinder).iterator().next(); + target = getTarget(pipFinder).iterator().next(); + } catch (Exception e) { + logger.debug("could not retrieve actor, operation, or target from PIP finder", e); + return StdPIPResponse.PIP_RESPONSE_EMPTY; + } + + String timeWindow = timeWindowVal + " " + timeWindowScale; + + logger.debug("Going to query DB about: {} {} {} {}", actor, operation, target, timeWindow); + int countFromDb = getCountFromDb(actor, operation, target, timeWindow); + + StdMutablePIPResponse stdPipResponse = new StdMutablePIPResponse(); + + this.addIntegerAttribute(stdPipResponse, new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE), + new IdentifierImpl(XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT), countFromDb, pipRequest); + + return new StdPIPResponse(stdPipResponse); + } + + @Override + public void configure(String id, Properties properties) throws PIPException { + super.configure(id, properties); + + if (this.getDescription() == null) { + this.setDescription(DEFAULT_DESCRIPTION); + } + if (this.getIssuer() == null) { + this.setIssuer(DEFAULT_ISSUER); + } + } + + private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) { + PIPResponse pipResponse = null; + + try { + pipResponse = pipFinder.getMatchingAttributes(pipRequest, this); + } catch (PIPException ex) { + logger.error("getAttribute threw:", ex); + return null; + } + if (pipResponse == null) { + return null; + } + if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) { + if (logger.isWarnEnabled()) { + logger.warn("PIP response error {}: {}", pipRequest.getAttributeId().stringValue(), + pipResponse.getStatus().toString()); + } + return null; + } + if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) { + if (logger.isWarnEnabled()) { + logger.warn("No attributes in POP response {}: {}", pipRequest.getAttributeId().stringValue(), + pipResponse.getStatus().toString()); + } + return null; + } + return pipResponse; + } + + private Set getActor(PIPFinder pipFinder) { + /* + * Get the AT&T UID from either the subject id or the attuid property + */ + PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_ACTOR, pipFinder); + if (pipResponseAttUid == null) { + return new HashSet<>(); + } + + /* + * Iterate over all of the returned results and do the LDAP requests + */ + Collection listAttUids = pipResponseAttUid.getAttributes(); + Set setAttUids = new HashSet<>(); + for (Attribute attributeAttUid : listAttUids) { + Iterator> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING); + if (iterAttributeValues != null) { + while (iterAttributeValues.hasNext()) { + String attuid = iterAttributeValues.next().getValue(); + if (attuid != null) { + setAttUids.add(attuid); + } + } + } + } + + return setAttUids; + } + + private Set getRecipe(PIPFinder pipFinder) { + /* + * Get the AT&T UID from either the subject id or the attuid property + */ + PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_RECIPE, pipFinder); + if (pipResponseAttUid == null) { + return new HashSet<>(); + } + + /* + * Iterate over all of the returned results and do the LDAP requests + */ + Collection listAttUids = pipResponseAttUid.getAttributes(); + Set setAttUids = new HashSet<>(); + for (Attribute attributeAttUid : listAttUids) { + Iterator> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING); + if (iterAttributeValues != null) { + while (iterAttributeValues.hasNext()) { + String attuid = iterAttributeValues.next().getValue(); + if (attuid != null) { + setAttUids.add(attuid); + } + } + } + } + + return setAttUids; + } + + private void addIntegerAttribute(StdMutablePIPResponse stdPipResponse, Identifier category, Identifier attributeId, + int value, PIPRequest pipRequest) { + AttributeValue attributeValue = null; + try { + attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value); + } catch (Exception ex) { + logger.error("Failed to convert {} to an AttributeValue", value, ex); + } + if (attributeValue != null) { + stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, + pipRequest.getIssuer()/* this.getIssuer() */, false)); + } + } + + private Set getTarget(PIPFinder pipFinder) { + /* + * Get the AT&T UID from either the subject id or the attuid property + */ + PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_TARGET, pipFinder); + if (pipResponseAttUid == null) { + return new HashSet<>(); + } + + /* + * Iterate over all of the returned results and do the LDAP requests + */ + Collection listAttUids = pipResponseAttUid.getAttributes(); + Set setAttUids = new HashSet<>(); + for (Attribute attributeAttUid : listAttUids) { + Iterator> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING); + if (iterAttributeValues != null) { + while (iterAttributeValues.hasNext()) { + String attuid = iterAttributeValues.next().getValue(); + if (attuid != null) { + setAttUids.add(attuid); + } + } + } + } + + return setAttUids; + } + + private static int getCountFromDb(String actor, String operation, String target, String timeWindow) { + // DB Properties + Properties props = new Properties(); + props.put(Util.ECLIPSE_LINK_KEY_URL, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL)); + props.put(Util.ECLIPSE_LINK_KEY_USER, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER)); + props.put(Util.ECLIPSE_LINK_KEY_PASS, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS)); + + + EntityManager em = null; + String opsHistPu = System.getProperty("OperationsHistoryPU"); + if (opsHistPu == null || !opsHistPu.equals("TestOperationsHistoryPU")) { + opsHistPu = "OperationsHistoryPU"; + } else { + props.clear(); + } + + try { + em = Persistence.createEntityManagerFactory(opsHistPu, props).createEntityManager(); + } catch (Exception ex) { + logger.error("PIP thread got Exception. Can't connect to Operations History DB -- {}", opsHistPu); + logger.error("getCountFromDb threw: ", ex); + return -1; + } + + long now = new Date().getTime(); + long diff; + try { + diff = now - getMsFromTimeWindow(timeWindow); + } catch (Exception ex) { + logger.error("PIP thread got Exception " + ex); + return -1; + } + + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("select count(*) as count from operationshistory10 where outcome<>'Failure_Guard'"); + sqlBuilder.append(" and actor= ?"); + sqlBuilder.append(" and operation= ?"); + sqlBuilder.append(" and target= ?"); + sqlBuilder.append(" and endtime between '"); + sqlBuilder.append(new Timestamp(diff)); + sqlBuilder.append("' and '"); + sqlBuilder.append(new Timestamp(now)); + sqlBuilder.append('\''); + + Query nq = em.createNativeQuery(sqlBuilder.toString()); + nq.setParameter(1, actor); + nq.setParameter(2, operation); + nq.setParameter(3, target); + + int ret = -1; + try { + ret = ((Number) nq.getSingleResult()).intValue(); + } catch (NoResultException | NonUniqueResultException ex) { + logger.error("getCountFromDb threw: ", ex); + return -1; + } + + em.close(); + + return ret; + } + + /** + * Get the Millisecond time from a time window string. + * + * @param timeWindow the time window string to parse + * @return the millisecond time from the time window string + * @throws PIPException On invalid time window strings + */ + private static long getMsFromTimeWindow(String timeWindowString) throws PIPException { + long ms = 0; + double multiplier = 0; + + String[] split = timeWindowString.split(" "); + if (split.length != 2) { + throw new PIPException("Invalid Value Unit pair for SQL"); + } + + ms = Long.parseLong(split[0]); + + if ("SECOND".compareToIgnoreCase(split[1]) == 0) { + multiplier = 1000; + } else if ("MINUTE".compareToIgnoreCase(split[1]) == 0) { + multiplier = 60000; + } else if ("HOUR".compareToIgnoreCase(split[1]) == 0) { + multiplier = 3.6e+6; + } else if ("DAY".compareToIgnoreCase(split[1]) == 0) { + multiplier = 8.64e+7; + } else if ("WEEK".compareToIgnoreCase(split[1]) == 0) { + multiplier = 6.048e+8; + } else if ("MONTH".compareToIgnoreCase(split[1]) == 0) { + multiplier = 2.628e+9; + } else if ("QUARTER".compareToIgnoreCase(split[1]) == 0) { + multiplier = 2.628e+9 * 3; + } else if ("YEAR".compareToIgnoreCase(split[1]) == 0) { + multiplier = 3.154e+10; + } else { + logger.error("{} not supported", split[1]); + } + + ms *= multiplier; + return ms; + } +} diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetStatus.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetStatus.java new file mode 100644 index 000000000..40b26c847 --- /dev/null +++ b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PipEngineGetStatus.java @@ -0,0 +1,311 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 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.guard; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPRequest; +import com.att.research.xacml.api.pip.PIPResponse; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdMutableAttribute; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.pip.StdMutablePIPResponse; +import com.att.research.xacml.std.pip.StdPIPRequest; +import com.att.research.xacml.std.pip.StdPIPResponse; +import com.att.research.xacml.std.pip.engines.StdConfigurableEngine; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.NoResultException; +import javax.persistence.NonUniqueResultException; +import javax.persistence.Persistence; +import javax.persistence.Query; + +import org.onap.policy.drools.system.PolicyEngine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PipEngineGetStatus extends StdConfigurableEngine { + private static final Logger logger = LoggerFactory.getLogger(PipEngineGetStatus.class); + + // + // Base issuer string. The issuer in the policy will contain the operations + // E.g., "org:onap:policy:guard:status:clname:testcl" + // + public static final String DEFAULT_ISSUER = "org:onap:policy:guard:status"; + public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operation Status from DB"; + + private static final String XML_SCHEMA_STRING = "http://www.w3.org/2001/XMLSchema#string"; + + private static final String XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT = + "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"; + private static final String XACML_ACTOR_ACTOR_ID = "urn:oasis:names:tc:xacml:1.0:actor:actor-id"; + private static final String XACML_ATTRIBUTE_CATEGORY_ACTION = + "urn:oasis:names:tc:xacml:3.0:attribute-category:action"; + private static final String XACML_OPERATION_OPERATION_ID = "urn:oasis:names:tc:xacml:1.0:operation:operation-id"; + private static final String XACML_ATTRIBUTE_CATEGORY_RESOURCE = + "urn:oasis:names:tc:xacml:3.0:attribute-category:resource"; + private static final String XACML_TARGET_TARGET_ID = "urn:oasis:names:tc:xacml:1.0:target:target-id"; + private static final String XACML_TEST_SQL_RESOURCE_OPERATIONS_STATUS = + "com:att:research:xacml:test:sql:resource:operations:status"; + + private static final PIPRequest PIP_REQUEST_ACTOR = + new StdPIPRequest(new IdentifierImpl(XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT), + new IdentifierImpl(XACML_ACTOR_ACTOR_ID), new IdentifierImpl(XML_SCHEMA_STRING)); + + private static final PIPRequest PIP_REQUEST_RECIPE = + new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_ACTION), + new IdentifierImpl(XACML_OPERATION_OPERATION_ID), new IdentifierImpl(XML_SCHEMA_STRING)); + + private static final PIPRequest PIP_REQUEST_TARGET = + new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE), + new IdentifierImpl(XACML_TARGET_TARGET_ID), new IdentifierImpl(XML_SCHEMA_STRING)); + + public PipEngineGetStatus() { + super(); + } + + @Override + public Collection attributesRequired() { + return Collections.emptySet(); + } + + @Override + public Collection attributesProvided() { + return Collections.emptySet(); + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { + logger.debug("Entering Status PIP"); + + /* + * First check to see if the issuer is set and then match it + */ + String issuer; + if ((issuer = pipRequest.getIssuer()) == null) { + + logger.debug("No issuer in the request..."); + logger.debug("Status PIP - No issuer in the request!"); + return StdPIPResponse.PIP_RESPONSE_EMPTY; + + } else if (!issuer.contains(this.getIssuer())) { + // Notice, we are checking here for the base issuer prefix. + logger.debug("Requested issuer '{}' does not match {}", issuer, getIssuer()); + logger.debug("Status PIP - Issuer {} does not match with: ", issuer, this.getIssuer()); + return StdPIPResponse.PIP_RESPONSE_EMPTY; + } + + String[] s1 = issuer.split("clname:"); + String clname = s1[1]; + String target = null; + try { + target = getTarget(pipFinder).iterator().next(); + } catch (Exception e) { + logger.debug("could not retrieve target from PIP finder", e); + return StdPIPResponse.PIP_RESPONSE_EMPTY; + } + + logger.debug("Going to query DB about: clname={}, target={}", clname, target); + String statusFromDb = getStatusFromDb(clname, target); + + StdMutablePIPResponse stdPipResponse = new StdMutablePIPResponse(); + + this.addStringAttribute(stdPipResponse, new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE), + new IdentifierImpl(XACML_TEST_SQL_RESOURCE_OPERATIONS_STATUS), statusFromDb, pipRequest); + + return new StdPIPResponse(stdPipResponse); + } + + @Override + public void configure(String id, Properties properties) throws PIPException { + super.configure(id, properties); + + if (this.getDescription() == null) { + this.setDescription(DEFAULT_DESCRIPTION); + } + if (this.getIssuer() == null) { + this.setIssuer(DEFAULT_ISSUER); + } + } + + private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) { + PIPResponse pipResponse = null; + + try { + pipResponse = pipFinder.getMatchingAttributes(pipRequest, this); + } catch (PIPException ex) { + logger.error("getAttribute threw:", ex); + return null; + } + if (pipResponse == null) { + return null; + } + if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) { + logger.warn("PIP response error {}: {}", pipRequest.getAttributeId().stringValue(), + pipResponse.getStatus()); + return null; + } + if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) { + logger.warn("No attributes in POP response {}: {}", pipRequest.getAttributeId().stringValue(), + pipResponse.getStatus()); + return null; + } + return pipResponse; + } + + private void addStringAttribute(StdMutablePIPResponse stdPipResponse, Identifier category, Identifier attributeId, + String value, PIPRequest pipRequest) { + AttributeValue attributeValue = null; + try { + attributeValue = DataTypes.DT_STRING.createAttributeValue(value); + } catch (Exception ex) { + logger.error("Failed to convert {} to an AttributeValue", value, ex); + } + if (attributeValue != null) { + stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, + pipRequest.getIssuer()/* this.getIssuer() */, false)); + } + } + + private Set getTarget(PIPFinder pipFinder) { + /* + * Get the UID from either the subject id or the uid property + */ + PIPResponse pipResponseUid = this.getAttribute(PIP_REQUEST_TARGET, pipFinder); + if (pipResponseUid == null) { + return new HashSet<>(); + } + + /* + * Iterate over all of the returned results and do the LDAP requests + */ + Collection listUids = pipResponseUid.getAttributes(); + Set setUids = new HashSet<>(); + for (Attribute attributeUid : listUids) { + Iterator> iterAttributeValues = attributeUid.findValues(DataTypes.DT_STRING); + if (iterAttributeValues != null) { + while (iterAttributeValues.hasNext()) { + String uid = iterAttributeValues.next().getValue(); + if (uid != null) { + setUids.add(uid); + } + } + } + } + + return setUids; + } + + private static String getStatusFromDb(String clname, String target) { + // + // DB Properties + // + Properties props = new Properties(); + try { + props.put(Util.ECLIPSE_LINK_KEY_URL, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL)); + props.put(Util.ECLIPSE_LINK_KEY_USER, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER)); + props.put(Util.ECLIPSE_LINK_KEY_PASS, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS)); + } catch (NullPointerException e) { + logger.error("getStatusFromDB: {} when setting properties", e.getMessage()); + } + // + // Set opsHistPu to the correct value and clear properties if necessary. + // + String opsHistPu = System.getProperty("OperationsHistoryPU"); + if (opsHistPu == null || !opsHistPu.equals("TestOperationsHistoryPU")) { + opsHistPu = "OperationsHistoryPU"; + } else { + props.clear(); + } + // + // Set up the EntityManager + // + EntityManagerFactory emf = null; + EntityManager em = null; + try { + emf = Persistence.createEntityManagerFactory(opsHistPu, props); + } catch (Exception ex) { + logger.error("PIP thread got Exception. Can't connect to Operations History DB -- {}", opsHistPu); + logger.error("getStatusFromDb threw: ", ex); + return null; + } + try { + em = emf.createEntityManager(); + } catch (Exception ex) { + logger.error("PIP thread got Exception. Problem creating EntityManager"); + logger.error("getStatusFromDb threw: ", ex); + emf.close(); + return null; + } + // + // Create the query + // + String sql = "select outcome from operationshistory10 where" + + " clname= ?" + + " and target= ?" + + " order by endtime desc limit 1"; + Query nq = em.createNativeQuery(sql); + nq.setParameter(1, clname); + nq.setParameter(2, target); + logger.debug("SQL query: {}, {}, {}", sql, clname, target); + // + // Run the query + // + String ret = null; + try{ + ret = ((String)nq.getSingleResult()); + } catch(NoResultException ex) { + logger.debug("NoResultException for getSingleResult()"); + ret = "NO_MATCHING_ENTRY"; + } catch(Exception ex){ + logger.error("getStatusFromDB threw: ", ex); + } + if (ret != null) { + logger.debug("SQL query result: {}", ret); + } + // + // Clean up and return the result + // + try { + em.close(); + } catch(Exception ex){ + logger.error("getStatusFromDB threw: ", ex); + } + try { + emf.close(); + } catch(Exception ex){ + logger.error("getStatusFromDB threw: ", ex); + } + return ret; + } +} diff --git a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetHistoryTest.java b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetHistoryTest.java index 5780cecd6..288c6ca33 100644 --- a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetHistoryTest.java +++ b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetHistoryTest.java @@ -67,7 +67,7 @@ import org.junit.Test; import org.onap.policy.drools.system.PolicyEngine; public class PipEngineGetHistoryTest { - static PIPEngineGetHistory pegh; + static PipEngineGetHistory pegh; private static final String ISSUER = "issuerIntw:mid:end"; private static EntityManagerFactory emf; @@ -80,9 +80,9 @@ public class PipEngineGetHistoryTest { public static void testPipEngineGetHistory() { pegh = null; try { - pegh = new PIPEngineGetHistory(); + pegh = new PipEngineGetHistory(); } catch (Exception e) { - fail("PIPEngineGetHistory constructor failed"); + fail("PipEngineGetHistory constructor failed"); } // Set PU @@ -108,8 +108,17 @@ public class PipEngineGetHistoryTest { em.getTransaction().commit(); } + /** + * Clean up test class. + */ @AfterClass public static void tearDown() { + String sql = "DROP TABLE `operationshistory10`"; + Query nq = em.createNativeQuery(sql); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + em.close(); emf.close(); } @@ -174,7 +183,7 @@ public class PipEngineGetHistoryTest { Method method = null; int count = -1; try { - method = PIPEngineGetHistory.class.getDeclaredMethod("getCountFromDb", String.class, String.class, + method = PipEngineGetHistory.class.getDeclaredMethod("getCountFromDb", String.class, String.class, String.class, String.class); method.setAccessible(true); count = (int) method.invoke(null, "actor", "op", "target", "1 MINUTE"); @@ -204,7 +213,7 @@ public class PipEngineGetHistoryTest { @Test public void testConfigure() throws PIPException { - PIPEngineGetHistory pegh = new PIPEngineGetHistory(); + PipEngineGetHistory pegh = new PipEngineGetHistory(); pegh.configure("Dorothy", new Properties()); pegh.setDescription(null); @@ -214,7 +223,7 @@ public class PipEngineGetHistoryTest { @Test public void getAttributesTest() throws URISyntaxException, PIPException, FactoryException { - PIPEngineGetHistory pegh = new PIPEngineGetHistory(); + PipEngineGetHistory pegh = new PipEngineGetHistory(); pegh.setIssuer("Dorothy"); Identifier identifierCategory = new IdentifierImpl(new URI("http://somewhere.over.the.rainbow/category"));; @@ -233,7 +242,7 @@ public class PipEngineGetHistoryTest { @Test public void timeWindowTest() throws URISyntaxException, PIPException, FactoryException { - PIPEngineGetHistory pegh = new PIPEngineGetHistory(); + PipEngineGetHistory pegh = new PipEngineGetHistory(); pegh.setIssuer("Dorothy"); Identifier identifierCategory = new IdentifierImpl(new URI("http://somewhere.over.the.rainbow/category"));; diff --git a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetStatusTest.java b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetStatusTest.java new file mode 100644 index 000000000..cf83c883c --- /dev/null +++ b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PipEngineGetStatusTest.java @@ -0,0 +1,411 @@ +/*- + * ============LICENSE_START======================================================= + * guard + * ================================================================================ + * Copyright (C) 2018 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.guard; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.att.research.xacml.api.Attribute; +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.api.pip.PIPEngine; +import com.att.research.xacml.api.pip.PIPException; +import com.att.research.xacml.api.pip.PIPFinder; +import com.att.research.xacml.api.pip.PIPRequest; +import com.att.research.xacml.api.pip.PIPResponse; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdAttribute; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.pip.StdPIPRequest; +import com.att.research.xacml.std.pip.StdPIPResponse; +import com.att.research.xacml.std.pip.finders.EngineFinder; +import com.att.research.xacml.util.FactoryException; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Properties; +import java.util.UUID; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.Query; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.drools.system.PolicyEngine; + +public class PipEngineGetStatusTest { + static PipEngineGetStatus pegs; + private static final String ISSUER = "issuer:clname:testclname"; + + private static EntityManagerFactory emf; + private static EntityManager em; + + /** + * Set up test class. + */ + @BeforeClass + public static void testPipEngineGetStatus() { + pegs = null; + try { + pegs = new PipEngineGetStatus(); + } catch (Exception e) { + fail("PipEngineGetStatus constructor failed"); + } + + // Set PU + System.setProperty(Util.PU_KEY, Util.JUNITPU); + + // Enter dummy props to avoid nullPointerException + PolicyEngine.manager.setEnvironmentProperty(Util.ONAP_KEY_URL, "a"); + PolicyEngine.manager.setEnvironmentProperty(Util.ONAP_KEY_USER, "b"); + PolicyEngine.manager.setEnvironmentProperty(Util.ONAP_KEY_PASS, "c"); + + // Connect to in-mem db + emf = Persistence.createEntityManagerFactory(Util.JUNITPU); + em = emf.createEntityManager(); + + // Create necessary table + String sql = "CREATE TABLE `operationshistory10` (" + "`CLNAME` varchar(255)," + "`requestID` varchar(100)," + + "`actor` varchar(50) ," + "`operation` varchar(50)," + "`target` varchar(50)," + + "`starttime` timestamp," + "`outcome` varchar(50)," + "`message` varchar(255)," + + "`subrequestId` varchar(100)," + "`endtime` timestamp" + ")"; + Query nq = em.createNativeQuery(sql); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + } + + /** + * Clean up test class. + */ + @AfterClass + public static void tearDown() { + String sql = "DROP TABLE `operationshistory10`"; + Query nq = em.createNativeQuery(sql); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + em.close(); + emf.close(); + } + + /** + * Setup method. + */ + @Before + public void setUp() { + // clear the table + String sql = "DELETE FROM `operationshistory10`"; + Query nq = em.createNativeQuery(sql); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + } + + @Test + public void testAttributesRequired() { + assertTrue(pegs.attributesRequired().isEmpty()); + } + + @Test + public void testAttributesProvided() { + assertTrue(pegs.attributesProvided().isEmpty()); + } + + @Test + public void testGetAttributes() { + StdPIPRequest mockPipRequest = mock(StdPIPRequest.class); + EngineFinder mockPipFinder = mock(EngineFinder.class); + + // Test issuer null + when(mockPipRequest.getIssuer()).thenReturn(null); + try { + assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pegs.getAttributes(mockPipRequest, mockPipFinder)); + } catch (Exception e) { + fail("getAttributes failed"); + } + + // Test issuer not equal to our issuer + pegs.setIssuer(ISSUER); + when(mockPipRequest.getIssuer()).thenReturn("something else"); + try { + assertEquals(StdPIPResponse.PIP_RESPONSE_EMPTY, pegs.getAttributes(mockPipRequest, mockPipFinder)); + } catch (Exception e) { + fail("getAttributes failed"); + } + + // Test issuer equal to our issuer + when(mockPipRequest.getIssuer()).thenReturn(ISSUER); + try { + assertNotNull(pegs.getAttributes(mockPipRequest, mockPipFinder)); + } catch (Exception e) { + // Normal to catch exception + } + } + + @Test + public void testGetStatusFromDb() { + + // Use reflection to run getStatsFromDB + Method method = null; + String status = null; + String addEntry; + Query nq; + + // Add an entry + addEntry = "insert into operationshistory10 (outcome, CLNAME, actor, operation, target, endtime)" + + "values('1','testcl', 'actor', 'op', 'testtarget', CURRENT_TIMESTAMP())"; + nq = em.createNativeQuery(addEntry); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + + try { + method = PipEngineGetStatus.class.getDeclaredMethod("getStatusFromDb", String.class, String.class); + method.setAccessible(true); + status = (String) method.invoke(null, "testcl", "testtarget"); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException e) { + fail(e.getLocalizedMessage()); + } + + // Status should be "success" + assertEquals("1", status); + + // Add entries + addEntry = "insert into operationshistory10 (outcome, CLNAME, actor, operation, target, endtime)" + + "values('2','testcl', 'actor', 'op', 'testtarget', CURRENT_TIMESTAMP())"; + nq = em.createNativeQuery(addEntry); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + + addEntry = "insert into operationshistory10 (outcome, CLNAME, actor, operation, target, endtime)" + + "values('3','testcl', 'actor', 'op', 'testtarget2', CURRENT_TIMESTAMP())"; + nq = em.createNativeQuery(addEntry); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + + addEntry = "insert into operationshistory10 (outcome, CLNAME, actor, operation, target, endtime)" + + "values('4','testcl2', 'actor', 'op', 'testtarget2', CURRENT_TIMESTAMP())"; + nq = em.createNativeQuery(addEntry); + em.getTransaction().begin(); + nq.executeUpdate(); + em.getTransaction().commit(); + + try { + method = PipEngineGetStatus.class.getDeclaredMethod("getStatusFromDb", String.class, String.class); + method.setAccessible(true); + status = (String) method.invoke(null, "testcl", "testtarget"); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException e) { + fail(e.getLocalizedMessage()); + } + assertEquals("2", status); + + try { + method = PipEngineGetStatus.class.getDeclaredMethod("getStatusFromDb", String.class, String.class); + method.setAccessible(true); + status = (String) method.invoke(null, "testcl", "testtarget2"); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException e) { + fail(e.getLocalizedMessage()); + } + assertEquals("3", status); + + try { + method = PipEngineGetStatus.class.getDeclaredMethod("getStatusFromDb", String.class, String.class); + method.setAccessible(true); + status = (String) method.invoke(null, "testcl2", "testtarget2"); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException e) { + fail(e.getLocalizedMessage()); + } + assertEquals("4", status); + } + + @Test + public void testConfigure() throws PIPException { + PipEngineGetStatus pegs = new PipEngineGetStatus(); + pegs.configure("Dorothy", new Properties()); + + pegs.setDescription(null); + pegs.setIssuer(null); + pegs.configure("Dorothy", new Properties()); + } + + private class DummyPipFinder implements PIPFinder { + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + return null; + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + try { + List attributeList = new ArrayList<>(); + Identifier categoryIdIn = new IdentifierImpl(new URI("http://somewhere.over.the.rainbow/category")); + Identifier dataTypeIdIn = new IdentifierImpl(new URI("http://www.w3.org/2001/XMLSchema#string")); + + Identifier attributeIdIn0 = new IdentifierImpl(new URI(UUID.randomUUID().toString())); + AttributeValue valueIn0 = new StdAttributeValue(dataTypeIdIn, "ActorDorothy"); + Attribute attribute0 = new StdAttribute(categoryIdIn, attributeIdIn0, valueIn0); + attributeList.add(attribute0); + + Identifier attributeIdIn1 = new IdentifierImpl(new URI(UUID.randomUUID().toString())); + AttributeValue valueIn1 = new StdAttributeValue(dataTypeIdIn, "OperationHomeFromOZ"); + Attribute attribute1 = new StdAttribute(categoryIdIn, attributeIdIn1, valueIn1); + attributeList.add(attribute1); + + Identifier attributeIdIn2 = new IdentifierImpl(new URI(UUID.randomUUID().toString())); + AttributeValue valueIn2 = new StdAttributeValue(dataTypeIdIn, "TargetWickedWitch"); + Attribute attribute2 = new StdAttribute(categoryIdIn, attributeIdIn2, valueIn2); + attributeList.add(attribute2); + + return new StdPIPResponse(attributeList); + } catch (Exception e) { + return null; + } + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public Collection getPIPEngines() { + return null; + } + } + + private class DummyPipFinderPipException implements PIPFinder { + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + return null; + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + throw new PIPException(); + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public Collection getPIPEngines() { + return null; + } + } + + private class DummyPipFinderResponseStatusNok implements PIPFinder { + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + return null; + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + Status status = new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Processing Error"); + return new StdPIPResponse(status); + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public Collection getPIPEngines() { + return null; + } + } + + private class DummyPipFinderResponseEmptyAttrs implements PIPFinder { + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + return null; + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude) throws PIPException { + List attributeList = new ArrayList<>(); + return new StdPIPResponse(attributeList); + } + + @Override + public PIPResponse getMatchingAttributes(PIPRequest pipRequest, PIPEngine exclude, PIPFinder pipFinderParent) + throws PIPException { + return null; + } + + @Override + public Collection getPIPEngines() { + return null; + } + } +} -- cgit 1.2.3-korg