2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.policy.xacml.std.pip.engines;
23 import java.math.BigInteger;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.Properties;
31 import javax.persistence.EntityManager;
32 import javax.persistence.Persistence;
33 import javax.persistence.Query;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.eclipse.persistence.config.PersistenceUnitProperties;
39 import com.att.research.xacml.api.Attribute;
40 import com.att.research.xacml.api.AttributeValue;
41 import com.att.research.xacml.api.Identifier;
42 import com.att.research.xacml.api.XACML;
43 import com.att.research.xacml.api.XACML3;
44 import com.att.research.xacml.api.pip.PIPException;
45 import com.att.research.xacml.api.pip.PIPFinder;
46 import com.att.research.xacml.api.pip.PIPRequest;
47 import com.att.research.xacml.api.pip.PIPResponse;
48 import com.att.research.xacml.std.IdentifierImpl;
49 import com.att.research.xacml.std.StdMutableAttribute;
50 import com.att.research.xacml.std.datatypes.DataTypes;
51 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
52 import com.att.research.xacml.std.pip.StdPIPRequest;
53 import com.att.research.xacml.std.pip.StdPIPResponse;
54 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
55 import com.att.research.xacml.util.XACMLProperties;
58 * PIP Engine for Implementing {@link com.att.research.xacml.std.pip.engines.ConfigurableEngine} interface to provide
59 * attribute retrieval from Operation History Table.
63 public class OperationHistoryEngine extends StdConfigurableEngine{
64 public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB";
65 public static final String DEFAULT_ISSUER = "org:onap:xacml:guard:historydb";
67 private static final Log LOGGER= LogFactory.getLog(OperationHistoryEngine.class);
69 private static final PIPRequest PIP_REQUEST_ACTOR = new StdPIPRequest(
70 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
71 new IdentifierImpl("actor"),
72 XACML.ID_DATATYPE_STRING);
74 private static final PIPRequest PIP_REQUEST_RECIPE = new StdPIPRequest(
75 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
76 new IdentifierImpl("recipe"),
77 XACML.ID_DATATYPE_STRING);
79 private static final PIPRequest PIP_REQUEST_TARGET = new StdPIPRequest(
80 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
81 new IdentifierImpl("target"),
82 XACML.ID_DATATYPE_STRING);
84 private void addIntegerAttribute(StdMutablePIPResponse stdPIPResponse, Identifier category, Identifier attributeId, int value, PIPRequest pipRequest) {
85 AttributeValue<BigInteger> attributeValue = null;
87 attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value);
88 } catch (Exception ex) {
89 LOGGER.error("Failed to convert " + value + " to an AttributeValue<Boolean>", ex);
91 if (attributeValue != null) {
92 stdPIPResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, pipRequest.getIssuer()/*this.getIssuer()*/, false));
96 public OperationHistoryEngine() {
101 public Collection<PIPRequest> attributesRequired() {
102 return new ArrayList<>();
106 public Collection<PIPRequest> attributesProvided() {
107 return new ArrayList<>();
111 public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
112 LOGGER.info("Entering FeqLimiter PIP");
114 * First check to see if the issuer is set and then match it
117 if ((string = pipRequest.getIssuer()) == null) {
118 LOGGER.info("FeqLimiter PIP - No issuer in the request!");
119 return StdPIPResponse.PIP_RESPONSE_EMPTY;
122 //Notice, we are checking here for the base issuer prefix.
123 if (!string.contains(this.getIssuer())) {
124 LOGGER.debug("Requested issuer '" + string + "' does not match " + (this.getIssuer() == null ? "null" : "'" + this.getIssuer() + "'"));
125 LOGGER.info("FeqLimiter PIP - Issuer "+ string +" does not match with: "+this.getIssuer());
126 return StdPIPResponse.PIP_RESPONSE_EMPTY;
129 String[] s1 = string.split("tw:");
130 String[] s2 = s1[1].split(":");
131 int timeWindowVal = Integer.parseInt(s2[0]);// number [of minutes, hours, days...]
132 String timeWindowScale = s2[1];//e.g., minute, hour, day, week, month, year
133 String actor = getActor(pipFinder).iterator().next();
134 String operation = getRecipe(pipFinder).iterator().next();
135 String target = getTarget(pipFinder).iterator().next();
136 String timeWindow = timeWindowVal + " " + timeWindowScale;
137 LOGGER.info("Going to query DB about: "+actor + " " + operation + " " + target + " " + timeWindow);
138 int countFromDB = getCountFromDB(actor, operation, target, timeWindowVal, timeWindowScale);
139 StdMutablePIPResponse stdPIPResponse = new StdMutablePIPResponse();
140 this.addIntegerAttribute(stdPIPResponse,
141 XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
142 new IdentifierImpl("count"),
145 return new StdPIPResponse(stdPIPResponse);
149 public void configure(String id, Properties properties) throws PIPException {
150 super.configure(id, properties);
151 if (this.getDescription() == null) {
152 this.setDescription(DEFAULT_DESCRIPTION);
154 if (this.getIssuer() == null) {
155 this.setIssuer(DEFAULT_ISSUER);
159 private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
160 PIPResponse pipResponse = null;
162 pipResponse = pipFinder.getMatchingAttributes(pipRequest, this);
163 if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) {
164 LOGGER.info("Error retrieving " + pipRequest.getAttributeId().stringValue() + ": " + pipResponse.getStatus().toString());
167 if (pipResponse!=null && pipResponse.getAttributes().isEmpty()) {
168 LOGGER.info("No value for " + pipRequest.getAttributeId().stringValue());
171 } catch (PIPException ex) {
172 LOGGER.error("PIPException getting subject-id attribute: " + ex.getMessage(), ex);
178 private Set<String> getActor(PIPFinder pipFinder) {
180 * Get the AT&T UID from either the subject id or the attuid property
182 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_ACTOR, pipFinder);
183 if (pipResponseATTUID == null) {
184 return new HashSet<>();
187 * Iterate over all of the returned results and do the LDAP requests
189 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
190 Set<String> setATTUIDs = new HashSet<>();
191 for (Attribute attributeATTUID: listATTUIDs) {
192 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
193 if (iterAttributeValues != null) {
194 while (iterAttributeValues.hasNext()) {
195 String attuid = iterAttributeValues.next().getValue();
196 if (attuid != null) {
197 setATTUIDs.add(attuid);
205 private Set<String> getRecipe(PIPFinder pipFinder) {
207 * Get the AT&T UID from either the subject id or the attuid property
209 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_RECIPE, pipFinder);
210 if (pipResponseATTUID == null) {
211 return new HashSet<>();
214 * Iterate over all of the returned results and do the LDAP requests
216 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
217 Set<String> setATTUIDs = new HashSet<>();
218 for (Attribute attributeATTUID: listATTUIDs) {
219 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
220 if (iterAttributeValues != null) {
221 while (iterAttributeValues.hasNext()) {
222 String attuid = iterAttributeValues.next().getValue();
223 if (attuid != null) {
224 setATTUIDs.add(attuid);
233 private Set<String> getTarget(PIPFinder pipFinder) {
235 * Get the AT&T UID from either the subject id or the attuid property
237 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_TARGET, pipFinder);
238 if (pipResponseATTUID == null) {
239 return new HashSet<>();
242 * Iterate over all of the returned results and do the LDAP requests
244 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
245 Set<String> setATTUIDs = new HashSet<>();
246 for (Attribute attributeATTUID: listATTUIDs) {
247 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
248 if (iterAttributeValues != null) {
249 while (iterAttributeValues.hasNext()) {
250 String attuid = iterAttributeValues.next().getValue();
251 if (attuid != null) {
252 setATTUIDs.add(attuid);
260 private static int getCountFromDB(String actor, String operation, String target, int timeWindow, String timeUnits){
263 Properties properties = XACMLProperties.getProperties();
264 properties.setProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, "META-INF/operationHistoryPU.xml");
265 em = Persistence.createEntityManagerFactory("OperationsHistoryPU",properties).createEntityManager();
267 LOGGER.error("Test thread got Exception " + e.getLocalizedMessage() + " Can't connect to Operations History DB.", e);
270 // Preventing SQL injection
271 if(!validTimeUnits(timeUnits)){
272 LOGGER.error("given PIP timeUnits is not valid. " + timeUnits);
276 String sql = "select count(*) as count from operationshistory10 where outcome<>'Failure_Guard' and actor=?"
279 + " and endtime between date_sub(now(),interval ? "+timeUnits+") and now()";
280 Query nq = em.createNativeQuery(sql);
281 nq.setParameter(1, actor);
282 nq.setParameter(2, operation);
283 nq.setParameter(3, target);
284 nq.setParameter(4, timeWindow);
285 int ret = ((Number)nq.getSingleResult()).intValue();
286 LOGGER.info("###########************** History count: " + ret);
291 // Validating Time Units to prevent SQL Injection.
292 private static boolean validTimeUnits(String timeUnits) {
293 return (timeUnits.equalsIgnoreCase("minute") || timeUnits.equalsIgnoreCase("hour") || timeUnits.equalsIgnoreCase("day")
294 || timeUnits.equalsIgnoreCase("week") || timeUnits.equalsIgnoreCase("month")||timeUnits.equalsIgnoreCase("year"))?