1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * Copyright © 2017 Amdocs
\r
7 * * ===========================================================================
\r
8 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
9 * * you may not use this file except in compliance with the License.
\r
10 * * You may obtain a copy of the License at
\r
12 * * http://www.apache.org/licenses/LICENSE-2.0
\r
14 * * Unless required by applicable law or agreed to in writing, software
\r
15 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
16 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
17 * * See the License for the specific language governing permissions and
\r
18 * * limitations under the License.
\r
19 * * ============LICENSE_END====================================================
\r
21 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
23 ******************************************************************************/
\r
24 package com.att.cadi.cm;
\r
26 import java.io.BufferedReader;
\r
27 import java.io.File;
\r
28 import java.io.FileInputStream;
\r
29 import java.io.FileOutputStream;
\r
30 import java.io.IOException;
\r
31 import java.io.InputStreamReader;
\r
32 import java.net.InetAddress;
\r
33 import java.net.UnknownHostException;
\r
34 import java.security.KeyStore;
\r
35 import java.security.cert.X509Certificate;
\r
36 import java.util.ArrayDeque;
\r
37 import java.util.Deque;
\r
38 import java.util.GregorianCalendar;
\r
39 import java.util.HashMap;
\r
40 import java.util.Iterator;
\r
41 import java.util.Map;
\r
42 import java.util.Map.Entry;
\r
43 import java.util.Properties;
\r
45 import com.att.cadi.Access;
\r
46 import com.att.cadi.Symm;
\r
47 import com.att.cadi.aaf.client.ErrMessage;
\r
48 import com.att.cadi.aaf.v2_0.AAFCon;
\r
49 import com.att.cadi.aaf.v2_0.AAFConHttp;
\r
50 import com.att.cadi.client.EnvAccess;
\r
51 import com.att.cadi.client.Future;
\r
52 import com.att.cadi.config.Config;
\r
53 import com.att.cadi.http.HBasicAuthSS;
\r
54 import com.att.inno.env.Data.TYPE;
\r
55 import com.att.inno.env.Env;
\r
56 import com.att.inno.env.TimeTaken;
\r
57 import com.att.inno.env.Trans;
\r
58 import com.att.inno.env.util.Chrono;
\r
59 import com.att.inno.env.util.Split;
\r
60 import com.att.rosetta.env.RosettaDF;
\r
61 import com.att.rosetta.env.RosettaEnv;
\r
63 import certman.v1_0.Artifacts;
\r
64 import certman.v1_0.Artifacts.Artifact;
\r
65 import certman.v1_0.CertInfo;
\r
66 import certman.v1_0.CertificateRequest;
\r
68 public class CmAgent {
\r
69 private static final String PRINT = "print";
\r
70 private static final String FILE = "file";
\r
71 private static final String PKCS12 = "pkcs12";
\r
72 private static final String JKS = "jks";
\r
73 private static final String SCRIPT="script";
\r
75 private static final String CM_VER = "1.0";
\r
76 public static final int PASS_SIZE = 24;
\r
77 private static int TIMEOUT;
\r
79 private static MyConsole cons;
\r
81 private static RosettaDF<CertificateRequest> reqDF;
\r
82 private static RosettaDF<CertInfo> certDF;
\r
83 private static RosettaDF<Artifacts> artifactsDF;
\r
84 private static ErrMessage errMsg;
\r
85 private static Map<String,PlaceArtifact> placeArtifact;
\r
86 private static RosettaEnv env;
\r
88 public static void main(String[] args) {
\r
90 env = new RosettaEnv(Config.CADI_PROP_FILES,args);
\r
91 Deque<String> cmds = new ArrayDeque<String>();
\r
92 for(String p : args) {
\r
93 if(p.indexOf('=')<0) {
\r
98 if(cmds.size()==0) {
\r
99 System.out.println("Usage: java -jar <cadi-aaf-*-full.jar> cmd [<tag=value>]*");
\r
100 System.out.println(" create <mechID> [<machine>]");
\r
101 System.out.println(" read <mechID> [<machine>]");
\r
102 System.out.println(" update <mechID> [<machine>]");
\r
103 System.out.println(" delete <mechID> [<machine>]");
\r
104 System.out.println(" copy <mechID> <machine> <newmachine>[,<newmachine>]*");
\r
105 System.out.println(" place <mechID> [<machine>]");
\r
106 System.out.println(" showpass <mechID> [<machine>]");
\r
107 System.out.println(" check <mechID> [<machine>]");
\r
111 TIMEOUT = Integer.parseInt(env.getProperty(Config.AAF_CONN_TIMEOUT, "5000"));
\r
112 cons = TheConsole.implemented()?new TheConsole():new SubStandardConsole();
\r
115 reqDF = env.newDataFactory(CertificateRequest.class);
\r
116 artifactsDF = env.newDataFactory(Artifacts.class);
\r
117 certDF = env.newDataFactory(CertInfo.class);
\r
118 errMsg = new ErrMessage(env);
\r
120 placeArtifact = new HashMap<String,PlaceArtifact>();
\r
121 placeArtifact.put(JKS, new PlaceArtifactInKeystore(JKS));
\r
122 placeArtifact.put(PKCS12, new PlaceArtifactInKeystore(PKCS12));
\r
123 placeArtifact.put(FILE, new PlaceArtifactInFiles());
\r
124 placeArtifact.put(PRINT, new PlaceArtifactOnStream(System.out));
\r
125 placeArtifact.put(SCRIPT, new PlaceArtifactScripts());
\r
127 Access access = new EnvAccess(env);
\r
128 Trans trans = env.newTrans();
\r
130 getProperty(env,false, Config.CM_URL,Config.CM_URL+": ");
\r
131 String str=env.getProperty(Config.CADI_ALIAS);
\r
132 if(str==null) { // ask for MechID pass
\r
133 getProperty(env,false,Config.AAF_MECHID,"Your Identity: ");
\r
134 getProperty(env,true,Config.AAF_MECHPASS,"Password: ");
\r
136 AAFCon<?> aafcon = new AAFConHttp(access,Config.CM_URL);
\r
138 String cmd = cmds.removeFirst();
\r
139 if("place".equals(cmd)) {
\r
140 placeCerts(trans,aafcon,cmds);
\r
141 } else if("create".equals(cmd)) {
\r
142 createArtifact(trans, aafcon,cmds);
\r
143 } else if("read".equals(cmd)) {
\r
144 readArtifact(trans, aafcon, cmds);
\r
145 } else if("copy".equals(cmd)) {
\r
146 copyArtifact(trans, aafcon, cmds);
\r
147 } else if("update".equals(cmd)) {
\r
148 updateArtifact(trans, aafcon, cmds);
\r
149 } else if("delete".equals(cmd)) {
\r
150 deleteArtifact(trans, aafcon, cmds);
\r
151 } else if("showpass".equals(cmd)) {
\r
152 showPass(trans,aafcon,cmds);
\r
153 } else if("check".equals(cmd)) {
\r
155 exitCode = check(trans,aafcon,cmds);
\r
156 } catch (Exception e) {
\r
161 cons.printf("Unknown command \"%s\"\n", cmd);
\r
164 StringBuilder sb = new StringBuilder();
\r
165 trans.auditTrail(4, sb, Trans.REMOTE);
\r
166 if(sb.length()>0) {
\r
167 trans.info().log("Trans Info\n",sb);
\r
170 } catch (Exception e) {
\r
171 e.printStackTrace();
\r
174 System.exit(exitCode);
\r
178 private static String getProperty(Env env, boolean secure, String tag, String prompt, Object ... def) {
\r
180 if((value=env.getProperty(tag))==null) {
\r
182 value = new String(cons.readPassword(prompt, def));
\r
184 value = cons.readLine(prompt,def).trim();
\r
187 if(value.length()>0) {
\r
188 env.setProperty(tag,value);
\r
189 } else if(def.length==1) {
\r
190 value=def[0].toString();
\r
191 env.setProperty(tag,value);
\r
198 private interface MyConsole {
\r
199 public String readLine(String fmt, Object ... args);
\r
200 public char[] readPassword(String fmt, Object ... args);
\r
201 public void printf(String fmt, Object ...args);
\r
204 private static class TheConsole implements MyConsole {
\r
206 public String readLine(String fmt, Object... args) {
\r
207 String rv = System.console().readLine(fmt, args);
\r
208 if(args.length>0 && args[0]!=null && rv.length()==0) {
\r
209 rv = args[0].toString();
\r
215 public char[] readPassword(String fmt, Object... args) {
\r
216 return System.console().readPassword(fmt, args);
\r
219 public static boolean implemented() {
\r
220 return System.console()!=null;
\r
224 public void printf(String fmt, Object... args) {
\r
225 System.console().printf(fmt, args);
\r
229 // Substandard, because System.in doesn't do Passwords..
\r
230 private static class SubStandardConsole implements MyConsole {
\r
231 BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
\r
233 public String readLine(String fmt, Object... args) {
\r
236 System.out.printf(fmt,args);
\r
237 rv = br.readLine();
\r
238 if(args.length==1 && rv.length()==0) {
\r
239 rv = args[0].toString();
\r
241 } catch (IOException e) {
\r
242 System.err.println("uh oh...");
\r
249 public char[] readPassword(String fmt, Object... args) {
\r
251 System.out.printf(fmt,args);
\r
252 return br.readLine().toCharArray();
\r
253 } catch (IOException e) {
\r
254 System.err.println("uh oh...");
\r
255 return new char[0];
\r
260 public void printf(String fmt, Object... args) {
\r
261 System.out.printf(fmt, args);
\r
265 // private static class AutoData implements MyConsole {
\r
266 //// private Env env;
\r
267 // private Map<String,String> data;
\r
270 // public String readLine(String fmt, Object... args) {
\r
271 // String rv=data.get(fmt);
\r
272 // return rv==null?"":rv;
\r
276 // public char[] readPassword(String fmt, Object... args) {
\r
277 // String rv=data.get(fmt);
\r
278 // return rv==null?new char[0]:rv.toCharArray();
\r
282 // public void printf(String fmt, Object... args) {
\r
283 // System.out.printf(fmt, args);
\r
288 private static String mechID(Deque<String> cmds) {
\r
289 if(cmds.size()<1) {
\r
290 String alias = env.getProperty(Config.CADI_ALIAS);
\r
291 return alias!=null?alias:cons.readLine("MechID: ");
\r
293 return cmds.removeFirst();
\r
296 private static String machine(Deque<String> cmds) throws UnknownHostException {
\r
297 if(cmds.size()>0) {
\r
298 return cmds.removeFirst();
\r
300 String mach = env.getProperty(Config.HOSTNAME);
\r
301 return mach!=null?mach:InetAddress.getLocalHost().getHostName();
\r
305 private static String[] machines(Deque<String> cmds) {
\r
307 if(cmds.size()>0) {
\r
308 machines = cmds.removeFirst();
\r
310 machines = cons.readLine("Machines (sep by ','): ");
\r
312 return Split.split(',', machines);
\r
315 private static void createArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
316 String mechID = mechID(cmds);
\r
317 String machine = machine(cmds);
\r
319 Artifacts artifacts = new Artifacts();
\r
320 Artifact arti = new Artifact();
\r
321 artifacts.getArtifact().add(arti);
\r
322 arti.setMechid(mechID!=null?mechID:cons.readLine("MechID: "));
\r
323 arti.setMachine(machine!=null?machine:cons.readLine("Machine (%s): ",InetAddress.getLocalHost().getHostName()));
\r
324 arti.setCa(cons.readLine("CA: (%s): ","aaf"));
\r
326 String resp = cons.readLine("Types [file,jks,pkcs12] (%s): ", "jks");
\r
327 for(String s : Split.splitTrim(',', resp)) {
\r
328 arti.getType().add(s);
\r
330 // Always do Script
\r
331 if(!resp.contains(SCRIPT)) {
\r
332 arti.getType().add(SCRIPT);
\r
335 // Note: Sponsor is set on Creation by CM
\r
336 String configRootName = AAFCon.reverseDomain(arti.getMechid());
\r
337 arti.setAppName(cons.readLine("AppName (%s): ",configRootName));
\r
338 arti.setDir(cons.readLine("Directory (%s): ", System.getProperty("user.dir")));
\r
339 arti.setOsUser(cons.readLine("OS User (%s): ", System.getProperty("user.name")));
\r
340 arti.setRenewDays(Integer.parseInt(cons.readLine("Renewal Days (%s):", "30")));
\r
341 arti.setNotification(toNotification(cons.readLine("Notification (mailto owner):", "")));
\r
343 TimeTaken tt = trans.start("Create Artifact", Env.REMOTE);
\r
345 Future<Artifacts> future = aafcon.client(CM_VER).create("/cert/artifacts", artifactsDF, artifacts);
\r
346 if(future.get(TIMEOUT)) {
\r
347 trans.info().printf("Call to AAF Certman successful %s, %s",arti.getMechid(), arti.getMachine());
\r
349 trans.error().printf("Call to AAF Certman failed, %s",
\r
350 errMsg.toMsg(future));
\r
357 private static String toNotification(String notification) {
\r
358 if(notification==null) {
\r
360 } else if(notification.length()>0) {
\r
361 if(notification.indexOf(':')<0) {
\r
362 notification = "mailto:" + notification;
\r
365 return notification;
\r
369 private static void readArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
370 String mechID = mechID(cmds);
\r
371 String machine = machine(cmds);
\r
373 TimeTaken tt = trans.start("Read Artifact", Env.SUB);
\r
375 Future<Artifacts> future = aafcon.client(CM_VER)
\r
376 .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
\r
378 if(future.get(TIMEOUT)) {
\r
379 boolean printed = false;
\r
380 for(Artifact a : future.value.getArtifact()) {
\r
381 cons.printf("MechID: %s\n",a.getMechid());
\r
382 cons.printf(" Sponsor: %s\n",a.getSponsor());
\r
383 cons.printf("Machine: %s\n",a.getMachine());
\r
384 cons.printf("CA: %s\n",a.getCa());
\r
385 StringBuilder sb = new StringBuilder();
\r
386 boolean first = true;
\r
387 for(String t : a.getType()) {
\r
388 if(first) {first=false;}
\r
389 else{sb.append(',');}
\r
392 cons.printf("Types: %s\n",sb);
\r
393 cons.printf("AppName: %s\n",a.getAppName());
\r
394 cons.printf("Directory: %s\n",a.getDir());
\r
395 cons.printf("O/S User: %s\n",a.getOsUser());
\r
396 cons.printf("Renew Days: %d\n",a.getRenewDays());
\r
397 cons.printf("Notification %s\n",a.getNotification());
\r
401 cons.printf("Artifact for %s %s does not exist", mechID, machine);
\r
404 trans.error().log(errMsg.toMsg(future));
\r
411 private static void copyArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
412 String mechID = mechID(cmds);
\r
413 String machine = machine(cmds);
\r
414 String[] newmachs = machines(cmds);
\r
415 if(newmachs==null || newmachs == null) {
\r
416 trans.error().log("No machines listed to copy to");
\r
418 TimeTaken tt = trans.start("Copy Artifact", Env.REMOTE);
\r
420 Future<Artifacts> future = aafcon.client(CM_VER)
\r
421 .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
\r
423 if(future.get(TIMEOUT)) {
\r
424 boolean printed = false;
\r
425 for(Artifact a : future.value.getArtifact()) {
\r
426 for(String m : newmachs) {
\r
428 Future<Artifacts> fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, future.value);
\r
429 if(fup.get(TIMEOUT)) {
\r
430 trans.info().printf("Copy of %s %s successful to %s",mechID,machine,m);
\r
432 trans.error().printf("Call to AAF Certman failed, %s",
\r
433 errMsg.toMsg(fup));
\r
440 cons.printf("Artifact for %s %s does not exist", mechID, machine);
\r
443 trans.error().log(errMsg.toMsg(future));
\r
451 private static void updateArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
452 String mechID = mechID(cmds);
\r
453 String machine = machine(cmds);
\r
455 TimeTaken tt = trans.start("Update Artifact", Env.REMOTE);
\r
457 Future<Artifacts> fread = aafcon.client(CM_VER)
\r
458 .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
\r
460 if(fread.get(TIMEOUT)) {
\r
461 Artifacts artifacts = new Artifacts();
\r
462 for(Artifact a : fread.value.getArtifact()) {
\r
463 Artifact arti = new Artifact();
\r
464 artifacts.getArtifact().add(arti);
\r
466 cons.printf("For %s on %s\n", a.getMechid(),a.getMachine());
\r
467 arti.setMechid(a.getMechid());
\r
468 arti.setMachine(a.getMachine());
\r
469 arti.setCa(cons.readLine("CA: (%s): ",a.getCa()));
\r
470 StringBuilder sb = new StringBuilder();
\r
471 boolean first = true;
\r
472 for(String t : a.getType()) {
\r
473 if(first) {first=false;}
\r
474 else{sb.append(',');}
\r
478 String resp = cons.readLine("Types [file,jks,pkcs12] (%s): ", sb);
\r
479 for(String s : Split.splitTrim(',', resp)) {
\r
480 arti.getType().add(s);
\r
482 // Always do Script
\r
483 if(!resp.contains(SCRIPT)) {
\r
484 arti.getType().add(SCRIPT);
\r
487 // Note: Sponsor is set on Creation by CM
\r
488 arti.setAppName(cons.readLine("AppName (%s): ",a.getAppName()));
\r
489 arti.setDir(cons.readLine("Directory (%s): ", a.getDir()));
\r
490 arti.setOsUser(cons.readLine("OS User (%s): ", a.getOsUser()));
\r
491 arti.setRenewDays(Integer.parseInt(cons.readLine("Renew Days (%s):", a.getRenewDays())));
\r
492 arti.setNotification(toNotification(cons.readLine("Notification (%s):", a.getNotification())));
\r
495 if(artifacts.getArtifact().size()==0) {
\r
496 cons.printf("Artifact for %s %s does not exist", mechID, machine);
\r
498 Future<Artifacts> fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, artifacts);
\r
499 if(fup.get(TIMEOUT)) {
\r
500 trans.info().printf("Call to AAF Certman successful %s, %s",mechID,machine);
\r
502 trans.error().printf("Call to AAF Certman failed, %s",
\r
503 errMsg.toMsg(fup));
\r
507 trans.error().printf("Call to AAF Certman failed, %s %s, %s",
\r
508 errMsg.toMsg(fread),mechID,machine);
\r
515 private static void deleteArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
516 String mechid = mechID(cmds);
\r
517 String machine = mechID(cmds);
\r
519 TimeTaken tt = trans.start("Delete Artifact", Env.REMOTE);
\r
521 Future<Void> future = aafcon.client(CM_VER)
\r
522 .delete("/cert/artifacts/"+mechid+"/"+machine,"application/json" );
\r
524 if(future.get(TIMEOUT)) {
\r
525 trans.info().printf("Call to AAF Certman successful %s, %s",mechid,machine);
\r
527 trans.error().printf("Call to AAF Certman failed, %s %s, %s",
\r
528 errMsg.toMsg(future),mechid,machine);
\r
537 private static boolean placeCerts(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
538 boolean rv = false;
\r
539 String mechID = mechID(cmds);
\r
540 String machine = machine(cmds);
\r
542 TimeTaken tt = trans.start("Place Artifact", Env.REMOTE);
\r
544 Future<Artifacts> acf = aafcon.client(CM_VER)
\r
545 .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
\r
546 if(acf.get(TIMEOUT)) {
\r
547 // Have to wait for JDK 1.7 source...
\r
548 //switch(artifact.getType()) {
\r
549 if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) {
\r
550 cons.printf("There are no artifacts for %s %s", mechID, machine);
\r
552 for(Artifact a : acf.value.getArtifact()) {
\r
553 CertificateRequest cr = new CertificateRequest();
\r
554 cr.setMechid(a.getMechid());
\r
555 cr.setSponsor(a.getSponsor());
\r
556 cr.getFqdns().add(a.getMachine());
\r
557 Future<String> f = aafcon.client(CM_VER)
\r
558 .setQueryParams("withTrust")
\r
559 .updateRespondString("/cert/" + a.getCa(),reqDF, cr);
\r
560 if(f.get(TIMEOUT)) {
\r
561 CertInfo capi = certDF.newData().in(TYPE.JSON).load(f.body()).asObject();
\r
562 for(String type : a.getType()) {
\r
563 PlaceArtifact pa = placeArtifact.get(type);
\r
565 if(rv = pa.place(trans, capi, a)) {
\r
566 notifyPlaced(a,rv);
\r
570 // Cover for the above multiple pass possibilities with some static Data, then clear per Artifact
\r
571 ArtifactDir.clear();
\r
573 trans.error().log(errMsg.toMsg(f));
\r
578 trans.error().log(errMsg.toMsg(acf));
\r
586 private static void notifyPlaced(Artifact a, boolean rv) {
\r
591 private static void showPass(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
592 String mechID = mechID(cmds);
\r
593 String machine = machine(cmds);
\r
595 TimeTaken tt = trans.start("Show Password", Env.REMOTE);
\r
597 Future<Artifacts> acf = aafcon.client(CM_VER)
\r
598 .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
\r
599 if(acf.get(TIMEOUT)) {
\r
600 // Have to wait for JDK 1.7 source...
\r
601 //switch(artifact.getType()) {
\r
602 if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) {
\r
603 cons.printf("No Artifacts found for %s on %s", mechID, machine);
\r
605 String id = aafcon.defID();
\r
607 for(Artifact a : acf.value.getArtifact()) {
\r
608 allowed = id!=null && (id.equals(a.getSponsor()) ||
\r
609 (id.equals(a.getMechid())
\r
610 && aafcon.securityInfo().defSS.getClass().isAssignableFrom(HBasicAuthSS.class)));
\r
612 Future<String> pf = aafcon.client(CM_VER).read("/cert/may/" +
\r
613 a.getAppName() + ".certman|"+a.getCa()+"|showpass","*/*");
\r
614 if(pf.get(TIMEOUT)) {
\r
617 trans.error().log(errMsg.toMsg(pf));
\r
621 File dir = new File(a.getDir());
\r
622 Properties props = new Properties();
\r
623 FileInputStream fis = new FileInputStream(new File(dir,a.getAppName()+".props"));
\r
627 fis = new FileInputStream(new File(dir,a.getAppName()+".chal"));
\r
633 File f = new File(dir,a.getAppName()+".keyfile");
\r
635 Symm symm = Symm.obtain(f);
\r
637 for(Iterator<Entry<Object,Object>> iter = props.entrySet().iterator(); iter.hasNext();) {
\r
638 Entry<Object,Object> en = iter.next();
\r
639 if(en.getValue().toString().startsWith("enc:???")) {
\r
640 System.out.printf("%s=%s\n", en.getKey(), symm.depass(en.getValue().toString()));
\r
644 trans.error().printf("%s.keyfile must exist to read passwords for %s on %s",
\r
645 f.getCanonicalPath(),a.getMechid(), a.getMachine());
\r
651 trans.error().log(errMsg.toMsg(acf));
\r
661 * Check returns Error Codes, so that Scripts can know what to do
\r
663 * 0 - Check Complete, nothing to do
\r
664 * 1 - General Error
\r
665 * 2 - Error for specific Artifact - read check.msg
\r
666 * 10 - Certificate Updated - check.msg is email content
\r
672 * @throws Exception
\r
674 private static int check(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
\r
676 String mechID = mechID(cmds);
\r
677 String machine = machine(cmds);
\r
679 TimeTaken tt = trans.start("Check Certificate", Env.REMOTE);
\r
682 Future<Artifacts> acf = aafcon.client(CM_VER)
\r
683 .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
\r
684 if(acf.get(TIMEOUT)) {
\r
685 // Have to wait for JDK 1.7 source...
\r
686 //switch(artifact.getType()) {
\r
687 if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) {
\r
688 cons.printf("No Artifacts found for %s on %s", mechID, machine);
\r
690 String id = aafcon.defID();
\r
691 GregorianCalendar now = new GregorianCalendar();
\r
692 for(Artifact a : acf.value.getArtifact()) {
\r
693 if(id.equals(a.getMechid())) {
\r
694 File dir = new File(a.getDir());
\r
695 Properties props = new Properties();
\r
696 FileInputStream fis = new FileInputStream(new File(dir,a.getAppName()+".props"));
\r
706 if((prop=props.getProperty(Config.CADI_KEYFILE))==null ||
\r
707 !(f=new File(prop)).exists()) {
\r
708 trans.error().printf("Keyfile must exist to check Certificates for %s on %s",
\r
709 a.getMechid(), a.getMachine());
\r
711 String ksf = props.getProperty(Config.CADI_KEYSTORE);
\r
712 String ksps = props.getProperty(Config.CADI_KEYSTORE_PASSWORD);
\r
713 if(ksf==null || ksps == null) {
\r
714 trans.error().printf("Properties %s and %s must exist to check Certificates for %s on %s",
\r
715 Config.CADI_KEYSTORE, Config.CADI_KEYSTORE_PASSWORD,a.getMechid(), a.getMachine());
\r
717 KeyStore ks = KeyStore.getInstance("JKS");
\r
718 Symm symm = Symm.obtain(f);
\r
720 fis = new FileInputStream(ksf);
\r
722 ks.load(fis,symm.depass(ksps).toCharArray());
\r
726 X509Certificate cert = (X509Certificate)ks.getCertificate(mechID);
\r
730 msg = String.format("X509Certificate does not exist for %s on %s in %s",
\r
731 a.getMechid(), a.getMachine(), ksf);
\r
732 trans.error().log(msg);
\r
735 GregorianCalendar renew = new GregorianCalendar();
\r
736 renew.setTime(cert.getNotAfter());
\r
737 renew.add(GregorianCalendar.DAY_OF_MONTH,-1*a.getRenewDays());
\r
738 if(renew.after(now)) {
\r
739 msg = String.format("As of %s, X509Certificate for %s on %s, expiration %s is still within %d renewal days.\n",
\r
740 Chrono.dateOnlyStamp(), a.getMechid(), a.getMachine(), cert.getNotAfter(),a.getRenewDays());
\r
741 trans.info().log(msg);
\r
742 exitCode = 0; // OK
\r
744 trans.info().printf("X509Certificate for %s on %s expiration, %s, needs Renewal.\n",
\r
745 a.getMechid(), a.getMachine(),cert.getNotAfter());
\r
746 cmds.offerLast(mechID);
\r
747 cmds.offerLast(machine);
\r
748 if(placeCerts(trans,aafcon,cmds)) {
\r
749 msg = String.format("X509Certificate for %s on %s has been renewed. Ensure services using are refreshed.\n",
\r
750 a.getMechid(), a.getMachine());
\r
751 exitCode = 10; // Refreshed
\r
753 msg = String.format("X509Certificate for %s on %s attempted renewal, but failed. Immediate Investigation is required!\n",
\r
754 a.getMechid(), a.getMachine());
\r
755 exitCode = 1; // Error Renewing
\r
760 FileOutputStream fos = new FileOutputStream(a.getDir()+'/'+a.getAppName()+".msg");
\r
762 fos.write(msg.getBytes());
\r
774 trans.error().log(errMsg.toMsg(acf));
\r