2 * ============LICENSE_START====================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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====================================================
22 package org.onap.aaf.auth.batch.update;
24 import java.io.BufferedReader;
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;
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;
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;
82 private File deletesFile;
84 public ExpiringOrig(AuthzTrans trans) throws APIException, IOException, OrganizationException {
86 trans.info().log("Starting Connection Process");
88 noAvg = env.newTransNoAvg();
89 noAvg.setUser(new BatchPrincipal("batch:Expiring"));
91 TimeTaken tt0 = trans.start("Cassandra Initialization", Env.SUB);
93 crPrint = new CredPrint("Expired:");
95 TimeTaken tt = trans.start("Connect to Cluster with DAOs", Env.REMOTE);
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);
105 // Reusing... don't destroy
106 apprDAO = urFutureApprove.question().approvalDAO;
107 futureDAO = urFutureApprove.question().futureDAO;
109 TimeTaken tt2 = trans.start("Connect to Cluster", Env.REMOTE);
111 session = urFutureApprove.getSession(trans);
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!!!");
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());
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);
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");
141 throw new APIException("ALERT_TO_ADDRESS property is required");
143 email.addTo(address);
151 protected void run(AuthzTrans trans) {
152 // Setup Date boundaries
154 final GregorianCalendar gc = new GregorianCalendar();
155 final Date now = gc.getTime();
157 gc.add(GregorianCalendar.MONTH, 1);
158 Date future = gc.getTime();
159 // Date earliest = null;
163 gc.add(GregorianCalendar.DAY_OF_MONTH, -7); // save Expired Roles for 7 days.
164 Date tooLate = gc.getTime();
168 // Clean out Approvals UserRoles are fixed up.
170 for (List<Approval> la : Approval.byUser.values()) {
171 for (Approval a : la ) {
173 if (memo!=null && (memo.contains("Re-Approval") || memo.contains("Re-Validate"))) {
174 String role = a.getRole();
176 UserRole ur = UserRole.get(a.getUser(), a.getRole());
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());
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());
194 f.delayedDelete(noAvg, futureDAO, dryRun, "Approvals removed");
201 trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
202 Future.resetLocalData();
203 Approval.resetLocalData();
204 } catch (Exception t) {
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());
217 Result<OP_STATUS> ruf = urFutureApproveExec.exec(noAvg,la,f);
225 f.delayedDelete(noAvg, futureDAO, dryRun,OP_STATUS.L.desc());
226 Approval.delayDelete(noAvg, apprDAO, dryRun, la,OP_STATUS.L.desc());
234 trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
235 Future.resetLocalData();
236 Approval.resetLocalData();
237 } catch (Exception t) {
242 trans.info().log("### Remove Expired on ",Future.data.size(), "Items, or premature ones");
244 String expiredBeforeNow = "Expired before " + tooLate;
245 String expiredAfterFuture = "Expired after " + future;
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);
257 trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
258 Future.resetLocalData();
259 Approval.resetLocalData();
260 } catch (Exception t) {
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) {
272 if (app.getTicket()==null) {
275 f = Future.data.get(app.getTicket());
276 if (Future.pendingDelete(f)) {
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);
287 switch(app.getStatus()) {
290 app.delayDelete(noAvg,apprDAO, isDryRun(), "ticketDeleted");
293 switch(app.getType()) {
295 boolean anOwner=false;
296 String approle = app.getRole();
298 Role role = Role.byName.get(approle);
300 app.delayDelete(noAvg, apprDAO, dryRun, "Role No Longer Exists");
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);
308 for (UserRole ur : lur) {
309 if (ur.user().equals(app.getApprover())) {
318 app.delayDelete(noAvg, apprDAO, dryRun, "No longer Owner");
325 Identity identity = org.getIdentity(noAvg, app.getUser());
326 if (identity==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);
332 if (!app.getApprover().equals(identity.responsibleTo().fullID())) {
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);
339 } catch (OrganizationException e) {
349 trans.info().log("### Removed",Future.sizeForDeletion(),"Future and",Approval.sizeForDeletion(),"Approvals");
350 Future.resetLocalData();
351 Approval.resetLocalData();
352 } catch (Exception t) {
356 int count = 0, deleted=0, delayedURDeletes = 0;
358 // Run for User Roles
359 trans.info().log("Checking for Expired User Roles");
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");
366 ur.delayDelete(noAvg, "Not Part of Organization", dryRun);
371 if (NS.data.get(ur.ns())==null) {
372 ur.delayDelete(noAvg,"Namespace " + ur.ns() + " does not exist.",dryRun);
375 } else if (!Role.byName.containsKey(ur.role())) {
376 ur.delayDelete(noAvg,"Role " + ur.role() + " does not exist.",dryRun);
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)");
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);
387 //trans.logAuditTrail(trans.info());
388 } else if (ur.expires().before(future) && ur.expires().after(now)) {
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());
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) {
406 urFutureApprove.exec(noAvg, ur,"");
411 } catch (OrganizationException e) {
412 env.info().log(e,"Exiting ...");
414 env.info().log("Found",count,"user roles expiring before",future);
415 env.info().log("deleting",deleted,"user roles expiring before",tooLate);
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();
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",
431 msg.line("Review the File. If data is ok, Use ExpiringP2 BatchProcess to complete the deletions");
434 email.exec(trans, org, "Email Support");
438 BufferedReader br = new BufferedReader(new FileReader(deletesFile));
440 ExpiringP2.deleteURs(noAvg, br, urDelete, null /* don't touch Cache here*/);
444 } catch (IOException io) {
445 noAvg.error().log(io);
450 String str = String.format("%d UserRoles modified or deleted", count);
451 cacheTouch.exec(trans, "user_role", str);
455 trans.info().log("Checking for Expired Credentials");
459 CredDAO.Data crd = new CredDAO.Data();
461 for ( Cred creds : Cred.data.values()) {
463 for (int type : creds.types()) {
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)) {
474 if (last.before(future)) {
476 crPrint.exec(noAvg, crd,"");
483 String str = String.format("Found %d current creds expiring before %s", count, Chrono.dateOnlyStamp(future));
485 cacheTouch.exec(trans, "cred", str);
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);