AT&T 2.0.19 Code drop, stage 2
[aaf/authz.git] / cadi / core / src / main / java / org / onap / aaf / cadi / PropAccess.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 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
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.aaf.cadi;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.PrintStream;
29 import java.text.SimpleDateFormat;
30 import java.util.ArrayList;
31 import java.util.Date;
32 import java.util.List;
33 import java.util.Map.Entry;
34
35 import org.onap.aaf.cadi.config.Config;
36 import org.onap.aaf.cadi.config.SecurityInfo;
37
38 import java.util.Properties;
39
40 public class PropAccess implements Access {
41         private static final SimpleDateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
42
43         public static Level DEFAULT = Level.AUDIT;
44         
45         private Symm symm;
46         private int level;
47         private Properties props;
48         private List<String> recursionProtection = null;
49         private LogIt logIt;
50         private String name;
51
52         public PropAccess() {
53                 logIt = new StreamLogIt(System.out);
54                 init(null);
55         }
56         
57         /**
58          * This Constructor soly exists to instantiate Servlet Context Based Logging that will call "init" later.
59          * @param sc
60          */
61         protected PropAccess(Object o) {
62                 logIt = new StreamLogIt(System.out);
63                 props = new Properties();
64         }
65         
66         public PropAccess(String ... args) {
67                 this(System.out,args);
68         }
69         
70         public PropAccess(PrintStream ps, String[] args) {
71                 logIt = new StreamLogIt(ps==null?System.out:ps);
72                 Properties nprops=new Properties();
73                 int eq;
74                 for(String arg : args) {
75                         if((eq=arg.indexOf('='))>0) {
76                                 nprops.setProperty(arg.substring(0, eq),arg.substring(eq+1));
77                         }
78                 }
79                 init(nprops);
80         }
81         
82         public PropAccess(LogIt logit, String[] args) {
83                 logIt = logit;
84         }
85         
86         public PropAccess(Properties p) {
87                 this(System.out,p);
88         }
89         
90         public PropAccess(PrintStream ps, Properties p) {
91                 logIt = new StreamLogIt(ps==null?System.out:ps);
92                 init(p);
93         }
94         
95         protected void init(Properties p) {
96                 // Make sure these two are set before any changes in Logging
97                 name = "cadi";
98                 level=DEFAULT.maskOf();
99                 
100                 props = new Properties();
101                 // First, load related System Properties
102                 for(Entry<Object,Object> es : System.getProperties().entrySet()) {
103                         String key = es.getKey().toString();
104                         for(String start : new String[] {"cadi_","aaf_","cm_"}) {
105                                 if(key.startsWith(start)) {
106                                         props.put(key, es.getValue());
107                                 }
108                         }                       
109                 }
110                 // Second, overlay or fill in with Passed in Props
111                 if(p!=null) {
112                         props.putAll(p);
113                 }
114                 
115                 // Third, load any Chained Property Files
116                 load(props.getProperty(Config.CADI_PROP_FILES));
117                 
118                 String sLevel = props.getProperty(Config.CADI_LOGLEVEL); 
119                 if(sLevel!=null) {
120                         level=Level.valueOf(sLevel).maskOf(); 
121                 }
122                 // Setup local Symmetrical key encryption
123                 if(symm==null) {
124                         try {
125                                 symm = Symm.obtain(this);
126                         } catch (CadiException e) {
127                                 System.err.append("FATAL ERROR: Cannot obtain Key Information.");
128                                 e.printStackTrace(System.err);
129                                 System.exit(1);
130                         }
131                 }
132                 
133                 name = props.getProperty(Config.CADI_LOGNAME, name);
134                 
135                 specialConversions();
136         }
137
138         private void specialConversions() {
139                 // Critical - if no Security Protocols set, then set it.  We'll just get messed up if not
140                 if(props.get(Config.CADI_PROTOCOLS)==null) {
141                         props.setProperty(Config.CADI_PROTOCOLS, SecurityInfo.HTTPS_PROTOCOLS_DEFAULT);
142                 }
143                 
144                 Object temp;
145                 temp=props.get(Config.CADI_PROTOCOLS);
146                 if(props.get(Config.HTTPS_PROTOCOLS)==null && temp!=null) {
147                         props.put(Config.HTTPS_PROTOCOLS, temp);
148                 }
149                 
150                 if(temp!=null) {
151                         if("1.7".equals(System.getProperty("java.specification.version")) 
152                                         && (temp==null || (temp instanceof String && ((String)temp).contains("TLSv1.2")))) {
153                                 System.setProperty(Config.HTTPS_CIPHER_SUITES, Config.HTTPS_CIPHER_SUITES_DEFAULT);
154                         }
155                 }
156         }
157
158         private void load(String cadi_prop_files) {
159                 if(cadi_prop_files==null) {
160                         return;
161                 }
162                 String prevKeyFile = props.getProperty(Config.CADI_KEYFILE);
163                 int prev = 0, end = cadi_prop_files.length();
164                 int idx;
165                 String filename;
166                 while(prev<end) {
167                         idx = cadi_prop_files.indexOf(File.pathSeparatorChar,prev);
168                         if(idx<0) {
169                                 idx = end;
170                         }
171                         File file = new File(filename=cadi_prop_files.substring(prev,idx));
172                         if(file.exists()) {
173                                 printf(Level.INIT,"Loading CADI Properties from %s",file.getAbsolutePath());
174                                 try {
175                                         FileInputStream fis = new FileInputStream(file);
176                                         try {
177                                                 props.load(fis);
178                                                 // Recursively Load
179                                                 String chainProp = props.getProperty(Config.CADI_PROP_FILES);
180                                                 if(chainProp!=null) {
181                                                         if(recursionProtection==null) {
182                                                                 recursionProtection = new ArrayList<String>();
183                                                                 recursionProtection.add(cadi_prop_files);
184                                                         }
185                                                         if(!recursionProtection.contains(chainProp)) {
186                                                                 recursionProtection.add(chainProp);
187                                                                 load(chainProp); // recurse
188                                                         }
189                                                 }
190                                         } finally {
191                                                 fis.close();
192                                         }
193                                 } catch (Exception e) {
194                                         log(e,filename,"cannot be opened");
195                                 }
196                         } else {
197                                 printf(Level.WARN,"Warning: recursive CADI Property %s does not exist",file.getAbsolutePath());
198                         }
199                         prev = idx+1;
200                 }
201                 
202                 // Trim 
203                 for(Entry<Object, Object> es : props.entrySet()) {
204                         Object value = es.getValue();
205                         if(value instanceof String) {
206                                 String trim = ((String)value).trim();
207                                 if(trim!=value) { // Yes, I want OBJECT equals
208                                         props.setProperty((String)es.getKey(), trim);
209                                 }
210                         }
211                 }
212                 // Reset Symm if Keyfile Changes:
213                 String newKeyFile = props.getProperty(Config.CADI_KEYFILE);
214                 if((prevKeyFile!=null && newKeyFile!=null) || (newKeyFile!=null && !newKeyFile.equals(prevKeyFile))) {
215                         try {
216                                 symm = Symm.obtain(this);
217                         } catch (CadiException e) {
218                                 System.err.append("FATAL ERROR: Cannot obtain Key Information.");
219                                 e.printStackTrace(System.err);
220                                 System.exit(1);
221                         }
222
223                         prevKeyFile=newKeyFile;
224                 }
225                 
226                 String loglevel = props.getProperty(Config.CADI_LOGLEVEL);
227                 if(loglevel!=null) {
228                         try {
229                                 level=Level.valueOf(loglevel).maskOf();
230                         } catch (IllegalArgumentException e) {
231                                 printf(Level.ERROR,"%s=%s is an Invalid Log Level",Config.CADI_LOGLEVEL,loglevel);
232                         }
233                 }
234                 
235                 specialConversions();
236         }
237         
238         @Override
239         public void load(InputStream is) throws IOException {
240                 props.load(is);
241                 load(props.getProperty(Config.CADI_PROP_FILES));
242         }
243
244         @Override
245         public void log(Level level, Object ... elements) {
246                 if(willLog(level)) {
247                         logIt.push(level,elements);
248                 }
249         }
250         
251         protected StringBuilder buildMsg(Level level, Object[] elements) {
252                 StringBuilder sb = new StringBuilder(iso8601.format(new Date()));
253                 sb.append(' ');
254                 sb.append(level.name());
255                 sb.append(" [");
256                 sb.append(name);
257                 
258                 int end = elements.length;
259                 if(end<=0) {
260                         sb.append("] ");
261                 } else {
262                         int idx = 0;
263                         if(elements[idx] instanceof Integer) {
264                                 sb.append('-');
265                                 sb.append(elements[idx]);
266                                 ++idx;
267                         }
268                         sb.append("] ");
269                         String s;
270                         boolean first = true;
271                         for(Object o : elements) {
272                                 if(o!=null) {
273                                         s=o.toString();
274                                         if(first) {
275                                                 first = false;
276                                         } else {
277                                                 int l = s.length();
278                                                 if(l>0) {
279                                                         switch(s.charAt(l-1)) {
280                                                                 case ' ':
281                                                                         break;
282                                                                 default:
283                                                                         sb.append(' ');
284                                                         }
285                                                 }
286                                         }
287                                         sb.append(s);
288                                 }
289                         }
290                 }
291                 return sb;
292         }
293
294         @Override
295         public void log(Exception e, Object... elements) {
296                 log(Level.ERROR,e.getMessage(),elements);
297                 e.printStackTrace(System.err);
298         }
299
300         @Override
301         public void printf(Level level, String fmt, Object... elements) {
302                 if(willLog(level)) {
303                         log(level,String.format(fmt, elements));
304                 }
305         }
306
307         @Override
308         public void setLogLevel(Level level) {
309                 this.level = level.maskOf();
310         }
311
312         @Override
313         public boolean willLog(Level level) {
314                 return level.inMask(this.level);
315         }
316
317         @Override
318         public ClassLoader classLoader() {
319                 return ClassLoader.getSystemClassLoader();
320         }
321
322         @Override
323         public String getProperty(String tag, String def) {
324                 return props.getProperty(tag,def);
325         }
326
327         @Override
328         public String decrypt(String encrypted, boolean anytext) throws IOException {
329                 return (encrypted!=null && (anytext==true || encrypted.startsWith(Symm.ENC)))
330                         ? symm.depass(encrypted)
331                         : encrypted;
332         }
333         
334         public String encrypt(String unencrypted) throws IOException {
335                 return Symm.ENC+symm.enpass(unencrypted);
336         }
337
338         //////////////////
339         // Additional
340         //////////////////
341         public String getProperty(String tag) {
342                 return props.getProperty(tag);
343         }
344         
345
346         public Properties getProperties() {
347                 return props;
348         }
349
350         public void setProperty(String tag, String value) {
351                 if(value!=null) {
352                         props.put(tag, value);
353                         if(Config.CADI_KEYFILE.equals(tag)) {
354                                 // reset decryption too
355                                 try {
356                                         symm = Symm.obtain(this);
357                                 } catch (CadiException e) {
358                                         System.err.append("FATAL ERROR: Cannot obtain Key Information.");
359                                         e.printStackTrace(System.err);
360                                         System.exit(1);
361                                 }
362                         }
363                 }
364         }
365
366         public interface LogIt {
367                 public void push(Level level, Object ... elements) ;
368         }
369         
370         private class StreamLogIt implements LogIt {
371                 private PrintStream ps;
372                 
373                 public StreamLogIt(PrintStream ps) {
374                         this.ps = ps;
375                 }
376                 @Override
377                 public void push(Level level, Object ... elements) {
378                         ps.println(buildMsg(level,elements));
379                         ps.flush();
380                 }
381                 
382         }
383
384         public void set(LogIt logit) {
385                 logIt = logit;
386         }
387 }