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.math.BigInteger;
24 import java.sql.Timestamp;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Date;
28 import java.util.HashSet;
29 import java.util.Iterator;
30 import java.util.Properties;
33 import javax.persistence.EntityManager;
34 import javax.persistence.NoResultException;
35 import javax.persistence.NonUniqueResultException;
36 import javax.persistence.Persistence;
37 import javax.persistence.Query;
39 import org.onap.policy.drools.system.PolicyEngine;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 import com.att.research.xacml.api.Attribute;
44 import com.att.research.xacml.api.AttributeValue;
45 import com.att.research.xacml.api.Identifier;
46 import com.att.research.xacml.api.pip.PIPException;
47 import com.att.research.xacml.api.pip.PIPFinder;
48 import com.att.research.xacml.api.pip.PIPRequest;
49 import com.att.research.xacml.api.pip.PIPResponse;
50 import com.att.research.xacml.std.IdentifierImpl;
51 import com.att.research.xacml.std.StdMutableAttribute;
52 import com.att.research.xacml.std.datatypes.DataTypes;
53 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
54 import com.att.research.xacml.std.pip.StdPIPRequest;
55 import com.att.research.xacml.std.pip.StdPIPResponse;
56 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
58 public class PIPEngineGetHistory extends StdConfigurableEngine{
59 private static final Logger logger = LoggerFactory.getLogger(PIPEngineGetHistory.class);
62 // Base issuer string. The issuer in the policy will also contain time window information
63 // E.g., "com:att:research:xacml:guard:historydb:tw:10:min"
65 public static final String DEFAULT_ISSUER = "com:att:research:xacml:guard:historydb";
66 public static final String DEFAULT_DESCRIPTION = "PIP for retrieving Operations History from DB";
68 private static final String XML_SCHEMA_STRING = "http://www.w3.org/2001/XMLSchema#string";
70 private static final String XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
71 private static final String XACML_ACTOR_ACTOR_ID = "urn:oasis:names:tc:xacml:1.0:actor:actor-id";
72 private static final String XACML_ATTRIBUTE_CATEGORY_ACTION ="urn:oasis:names:tc:xacml:3.0:attribute-category:action";
73 private static final String XACML_OPERATION_OPERATION_ID ="urn:oasis:names:tc:xacml:1.0:operation:operation-id";
74 private static final String XACML_ATTRIBUTE_CATEGORY_RESOURCE ="urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
75 private static final String XACML_TARGET_TARGET_ID ="urn:oasis:names:tc:xacml:1.0:target:target-id";
76 private static final String XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT = "com:att:research:xacml:test:sql:resource:operations:count";
78 private static final PIPRequest PIP_REQUEST_ACTOR = new StdPIPRequest(
79 new IdentifierImpl(XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT),
80 new IdentifierImpl(XACML_ACTOR_ACTOR_ID),
81 new IdentifierImpl(XML_SCHEMA_STRING));
83 private static final PIPRequest PIP_REQUEST_RECIPE = new StdPIPRequest(
84 new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_ACTION),
85 new IdentifierImpl(XACML_OPERATION_OPERATION_ID),
86 new IdentifierImpl(XML_SCHEMA_STRING));
88 private static final PIPRequest PIP_REQUEST_TARGET = new StdPIPRequest(
89 new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE),
90 new IdentifierImpl(XACML_TARGET_TARGET_ID),
91 new IdentifierImpl(XML_SCHEMA_STRING));
93 public PIPEngineGetHistory() {
98 public Collection<PIPRequest> attributesRequired() {
99 return Collections.emptySet();
103 public Collection<PIPRequest> attributesProvided() {
104 return Collections.emptySet();
108 public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
109 logger.debug("Entering FeqLimiter PIP");
112 * First check to see if the issuer is set and then match it
115 if ((string = pipRequest.getIssuer()) == null) {
117 logger.debug("No issuer in the request...");
118 logger.debug("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 '{}' does not match {}", string, getIssuer());
125 logger.debug("FeqLimiter PIP - Issuer {} does not match with: ", string, this.getIssuer());
126 return StdPIPResponse.PIP_RESPONSE_EMPTY;
130 String[] s1 = string.split("tw:");
131 String[] s2 = s1[1].split(":");
132 String timeWindowVal = s2[0];// number [of minutes, hours, days...]
133 String timeWindowScale = s2[1];//e.g., minute, hour, day, week, month, year
136 String operation = null;
137 String target = null;
139 actor = getActor(pipFinder).iterator().next();
140 operation = getRecipe(pipFinder).iterator().next();
141 target = getTarget(pipFinder).iterator().next();
142 } catch (Exception e) {
143 logger.debug("could not retrieve actor, operation, or target from PIP finder", e);
144 return StdPIPResponse.PIP_RESPONSE_EMPTY;
147 String timeWindow = timeWindowVal + " " + timeWindowScale;
149 logger.debug("Going to query DB about: {} {} {} {}", actor, operation, target, timeWindow);
150 int countFromDB = getCountFromDB(actor, operation, target, timeWindow);
152 StdMutablePIPResponse stdPIPResponse = new StdMutablePIPResponse();
154 this.addIntegerAttribute(stdPIPResponse,
155 new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE),
156 new IdentifierImpl(XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT),
160 return new StdPIPResponse(stdPIPResponse);
164 public void configure(String id, Properties properties) throws PIPException {
165 super.configure(id, properties);
167 if (this.getDescription() == null) {
168 this.setDescription(DEFAULT_DESCRIPTION);
170 if (this.getIssuer() == null) {
171 this.setIssuer(DEFAULT_ISSUER);
175 private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
176 PIPResponse pipResponse = null;
179 pipResponse = pipFinder.getMatchingAttributes(pipRequest, this);
180 } catch (PIPException ex) {
181 logger.error("getAttribute threw:", ex);
184 if (pipResponse == null) {
187 if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) {
188 if (logger.isWarnEnabled()) {
189 logger.warn("PIP response error {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString());
193 if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) {
194 if (logger.isWarnEnabled()) {
195 logger.warn("No attributes in POP response {}: {}", pipRequest.getAttributeId().stringValue(), pipResponse.getStatus().toString());
202 private Set<String> getActor(PIPFinder pipFinder) {
204 * Get the AT&T UID from either the subject id or the attuid property
206 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_ACTOR, pipFinder);
207 if (pipResponseATTUID == null) {
208 return new HashSet<>();
212 * Iterate over all of the returned results and do the LDAP requests
214 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
215 Set<String> setATTUIDs = new HashSet<>();
216 for (Attribute attributeATTUID: listATTUIDs) {
217 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
218 if (iterAttributeValues != null) {
219 while (iterAttributeValues.hasNext()) {
220 String attuid = iterAttributeValues.next().getValue();
221 if (attuid != null) {
222 setATTUIDs.add(attuid);
231 private Set<String> getRecipe(PIPFinder pipFinder) {
233 * Get the AT&T UID from either the subject id or the attuid property
235 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_RECIPE, pipFinder);
236 if (pipResponseATTUID == null) {
237 return new HashSet<>();
241 * Iterate over all of the returned results and do the LDAP requests
243 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
244 Set<String> setATTUIDs = new HashSet<>();
245 for (Attribute attributeATTUID: listATTUIDs) {
246 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
247 if (iterAttributeValues != null) {
248 while (iterAttributeValues.hasNext()) {
249 String attuid = iterAttributeValues.next().getValue();
250 if (attuid != null) {
251 setATTUIDs.add(attuid);
260 private void addIntegerAttribute(StdMutablePIPResponse stdPIPResponse, Identifier category, Identifier attributeId, int value, PIPRequest pipRequest) {
261 AttributeValue<BigInteger> attributeValue = null;
263 attributeValue = DataTypes.DT_INTEGER.createAttributeValue(value);
264 } catch (Exception ex) {
265 logger.error("Failed to convert {} to an AttributeValue<Boolean>",value, ex);
267 if (attributeValue != null) {
268 stdPIPResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue, pipRequest.getIssuer()/*this.getIssuer()*/, false));
272 private Set<String> getTarget(PIPFinder pipFinder) {
274 * Get the AT&T UID from either the subject id or the attuid property
276 PIPResponse pipResponseATTUID = this.getAttribute(PIP_REQUEST_TARGET, pipFinder);
277 if (pipResponseATTUID == null) {
278 return new HashSet<>();
282 * Iterate over all of the returned results and do the LDAP requests
284 Collection<Attribute> listATTUIDs = pipResponseATTUID.getAttributes();
285 Set<String> setATTUIDs = new HashSet<>();
286 for (Attribute attributeATTUID: listATTUIDs) {
287 Iterator<AttributeValue<String>> iterAttributeValues = attributeATTUID.findValues(DataTypes.DT_STRING);
288 if (iterAttributeValues != null) {
289 while (iterAttributeValues.hasNext()) {
290 String attuid = iterAttributeValues.next().getValue();
291 if (attuid != null) {
292 setATTUIDs.add(attuid);
301 private static int getCountFromDB(String actor, String operation, String target, String timeWindow){
303 Properties props = new Properties();
304 props.put(Util.ECLIPSE_LINK_KEY_URL, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL));
305 props.put(Util.ECLIPSE_LINK_KEY_USER, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER));
306 props.put(Util.ECLIPSE_LINK_KEY_PASS, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS));
309 EntityManager em = null;
310 String opsHistPU = System.getProperty("OperationsHistoryPU");
311 if (opsHistPU == null || !opsHistPU.equals("TestOperationsHistoryPU")){
312 opsHistPU = "OperationsHistoryPU";
319 em = Persistence.createEntityManagerFactory(opsHistPU, props).createEntityManager();
320 } catch(Exception ex){
321 logger.error("PIP thread got Exception. Can't connect to Operations History DB -- {}", opsHistPU);
322 logger.error("getCountFromDB threw: ", ex);
326 long now = new Date().getTime();
329 diff = now - getMSFromTimeWindow(timeWindow);
330 } catch (Exception ex) {
331 logger.error("PIP thread got Exception " + ex);
335 StringBuilder sqlBuilder = new StringBuilder();
336 sqlBuilder.append("select count(*) as count from operationshistory10 where outcome<>'Failure_Guard'");
337 sqlBuilder.append(" and actor= ?");
338 sqlBuilder.append(" and operation= ?");
339 sqlBuilder.append(" and target= ?");
340 sqlBuilder.append(" and endtime between '");
341 sqlBuilder.append(new Timestamp(diff));
342 sqlBuilder.append("' and '");
343 sqlBuilder.append(new Timestamp(now));
344 sqlBuilder.append('\'');
346 Query nq = em.createNativeQuery(sqlBuilder.toString());
347 nq.setParameter(1, actor);
348 nq.setParameter(2, operation);
349 nq.setParameter(3, target);
353 ret = ((Number)nq.getSingleResult()).intValue();
355 catch(NoResultException | NonUniqueResultException ex){
356 logger.error("getCountFromDB threw: ", ex);
366 * Get the Millisecond time from a time window string
367 * @param timeWindow the time window string to parse
368 * @return the millisecond time from the time window string
369 * @throws PIPException On invalid time window strings
371 private static long getMSFromTimeWindow(String timeWindowString) throws PIPException {
373 double multiplier = 0;
375 String[] split = timeWindowString.split(" ");
376 if (split.length != 2) {
377 throw new PIPException("Invalid Value Unit pair for SQL");
380 ms = Long.parseLong(split[0]);
382 if("SECOND".compareToIgnoreCase(split[1]) == 0){
385 else if("MINUTE".compareToIgnoreCase(split[1]) == 0){
388 else if("HOUR".compareToIgnoreCase(split[1]) == 0){
391 else if("DAY".compareToIgnoreCase(split[1]) == 0){
392 multiplier = 8.64e+7;
394 else if("WEEK".compareToIgnoreCase(split[1]) == 0){
395 multiplier = 6.048e+8;
397 else if("MONTH".compareToIgnoreCase(split[1]) == 0){
398 multiplier = 2.628e+9;
400 else if("QUARTER".compareToIgnoreCase(split[1]) == 0){
401 multiplier = 2.628e+9 * 3;
403 else if("YEAR".compareToIgnoreCase(split[1]) == 0){
404 multiplier = 3.154e+10;
407 logger.error("{} not supported", split[1]);