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.onap.policy.guard;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.math.BigInteger;
26 import java.sql.Timestamp;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.Date;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.Properties;
35 import javax.persistence.EntityManager;
36 import javax.persistence.NoResultException;
37 import javax.persistence.NonUniqueResultException;
38 import javax.persistence.Persistence;
39 import javax.persistence.Query;
41 import org.onap.policy.drools.system.PolicyEngine;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 import com.att.research.xacml.api.Attribute;
46 import com.att.research.xacml.api.AttributeValue;
47 import com.att.research.xacml.api.Identifier;
48 import com.att.research.xacml.api.pip.PIPException;
49 import com.att.research.xacml.api.pip.PIPFinder;
50 import com.att.research.xacml.api.pip.PIPRequest;
51 import com.att.research.xacml.api.pip.PIPResponse;
52 import com.att.research.xacml.std.IdentifierImpl;
53 import com.att.research.xacml.std.StdMutableAttribute;
54 import com.att.research.xacml.std.datatypes.DataTypes;
55 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
56 import com.att.research.xacml.std.pip.StdPIPRequest;
57 import com.att.research.xacml.std.pip.StdPIPResponse;
58 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
62 public class PIPEngineGetHistory extends StdConfigurableEngine{
64 private interface DateUtil{
65 public class DateUtilException extends Exception {
66 private static final long serialVersionUID = 2612662650481443076L;
68 public DateUtilException(String message) {
75 public DateUtil init(String sqlValUnit) throws DateUtilException;
78 private static final Logger logger = LoggerFactory.getLogger(PIPEngineGetHistory.class);
80 public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB";
85 // Base issuer string. The issuer in the policy will also contain time window information
86 // E.g., "com:att:research:xacml:guard:historydb:tw:10:min"
88 public static final String DEFAULT_ISSUER = "com:att:research:xacml:guard:historydb";
91 private static final PIPRequest PIP_REQUEST_ACTOR = new StdPIPRequest(
92 new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"),
93 new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:actor:actor-id"),
94 new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string"));
96 private static final PIPRequest PIP_REQUEST_RECIPE = new StdPIPRequest(
97 new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:action"),
98 new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:operation:operation-id"),
99 new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string"));
101 private static final PIPRequest PIP_REQUEST_TARGET = new StdPIPRequest(
102 new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"),
103 new IdentifierImpl("urn:oasis:names:tc:xacml:1.0:target:target-id"),
104 new IdentifierImpl("http://www.w3.org/2001/XMLSchema#string"));
107 private void addIntegerAttribute(StdMutablePIPResponse stdPIPResponse, Identifier category, Identifier attributeId, int value, PIPRequest pipRequest) {
108 AttributeValue<BigInteger> attributeValue = null;
110 attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value);
111 } catch (Exception ex) {
112 logger.error("Failed to convert {} to an AttributeValue<Boolean>",value, ex);
114 if (attributeValue != null) {
115 stdPIPResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, pipRequest.getIssuer()/*this.getIssuer()*/, false));
121 public PIPEngineGetHistory() {
123 // TODO Auto-generated constructor stub
129 public Collection<PIPRequest> attributesRequired() {
130 // TODO Auto-generated method stub
131 return Collections.emptySet();
135 public Collection<PIPRequest> attributesProvided() {
136 // TODO Auto-generated method stub
137 return Collections.emptySet();
141 public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
142 // TODO Auto-generated method stub
143 logger.debug("Entering FeqLimiter PIP");
146 * First check to see if the issuer is set and then match it
149 if ((string = pipRequest.getIssuer()) == null) {
151 logger.debug("No issuer in the request...");
152 logger.debug("FeqLimiter PIP - No issuer in the request!");
153 return StdPIPResponse.PIP_RESPONSE_EMPTY;
156 //Notice, we are checking here for the base issuer prefix.
157 if (!string.contains(this.getIssuer())) {
158 logger.debug("Requested issuer '{}' does not match {}", string, getIssuer());
159 logger.debug("FeqLimiter PIP - Issuer {} does not match with: ", string, this.getIssuer());
160 return StdPIPResponse.PIP_RESPONSE_EMPTY;
164 String[] s1 = string.split("tw:");
165 String[] s2 = s1[1].split(":");
166 String timeWindowVal = s2[0];// number [of minutes, hours, days...]
167 String timeWindowScale = s2[1];//e.g., minute, hour, day, week, month, year
169 String actor = getActor(pipFinder).iterator().next();
170 String operation = getRecipe(pipFinder).iterator().next();
171 String target = getTarget(pipFinder).iterator().next();
173 String timeWindow = timeWindowVal + " " + timeWindowScale;
175 logger.debug("Going to query DB about: {} {} {} {}", actor, operation, target, timeWindow);
176 int countFromDB = getCountFromDB(actor, operation, target, timeWindow);
178 StdMutablePIPResponse stdPIPResponse = new StdMutablePIPResponse();
180 this.addIntegerAttribute(stdPIPResponse,
181 new IdentifierImpl("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"),
182 new IdentifierImpl("com:att:research:xacml:test:sql:resource:operations:count"),
186 return new StdPIPResponse(stdPIPResponse);
191 public void configure(String id, Properties properties) throws PIPException {
192 super.configure(id, properties);
194 if (this.getDescription() == null) {
195 this.setDescription(DEFAULT_DESCRIPTION);
197 if (this.getIssuer() == null) {
198 this.setIssuer(DEFAULT_ISSUER);
204 private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
205 PIPResponse pipResponse = null;
208 pipResponse = pipFinder.getMatchingAttributes(pipRequest, this);
209 } catch (PIPException ex) {
210 logger.error("getAttribute threw:", ex);
213 if (pipResponse == null) {
216 if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) {
217 logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString());
220 if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) {
221 logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString());
222 logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus());
225 if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) {
226 logger.warn("Error retrieving {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus());
233 private Set<String> getActor(PIPFinder pipFinder) {
235 * Get the AT&T UID from either the subject id or the attuid property
237 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_ACTOR, pipFinder);
238 if (pipResponseATTUID == null) {
243 * Iterate over all of the returned results and do the LDAP requests
245 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
246 Set<String> setATTUIDs = new HashSet<String>();
247 for (Attribute attributeATTUID: listATTUIDs) {
248 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
249 if (iterAttributeValues != null) {
250 while (iterAttributeValues.hasNext()) {
251 String attuid = iterAttributeValues.next().getValue();
252 if (attuid != null) {
253 setATTUIDs.add(attuid);
262 private Set<String> getRecipe(PIPFinder pipFinder) {
264 * Get the AT&T UID from either the subject id or the attuid property
266 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_RECIPE, pipFinder);
267 if (pipResponseATTUID == null) {
272 * Iterate over all of the returned results and do the LDAP requests
274 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
275 Set<String> setATTUIDs = new HashSet<String>();
276 for (Attribute attributeATTUID: listATTUIDs) {
277 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
278 if (iterAttributeValues != null) {
279 while (iterAttributeValues.hasNext()) {
280 String attuid = iterAttributeValues.next().getValue();
281 if (attuid != null) {
282 setATTUIDs.add(attuid);
292 private Set<String> getTarget(PIPFinder pipFinder) {
294 * Get the AT&T UID from either the subject id or the attuid property
296 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_TARGET, pipFinder);
297 if (pipResponseATTUID == null) {
302 * Iterate over all of the returned results and do the LDAP requests
304 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
305 Set<String> setATTUIDs = new HashSet<String>();
306 for (Attribute attributeATTUID: listATTUIDs) {
307 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
308 if (iterAttributeValues != null) {
309 while (iterAttributeValues.hasNext()) {
310 String attuid = iterAttributeValues.next().getValue();
311 if (attuid != null) {
312 setATTUIDs.add(attuid);
321 private static int getCountFromDB(String actor, String operation, String target, String timeWindow){
324 Properties props = new Properties();
325 props.put(Util.ECLIPSE_LINK_KEY_URL, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL));
326 props.put(Util.ECLIPSE_LINK_KEY_USER, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER));
327 props.put(Util.ECLIPSE_LINK_KEY_PASS, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS));
330 EntityManager em = null;
331 String OpsHistPU = System.getProperty("OperationsHistoryPU");
332 if(OpsHistPU == null || !OpsHistPU.equals("TestOperationsHistoryPU")){
333 OpsHistPU = "OperationsHistoryPU";
339 em = Persistence.createEntityManagerFactory(OpsHistPU, props).createEntityManager();
340 }catch(Exception ex){
341 logger.error("PIP thread got Exception. Can't connect to Operations History DB -- {}", OpsHistPU);
342 logger.error("getCountFromDB threw: ", ex);
346 DateUtil dateUtil = new DateUtil(){
348 private double multiplier = 0;
351 public DateUtil init(String sqlValUnit) throws DateUtilException{
352 String[] split = sqlValUnit.split(" ");
353 if(split.length != 2){
354 throw new DateUtilException("Invalid Value Unit pair for SQL");
357 ms = Long.parseLong(split[0]);
359 if("SECOND".compareToIgnoreCase(split[1]) == 0){
362 else if("MINUTE".compareToIgnoreCase(split[1]) == 0){
365 else if("HOUR".compareToIgnoreCase(split[1]) == 0){
368 else if("DAY".compareToIgnoreCase(split[1]) == 0){
369 multiplier = 8.64e+7;
371 else if("WEEK".compareToIgnoreCase(split[1]) == 0){
372 multiplier = 6.048e+8;
374 else if("MONTH".compareToIgnoreCase(split[1]) == 0){
375 multiplier = 2.628e+9;
377 else if("QUARTER".compareToIgnoreCase(split[1]) == 0){
378 multiplier = 2.628e+9 * 3;
380 else if("YEAR".compareToIgnoreCase(split[1]) == 0){
381 multiplier = 3.154e+10;
384 logger.error("{} not supported", split[1]);
395 long now = new Date().getTime();
398 diff = now - dateUtil.init(timeWindow).getMs();
399 } catch (Exception ex) {
400 logger.error("PIP thread got Exception " + ex);
404 String sql = "select count(*) as count from operationshistory10 where outcome<>'Failure_Guard'"
406 + " and operation= ?"
408 + " and endtime between '" + new Timestamp(diff) + "' and '" + new Timestamp(now) + "'";
410 Query nq = em.createNativeQuery(sql);
411 nq.setParameter(0, actor);
412 nq.setParameter(1, operation);
413 nq.setParameter(2, target);
417 ret = ((Number)nq.getSingleResult()).intValue();
419 catch(NoResultException | NonUniqueResultException ex){
420 logger.error("getCountFromDB threw: ", ex);