Keep only clean TestCases, remove 2 license issues
[aaf/authz.git] / auth / auth-batch / src / main / java / org / onap / aaf / auth / Batch.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.auth;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.PrintStream;
30 import java.lang.reflect.Constructor;
31 import java.net.InetAddress;
32 import java.net.URL;
33 import java.net.UnknownHostException;
34 import java.nio.ByteBuffer;
35 import java.text.SimpleDateFormat;
36 import java.util.GregorianCalendar;
37 import java.util.HashSet;
38 import java.util.List;
39 import java.util.Set;
40 import java.util.TimeZone;
41
42 import org.apache.log4j.Logger;
43 import org.onap.aaf.auth.common.Define;
44 import org.onap.aaf.auth.dao.CassAccess;
45 import org.onap.aaf.auth.dao.cass.RoleDAO;
46 import org.onap.aaf.auth.dao.cass.UserRoleDAO;
47 import org.onap.aaf.auth.dao.hl.Question;
48 import org.onap.aaf.auth.env.AuthzEnv;
49 import org.onap.aaf.auth.env.AuthzTrans;
50 import org.onap.aaf.auth.layer.Result;
51 import org.onap.aaf.auth.org.Organization;
52 import org.onap.aaf.auth.org.Organization.Identity;
53 import org.onap.aaf.auth.org.OrganizationException;
54 import org.onap.aaf.auth.org.OrganizationFactory;
55 import org.onap.aaf.cadi.PropAccess;
56 import org.onap.aaf.misc.env.APIException;
57 import org.onap.aaf.misc.env.Env;
58 import org.onap.aaf.misc.env.StaticSlot;
59 import org.onap.aaf.misc.env.TimeTaken;
60 import org.onap.aaf.misc.env.impl.Log4JLogTarget;
61 import org.onap.aaf.misc.env.log4j.LogFileNamer;
62
63 import com.datastax.driver.core.Cluster;
64 import com.datastax.driver.core.ResultSet;
65 import com.datastax.driver.core.Row;
66 import com.datastax.driver.core.Session;
67 import com.datastax.driver.core.Statement;
68
69 public abstract class Batch {
70
71         private static String ROOT_NS;
72
73         private static StaticSlot ssargs;
74
75         protected static final String STARS = "*****";
76
77     protected final Cluster cluster; 
78     protected static AuthzEnv env;
79     protected static Session session;
80     protected static Logger aspr;
81     protected static Set<String> specialNames;
82     protected static boolean dryRun; 
83         protected static String batchEnv;
84
85         public static final String CASS_ENV = "CASS_ENV";
86         public static final String LOG_DIR = "LOG_DIR";
87     protected final static String PUNT="punt";
88     protected final static String MAX_EMAILS="MAX_EMAILS";
89     protected final static String VERSION="VERSION";
90     public final static String GUI_URL="GUI_URL";
91     
92     protected final static String ORA_URL="ora_url";
93     protected final static String ORA_PASSWORD="ora_password";
94         protected final Organization org;
95
96
97     
98     protected Batch(AuthzEnv env) throws APIException, IOException, OrganizationException {
99         // Be able to change Environments
100         // load extra properties, i.e.
101         // PERF.cassandra.clusters=....
102         batchEnv = env.getProperty(CASS_ENV);
103         if(batchEnv != null) {
104                 batchEnv = batchEnv.trim();
105                 env.info().log("Redirecting to ",batchEnv,"environment");
106                 String str;
107                 for(String key : new String[]{
108                                 CassAccess.CASSANDRA_CLUSTERS,
109                                 CassAccess.CASSANDRA_CLUSTERS_PORT,
110                                 CassAccess.CASSANDRA_CLUSTERS_USER_NAME,
111                                 CassAccess.CASSANDRA_CLUSTERS_PASSWORD,
112                                 VERSION,GUI_URL,PUNT,MAX_EMAILS,
113                                 LOG_DIR,
114                                 "SPECIAL_NAMES"
115                                 }) {
116                         if((str = env.getProperty(batchEnv+'.'+key))!=null) {
117                             env.setProperty(key, str);
118                         }
119                 }
120         }
121
122         // Setup for Dry Run
123         cluster = CassAccess.cluster(env,batchEnv);
124         env.info().log("cluster name - ",cluster.getClusterName());
125         String dryRunStr = env.getProperty( "DRY_RUN" );
126         if ( dryRunStr == null || dryRunStr.trim().equals("false") ) {
127                     dryRun = false;
128                 } else {
129             dryRun = true;
130             env.info().log("dryRun set to TRUE");
131         }
132
133                 org = OrganizationFactory.init(env);
134                 org.setTestMode(dryRun);
135
136                 // Special names to allow behaviors beyond normal rules
137         specialNames = new HashSet<String>();
138         String names = env.getProperty( "SPECIAL_NAMES" );
139         if ( names != null )
140         {
141             env.info().log("Loading SPECIAL_NAMES");
142             for (String s :names.split(",") )
143             {
144                 env.info().log("\tspecial: " + s );
145                 specialNames.add( s.trim() );
146             }
147         }
148     }
149
150     protected abstract void run(AuthzTrans trans);
151     protected abstract void _close(AuthzTrans trans);
152     
153     public String[] args() {
154         return (String[])env.get(ssargs);
155     }
156         
157     public boolean isDryRun()
158     {
159         return dryRun;
160     }
161     
162         public boolean isSpecial(String user) {
163                 if (specialNames != null && specialNames.contains(user)) {
164                         env.info().log("specialName: " + user);
165
166                         return (true);
167                 } else {
168                         return (false);
169                 }
170         }
171         
172         public boolean isMechID(String user) {
173                 if (user.matches("m[0-9][0-9][0-9][0-9][0-9]")) {
174                         return (true);
175                 } else {
176                         return (false);
177                 }
178         }
179
180         protected PrintStream fallout(PrintStream _fallout, String logType)
181                         throws IOException {
182                 PrintStream fallout = _fallout;
183                 if (fallout == null) {
184                         File dir = new File("logs");
185                         if (!dir.exists()) {
186                                 dir.mkdirs();
187                         }
188
189                         File f = null;
190                         // String os = System.getProperty("os.name").toLowerCase();
191                         long uniq = System.currentTimeMillis();
192
193                         f = new File(dir, getClass().getSimpleName() + "_" + logType + "_"
194                                         + uniq + ".log");
195
196                         fallout = new PrintStream(new FileOutputStream(f, true));
197                 }
198                 return fallout;
199         }
200
201         public Organization getOrgFromID(AuthzTrans trans, String user) {
202                 Organization org;
203                 try {
204                         org = OrganizationFactory.obtain(trans.env(),user.toLowerCase());
205                 } catch (OrganizationException e1) {
206                         trans.error().log(e1);
207                         org=null;
208                 }
209
210                 if (org == null) {
211                         PrintStream fallout = null;
212
213                         try {
214                                 fallout = fallout(fallout, "Fallout");
215                                 fallout.print("INVALID_ID,");
216                                 fallout.println(user);
217                         } catch (Exception e) {
218                                 env.error().log("Could not write to Fallout File", e);
219                         }
220                         return (null);
221                 }
222
223                 return (org);
224         }
225         
226         public static Row executeDeleteQuery(Statement stmt) {
227                 Row row = null;
228                 if (!dryRun) {
229                         row = session.execute(stmt).one();
230                 }
231
232                 return (row);
233
234         }
235         
236         public static int acquireRunLock(String className) {
237                 Boolean testEnv = true;
238                 String envStr = env.getProperty("AFT_ENVIRONMENT");
239
240                 if (envStr != null) {
241                         if (envStr.equals("AFTPRD")) {
242                                 testEnv = false;
243                         }
244                 } else {
245                         env.fatal()
246                                         .log("AFT_ENVIRONMENT property is required and was not found. Exiting.");
247                         System.exit(1);
248                 }
249
250                 if (testEnv) {
251                         env.info().log("TESTMODE: skipping RunLock");
252                         return (1);
253                 }
254
255                 String hostname = null;
256                 try {
257                         hostname = InetAddress.getLocalHost().getHostName();
258                 } catch (UnknownHostException e) {
259                         e.printStackTrace();
260                         env.warn().log("Unable to get hostname");
261                         return (0);
262                 }
263
264                 ResultSet existing = session.execute(String.format(
265                                 "select * from authz.run_lock where class = '%s'", className));
266
267                 for (Row row : existing) {
268                         long curr = System.currentTimeMillis();
269                         ByteBuffer lastRun = row.getBytesUnsafe(2); // Can I get this field
270                                                                                                                 // by name?
271
272                         long interval = (1 * 60 * 1000); // @@ Create a value in props file
273                                                                                                 // for this
274                         long prev = lastRun.getLong();
275
276                         if ((curr - prev) <= interval) {
277                                 env.warn().log(
278                                                 String.format("Too soon! Last run was %d minutes ago.",
279                                                                 ((curr - prev) / 1000) / 60));
280                                 env.warn().log(
281                                                 String.format("Min time between runs is %d minutes ",
282                                                                 (interval / 1000) / 60));
283                                 env.warn().log(
284                                                 String.format("Last ran on machine: %s at %s",
285                                                                 row.getString("host"), row.getDate("start")));
286                                 return (0);
287                         } else {
288                                 env.info().log("Delete old lock");
289                                 deleteLock(className);
290                         }
291                 }
292
293                 GregorianCalendar current = new GregorianCalendar();
294
295                 // We want our time in UTC, hence "+0000"
296                 SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+0000");
297                 fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
298
299                 String cql = String
300                                 .format("INSERT INTO authz.run_lock (class,host,start) VALUES ('%s','%s','%s') IF NOT EXISTS",
301                                                 className, hostname, fmt.format(current.getTime()));
302
303                 env.info().log(cql);
304
305                 Row row = session.execute(cql).one();
306                 if (!row.getBool("[applied]")) {
307                         env.warn().log("Lightweight Transaction failed to write lock.");
308                         env.warn().log(
309                                         String.format("host with lock: %s, running at %s",
310                                                         row.getString("host"), row.getDate("start")));
311                         return (0);
312                 }
313                 return (1);
314         }
315         
316     private static void deleteLock( String className) {
317         Row row = session.execute( String.format( "DELETE FROM authz.run_lock WHERE class = '%s' IF EXISTS", className ) ).one();
318         if (! row.getBool("[applied]")) {
319             env.info().log( "delete failed" );
320         }
321     }
322
323     private static void transferVMProps(AuthzEnv env, String ... props) {
324                 String value;
325                 for(String key : props) {
326                         if((value = System.getProperty(key))!=null) {
327                             env.setProperty(key, value);
328                         }
329                 }
330         }
331         
332         // IMPORTANT! VALIDATE Organization isUser method
333     protected void checkOrganizationAcccess(AuthzTrans trans, Question q) throws APIException, OrganizationException {
334                 Set<String> testUsers = new HashSet<String>();
335                 Result<List<RoleDAO.Data>> rrd = q.roleDAO.readNS(trans, ROOT_NS);
336                 if(rrd.isOK()) {
337                         for(RoleDAO.Data r : rrd.value) {
338                                 Result<List<UserRoleDAO.Data>> rur = q.userRoleDAO.readByRole(trans, r.fullName());
339                                 if(rur.isOK()) {
340                                         for(UserRoleDAO.Data udd : rur.value) {
341                                                 testUsers.add(udd.user);
342                                         }
343                                 }
344                         }
345                 }
346                 if(testUsers.size()<2) {
347                         throw new APIException("Not enough Users in Roles for " + ROOT_NS + " to Validate");
348                 }
349                 
350                 Identity iden;
351                 for(String user : testUsers) {
352                         if((iden=org.getIdentity(trans,user))==null) {
353                                 throw new APIException("Failed Organization Entity Validation Check: " + user);
354                         } else {
355                                 trans.info().log("Organization Validation Check: " + iden.id());
356                         }
357                 }
358     }
359     
360     protected static String logDir() {
361         String ld = env.getProperty(LOG_DIR);
362         if(ld==null) {
363                 if(batchEnv==null) { // Deployed Batch doesn't use different ENVs, and a common logdir
364                                 ld = "logs/";
365                         } else {
366                                 ld = "logs/"+batchEnv;
367                         }
368         }
369         return ld;
370     }
371         protected int count(String str, char c) {
372                 if(str==null || str.isEmpty()) {
373                         return 0;
374                 } else {
375                         int count=1;
376                         for(int i=str.indexOf(c);i>=0;i=str.indexOf(c,i+1)) {
377                                 ++count;
378                         }
379                         return count;
380                 }
381         }
382
383         public final void close(AuthzTrans trans) {
384             _close(trans);
385             cluster.close();
386         }
387
388         public static void main(String[] args) {
389                 PropAccess access = new PropAccess(args);
390                 InputStream is = null;
391                 String filename;
392                 String propLoc;
393                 try {
394                         Define.set(access);
395                         ROOT_NS=Define.ROOT_NS();
396                         
397                         File f = new File("etc/authzBatch.props");
398                         try {
399                                 if (f.exists()) {
400                                         filename = f.getAbsolutePath();
401                                         is = new FileInputStream(f);
402                                         propLoc = f.getPath();
403                                 } else {
404                                         URL rsrc = ClassLoader.getSystemResource("authBatch.props");
405                                         filename = rsrc.toString();
406                                         is = rsrc.openStream();
407                                         propLoc = rsrc.getPath();
408                                 }
409                                 access.load(is);
410                         } finally {
411                                 if (is == null) {
412                                         System.err.println("authBatch.props must exist in etc dir, or in Classpath");
413                                         System.exit(1);
414                                 }
415                                 is.close();
416                         }
417
418                         env = new AuthzEnv(access);
419
420                         transferVMProps(env, CASS_ENV, "DRY_RUN", "NS", "Organization");
421
422                         // Flow all Env Logs to Log4j, with ENV
423
424                         LogFileNamer lfn;
425                         if ((batchEnv = env.getProperty(CASS_ENV)) == null) {
426                                 lfn = new LogFileNamer(logDir()).noPID();
427                         } else {
428                                 lfn = new LogFileNamer(logDir()).noPID();
429                         }
430
431                         lfn.setAppender("authz-batch");
432                         lfn.setAppender("aspr|ASPR");
433                         lfn.setAppender("sync");
434                         lfn.setAppender("jobchange");
435                         lfn.setAppender("validateuser");
436                         aspr = Logger.getLogger("aspr");
437                         Log4JLogTarget.setLog4JEnv("authz-batch", env);
438                         if (filename != null) {
439                                 env.init().log("Instantiated properties from", filename);
440                         }
441
442                         // Log where Config found
443                         env.info().log("Configuring from", propLoc);
444                         propLoc = null;
445
446                         Batch batch = null;
447                         // setup ATTUser and Organization Slots before starting this:
448                         // TODO redo this
449                         // env.slot(ATT.ATT_USERSLOT);
450                         //
451                         // OrganizationFactory.setDefaultOrg(env, ATT.class.getName());
452                         AuthzTrans trans = env.newTrans();
453
454                         TimeTaken tt = trans.start("Total Run", Env.SUB);
455                         try {
456                                 int len = args.length;
457                                 if (len > 0) {
458                                         String toolName = args[0];
459                                         len -= 1;
460                                         if (len < 0)
461                                                 len = 0;
462                                         String nargs[] = new String[len];
463                                         if (len > 0) {
464                                                 System.arraycopy(args, 1, nargs, 0, len);
465                                         }
466
467                                         env.put(ssargs = env.staticSlot("ARGS"), nargs);
468
469                                         /*
470                                          * Add New Batch Programs (inherit from Batch) here
471                                          */
472
473                                         // Might be a Report, Update or Temp Batch
474                                         Class<?> cls;
475                                         String classifier = "";
476                                         try {
477                                                 cls = ClassLoader.getSystemClassLoader().loadClass("org.onap.aaf.auth.update." + toolName);
478                                                 classifier = "Update:";
479                                         } catch (ClassNotFoundException e) {
480                                                 try {
481                                                         cls = ClassLoader.getSystemClassLoader().loadClass("org.onap.aaf.auth.reports." + toolName);
482                                                         classifier = "Report:";
483                                                 } catch (ClassNotFoundException e2) {
484                                                         try {
485                                                                 cls = ClassLoader.getSystemClassLoader()
486                                                                                 .loadClass("org.onap.aaf.auth.temp." + toolName);
487                                                                 classifier = "Temp Utility:";
488                                                         } catch (ClassNotFoundException e3) {
489                                                                 cls = null;
490                                                         }
491                                                 }
492                                         }
493                                         if (cls != null) {
494                                                 Constructor<?> cnst = cls.getConstructor(new Class[] { AuthzTrans.class });
495                                                 batch = (Batch) cnst.newInstance(trans);
496                                                 env.info().log("Begin", classifier, toolName);
497                                         }
498                                 
499
500                                         if (batch == null) {
501                                                 trans.error().log("No Batch named", toolName, "found");
502                                         }
503                                         /*
504                                          * End New Batch Programs (inherit from Batch) here
505                                          */
506
507                                 }
508                                 if (batch != null) {
509                                         batch.run(trans);
510                                 }
511                         } finally {
512                                 tt.done();
513                                 if (batch != null) {
514                                         batch.close(trans);
515                                 }
516                                 StringBuilder sb = new StringBuilder("Task Times\n");
517                                 trans.auditTrail(4, sb, AuthzTrans.SUB, AuthzTrans.REMOTE);
518                                 trans.info().log(sb);
519                         }
520                 } catch (Exception e) {
521                         e.printStackTrace(System.err);
522                         // Exceptions thrown by DB aren't stopping the whole process.
523                         System.exit(1);
524                 }
525         }
526
527 }
528