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.update;
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;
37 import java.util.Map.Entry;
41 import java.util.TreeMap;
42 >>>>>>> a6baa197... Expire, Remove Batch, restore
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;
63 import org.onap.aaf.auth.org.Organization.Identity;
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;
73 import java.util.TreeMap;
76 public class NotifyCredExpiring extends Batch {
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----------------------------------------------------------------";
87 private int maxEmails;
88 private final PrintStream ps;
89 private final AuthzTrans noAvg;
90 private String supportEmailAddr;
92 private CSVInfo csvInfo;
94 public NotifyCredExpiring(AuthzTrans trans) throws APIException, IOException, OrganizationException {
96 TimeTaken tt = trans.start("Connect to Cluster", Env.REMOTE);
98 session = cluster.connect();
103 noAvg = env.newTransNoAvg();
104 noAvg.setUser(new BatchPrincipal("batch:NotifyCredExpiring"));
107 email = new EmailPrint();
109 maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3"));
112 maxEmails = Integer.parseInt(trans.getProperty("MAX_EMAILS","3"));
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)')");
123 boolean quit = false;
124 if(args().length<1) {
125 System.err.println("Need CSV formatted Expiring Report");
128 File f = new File(logDir(),args()[0]);
129 System.out.println("Reading " + f.getCanonicalPath());
133 if(args().length<2) {
134 System.err.println("Need Email Template");
141 csvInfo = new CSVInfo(System.err);
144 } catch (CadiException e) {
145 throw new APIException(e);
148 Notification.load(trans, session, Notification.v2_0_18);
150 UserRole.load(trans, session, UserRole.v2_0_11);
152 >>>>>>> a6baa197... Expire, Remove Batch, restore
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":"");
159 protected void run(AuthzTrans trans) {
162 Map<String,List<LastCred>> ownerCreds = new TreeMap<>();
165 List<LastCred> noOwner = new ArrayList<>();
166 ownerCreds.put(UNKNOWN_ID,noOwner);
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);
178 // ownerCreds.put(owner, (llc=new ArrayList<>()));
180 // llc.add(new LastCred(c,last));
183 // noOwner.add(new LastCred(c,last));
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;
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);
201 // logMessage.setLength(0);
202 // if (maxEmails>emailCount) {
203 // bCritical=bNormal=bEarly = false;
206 // email.addTo(user==null?supportEmailAddr:user.email());
208 // ownNotf = Notification.get(es.getKey(),TYPE.CN);
209 // if (ownNotf==null) {
210 // ownNotf = Notification.create(user==null?UNKNOWN_ID:user.fullID(), TYPE.CN);
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());
218 // String id_exp_fmt = "\t%-"+length+"s %15s %s";
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);
232 // } else if (lc.last.after(critical) && lc.last.before(must) &&
233 // (ownNotf.last==null || ownNotf.last.before(withinLastWeek))) {
235 // boolean last2wks = lc.last.before(within2Weeks);
238 // Identity supvsr = user.responsibleTo();
239 // email.addCC(supvsr.email());
240 // } catch (OrganizationException e) {
241 // trans.error().log(e, "Supervisor cannot be looked up");
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);
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);
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());
273 // } catch (OrganizationException e) {
274 // trans.error().log(e, "Supervisor cannot be looked up");
277 // if (bEarly || bNormal || bCritical) {
278 // if (logMessage.length()==0) {
279 // logMessage.append("NotifyCredExpiring");
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));
289 // if (bEarly || bNormal || bCritical) {
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));
298 // Result<Void> rv = email.exec(trans, org,"");
301 // if (!isDryRun()) {
302 // ownNotf.update(noAvg, session, false);
303 // // SET LastNotification
305 // email.log(ps,logMessage.toString());
307 // trans.error().log(rv.errorString());
312 // } catch (OrganizationException e) {
313 // trans.info().log(e);
316 trans.info().printf("%d emails sent for %s", emailCount,batchEnv);
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;
326 public CSVInfo(PrintStream out) {
328 credv = new NotifyCredVisitor(llc = new ArrayList<>());
332 public void visit(List<String> row) throws IOException, CadiException {
335 case NotifyCredVisitor.SUPPORTS:
339 if(unsupported==null) {
340 unsupported = new HashSet<String>();
342 if(!unsupported.contains(row.get(0))) {
343 unsupported.add(row.get(0));
344 out.println("Unsupported Type: " + row.get(0));
350 private static class Contact {
351 public List<String> contacts;
352 private List<UserRole> owners;
354 public Contact(final String ns) {
355 contacts = new ArrayList<>();
359 public void loadFromNS(final String ns) {
360 owners = UserRole.getByRole().get(ns+".owner");
364 private static class LastCred extends Contact {
365 public final String id;
366 public final int type;
367 public final Date expires;
369 public LastCred(final String id, final String ns, final int type, final Date expires) {
373 this.expires = expires;
377 private static class NotifyCredVisitor implements CSV.Visitor {
378 public static final String SUPPORTS = "cred";
379 private final List<LastCred> lastCred;
381 public NotifyCredVisitor(final List<LastCred> lastCred) {
382 this.lastCred = lastCred;
386 public void visit(List<String> row) throws IOException, CadiException {
388 lastCred.add(new LastCred(
391 Integer.parseInt(row.get(3)),
392 Chrono.dateOnlyFmt.parse(row.get(4))
395 } catch (NumberFormatException | ParseException e) {
396 throw new CadiException(e);
402 protected void _close(AuthzTrans trans) {