d57da3017d54ea46947676817234b0c80743901a
[policy/xacml-pdp.git] / applications / common / src / main / java / org / onap / policy / pdp / xacml / application / common / std / StdOnapPip.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
4  * Modifications Copyright (C) 2020 Bell Canada. All rights reserved.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.pdp.xacml.application.common.std;
23
24 import com.att.research.xacml.api.Attribute;
25 import com.att.research.xacml.api.AttributeValue;
26 import com.att.research.xacml.api.DataTypeException;
27 import com.att.research.xacml.api.Identifier;
28 import com.att.research.xacml.api.XACML3;
29 import com.att.research.xacml.api.pip.PIPException;
30 import com.att.research.xacml.api.pip.PIPFinder;
31 import com.att.research.xacml.api.pip.PIPRequest;
32 import com.att.research.xacml.api.pip.PIPResponse;
33 import com.att.research.xacml.std.StdMutableAttribute;
34 import com.att.research.xacml.std.datatypes.DataTypes;
35 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
36 import com.att.research.xacml.std.pip.StdPIPRequest;
37 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
38 import java.math.BigInteger;
39 import java.util.Collection;
40 import java.util.Collections;
41 import java.util.Iterator;
42 import java.util.Properties;
43 import javax.persistence.EntityManager;
44 import javax.persistence.Persistence;
45 import lombok.AccessLevel;
46 import lombok.NoArgsConstructor;
47 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 @NoArgsConstructor(access = AccessLevel.PROTECTED)
52 public abstract class StdOnapPip extends StdConfigurableEngine {
53     protected static Logger logger = LoggerFactory.getLogger(StdOnapPip.class);
54
55     protected static final PIPRequest PIP_REQUEST_ACTOR   = new StdPIPRequest(
56             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
57             ToscaDictionary.ID_RESOURCE_GUARD_ACTOR,
58             XACML3.ID_DATATYPE_STRING);
59
60     protected static final PIPRequest PIP_REQUEST_RECIPE  = new StdPIPRequest(
61             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
62             ToscaDictionary.ID_RESOURCE_GUARD_RECIPE,
63             XACML3.ID_DATATYPE_STRING);
64
65     protected static final PIPRequest PIP_REQUEST_TARGET  = new StdPIPRequest(
66             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
67             ToscaDictionary.ID_RESOURCE_GUARD_TARGETID,
68             XACML3.ID_DATATYPE_STRING);
69
70     protected Properties properties;
71     protected EntityManager em;
72     protected String issuer;
73     protected boolean shutdown = false;
74
75     @Override
76     public Collection<PIPRequest> attributesProvided() {
77         return Collections.emptyList();
78     }
79
80     @Override
81     public synchronized void configure(String id, Properties properties) throws PIPException {
82         //
83         // This most likely will never get called since configure is called
84         // upon startup.
85         //
86         if (this.shutdown) {
87             throw new PIPException("Engine is shutdown.");
88         }
89         super.configure(id, properties);
90         logger.info("Configuring historyDb PIP {}", properties);
91         this.properties = properties;
92         //
93         // Create our entity manager
94         //
95         em = null;
96         try {
97             //
98             // In case there are any overloaded properties for the JPA
99             //
100             var emProperties = new Properties();
101             emProperties.putAll(properties);
102
103             //
104             // Create the entity manager factory
105             //
106             em = Persistence.createEntityManagerFactory(
107                     properties.getProperty(this.issuer + ".persistenceunit"),
108                     emProperties).createEntityManager();
109         } catch (Exception e) {
110             logger.error("Persistence failed {} operations history db", e.getLocalizedMessage(), e);
111         }
112     }
113
114     @Override
115     public synchronized void shutdown() {
116         if (this.em != null) {
117             this.em.close();
118             this.em = null;
119         }
120         this.shutdown = true;
121     }
122
123     protected String getAttribute(PIPFinder pipFinder, PIPRequest pipRequest) {
124         //
125         // Get the actor value
126         //
127         var pipResponse = this.getAttribute(pipRequest, pipFinder);
128         if (pipResponse == null) {
129             logger.error("Need actor attribute which is not found");
130             return null;
131         }
132         //
133         // Find the actor
134         //
135         return findFirstAttributeValue(pipResponse);
136     }
137
138     protected PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
139         PIPResponse pipResponse = null;
140         try {
141             pipResponse = pipFinder.getMatchingAttributes(pipRequest, this);
142             if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) {
143                 logger.info("get attribute error retrieving {}: {}", pipRequest.getAttributeId(),
144                                 pipResponse.getStatus());
145                 pipResponse = null;
146             }
147             if (pipResponse != null && pipResponse.getAttributes().isEmpty()) {
148                 logger.info("No value for {}", pipRequest.getAttributeId());
149                 pipResponse = null;
150             }
151         } catch (PIPException ex) {
152             logger.error("PIPException getting subject-id attribute", ex);
153         }
154         return pipResponse;
155     }
156
157     protected String findFirstAttributeValue(PIPResponse pipResponse) {
158         for (Attribute attribute: pipResponse.getAttributes()) {
159             Iterator<AttributeValue<String>> iterAttributeValues    = attribute.findValues(DataTypes.DT_STRING);
160             while (iterAttributeValues.hasNext()) {
161                 String value   = iterAttributeValues.next().getValue();
162                 if (value != null) {
163                     return value;
164                 }
165             }
166         }
167         return null;
168     }
169
170     protected void addIntegerAttribute(StdMutablePIPResponse stdPipResponse, Identifier category,
171             Identifier attributeId, int value, PIPRequest pipRequest) {
172         AttributeValue<BigInteger> attributeValue   = null;
173         try {
174             attributeValue  = makeInteger(value);
175         } catch (Exception e) {
176             logger.error("Failed to convert {} to integer", value, e);
177         }
178         if (attributeValue != null) {
179             stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
180                     pipRequest.getIssuer(), false));
181         }
182     }
183
184     protected void addLongAttribute(StdMutablePIPResponse stdPipResponse, Identifier category,
185             Identifier attributeId, long value, PIPRequest pipRequest) {
186         AttributeValue<BigInteger> attributeValue   = null;
187         try {
188             attributeValue  = makeLong(value);
189         } catch (Exception e) {
190             logger.error("Failed to convert {} to long", value, e);
191         }
192         if (attributeValue != null) {
193             stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
194                     pipRequest.getIssuer(), false));
195         }
196     }
197
198     protected void addStringAttribute(StdMutablePIPResponse stdPipResponse, Identifier category, Identifier attributeId,
199             String value, PIPRequest pipRequest) {
200         AttributeValue<String> attributeValue = null;
201         try {
202             attributeValue = makeString(value);
203         } catch (Exception ex) {
204             logger.error("Failed to convert {} to an AttributeValue<String>", value, ex);
205         }
206         if (attributeValue != null) {
207             stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
208                     pipRequest.getIssuer(), false));
209         }
210     }
211
212     // these may be overridden by junit tests
213
214     protected AttributeValue<BigInteger> makeInteger(int value) throws DataTypeException {
215         return DataTypes.DT_INTEGER.createAttributeValue(value);
216     }
217
218     protected AttributeValue<BigInteger> makeLong(long value) throws DataTypeException {
219         return DataTypes.DT_INTEGER.createAttributeValue(value);
220     }
221
222     protected AttributeValue<String> makeString(String value) throws DataTypeException {
223         return DataTypes.DT_STRING.createAttributeValue(value);
224     }
225
226 }