From e92ff832cf993db876f22b2d27562fedf59f5043 Mon Sep 17 00:00:00 2001 From: Tarun Tej Velaga Date: Mon, 24 Jul 2017 17:13:43 +0000 Subject: [Policy-52, Policy-92, Policy-93] Policy Enhancements and bugfixes Change-Id: I5675cf4527e17963b3142cf7184c0df31a766197 Signed-off-by: Tarun Tej Velaga --- .../std/pip/engines/OperationHistoryEngine.java | 297 +++++++++++++++++++++ .../xacml/std/pip/engines/aaf/AAFEngine.java | 6 +- .../main/resources/META-INF/operationHistoryPU.xml | 33 +++ 3 files changed, 333 insertions(+), 3 deletions(-) create mode 100644 ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/OperationHistoryEngine.java create mode 100644 ECOMP-XACML/src/main/resources/META-INF/operationHistoryPU.xml (limited to 'ECOMP-XACML/src/main') diff --git a/ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/OperationHistoryEngine.java b/ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/OperationHistoryEngine.java new file mode 100644 index 000000000..30b59cdd8 --- /dev/null +++ b/ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/OperationHistoryEngine.java @@ -0,0 +1,297 @@ +/*- + * ============LICENSE_START======================================================= + * ECOMP-XACML + * ================================================================================ + * 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.openecomp.policy.xacml.std.pip.engines; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Properties; +import java.util.Set; + +import javax.persistence.EntityManager; +import javax.persistence.Persistence; +import javax.persistence.Query; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.eclipse.persistence.config.PersistenceUnitProperties; + +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.XACML; +import com.att.research.xacml.api.XACML3; +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 com.att.research.xacml.util.XACMLProperties; + +/** + * PIP Engine for Implementing {@link com.att.research.xacml.std.pip.engines.ConfigurableEngine} interface to provide + * attribute retrieval from Operation History Table. + * + * @version $Revision$ + */ +public class OperationHistoryEngine extends StdConfigurableEngine{ + public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB"; + public static final String DEFAULT_ISSUER = "org:onap:xacml:guard:historydb"; + + private static final Log LOGGER= LogFactory.getLog(OperationHistoryEngine.class); + + private static final PIPRequest PIP_REQUEST_ACTOR = new StdPIPRequest( + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, + new IdentifierImpl("actor"), + XACML.ID_DATATYPE_STRING); + + private static final PIPRequest PIP_REQUEST_RECIPE = new StdPIPRequest( + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, + new IdentifierImpl("recipe"), + XACML.ID_DATATYPE_STRING); + + private static final PIPRequest PIP_REQUEST_TARGET = new StdPIPRequest( + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, + new IdentifierImpl("target"), + XACML.ID_DATATYPE_STRING); + + 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 " + value + " to an AttributeValue", ex); + } + if (attributeValue != null) { + stdPIPResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, pipRequest.getIssuer()/*this.getIssuer()*/, false)); + } + } + + public OperationHistoryEngine() { + super(); + } + + @Override + public Collection attributesRequired() { + return new ArrayList<>(); + } + + @Override + public Collection attributesProvided() { + return new ArrayList<>(); + } + + @Override + public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException { + LOGGER.info("Entering FeqLimiter PIP"); + /* + * First check to see if the issuer is set and then match it + */ + String string; + if ((string = pipRequest.getIssuer()) == null) { + LOGGER.info("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 '" + string + "' does not match " + (this.getIssuer() == null ? "null" : "'" + this.getIssuer() + "'")); + LOGGER.info("FeqLimiter PIP - Issuer "+ string +" does not match with: "+this.getIssuer()); + return StdPIPResponse.PIP_RESPONSE_EMPTY; + } + } + String[] s1 = string.split("tw:"); + String[] s2 = s1[1].split(":"); + int timeWindowVal = Integer.parseInt(s2[0]);// number [of minutes, hours, days...] + String timeWindowScale = s2[1];//e.g., minute, hour, day, week, month, year + String actor = getActor(pipFinder).iterator().next(); + String operation = getRecipe(pipFinder).iterator().next(); + String target = getTarget(pipFinder).iterator().next(); + String timeWindow = timeWindowVal + " " + timeWindowScale; + LOGGER.info("Going to query DB about: "+actor + " " + operation + " " + target + " " + timeWindow); + int countFromDB = getCountFromDB(actor, operation, target, timeWindowVal, timeWindowScale); + StdMutablePIPResponse stdPIPResponse = new StdMutablePIPResponse(); + this.addIntegerAttribute(stdPIPResponse, + XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, + new IdentifierImpl("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); + if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) { + LOGGER.info("Error retrieving " + pipRequest.getAttributeId().stringValue() + ": " + pipResponse.getStatus().toString()); + pipResponse = null; + } + if (pipResponse!=null && pipResponse.getAttributes().isEmpty()) { + LOGGER.info("No value for " + pipRequest.getAttributeId().stringValue()); + pipResponse = null; + } + } catch (PIPException ex) { + LOGGER.error("PIPException getting subject-id attribute: " + ex.getMessage(), ex); + } + 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 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, int timeWindow, String timeUnits){ + EntityManager em; + try{ + Properties properties = XACMLProperties.getProperties(); + properties.setProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, "META-INF/operationHistoryPU.xml"); + em = Persistence.createEntityManagerFactory("OperationsHistoryPU",properties).createEntityManager(); + }catch(Exception e){ + LOGGER.error("Test thread got Exception " + e.getLocalizedMessage() + " Can't connect to Operations History DB.", e); + return -1; + } + // Preventing SQL injection + if(!validTimeUnits(timeUnits)){ + LOGGER.error("given PIP timeUnits is not valid. " + timeUnits); + em.close(); + return -1; + } + String sql = "select count(*) as count from operationshistory10 where outcome<>'Failure_Guard' and actor=?" + + " and operation=?" + + " and target=?" + + " and endtime between date_sub(now(),interval ? "+timeUnits+") and now()"; + Query nq = em.createNativeQuery(sql); + nq.setParameter(1, actor); + nq.setParameter(2, operation); + nq.setParameter(3, target); + nq.setParameter(4, timeWindow); + int ret = ((Number)nq.getSingleResult()).intValue(); + LOGGER.info("###########************** History count: " + ret); + em.close(); + return ret; + } + + // Validating Time Units to prevent SQL Injection. + private static boolean validTimeUnits(String timeUnits) { + return (timeUnits.equalsIgnoreCase("minute") || timeUnits.equalsIgnoreCase("hour") || timeUnits.equalsIgnoreCase("day") + || timeUnits.equalsIgnoreCase("week") || timeUnits.equalsIgnoreCase("month")||timeUnits.equalsIgnoreCase("year"))? + true: false; + } +} diff --git a/ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/aaf/AAFEngine.java b/ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/aaf/AAFEngine.java index 92c963a10..bdf4d342d 100644 --- a/ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/aaf/AAFEngine.java +++ b/ECOMP-XACML/src/main/java/org/openecomp/policy/xacml/std/pip/engines/aaf/AAFEngine.java @@ -52,14 +52,14 @@ import com.att.research.xacml.util.XACMLProperties; /** * PIP Engine for Implementing {@link com.att.research.xacml.std.pip.engines.ConfigurableEngine} interface to provide - * attribute retrieval from AT&T AAF interface. + * attribute retrieval from AAF interface. * * @version $Revision$ */ public class AAFEngine extends StdConfigurableEngine { - public static final String DEFAULT_DESCRIPTION = "PIP for authenticating aaf attributes using the AT&T AAF REST interface"; - public static final String DEFAULT_ISSUER = "att-aaf"; + public static final String DEFAULT_DESCRIPTION = "PIP for authenticating aaf attributes using the AAF REST interface"; + public static final String DEFAULT_ISSUER = "aaf"; private static final String SUCCESS = "Success"; diff --git a/ECOMP-XACML/src/main/resources/META-INF/operationHistoryPU.xml b/ECOMP-XACML/src/main/resources/META-INF/operationHistoryPU.xml new file mode 100644 index 000000000..a3770d385 --- /dev/null +++ b/ECOMP-XACML/src/main/resources/META-INF/operationHistoryPU.xml @@ -0,0 +1,33 @@ + + + + + + org.eclipse.persistence.jpa.PersistenceProvider + + + + + + + \ No newline at end of file -- cgit 1.2.3-korg