Initial OpenECOMP policy/engine commit
[policy/engine.git] / ECOMP-PDP-REST / src / main / java / org / openecomp / policy / pdp / rest / XACMLPdpRegisterThread.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-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.openecomp.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.openecomp.policy.pdp.rest.XACMLPdpServlet.PutRequest;
39 import org.openecomp.policy.rest.XACMLRestProperties;
40
41 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
42 import com.att.research.xacml.util.XACMLProperties;
43
44 import org.openecomp.policy.common.logging.ECOMPLoggingContext;
45 import org.openecomp.policy.common.logging.eelf.PolicyLogger;
46 import org.openecomp.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 ECOMPLoggingContext baseLoggingContext = null;
52         
53
54
55         public volatile boolean isRunning = false;
56         
57         public XACMLPdpRegisterThread(ECOMPLoggingContext 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                 ECOMPLoggingContext loggingContext = new ECOMPLoggingContext(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                         // TODO:EELF Cleanup - Remove logger
114                         //PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "XACMLPdpRegisterThread", "Failed to open PIP property file");
115                 }
116                 while(papUrls.hasMoreUrls()){
117                         String papID = papUrls.getUserId();
118                         String papPass = papUrls.getPass();
119                         Base64.Encoder encoder = Base64.getEncoder();
120                         String encoding = encoder.encodeToString((papID+":"+papPass).getBytes(StandardCharsets.UTF_8));
121                         HttpURLConnection connection = null;
122                         try {
123                                 // get a new transaction (request) ID and update the logging context.
124                                 // each time through the outer loop is considered a new transaction.
125                                 // each time through the inner loop (which handles redirects) is a
126                                 // continuation of the same transaction.
127                                 UUID requestID = UUID.randomUUID();
128                                 loggingContext.setRequestID(requestID.toString());
129                                 //PolicyLogger.info("Request Id generated in XACMLPdpRegisterThread under XACML-PDP-REST");
130                                 loggingContext.transactionStarted();
131                                 //
132                                 // Get the list of PAP Servlet URLs from the property file
133                                 //
134                                 //String papUrlList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
135                                 //String[] papUrls = papUrlList.split(",");
136                                 //PapUrlResolver.setPapUrls(papUrls);
137                                 URL url = new URL(papUrls.getUrl());
138                                 logger.info("Registering with " + url.toString());
139                                 //PolicyLogger.info("new transaction (request) ID and update to logging context in XACMLPdpRegisterThread");
140                                 boolean finished = false;
141                                 while (! finished) {
142                                         //
143                                         // Open up the connection
144                                         //
145                                         connection = (HttpURLConnection)url.openConnection();
146                                         //
147                                         // Setup our method and headers
148                                         //
149                             connection.setRequestMethod("POST");
150                             connection.setRequestProperty("Authorization", "Basic " + encoding);
151                                         connection.setRequestProperty("Accept", "text/x-java-properties");
152                             connection.setRequestProperty("Content-Type", "text/x-java-properties");
153                             connection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_ID, XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_ID));
154                             connection.setRequestProperty(XACMLRestProperties.PROP_PDP_HTTP_HEADER_JMX_PORT, XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_JMX_PORT));
155                             connection.setRequestProperty("X-ECOMP-RequestID", requestID.toString());
156                             connection.setUseCaches(false);
157                             //
158                             // Adding this in. It seems the HttpUrlConnection class does NOT
159                             // properly forward our headers for POST re-direction. It does so
160                             // for a GET re-direction.
161                             //
162                             // So we need to handle this ourselves.
163                             //
164                             connection.setInstanceFollowRedirects(false);
165                                 connection.setDoOutput(true);
166                                 connection.setDoInput(true);
167                                 try {
168                                         //
169                                         // Send our current policy configuration
170                                         //
171                                         String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + tempRootPoliciesProperty;
172                                         lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + tempReferencedPoliciesProperty + "\n";
173                                         try (InputStream listsInputStream = new ByteArrayInputStream(lists.getBytes());                                                 
174                                                         OutputStream os = connection.getOutputStream()) {
175                                                 IOUtils.copy(listsInputStream, os);
176
177                                                 //
178                                                 // Send our current PIP configuration
179                                                 //
180                                                 //IOUtils.copy(pipInputStream, os);
181                                                 tempPipConfigProperties.store(os, "");
182                                         }
183                                 } catch (Exception e) {
184                                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Failed to send property file", e);
185                                         // TODO:EELF Cleanup - Remove logger
186                                         //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to send property file");
187                                 }
188                             //
189                             // Do the connect
190                             //
191                             connection.connect();
192                             if (connection.getResponseCode() == 204) {
193                                 logger.info("Success. We are configured correctly.");
194                                 // TODO:EELF Cleanup - Remove logger
195                                 //PolicyLogger.info("Success. We are configured correctly.");
196                                 loggingContext.transactionEnded();
197                      //         auditLogger.info("Success. We are configured correctly.");
198                                 // TODO:EELF Cleanup - Remove logger
199                                 PolicyLogger.audit("Success. We are configured correctly.");
200                                 papUrls.registered();
201                                 finished = true;
202                                 registered = true;                              
203                             } else if (connection.getResponseCode() == 200) {
204                                 logger.info("Success. We have a new configuration.");
205                                 // TODO:EELF Cleanup - Remove logger
206                                 //PolicyLogger.info("Success. We have a new configuration.");
207                                 loggingContext.transactionEnded();
208                                 // TODO:EELF Cleanup - Remove logger
209                                 //auditLogger.info("Success. We have a new configuration.");
210                                 PolicyLogger.audit("Success. We have a new configuration.");
211                                 papUrls.registered();
212                                 Properties properties = new Properties();
213                                 properties.load(connection.getInputStream());                           
214                                 logger.info("New properties: " + properties.toString());
215                                 //
216                                 // Queue it
217                                 //
218                                 // The incoming properties does NOT include urls                                
219                                 //FIXME: problem here is that we need the properties to be filled in BEFORE this thread continues and registers with another pap
220                                 Properties returnedPolicyProperties = XACMLProperties.getPolicyProperties(properties, false);
221                                 tempRootPoliciesProperty = new String(returnedPolicyProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES));
222                                 tempReferencedPoliciesProperty = new String(returnedPolicyProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES));                             
223                                 Properties returnedPipProperties = XACMLProperties.getPipProperties(properties);
224                                 Properties threadSafeReturnedPipProperties = new Properties();
225                                 ByteArrayOutputStream threadSafeReturnedPipPropertiesOs = new ByteArrayOutputStream();
226                                 returnedPipProperties.store(threadSafeReturnedPipPropertiesOs, "");                             
227                                 InputStream threadSafeReturnedPipPropertiesIs = new ByteArrayInputStream(threadSafeReturnedPipPropertiesOs.toByteArray());
228                                 threadSafeReturnedPipProperties.load(threadSafeReturnedPipPropertiesIs);
229                                 tempPipConfigProperties = threadSafeReturnedPipProperties;
230                                 //FIXME: how will pipproperties respond to threading?
231
232                                 PutRequest req = new PutRequest(returnedPolicyProperties,returnedPipProperties);
233                                 XACMLPdpServlet.queue.offer(req);
234                                 //
235                                 // We are now registered
236                                 //
237                                 finished = true;
238                                 registered=true;
239                             } else if (connection.getResponseCode() >= 300 && connection.getResponseCode()  <= 399) {
240                                 //
241                                 // Re-direction
242                                 //
243                                 String newLocation = connection.getHeaderField("Location");
244                                 if (newLocation == null || newLocation.isEmpty()) {
245                                         logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location");
246                                         // TODO:EELF Cleanup - Remove logger
247                                         //PolicyLogger.warn(MessageCodes.ERROR_SYSTEM_ERROR, "Did not receive a valid re-direction location");
248                                         loggingContext.transactionEnded();
249                                         auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location");
250                                         // TODO:EELF Cleanup - Remove logger
251                                         PolicyLogger.audit("Transaction Failed - See Error.log");
252                                         finished = true;
253                                 } else {
254                                         //FIXME: how to handle this
255                                         logger.info("New Location: " + newLocation);
256                                         // TODO:EELF Cleanup - Remove logger
257                                         //PolicyLogger.info("New Location: " + newLocation);
258                                         url = new URL(newLocation);
259                                 }
260                             } else {
261                                 logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
262                                 // TODO:EELF Cleanup - Remove logger
263                                 //PolicyLogger.warn(MessageCodes.ERROR_SYSTEM_ERROR, "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
264                                 loggingContext.transactionEnded();
265                                 auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
266                                 // TODO:EELF Cleanup - Remove logger
267                                 PolicyLogger.audit("Transaction Failed - See Error.log");
268                                 finished = true;
269                                 papUrls.failed();
270                             }
271                                 }
272                         } catch (Exception e) {
273                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
274                                 // TODO:EELF Cleanup - Remove logger
275                                 //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
276                                 PolicyLogger.audit("Transaction Failed - See Error.log");
277                 loggingContext.transactionEnded();
278                 // TODO:EELF look at this error going to audit.  decide what to do.
279                 //auditLogger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);        
280                 // TODO:EELF Cleanup - Remove logger
281                                 papUrls.failed();
282                         } finally {
283                                 // cleanup the connection
284                                 if (connection != null) {
285                                         try {
286                                                 // For some reason trying to get the inputStream from the connection
287                                                 // throws an exception rather than returning null when the InputStream does not exist.
288                                                 InputStream is = null;
289                                                 try {
290                                                         is = connection.getInputStream();
291                                                 } catch (Exception e1) {
292                                                         // ignore this
293                                                 }
294                                                 if (is != null) {
295                                                         is.close();
296                                                 }
297
298                                         } catch (IOException ex) {
299                                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to close connection: " + ex, ex);
300                                                 // TODO:EELF Cleanup - Remove logger
301                                                 //PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, ex, "Failed to close connection");
302                                         }
303                                         connection.disconnect();
304                                 }
305                         }
306                         //
307                         // Wait a little while to try again
308                         //
309                         /*
310                         try {
311                                 if (registered == false) {
312                                         if (retries > 0) {
313                                                 retries--;
314                                         } else if (retries == 0) {
315                                                 break;
316                                         }
317                                         Thread.sleep(seconds * 1000);
318                                 }
319                         } catch (InterruptedException e) {
320                                 interrupted = true;
321                                 this.terminate();
322                         }
323                         */
324                         //end of hasMoreUrls while loop
325                         papUrls.getNext();
326                 }
327                 synchronized(this) {
328                         this.isRunning = false;
329                 }
330                 logger.info("Thread exiting...(registered=" + registered + ", interrupted=" + interrupted + ", isRunning=" + this.isRunning() + ", retries=" + "0" + ")");
331         }
332
333 }