Expire, Remove Batch, restore
[aaf/authz.git] / auth / auth-batch / src / main / java / org / onap / aaf / auth / update / NotifyCredExpiring.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.update;
23
24 import java.io.File;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.PrintStream;
28 import java.text.ParseException;
29 import java.util.ArrayList;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.Date;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Map.Entry;
38 <<<<<<< HEAD
39 =======
40 import java.util.Set;
41 import java.util.TreeMap;
42 >>>>>>> a6baa197... Expire, Remove Batch, restore
43
44 import org.onap.aaf.auth.Batch;
45 import org.onap.aaf.auth.BatchPrincipal;
46 import org.onap.aaf.auth.actions.Email;
47 import org.onap.aaf.auth.actions.EmailPrint;
48 import org.onap.aaf.auth.actions.Message;
49 import org.onap.aaf.auth.dao.cass.CredDAO;
50 import org.onap.aaf.auth.dao.hl.Question;
51 import org.onap.aaf.auth.env.AuthzTrans;
52 import org.onap.aaf.auth.helpers.Cred;
53 import org.onap.aaf.auth.helpers.NS;
54 import org.onap.aaf.auth.helpers.Notification;
55 import org.onap.aaf.auth.helpers.UserRole;
56 import org.onap.aaf.auth.helpers.Notification.TYPE;
57 import org.onap.aaf.auth.layer.Result;
58 import org.onap.aaf.auth.org.EmailWarnings;
59 import org.onap.aaf.auth.org.Organization;
60 import org.onap.aaf.auth.org.OrganizationException;
61 import org.onap.aaf.auth.org.OrganizationFactory;
62 <<<<<<< HEAD
63 import org.onap.aaf.auth.org.Organization.Identity;
64 =======
65 import org.onap.aaf.cadi.CadiException;
66 import org.onap.aaf.cadi.util.CSV;
67 >>>>>>> a6baa197... Expire, Remove Batch, restore
68 import org.onap.aaf.misc.env.APIException;
69 import org.onap.aaf.misc.env.Env;
70 import org.onap.aaf.misc.env.TimeTaken;
71 import org.onap.aaf.misc.env.util.Chrono;
72
73 import java.util.TreeMap;
74
75
76 public class NotifyCredExpiring extends Batch {
77
78     private static final String UNKNOWN_ID = "unknown@deprecated.id";
79     private static final String AAF_INSTANTIATED_MECHID = "AAF INSTANTIATED MECHID";
80     private static final String EXPIRATION_DATE = "EXPIRATION DATE";
81     private static final String QUICK_LINK = "QUICK LINK TO UPDATE PAGE";
82     private static final String DASH_1 = "-----------------------";
83     private static final String DASH_2 = "---------------";
84     private static final String DASH_3 = "----------------------------------------------------";
85     private static final String LINE = "\n----------------------------------------------------------------";
86     private Email email;
87     private int maxEmails;
88     private final PrintStream ps;
89     private final AuthzTrans noAvg;
90     private String supportEmailAddr;
91         private CSV csv;
92         private CSVInfo csvInfo;
93
94     public NotifyCredExpiring(AuthzTrans trans) throws APIException, IOException, OrganizationException {
95         super(trans.env());
96         TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE);
97         try {
98             session = cluster.connect();
99         } finally {
100             tt.done();
101         }
102         
103         noAvg = env.newTransNoAvg();
104         noAvg.setUser(new BatchPrincipal("batch:NotifyCredExpiring"));
105         
106         if (isDryRun()) {
107             email = new EmailPrint();
108             maxEmails=3;
109             maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3"));
110         } else {
111             email = new Email();
112             maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3"));
113         }
114         
115         email.subject("AAF Password Expiration Notification (ENV: %s)",batchEnv);
116         email.preamble("AAF (MOTS 22830) is the AT&T Authorization System used by many AT&T Tools and Applications.\n\n" +
117                 "  The following Credentials are expiring on the dates shown. Failure to act before the expiration date "
118                 + "will cause your App's Authentications to fail.\n");
119         email.signature("Sincerely,\nAAF Team (Our MOTS# 22830)\n"
120                 + "https://wiki.web.att.com/display/aaf/Contact+Us\n"
121                 + "(Use 'Other Misc Requests (TOPS)')");
122         
123         boolean quit = false;
124         if(args().length<1) {
125                 System.err.println("Need CSV formatted Expiring Report");
126                 quit = true;
127         } else {
128                 File f = new File(logDir(),args()[0]);
129                 System.out.println("Reading " + f.getCanonicalPath());
130                 csv = new CSV(f);
131         }
132         
133         if(args().length<2) {
134                 System.err.println("Need Email Template");
135                 //quit = true;
136         }
137         if(quit) {
138                 System.exit(2);
139         }
140         
141         csvInfo = new CSVInfo(System.err);
142         try {
143                         csv.visit(csvInfo);
144                 } catch (CadiException e) {
145                         throw new APIException(e);
146                 }
147         
148         Notification.load(trans, session, Notification.v2_0_18);
149 <<<<<<< HEAD
150         UserRole.load(trans, session, UserRole.v2_0_11);
151 =======
152 >>>>>>> a6baa197... Expire, Remove Batch, restore
153         
154         ps = new PrintStream(new FileOutputStream(logDir() + "/email"+Chrono.dateOnlyStamp()+".log",true));
155         ps.printf("### Approval Notify %s for %s%s\n",Chrono.dateTime(),batchEnv,dryRun?", DryRun":"");
156     }
157     
158     @Override
159     protected void run(AuthzTrans trans) {
160         
161         // Temp structures
162         Map<String,List<LastCred>> ownerCreds = new TreeMap<>();
163         
164
165         List<LastCred> noOwner = new ArrayList<>();
166         ownerCreds.put(UNKNOWN_ID,noOwner);
167         int emailCount=0;
168
169 //        // Get a list of ONLY the ones needing email by Owner
170 //        for (Entry<String, List<Cred>> es : Cred.byNS.entrySet()) {
171 //            for (Cred c : es.getValue()) {
172 //                List<UserRole> ownerURList = UserRole.getByRole().get(es.getKey()+".owner");
173 //                if (ownerURList!=null) {
174 //                    for (UserRole ur:ownerURList) {
175 //                        String owner = ur.user();
176 //                        List<LastCred> llc = ownerCreds.get(owner);
177 //                        if (llc==null) {
178 //                            ownerCreds.put(owner, (llc=new ArrayList<>()));
179 //                        }
180 //                        llc.add(new LastCred(c,last));
181 //                    }
182 //                } else {
183 //                    noOwner.add(new LastCred(c,last));
184 //                }
185 //            }
186 //        }
187 //        
188 //        boolean bCritical,bNormal,bEarly;
189 //        Message msg = new Message();
190 //        Notification ownNotf;
191 //        StringBuilder logMessage = new StringBuilder();
192 //        for (Entry<String,List<LastCred>> es : ownerCreds.entrySet()) {
193 //            String owner = es.getKey();
194 //            boolean header = true;
195 //            try {
196 //                Organization org = OrganizationFactory.obtain(env, owner);
197 //                Identity user = org.getIdentity(noAvg, owner);
198 //                if (!UNKNOWN_ID.equals(owner) && user==null) {
199 //                    ps.printf("Invalid Identity: %s\n", owner);
200 //                } else {
201 //                    logMessage.setLength(0);
202 //                    if (maxEmails>emailCount) {
203 //                        bCritical=bNormal=bEarly = false;
204 //                        email.clear();
205 //                        msg.clear();
206 //                        email.addTo(user==null?supportEmailAddr:user.email());
207 //
208 //                        ownNotf = Notification.get(es.getKey(),TYPE.CN);
209 //                        if (ownNotf==null) {
210 //                            ownNotf = Notification.create(user==null?UNKNOWN_ID:user.fullID(), TYPE.CN);
211 //                        }
212 //                        last = ownNotf.last;
213 //                        // Get Max ID size for formatting purposes
214 //                        int length = AAF_INSTANTIATED_MECHID.length();
215 //                        for (LastCred lc : es.getValue()) {
216 //                            length = Math.max(length, lc.cred.id.length());
217 //                        }
218 //                        String id_exp_fmt = "\t%-"+length+"s  %15s  %s";
219 //
220 //                        Collections.sort(es.getValue(),LastCred.COMPARE);
221 //                        for (LastCred lc : es.getValue()) {
222 //                            if (lc.last.after(must) && lc.last.before(early) && 
223 //                                (ownNotf.last==null || ownNotf.last.before(withinLastWeek))) {
224 //                                if (!bEarly && header) {
225 //                                    msg.line("\tThe following are friendly 2 month reminders, just in case you need to schedule your updates early.  "
226 //                                            + "You will be reminded next month\n");
227 //                                    msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK);
228 //                                    msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3);
229 //                                    header = false;
230 //                                }
231 //                                bEarly = true;
232 //                            } else if (lc.last.after(critical) && lc.last.before(must) && 
233 //                                    (ownNotf.last==null || ownNotf.last.before(withinLastWeek))) {
234 //                                if (!bNormal) {
235 //                                    boolean last2wks = lc.last.before(within2Weeks);
236 //                                    if (last2wks) {
237 //                                        try {
238 //                                            Identity supvsr = user.responsibleTo();
239 //                                            email.addCC(supvsr.email());
240 //                                        } catch (OrganizationException e) {
241 //                                            trans.error().log(e, "Supervisor cannot be looked up");
242 //                                        }
243 //                                    }
244 //                                    if (header) {
245 //                                        msg.line("\tIt is now important for you to update Passwords all all configurations using them for the following.\n" +
246 //                                                (last2wks?"\tNote: Your Supervisor is CCd\n":"\tNote: Your Supervisor will be notified if this is not being done before the last 2 weeks\n"));
247 //                                        msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK);
248 //                                        msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3);
249 //                                    }
250 //                                    header = false;
251 //                                }
252 //                                bNormal=true;
253 //                            } else if (lc.last.after(tooLate) && lc.last.before(critical)) { // Email Every Day, with Supervisor
254 //                                if (!bCritical && header) {
255 //                                    msg.line("\t!!! WARNING: These Credentials will expire in LESS THAN ONE WEEK !!!!\n" +
256 //                                             "\tYour supervisor is added to this Email\n");
257 //                                    msg.line(id_exp_fmt, AAF_INSTANTIATED_MECHID,EXPIRATION_DATE, QUICK_LINK);
258 //                                    msg.line(id_exp_fmt, DASH_1, DASH_2, DASH_3);
259 //                                    header = false;
260 //                                }
261 //                                bCritical = true;
262 //                                try {
263 //                                    if (user!=null) {
264 //                                        Identity supvsr = user.responsibleTo();
265 //                                        if (supvsr!=null) {
266 //                                            email.addCC(supvsr.email());
267 //                                            supvsr = supvsr.responsibleTo();
268 //                                            if (supvsr!=null) {
269 //                                                email.addCC(supvsr.email());
270 //                                            }
271 //                                        }
272 //                                    }
273 //                                } catch (OrganizationException e) {
274 //                                    trans.error().log(e, "Supervisor cannot be looked up");
275 //                                }
276 //                            }
277 //                            if (bEarly || bNormal || bCritical) {
278 //                                if (logMessage.length()==0) {
279 //                                    logMessage.append("NotifyCredExpiring");
280 //                                }
281 //                                logMessage.append("\n\t");
282 //                                logMessage.append(lc.cred.id);
283 //                                logMessage.append('\t');
284 //                                logMessage.append(Chrono.dateOnlyStamp(lc.last));
285 //                                msg.line(id_exp_fmt, lc.cred.id, Chrono.dateOnlyStamp(lc.last)+"     ",env.getProperty(GUI_URL)+"/creddetail?ns="+Question.domain2ns(lc.cred.id));
286 //                            }
287 //                        }
288 //                        
289 //                        if (bEarly || bNormal || bCritical) {
290 //                            msg.line(LINE);
291 //                            msg.line("Why are you receiving this Notification?\n");
292 //                                msg.line("You are the listed owner of one or more AAF Namespaces. ASPR requires that those responsible for "
293 //                                        + "applications and their access review them regularly for accuracy.  The AAF WIKI page for AT&T is https://wiki.web.att.com/display/aaf.  "
294 //                                        + "You might like https://wiki.web.att.com/display/aaf/AAF+in+a+Nutshell.  More detailed info regarding questions of being a Namespace Owner is available at https://wiki.web.att.com/pages/viewpage.action?pageId=594741363\n");
295 //                                msg.line("You may view the Namespaces you listed as Owner for in this AAF Env by viewing the following webpage:\n");
296 //                                msg.line("   %s/ns\n\n",env.getProperty(GUI_URL));
297 //                            email.msg(msg);
298 //                            Result<Void> rv = email.exec(trans, org,"");
299 //                            if (rv.isOK()) {
300 //                                ++emailCount;
301 //                                if (!isDryRun()) {
302 //                                    ownNotf.update(noAvg, session, false);
303 //                                    // SET LastNotification
304 //                                }
305 //                                email.log(ps,logMessage.toString());
306 //                            } else {
307 //                                trans.error().log(rv.errorString());
308 //                            }
309 //                        }
310 //                    }
311 //                }
312 //            } catch (OrganizationException e) {
313 //                trans.info().log(e);
314 //            }
315 //        }
316         trans.info().printf("%d emails sent for %s", emailCount,batchEnv);
317     }
318     
319     
320     private static class CSVInfo implements CSV.Visitor {
321         private PrintStream out;
322         private Set<String> unsupported;
323         private NotifyCredVisitor credv;
324         private List<LastCred> llc;
325         
326         public CSVInfo(PrintStream out) {
327                 this.out = out;
328                 credv = new NotifyCredVisitor(llc = new ArrayList<>());
329         }
330         
331                 @Override
332                 public void visit(List<String> row) throws IOException, CadiException {
333                         
334                         switch(row.get(0)) {
335                            case NotifyCredVisitor.SUPPORTS:
336                                    credv.visit(row);
337                                    break;
338                            default:
339                                    if(unsupported==null) {
340                                            unsupported = new HashSet<String>();
341                                    }
342                                    if(!unsupported.contains(row.get(0))) {
343                                            unsupported.add(row.get(0));
344                                            out.println("Unsupported Type: " + row.get(0));
345                                    }
346                         }
347                 }
348     }
349     
350     private static class Contact {
351         public List<String> contacts;
352                 private List<UserRole> owners;
353         
354         public Contact(final String ns) {
355                 contacts = new ArrayList<>();
356                 loadFromNS(ns);
357         }
358         
359         public void loadFromNS(final String ns) {
360                 owners = UserRole.getByRole().get(ns+".owner");
361         }
362     }
363     
364     private static class LastCred extends Contact {
365         public final String id;
366         public final int type;
367         public final Date expires;
368         
369         public LastCred(final String id, final String ns, final int type, final Date expires) {
370                         super(ns);
371                         this.id = id;
372                         this.type = type;
373                         this.expires = expires;
374                 }
375     }
376     
377     private static class NotifyCredVisitor implements CSV.Visitor {
378         public static final String SUPPORTS = "cred";
379                 private final List<LastCred> lastCred;
380         
381         public NotifyCredVisitor(final List<LastCred> lastCred) {
382                 this.lastCred = lastCred;
383         }
384         
385                 @Override
386                 public void visit(List<String> row) throws IOException, CadiException {
387                          try {
388                                 lastCred.add(new LastCred(
389                                         row.get(1), 
390                                         row.get(2),
391                                         Integer.parseInt(row.get(3)), 
392                                         Chrono.dateOnlyFmt.parse(row.get(4))
393                                         )
394                                 );
395                         } catch (NumberFormatException | ParseException e) {
396                                 throw new CadiException(e);
397                         }
398                 }
399     }
400     
401     @Override
402     protected void _close(AuthzTrans trans) {
403         session.close();
404         ps.close();
405     }
406 }