Merge "Fixed Sonar issues in AAF_CM"
[aaf/authz.git] / auth / auth-batch / src / main / java / org / onap / aaf / auth / batch / update / ExpiringOrig.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.batch.update;
23
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileOutputStream;
27 import java.io.FileReader;
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.util.Date;
31 import java.util.GregorianCalendar;
32 import java.util.List;
33 import java.util.UUID;
34
35 import org.onap.aaf.auth.batch.Batch;
36 import org.onap.aaf.auth.batch.BatchPrincipal;
37 import org.onap.aaf.auth.batch.actions.Action;
38 import org.onap.aaf.auth.batch.actions.ActionDAO;
39 import org.onap.aaf.auth.batch.actions.CacheTouch;
40 import org.onap.aaf.auth.batch.actions.CredDelete;
41 import org.onap.aaf.auth.batch.actions.CredPrint;
42 import org.onap.aaf.auth.batch.actions.Email;
43 import org.onap.aaf.auth.batch.actions.Message;
44 import org.onap.aaf.auth.batch.actions.URDelete;
45 import org.onap.aaf.auth.batch.actions.URFutureApprove;
46 import org.onap.aaf.auth.batch.actions.URFutureApproveExec;
47 import org.onap.aaf.auth.batch.actions.URPrint;
48 import org.onap.aaf.auth.batch.helpers.Approval;
49 import org.onap.aaf.auth.batch.helpers.Cred;
50 import org.onap.aaf.auth.batch.helpers.Future;
51 import org.onap.aaf.auth.batch.helpers.NS;
52 import org.onap.aaf.auth.batch.helpers.Role;
53 import org.onap.aaf.auth.batch.helpers.UserRole;
54 import org.onap.aaf.auth.batch.helpers.Cred.Instance;
55 import org.onap.aaf.auth.dao.cass.ApprovalDAO;
56 import org.onap.aaf.auth.dao.cass.CredDAO;
57 import org.onap.aaf.auth.dao.cass.FutureDAO;
58 import org.onap.aaf.auth.dao.hl.Function.FUTURE_OP;
59 import org.onap.aaf.auth.dao.hl.Function.OP_STATUS;
60 import org.onap.aaf.auth.env.AuthzTrans;
61 import org.onap.aaf.auth.layer.Result;
62 import org.onap.aaf.auth.org.OrganizationException;
63 import org.onap.aaf.auth.org.Organization.Identity;
64 import org.onap.aaf.misc.env.APIException;
65 import org.onap.aaf.misc.env.Env;
66 import org.onap.aaf.misc.env.TimeTaken;
67 import org.onap.aaf.misc.env.util.Chrono;
68
69 public class ExpiringOrig extends Batch {
70     private CredPrint crPrint;
71     private URFutureApprove urFutureApprove;
72     private URFutureApproveExec urFutureApproveExec;
73     private CredDelete crDelete;
74     private URDelete urDelete;
75     private final CacheTouch cacheTouch;
76     private final AuthzTrans noAvg;
77     private final ApprovalDAO apprDAO;
78     private final FutureDAO futureDAO;
79     private final PrintStream urDeleteF,urRecoverF;
80     private final URPrint urPrint;
81     private Email email;
82     private File deletesFile;
83
84     public ExpiringOrig(AuthzTrans trans) throws APIException, IOException, OrganizationException {
85         super(trans.env());
86         trans.info().log("Starting Connection Process");
87         
88         noAvg = env.newTransNoAvg();
89         noAvg.setUser(new BatchPrincipal("batch:Expiring"));
90         
91         TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB);
92         try {
93             crPrint = new CredPrint("Expired:");
94
95             TimeTaken tt = trans.start("Connect to Cluster with DAOs", Env.REMOTE);
96             try {
97                 urFutureApprove = new URFutureApprove(trans, cluster,isDryRun());
98 //                checkOrganizationAcccess(trans, urFutureApprove.question());
99                 urFutureApproveExec = new URFutureApproveExec(trans, urFutureApprove);
100                 urPrint = new URPrint("User Roles:");
101                 crDelete = new CredDelete(trans, urFutureApprove);
102                 urDelete = new URDelete(trans,urFutureApprove);
103                 cacheTouch = new CacheTouch(trans, urFutureApprove);
104                 
105                 // Reusing... don't destroy
106                 apprDAO = urFutureApprove.question().approvalDAO;
107                 futureDAO = urFutureApprove.question().futureDAO;
108
109                 TimeTaken tt2 = trans.start("Connect to Cluster", Env.REMOTE);
110                 try {
111                     session = urFutureApprove.getSession(trans);
112                 } finally {
113                     tt2.done();
114                 }
115             } finally {
116                 tt.done();
117             }
118             
119             File data_dir = new File(env.getProperty("aaf_data_dir"));
120             if (!data_dir.exists() || !data_dir.canWrite() || !data_dir.canRead()) {
121                 throw new IOException("Cannot read/write to Data Directory "+ data_dir.getCanonicalPath() + ": EXITING!!!");
122             }
123             UserRole.setDeleteStream(
124                 urDeleteF = new PrintStream(new FileOutputStream(deletesFile = new File(data_dir,"UserRoleDeletes.dat"),false)));
125             UserRole.setRecoverStream(
126                 urRecoverF = new PrintStream(new FileOutputStream(new File(data_dir,"UserRoleRecover.dat"),false)));
127             UserRole.load(trans, session, UserRole.v2_0_11, new UserRole.DataLoadVisitor());
128             
129             Cred.load(trans, session);
130             NS.load(trans, session,NS.v2_0_11);
131             Future.load(trans,session,Future.withConstruct);
132             Approval.load(trans,session,Approval.v2_0_17);
133             Role.load(trans, session);
134             
135             email = new Email();
136             email.subject("AAF Expiring Process Alert (ENV: %s)",batchEnv);
137             email.preamble("Expiring Process Alert for %s",batchEnv);
138             email.signature("Sincerely,\nAAF Expiring Batch Process\n");
139             String address = env.getProperty("ALERT_TO_ADDRESS");
140             if (address==null) {
141                 throw new APIException("ALERT_TO_ADDRESS property is required");
142             }
143             email.addTo(address);
144     
145         } finally {
146             tt0.done();
147         }
148     }
149
150     @Override
151     protected void run(AuthzTrans trans) {
152         // Setup Date boundaries
153         
154         final GregorianCalendar gc = new GregorianCalendar();
155         final Date now = gc.getTime();
156         
157         gc.add(GregorianCalendar.MONTH, 1);
158         Date future = gc.getTime();
159 //        Date earliest = null;
160
161         // reset
162         gc.setTime(now);
163         gc.add(GregorianCalendar.DAY_OF_MONTH, -7); // save Expired Roles for 7 days.
164         Date tooLate = gc.getTime();
165         
166         TimeTaken tt;
167        
168         // Clean out Approvals UserRoles are fixed up.
169         String memo;
170         for (List<Approval> la : Approval.byUser.values()) {
171             for (Approval a : la ) {
172                 memo = a.getMemo();
173                 if (memo!=null && (memo.contains("Re-Approval") || memo.contains("Re-Validate"))) {
174                         String role = a.getRole();
175                         if (role!=null) {
176                         UserRole ur = UserRole.get(a.getUser(), a.getRole());
177                         Future f=null;
178                         if (ur!=null) {
179                             if (ur.expires().after(future)) { // no need for Approval anymore
180                                 a.delayDelete(noAvg, apprDAO, dryRun, "User Role already Extended");
181                                 UUID tkt = a.getTicket();
182                                 if (tkt!=null && Future.data.containsKey(tkt)) {
183                                     f = Future.data.get(a.getTicket());
184                                 }
185                             }
186                         } else {
187                             a.delayDelete(noAvg, apprDAO, dryRun, "User Role does not exist");
188                             UUID tkt = a.getTicket();
189                             if (tkt !=null && Future.data.containsKey(tkt)) {
190                                 f = Future.data.get(a.getTicket());
191                             }
192                         }
193                         if (f!=null) {
194                             f.delayedDelete(noAvg, futureDAO, dryRun, "Approvals removed");
195                         }
196                         }
197                 }
198             }
199         }
200         try {
201                 trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
202                 Future.resetLocalData();
203             Approval.resetLocalData();
204             } catch (Exception t) {
205                 t.printStackTrace();
206             }
207     
208         // Run for Expired Futures
209         trans.info().log("Checking for Expired Approval/Futures");
210         tt = trans.start("Delete old Futures", Env.REMOTE);
211         trans.info().log("### Running Future Execution on ",Future.data.size(), "Items");
212         // Execute any Futures waiting
213             for (Future f : Future.data.values()) {
214                 if (f.memo().contains("Re-Approval") || f.memo().contains("Re-Validate")) {
215                     List<Approval> la = Approval.byTicket.get(f.id());
216                     if (la!=null) {
217                         Result<OP_STATUS> ruf = urFutureApproveExec.exec(noAvg,la,f);
218                         if (ruf.isOK()) {
219                             switch(ruf.value) {
220                                 case P:
221                                     break;
222                                 case E:
223                                 case D:
224                                 case L:
225                                     f.delayedDelete(noAvg, futureDAO, dryRun,OP_STATUS.L.desc());
226                                     Approval.delayDelete(noAvg, apprDAO, dryRun, la,OP_STATUS.L.desc());
227                                     break;
228                             }
229                         }
230                     }
231                 }
232             }
233             try {
234                 trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
235                 Future.resetLocalData();
236             Approval.resetLocalData();
237             } catch (Exception t) {
238                 t.printStackTrace();
239             }
240
241         
242         trans.info().log("### Remove Expired on ",Future.data.size(), "Items, or premature ones");
243         // Remove Expired
244         String expiredBeforeNow = "Expired before " + tooLate;
245         String expiredAfterFuture = "Expired after " + future;
246         try {
247                 for (Future f : Future.data.values()) {
248                     if (f.expires().before(tooLate)) {
249                         f.delayedDelete(noAvg,futureDAO,dryRun, expiredBeforeNow);
250                         Approval.delayDelete(noAvg, apprDAO, dryRun, Approval.byTicket.get(f.id()), expiredBeforeNow);
251                     } else if (f.expires().after(future)) {
252                         f.delayedDelete(noAvg,futureDAO,dryRun, expiredAfterFuture);
253                         Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), expiredAfterFuture);
254                     }
255                 }
256                 try {
257                     trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
258                     Future.resetLocalData();
259                 Approval.resetLocalData();
260                 } catch (Exception t) {
261                     t.printStackTrace();
262                 }
263         } finally {
264                 tt.done();    
265         }
266         
267         trans.info().log("### Checking Approvals valid (",Approval.byApprover.size(),"Items)");
268         // Make sure users of Approvals are still valid
269         for (List<Approval> lapp : Approval.byTicket.values()) {
270                 for (Approval app : lapp) {
271                     Future f;
272                     if (app.getTicket()==null) {
273                         f = null;
274                     } else {
275                         f = Future.data.get(app.getTicket());
276                         if (Future.pendingDelete(f)) {
277                             f=null;
278                         }
279                     }
280                     String msg;
281                     if (f!=null && app.getRole()!=null && Role.byName.get(app.getRole())==null) {
282                         f.delayedDelete(noAvg,futureDAO,dryRun,msg="Role '" + app.getRole() + "' no longer exists");
283                         Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), msg);
284                         continue;
285                     }
286                     
287                     switch(app.getStatus()) {
288                         case "pending":
289                             if (f==null) {
290                             app.delayDelete(noAvg,apprDAO, isDryRun(), "ticketDeleted");
291                             continue;
292                             }
293                             switch(app.getType()) {
294                                 case "owner":
295                                 boolean anOwner=false;
296                                     String approle = app.getRole();
297                                     if (approle!=null) {
298                                         Role role = Role.byName.get(approle);
299                                         if (role==null) {
300                                         app.delayDelete(noAvg, apprDAO, dryRun, "Role No Longer Exists");
301                                         continue;
302                                     } else {
303                                         // Make sure Owner Role exists
304                                         String owner = role.ns + ".owner";
305                                         if (Role.byName.containsKey(owner)) {
306                                                 List<UserRole> lur = UserRole.getByRole().get(owner);
307                                                 if (lur != null) {
308                                                     for (UserRole ur : lur) {
309                                                         if (ur.user().equals(app.getApprover())) {
310                                                             anOwner = true;
311                                                             break;
312                                                         }
313                                                     }
314                                                 }
315                                         }
316                                         }
317                                         if (!anOwner) {
318                                         app.delayDelete(noAvg, apprDAO, dryRun, "No longer Owner");
319                                         }
320     
321                                     }
322                                     break;
323                                 case "supervisor":
324                                 try {
325                                     Identity identity = org.getIdentity(noAvg, app.getUser());
326                                     if (identity==null) {
327                                         if (f!=null) {
328                                                 f.delayedDelete(noAvg,futureDAO,dryRun,msg = app.getUser() + " is no longer associated with " + org.getName());
329                                                 Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), msg);
330                                         }
331                                     } else {
332                                         if (!app.getApprover().equals(identity.responsibleTo().fullID())) {
333                                             if (f!=null) {
334                                                     f.delayedDelete(noAvg,futureDAO,dryRun,msg = app.getApprover() + " is no longer a Supervisor of " + app.getUser());
335                                                     Approval.delayDelete(noAvg,apprDAO,dryRun, Approval.byTicket.get(f.id()), msg);
336                                             }
337                                         }
338                                     }
339                                 } catch (OrganizationException e) {
340                                     e.printStackTrace();
341                                 }
342                                 break;
343                             }
344                             break;
345                     }
346                 }
347         }
348             try {
349                 trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
350                 Future.resetLocalData();
351             Approval.resetLocalData();
352             } catch (Exception t) {
353                 t.printStackTrace();
354             }
355         
356         int count = 0, deleted=0, delayedURDeletes = 0;
357
358         // Run for User Roles
359         trans.info().log("Checking for Expired User Roles");
360         try {
361                 for (UserRole ur : UserRole.getData()) {
362                     if (org.getIdentity(noAvg, ur.user())==null) {  // if not part of Organization;
363                         if (isSpecial(ur.user())) {
364                             trans.info().log(ur.user(),"is not part of organization, but may not be deleted");
365                         } else {
366                             ur.delayDelete(noAvg, "Not Part of Organization", dryRun);
367                             ++deleted;
368                             ++delayedURDeletes;
369                         }
370                     } else {
371                         if (NS.data.get(ur.ns())==null) {
372                             ur.delayDelete(noAvg,"Namespace " + ur.ns() + " does not exist.",dryRun);
373                             ++delayedURDeletes;
374                             ++deleted;
375                         } else if (!Role.byName.containsKey(ur.role())) {
376                             ur.delayDelete(noAvg,"Role " + ur.role() + " does not exist.",dryRun);
377                             ++deleted;
378                             ++delayedURDeletes;
379                         } else if (ur.expires().before(tooLate)) {
380                             if ("owner".equals(ur.rname())) { // don't delete Owners, even if Expired
381                                 urPrint.exec(noAvg,ur,"Owner Expired (but not deleted)");
382                             } else {
383                                 // In this case, when UR is expired, not dependent on other lookups, we delete straight out.
384                                 urDelete.exec(noAvg, ur,"Expired before " + tooLate);
385                                 ++deleted;
386                             }
387                             //trans.logAuditTrail(trans.info());
388                         } else if (ur.expires().before(future) && ur.expires().after(now)) {
389                             ++count;
390                             // Is there an Approval set already
391                             boolean needNew = true;
392                             if (ur.role()!=null && ur.user()!=null) {
393                                 List<Approval> abm = Approval.byUser.get(ur.user());
394                                 if (abm!=null) {
395                                     for (Approval a : abm) {
396                                         if (a.getOperation().equals(FUTURE_OP.A.name()) && ur.role().equals(a.getRole())) {
397                                             if (Future.data.get(a.getTicket())!=null) {
398                                                 needNew = false;
399                                                 break;
400                                             }
401                                         }
402                                     }
403                                 }
404                             }
405                             if (needNew) {
406                                 urFutureApprove.exec(noAvg, ur,"");
407                             }
408                         }
409                     }
410                 }
411         } catch (OrganizationException e) {
412             env.info().log(e,"Exiting ...");
413         } finally {
414                 env.info().log("Found",count,"user roles expiring before",future);
415                 env.info().log("deleting",deleted,"user roles expiring before",tooLate);
416         }
417         
418         // Actualize UR Deletes, or send Email
419         if (UserRole.sizeForDeletion()>0) {
420                 count+=UserRole.sizeForDeletion();
421             double onePercent = 0.01;
422             if (((double)UserRole.sizeForDeletion())/UserRole.getData().size() > onePercent) {
423                     Message msg = new Message();
424                     try {
425                     msg.line("Found %d of %d UserRoles marked for Deletion in file %s", 
426                         delayedURDeletes,UserRole.getData().size(),deletesFile.getCanonicalPath());
427                 } catch (IOException e) {
428                     msg.line("Found %d of %d UserRoles marked for Deletion.\n", 
429                             delayedURDeletes);
430                 }
431                     msg.line("Review the File.  If data is ok, Use ExpiringP2 BatchProcess to complete the deletions");
432                     
433                     email.msg(msg);
434                     email.exec(trans, org, "Email Support");
435             } else {
436                     urDeleteF.flush();
437                     try {
438                         BufferedReader br = new BufferedReader(new FileReader(deletesFile));
439                         try {
440                             ExpiringP2.deleteURs(noAvg, br, urDelete, null /* don't touch Cache here*/);
441                         } finally {
442                             br.close();
443                         }
444                     } catch (IOException io) {
445                         noAvg.error().log(io);
446                     }
447             }
448         }
449         if (count>0) {
450                 String str = String.format("%d UserRoles modified or deleted", count);
451                 cacheTouch.exec(trans, "user_role", str);
452         }
453         
454         // Run for Creds
455         trans.info().log("Checking for Expired Credentials");
456         System.out.flush();
457         count = 0;
458         try {
459                 CredDAO.Data crd = new CredDAO.Data();
460                 Date last = null;
461                 for ( Cred creds : Cred.data.values()) {
462                 crd.id = creds.id;
463                     for (int type : creds.types()) {
464                     crd.type = type;
465                         for ( Instance inst : creds.instances) {
466                             if (inst.expires.before(tooLate)) {
467                                 crd.expires = inst.expires;
468                                 crDelete.exec(noAvg, crd,"Expired before " + tooLate);
469                             } else if (last==null || inst.expires.after(last)) {
470                                 last = inst.expires;
471                             }
472                         }
473                         if (last!=null) {
474                             if (last.before(future)) {
475                                 crd.expires = last;
476                                 crPrint.exec(noAvg, crd,"");
477                                 ++count;
478                             }
479                         }
480                     }
481                 }
482         } finally {
483                 String str = String.format("Found %d current creds expiring before %s", count, Chrono.dateOnlyStamp(future));
484                 if (count>0) {
485                     cacheTouch.exec(trans, "cred", str);
486                 }
487         }
488         
489     }
490     
491     @Override
492     protected void _close(AuthzTrans trans) {
493         trans.info().log("End",this.getClass().getSimpleName(),"processing" );
494         for (Action<?,?,?> action : new Action<?,?,?>[] {crDelete}) {
495             if (action instanceof ActionDAO) {
496                 ((ActionDAO<?,?,?>)action).close(trans);
497             }
498         }
499         session.close();
500         urDeleteF.close();
501         urRecoverF.close();
502     }
503
504 }