Merge "Fix audit log to contain ending timestamp"
[policy/engine.git] / ONAP-PDP-REST / src / main / java / org / onap / policy / pdp / rest / XACMLPdpRegisterThread.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PDP-REST
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21
22 package org.onap.policy.pdp.rest;
23
24 import java.io.ByteArrayInputStream;
25 import java.io.ByteArrayOutputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.net.HttpURLConnection;
30 import java.net.URL;
31 import java.nio.charset.StandardCharsets;
32 import java.nio.file.Files;
33 import java.util.Base64;
34 import java.util.Properties;
35 import java.util.UUID;
36
37 import org.apache.commons.io.IOUtils;
38 import org.onap.policy.pdp.rest.XACMLPdpServlet.PutRequest;
39 import org.onap.policy.rest.XACMLRestProperties;
40
41 import org.onap.policy.xacml.api.XACMLErrorConstants;
42 import com.att.research.xacml.util.XACMLProperties;
43
44 import org.onap.policy.common.logging.ONAPLoggingContext;
45 import org.onap.policy.common.logging.eelf.PolicyLogger;
46 import org.onap.policy.common.logging.flexlogger.*; 
47
48 public class XACMLPdpRegisterThread implements Runnable {
49         private static final Logger LOGGER      = FlexLogger.getLogger(XACMLPdpRegisterThread.class);
50         private static final Logger auditLogger = FlexLogger.getLogger("auditLogger");
51         private ONAPLoggingContext baseLoggingContext = null;
52         
53
54
55         public volatile boolean isRunning = false;
56         
57         public XACMLPdpRegisterThread(ONAPLoggingContext baseLoggingContext) {
58                 this.baseLoggingContext = baseLoggingContext;
59         }
60
61         public synchronized boolean isRunning() {
62                 return this.isRunning;
63         }
64         
65         public synchronized void terminate() {
66                 this.isRunning = false;
67         }
68         
69         /**
70          * 
71          * This is our thread that runs on startup to tell the PAP server we are up-and-running.
72          * 
73          */
74         @Override
75         public void run() {
76                 synchronized(this) {
77                         this.isRunning = true;
78                 }
79                 // get a new logging context for the thread
80                 ONAPLoggingContext loggingContext = new ONAPLoggingContext(baseLoggingContext);
81                 loggingContext.setServiceName("PDP:PAP.register");
82                 //are we registered with at least one
83                 boolean registered = false;
84                 boolean interrupted = false;
85                 /*
86                 int seconds;
87                 try {
88                         seconds = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER_SLEEP));
89                 } catch (NumberFormatException e) {
90                         LOGGER.error( XACMLErrorConstants.ERROR_SYSTEM_ERROR +"REGISTER_SLEEP: ", e);
91                         seconds = 5;
92                 }
93                 if (seconds < 5) {
94                         seconds = 5;
95                 }
96                 int retries;
97                 try {
98                         retries = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER_RETRIES));
99                 } catch (NumberFormatException e) {
100                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +" REGISTER_SLEEP: ", e);
101                         retries = -1;
102                 }
103                 */
104                 PapUrlResolver papUrls = PapUrlResolver.getInstance();
105                 //while (! registered && ! interrupted && this.isRunning()) {
106                 String tempRootPoliciesProperty = XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES);
107                 String tempReferencedPoliciesProperty = XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES);
108                 Properties tempPipConfigProperties = new Properties();
109                 try(InputStream pipFile = Files.newInputStream(XACMLPdpLoader.getPIPConfig())){
110                         tempPipConfigProperties.load(pipFile);
111                 } catch(Exception e){
112                         LOGGER.error("Failed to open PIP property file", e);
113                 }
114                 while(papUrls.hasMoreUrls()){
115                         String papID = papUrls.getUserId();
116                         String papPass = papUrls.getPass();
117                         Base64.Encoder encoder = Base64.getEncoder();
118                         String encoding = encoder.encodeToString((papID+":"+papPass).getBytes(StandardCharsets.UTF_8));
119                         HttpURLConnection connection = null;
120                         try {
121                                 // get a new transaction (request) ID and update the logging context.
122                                 // each time through the outer loop is considered a new transaction.
123                                 // each time through the inner loop (which handles redirects) is a
124                                 // continuation of the same transaction.
125                                 UUID requestID = UUID.randomUUID();
126                                 loggingContext.setRequestID(requestID.toString());
127                                 //PolicyLogger.info("Request Id generated in XACMLPdpRegisterThread under XACML-PDP-REST");
128                                 loggingContext.transactionStarted();
129                                 //
130                                 // Get the list of PAP Servlet URLs from the property file
131                                 //
132                                 //String papUrlList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
133                                 //String[] papUrls = papUrlList.split(",");
134                                 //PapUrlResolver.setPapUrls(papUrls);
135                                 URL url = new URL(papUrls.getUrl());
136                                 LOGGER.info("Registering with " + url.toString());
137                                 //PolicyLogger.info("new transaction (request) ID and update to logging context in XACMLPdpRegisterThread");
138                                 boolean finished = false;
139                                 while (! finished) {
140                                         //
141                                         // Open up the connection
142                                         //
143                                         connection = (HttpURLConnection)url.openConnection();
144                                         //
145                                         // Setup our method and headers
146                                         //
147                             connection.setRequestMethod("POST");
148                             connection.setRequestProperty("Authorization", "Basic " + encoding);
149                                         connection.setRequestProperty("Accept", "text/x-java-properties");
150                             connection.setRequestProperty("Content-Type", "text/x-java-properties");
151                             connection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_ID, XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID));
152                             connection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_JMX_PORT, XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_JMX_PORT));
153                             connection.setRequestProperty("X-ECOMP-RequestID", requestID.toString());
154                             connection.setUseCaches(false);
155                             //
156                             // Adding this in. It seems the HttpUrlConnection class does NOT
157                             // properly forward our headers for POST re-direction. It does so
158                             // for a GET re-direction.
159                             //
160                             // So we need to handle this ourselves.
161                             //
162                             connection.setInstanceFollowRedirects(false);
163                                 connection.setDoOutput(true);
164                                 connection.setDoInput(true);
165                                 try {
166                                         //
167                                         // Send our current policy configuration
168                                         //
169                                         String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + tempRootPoliciesProperty;
170                                         lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + tempReferencedPoliciesProperty + "\n";
171                                         try (InputStream listsInputStream = new ByteArrayInputStream(lists.getBytes());                                                 
172                                                         OutputStream os = connection.getOutputStream()) {
173                                                 IOUtils.copy(listsInputStream, os);
174
175                                                 //
176                                                 // Send our current PIP configuration
177                                                 //
178                                                 //IOUtils.copy(pipInputStream, os);
179                                                 tempPipConfigProperties.store(os, "");
180                                         }
181                                 } catch (Exception e) {
182                                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Failed to send property file", e);
183                                 }
184                             //
185                             // Do the connect
186                             //
187                             connection.connect();
188                             if (connection.getResponseCode() == 204) {
189                                 LOGGER.info("Success. We are configured correctly.");
190                                 loggingContext.transactionEnded();
191                                 PolicyLogger.audit("Success. We are configured correctly.");
192                                 papUrls.registered();
193                                 finished = true;
194                                 registered = true;                              
195                             } else if (connection.getResponseCode() == 200) {
196                                 LOGGER.info("Success. We have a new configuration.");
197                                 loggingContext.transactionEnded();
198                                 PolicyLogger.audit("Success. We have a new configuration.");
199                                 papUrls.registered();
200                                 Properties properties = new Properties();
201                                 properties.load(connection.getInputStream());                           
202                                 LOGGER.info("New properties: " + properties.toString());
203                                 //
204                                 // Queue it
205                                 //
206                                 // The incoming properties does NOT include urls                            
207                                 Properties returnedPolicyProperties = XACMLProperties.getPolicyProperties(properties, false);
208                                 tempRootPoliciesProperty = new String(returnedPolicyProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES));
209                                 tempReferencedPoliciesProperty = new String(returnedPolicyProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES));                             
210                                 Properties returnedPipProperties = XACMLProperties.getPipProperties(properties);
211                                 Properties threadSafeReturnedPipProperties = new Properties();
212                                 ByteArrayOutputStream threadSafeReturnedPipPropertiesOs = new ByteArrayOutputStream();
213                                 returnedPipProperties.store(threadSafeReturnedPipPropertiesOs, "");                             
214                                 InputStream threadSafeReturnedPipPropertiesIs = new ByteArrayInputStream(threadSafeReturnedPipPropertiesOs.toByteArray());
215                                 threadSafeReturnedPipProperties.load(threadSafeReturnedPipPropertiesIs);
216                                 tempPipConfigProperties = threadSafeReturnedPipProperties;
217
218                                 PutRequest req = new PutRequest(returnedPolicyProperties,returnedPipProperties);
219                                 XACMLPdpServlet.queue.offer(req);
220                                 //
221                                 // We are now registered
222                                 //
223                                 finished = true;
224                                 registered=true;
225                             } else if (connection.getResponseCode() >= 300 && connection.getResponseCode()  <= 399) {
226                                 //
227                                 // Re-direction
228                                 //
229                                 String newLocation = connection.getHeaderField("Location");
230                                 if (newLocation == null || newLocation.isEmpty()) {
231                                         LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location");
232                                         loggingContext.transactionEnded();
233                                         auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location");
234                                         PolicyLogger.audit("Transaction Failed - See Error.log");
235                                         finished = true;
236                                 } else {
237                                         LOGGER.info("New Location: " + newLocation);
238                                         url = new URL(newLocation);
239                                 }
240                             } else {
241                                 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
242                                 loggingContext.transactionEnded();
243                                 auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
244                                 PolicyLogger.audit("Transaction Failed - See Error.log");
245                                 finished = true;
246                                 papUrls.failed();
247                             }
248                                 }
249                         } catch (Exception e) {
250                                 LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
251                                 loggingContext.transactionEnded();
252                                 PolicyLogger.audit("Transaction Failed - See Error.log");
253                                 papUrls.failed();
254                         } finally {
255                                 // cleanup the connection
256                                 if (connection != null) {
257                                         try {
258                                                 // For some reason trying to get the inputStream from the connection
259                                                 // throws an exception rather than returning null when the InputStream does not exist.
260                                                 InputStream is = null;
261                                                 try {
262                                                         is = connection.getInputStream();
263                                                 } catch (Exception e1) {
264                                                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to get Input Stream: " + e1);
265                                                 }
266                                                 if (is != null) {
267                                                         is.close();
268                                                 }
269
270                                         } catch (IOException ex) {
271                                                 LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to close connection: " + ex, ex);
272                                         }
273                                         connection.disconnect();
274                                 }
275                         }
276
277                         papUrls.getNext();
278                 }
279                 synchronized(this) {
280                         this.isRunning = false;
281                 }
282                 LOGGER.info("Thread exiting...(registered=" + registered + ", interrupted=" + interrupted + ", isRunning=" + this.isRunning() + ", retries=" + "0" + ")");
283         }
284
285 }