2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 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 com.att.research.xacml.api.Attribute;
24 import com.att.research.xacml.api.AttributeValue;
25 import com.att.research.xacml.api.Identifier;
26 import com.att.research.xacml.api.pip.PIPException;
27 import com.att.research.xacml.api.pip.PIPFinder;
28 import com.att.research.xacml.api.pip.PIPRequest;
29 import com.att.research.xacml.api.pip.PIPResponse;
30 import com.att.research.xacml.std.IdentifierImpl;
31 import com.att.research.xacml.std.StdMutableAttribute;
32 import com.att.research.xacml.std.datatypes.DataTypes;
33 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
34 import com.att.research.xacml.std.pip.StdPIPRequest;
35 import com.att.research.xacml.std.pip.StdPIPResponse;
36 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
38 import java.math.BigInteger;
39 import java.sql.Timestamp;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.Date;
43 import java.util.HashSet;
44 import java.util.Iterator;
45 import java.util.Properties;
48 import javax.persistence.EntityManager;
49 import javax.persistence.NoResultException;
50 import javax.persistence.NonUniqueResultException;
51 import javax.persistence.Persistence;
52 import javax.persistence.Query;
54 import org.onap.policy.drools.system.PolicyEngine;
55 import org.slf4j.Logger;
56 import org.slf4j.LoggerFactory;
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 =
71 "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
72 private static final String XACML_ACTOR_ACTOR_ID = "urn:oasis:names:tc:xacml:1.0:actor:actor-id";
73 private static final String XACML_ATTRIBUTE_CATEGORY_ACTION =
74 "urn:oasis:names:tc:xacml:3.0:attribute-category:action";
75 private static final String XACML_OPERATION_OPERATION_ID = "urn:oasis:names:tc:xacml:1.0:operation:operation-id";
76 private static final String XACML_ATTRIBUTE_CATEGORY_RESOURCE =
77 "urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
78 private static final String XACML_TARGET_TARGET_ID = "urn:oasis:names:tc:xacml:1.0:target:target-id";
79 private static final String XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT =
80 "com:att:research:xacml:test:sql:resource:operations:count";
82 private static final PIPRequest PIP_REQUEST_ACTOR =
83 new StdPIPRequest(new IdentifierImpl(XACML_SUBJECT_CATEGORY_ACCESS_SUBJECT),
84 new IdentifierImpl(XACML_ACTOR_ACTOR_ID), new IdentifierImpl(XML_SCHEMA_STRING));
86 private static final PIPRequest PIP_REQUEST_RECIPE =
87 new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_ACTION),
88 new IdentifierImpl(XACML_OPERATION_OPERATION_ID), new IdentifierImpl(XML_SCHEMA_STRING));
90 private static final PIPRequest PIP_REQUEST_TARGET =
91 new StdPIPRequest(new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE),
92 new IdentifierImpl(XACML_TARGET_TARGET_ID), new IdentifierImpl(XML_SCHEMA_STRING));
94 public PipEngineGetHistory() {
99 public Collection<PIPRequest> attributesRequired() {
100 return Collections.emptySet();
104 public Collection<PIPRequest> attributesProvided() {
105 return Collections.emptySet();
109 public PIPResponse getAttributes(PIPRequest pipRequest, PIPFinder pipFinder) throws PIPException {
110 logger.debug("Entering FeqLimiter PIP");
113 * First check to see if the issuer is set and then match it
116 if ((string = pipRequest.getIssuer()) == null) {
118 logger.debug("No issuer in the request...");
119 logger.debug("FeqLimiter PIP - No issuer in the request!");
120 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, new IdentifierImpl(XACML_ATTRIBUTE_CATEGORY_RESOURCE),
155 new IdentifierImpl(XACML_TEST_SQL_RESOURCE_OPERATIONS_COUNT), countFromDb, pipRequest);
157 return new StdPIPResponse(stdPipResponse);
161 public void configure(String id, Properties properties) throws PIPException {
162 super.configure(id, properties);
164 if (this.getDescription() == null) {
165 this.setDescription(DEFAULT_DESCRIPTION);
167 if (this.getIssuer() == null) {
168 this.setIssuer(DEFAULT_ISSUER);
172 private PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
173 PIPResponse pipResponse = null;
176 pipResponse = pipFinder.getMatchingAttributes(pipRequest, this);
177 } catch (PIPException ex) {
178 logger.error("getAttribute threw:", ex);
181 if (pipResponse == null) {
184 if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) {
185 if (logger.isWarnEnabled()) {
186 logger.warn("PIP response error {}: {}", pipRequest.getAttributeId().stringValue(),
187 pipResponse.getStatus());
191 if (pipResponse.getAttributes() != null && pipResponse.getAttributes().isEmpty()) {
192 if (logger.isWarnEnabled()) {
193 logger.warn("No attributes in POP response {}: {}", pipRequest.getAttributeId().stringValue(),
194 pipResponse.getStatus());
201 private Set<String> getActor(PIPFinder pipFinder) {
203 * Get the AT&T UID from either the subject id or the attuid property
205 PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_ACTOR, pipFinder);
206 if (pipResponseAttUid == null) {
207 return new HashSet<>();
211 * Iterate over all of the returned results and do the LDAP requests
213 Collection<Attribute> listAttUids = pipResponseAttUid.getAttributes();
214 Set<String> setAttUids = new HashSet<>();
215 for (Attribute attributeAttUid : listAttUids) {
216 Iterator<AttributeValue<String>> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING);
217 if (iterAttributeValues != null) {
218 while (iterAttributeValues.hasNext()) {
219 String attuid = iterAttributeValues.next().getValue();
220 if (attuid != null) {
221 setAttUids.add(attuid);
230 private Set<String> getRecipe(PIPFinder pipFinder) {
232 * Get the AT&T UID from either the subject id or the attuid property
234 PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_RECIPE, pipFinder);
235 if (pipResponseAttUid == null) {
236 return new HashSet<>();
240 * Iterate over all of the returned results and do the LDAP requests
242 Collection<Attribute> listAttUids = pipResponseAttUid.getAttributes();
243 Set<String> setAttUids = new HashSet<>();
244 for (Attribute attributeAttUid : listAttUids) {
245 Iterator<AttributeValue<String>> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING);
246 if (iterAttributeValues != null) {
247 while (iterAttributeValues.hasNext()) {
248 String attuid = iterAttributeValues.next().getValue();
249 if (attuid != null) {
250 setAttUids.add(attuid);
259 private void addIntegerAttribute(StdMutablePIPResponse stdPipResponse, Identifier category, Identifier attributeId,
260 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,
269 pipRequest.getIssuer()/* this.getIssuer() */, false));
273 private Set<String> getTarget(PIPFinder pipFinder) {
275 * Get the AT&T UID from either the subject id or the attuid property
277 PIPResponse pipResponseAttUid = this.getAttribute(PIP_REQUEST_TARGET, pipFinder);
278 if (pipResponseAttUid == null) {
279 return new HashSet<>();
283 * Iterate over all of the returned results and do the LDAP requests
285 Collection<Attribute> listAttUids = pipResponseAttUid.getAttributes();
286 Set<String> setAttUids = new HashSet<>();
287 for (Attribute attributeAttUid : listAttUids) {
288 Iterator<AttributeValue<String>> iterAttributeValues = attributeAttUid.findValues(DataTypes.DT_STRING);
289 if (iterAttributeValues != null) {
290 while (iterAttributeValues.hasNext()) {
291 String attuid = iterAttributeValues.next().getValue();
292 if (attuid != null) {
293 setAttUids.add(attuid);
302 private static int getCountFromDb(String actor, String operation, String target, String timeWindow) {
304 Properties props = new Properties();
305 props.put(Util.ECLIPSE_LINK_KEY_URL, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_URL));
306 props.put(Util.ECLIPSE_LINK_KEY_USER, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_USER));
307 props.put(Util.ECLIPSE_LINK_KEY_PASS, PolicyEngine.manager.getEnvironmentProperty(Util.ONAP_KEY_PASS));
310 EntityManager em = null;
311 String opsHistPu = System.getProperty("OperationsHistoryPU");
312 if (!"TestOperationsHistoryPU".equals(opsHistPu)) {
313 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();
354 } catch (NoResultException | NonUniqueResultException ex) {
355 logger.error("getCountFromDb threw: ", ex);
365 * 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) {
384 } else if ("MINUTE".compareToIgnoreCase(split[1]) == 0) {
386 } else if ("HOUR".compareToIgnoreCase(split[1]) == 0) {
388 } else if ("DAY".compareToIgnoreCase(split[1]) == 0) {
389 multiplier = 8.64e+7;
390 } else if ("WEEK".compareToIgnoreCase(split[1]) == 0) {
391 multiplier = 6.048e+8;
392 } else if ("MONTH".compareToIgnoreCase(split[1]) == 0) {
393 multiplier = 2.628e+9;
394 } else if ("QUARTER".compareToIgnoreCase(split[1]) == 0) {
395 multiplier = 2.628e+9 * 3;
396 } else if ("YEAR".compareToIgnoreCase(split[1]) == 0) {
397 multiplier = 3.154e+10;
399 logger.error("{} not supported", split[1]);