Refine Agent to create CADI Configs
[aaf/authz.git] / cadi / aaf / src / main / java / org / onap / aaf / cadi / cm / CmAgent.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.cadi.cm;
23
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileOutputStream;
27 import java.io.PrintStream;
28 import java.net.ConnectException;
29 import java.net.InetAddress;
30 import java.net.UnknownHostException;
31 import java.nio.file.Files;
32 import java.security.KeyStore;
33 import java.security.cert.X509Certificate;
34 import java.util.ArrayDeque;
35 import java.util.Date;
36 import java.util.Deque;
37 import java.util.GregorianCalendar;
38 import java.util.HashMap;
39 import java.util.Iterator;
40 import java.util.Map;
41 import java.util.Map.Entry;
42 import java.util.Properties;
43
44 import org.onap.aaf.cadi.CadiException;
45 import org.onap.aaf.cadi.CmdLine;
46 import org.onap.aaf.cadi.LocatorException;
47 import org.onap.aaf.cadi.PropAccess;
48 import org.onap.aaf.cadi.Symm;
49 import org.onap.aaf.cadi.aaf.client.ErrMessage;
50 import org.onap.aaf.cadi.aaf.v2_0.AAFCon;
51 import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp;
52 import org.onap.aaf.cadi.client.Future;
53 import org.onap.aaf.cadi.client.Rcli;
54 import org.onap.aaf.cadi.client.Retryable;
55 import org.onap.aaf.cadi.config.Config;
56 import org.onap.aaf.cadi.http.HBasicAuthSS;
57 import org.onap.aaf.cadi.locator.SingleEndpointLocator;
58 import org.onap.aaf.cadi.sso.AAFSSO;
59 import org.onap.aaf.cadi.util.FQI;
60 import org.onap.aaf.misc.env.APIException;
61 import org.onap.aaf.misc.env.Data.TYPE;
62 import org.onap.aaf.misc.env.Env;
63 import org.onap.aaf.misc.env.TimeTaken;
64 import org.onap.aaf.misc.env.Trans;
65 import org.onap.aaf.misc.env.util.Chrono;
66 import org.onap.aaf.misc.env.util.Split;
67 import org.onap.aaf.misc.rosetta.env.RosettaDF;
68 import org.onap.aaf.misc.rosetta.env.RosettaEnv;
69
70 import aaf.v2_0.Perm;
71 import aaf.v2_0.Perms;
72 import certman.v1_0.Artifacts;
73 import certman.v1_0.Artifacts.Artifact;
74 import certman.v1_0.CertInfo;
75 import certman.v1_0.CertificateRequest;
76 import locate.v1_1.Configuration;
77 import locate.v1_1.Configuration.Props;
78
79 public class CmAgent {
80         private static final String HASHES = "######################";
81         private static final String PRINT = "print";
82         private static final String FILE = "file";
83         private static final String PKCS12 = "pkcs12";
84         private static final String JKS = "jks";
85         private static final String SCRIPT="script";
86         
87         private static final String CM_VER = "1.0";
88         public static final int PASS_SIZE = 24;
89         private static int TIMEOUT;
90         
91         private static RosettaDF<CertificateRequest> reqDF;
92         private static RosettaDF<CertInfo> certDF;
93         private static RosettaDF<Artifacts> artifactsDF;
94         private static RosettaDF<Configuration> configDF;
95         private static RosettaDF<Perms> permDF;
96         private static ErrMessage errMsg;
97         private static Map<String,PlaceArtifact> placeArtifact;
98         private static RosettaEnv env;
99         
100         private static boolean doExit;
101
102         public static void main(String[] args) {
103                 int exitCode = 0;
104                 doExit = true;
105                 try {
106                         AAFSSO aafsso = new AAFSSO(args, new AAFSSO.ProcessArgs() {
107                                 @Override
108                                 public Properties process(String[] args, Properties props) {
109                                         if(args.length>1) {
110                                                 if(args[0].equals("validate")) {
111                                                         props.put(Config.CADI_PROP_FILES, args[1]);
112                                                 } else if (!args[0].equals("genkeypair")) {
113                                                         props.put("aaf_id", args[1]);
114                                                 }       
115                                         }
116                                         return props;
117                                 }
118                         });
119                         if(aafsso.loginOnly()) {
120                                 aafsso.setLogDefault();
121                                 aafsso.writeFiles();
122                                 System.out.println("AAF SSO information created in ~/.aaf");
123                         } else {
124                                 PropAccess access = aafsso.access();
125                                 env = new RosettaEnv(access.getProperties());
126                                 Deque<String> cmds = new ArrayDeque<String>();
127                                 for(String p : args) {
128                                         if("-noexit".equalsIgnoreCase(p)) {
129                                                 doExit = false;
130                                         } else if(p.indexOf('=') < 0) {
131                                                 cmds.add(p);
132                                         }
133                                 }
134                                 
135                                 if(cmds.size()==0) {
136                                         aafsso.setLogDefault();
137                                         // NOTE: CHANGE IN CMDS should be reflected in AAFSSO constructor, to get FQI->aaf-id or not
138                                         System.out.println("Usage: java -jar <cadi-aaf-*-full.jar> cmd [<tag=value>]*");
139                                         System.out.println("   create   <FQI> [<machine>]");
140                                         System.out.println("   read     <FQI> [<machine>]");
141                                         System.out.println("   update   <FQI> [<machine>]");
142                                         System.out.println("   delete   <FQI> [<machine>]");
143                                         System.out.println("   copy     <FQI> <machine> <newmachine>[,<newmachine>]*");
144                                         System.out.println("   place    <FQI> [<machine>]");
145                                         System.out.println("   showpass <FQI> [<machine>]");
146                                         System.out.println("   check    <FQI> [<machine>]");
147                                         System.out.println("   config   <FQI>");
148                                         System.out.println("   validate <cadi.props>");
149                                         System.out.println("   genkeypair");
150                                         if (doExit) {
151                                                 System.exit(1);
152                                         }
153                                 }
154                                 
155                                 TIMEOUT = Integer.parseInt(env.getProperty(Config.AAF_CONN_TIMEOUT, "5000"));
156                         
157                                 reqDF = env.newDataFactory(CertificateRequest.class);
158                                 artifactsDF = env.newDataFactory(Artifacts.class);
159                                 certDF = env.newDataFactory(CertInfo.class);
160                                 configDF = env.newDataFactory(Configuration.class);
161                                 permDF = env.newDataFactory(Perms.class);
162                                 errMsg = new ErrMessage(env);
163         
164                                 placeArtifact = new HashMap<String,PlaceArtifact>();
165                                 placeArtifact.put(JKS, new PlaceArtifactInKeystore(JKS));
166                                 placeArtifact.put(PKCS12, new PlaceArtifactInKeystore(PKCS12));
167                                 placeArtifact.put(FILE, new PlaceArtifactInFiles());
168                                 placeArtifact.put(PRINT, new PlaceArtifactOnStream(System.out));
169                                 placeArtifact.put(SCRIPT, new PlaceArtifactScripts());
170                                 
171                                 Trans trans = env.newTrans();
172                                 String token;
173                                 if((token=access.getProperty("oauth_token"))!=null) {
174                                         trans.setProperty("oauth_token", token);
175                                 }
176                                 try {
177                                         // show Std out again
178                                         aafsso.setLogDefault();
179                                         aafsso.setStdErrDefault();
180                                         
181                                         // if CM_URL can be obtained, add to sso.props, if written
182                                         String cm_url = getProperty(access,env,false, Config.CM_URL,Config.CM_URL+": ");
183                                         if(cm_url!=null) {
184                                                 aafsso.addProp(Config.CM_URL, cm_url);
185                                         }
186                                         aafsso.writeFiles();
187
188                                         AAFCon<?> aafcon = new AAFConHttp(access,Config.CM_URL);
189
190                                         String cmd = cmds.removeFirst();
191                                         switch(cmd) {
192                                                 case "place":
193                                                         placeCerts(trans,aafcon,cmds);
194                                                         break;
195                                                 case "create":
196                                                         createArtifact(trans, aafcon,cmds);
197                                                         break;
198                                                 case "read":
199                                                         readArtifact(trans, aafcon, cmds);
200                                                         break;
201                                                 case "copy":
202                                                         copyArtifact(trans, aafcon, cmds);
203                                                         break;
204                                                 case "update":
205                                                         updateArtifact(trans, aafcon, cmds);
206                                                         break;
207                                                 case "delete":
208                                                         deleteArtifact(trans, aafcon, cmds);
209                                                         break;
210                                                 case "showpass":
211                                                         showPass(trans, aafcon, cmds);
212                                                         break;
213                                                 case "config":
214                                                         initConfig(trans,access,aafcon,cmds);
215                                                         break;
216                                                 case "validate":
217                                                         validate(aafsso,aafcon);
218                                                         break;
219                                                 case "check":
220                                                         try {
221                                                                 exitCode = check(trans,aafcon,cmds);
222                                                         } catch (Exception e) {
223                                                                 exitCode = 1;
224                                                                 throw e;
225                                                         }
226                                                         break;
227                                                 default:
228                                                         AAFSSO.cons.printf("Unknown command \"%s\"\n", cmd);
229                                         }
230                                 } finally {
231                                         StringBuilder sb = new StringBuilder();
232                         trans.auditTrail(4, sb, Trans.REMOTE);
233                         if(sb.length()>0) {
234                                 trans.info().log("Trans Info\n",sb);
235                         }
236                                 }
237                                 aafsso.close();
238                         }
239                 } catch (Exception e) {
240                         e.printStackTrace();
241                 }
242                 if(exitCode != 0 && doExit) {
243                         System.exit(exitCode);
244                 }
245         }
246
247         private static String getProperty(PropAccess pa, Env env, boolean secure, String tag, String prompt, Object ... def) {
248                 String value;
249                 if((value=pa.getProperty(tag))==null) {
250                         if(secure) {
251                                 value = new String(AAFSSO.cons.readPassword(prompt, def));
252                         } else {
253                                 value = AAFSSO.cons.readLine(prompt,def).trim();
254                         }
255                         if(value!=null) {
256                                 if(value.length()>0) {
257                                         pa.setProperty(tag,value);
258                                         env.setProperty(tag,value);
259                                 } else if(def.length==1) {
260                                         value=def[0].toString();
261                                         pa.setProperty(tag,value);
262                                         env.setProperty(tag,value);
263                                 }
264                         }
265                 }
266                 return value;
267         }
268
269         private static String fqi(Deque<String> cmds) {
270                 if(cmds.size()<1) {
271                         String alias = env.getProperty(Config.CADI_ALIAS);
272                         return alias!=null?alias:AAFSSO.cons.readLine("MechID: ");
273                 }
274                 return cmds.removeFirst();      
275         }
276
277         private static String machine(Deque<String> cmds) throws UnknownHostException {
278                 if(cmds.size()>0) {
279                         return cmds.removeFirst();
280                 } else {
281                         String mach = env.getProperty(Config.HOSTNAME);
282                         return mach!=null?mach:InetAddress.getLocalHost().getHostName();
283                 }
284         }
285
286         private static String[] machines(Deque<String> cmds)  {
287                 String machines;
288                 if(cmds.size()>0) {
289                         machines = cmds.removeFirst();
290                 } else {
291                         machines = AAFSSO.cons.readLine("Machines (sep by ','): ");
292                 }
293                 return Split.split(',', machines);
294         }
295
296         private static void createArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
297                 String mechID = fqi(cmds);
298                 String machine = machine(cmds);
299
300                 Artifacts artifacts = new Artifacts();
301                 Artifact arti = new Artifact();
302                 artifacts.getArtifact().add(arti);
303                 arti.setMechid(mechID!=null?mechID:AAFSSO.cons.readLine("MechID: "));
304                 arti.setMachine(machine!=null?machine:AAFSSO.cons.readLine("Machine (%s): ",InetAddress.getLocalHost().getHostName()));
305                 arti.setCa(AAFSSO.cons.readLine("CA: (%s): ","aaf"));
306                 
307                 String resp = AAFSSO.cons.readLine("Types [file,jks,script] (%s): ", "jks");
308                 for(String s : Split.splitTrim(',', resp)) {
309                         arti.getType().add(s);
310                 }
311                 // Always do Script
312                 if(!resp.contains(SCRIPT)) {
313                         arti.getType().add(SCRIPT);
314                 }
315
316                 // Note: Sponsor is set on Creation by CM
317                 String configRootName = FQI.reverseDomain(arti.getMechid());
318                 arti.setNs(AAFSSO.cons.readLine("Namespace (%s): ",configRootName));
319                 arti.setDir(AAFSSO.cons.readLine("Directory (%s): ", System.getProperty("user.dir")));
320                 arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", System.getProperty("user.name")));
321                 arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renewal Days (%s):", "30")));
322                 arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (mailto owner):", "")));
323                 
324                 TimeTaken tt = trans.start("Create Artifact", Env.REMOTE);
325                 try {
326                         Future<Artifacts> future = aafcon.client(CM_VER).create("/cert/artifacts", artifactsDF, artifacts);
327                         if(future.get(TIMEOUT)) {
328                                 trans.info().printf("Call to AAF Certman successful %s, %s",arti.getMechid(), arti.getMachine());
329                         } else {
330                                 trans.error().printf("Call to AAF Certman failed, %s",
331                                         errMsg.toMsg(future));
332                         }
333                 } finally {
334                         tt.done();
335                 }
336         }
337
338         private static String toNotification(String notification) {
339                 if(notification==null) {
340                         notification="";
341                 } else if(notification.length()>0) {
342                         if(notification.indexOf(':')<0) {
343                                 notification = "mailto:" + notification;
344                         }
345                 }
346                 return notification;
347         }
348         
349
350         private static void readArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
351                 String mechID = fqi(cmds);
352                 String machine = machine(cmds);
353
354                 TimeTaken tt = trans.start("Read Artifact", Env.SUB);
355                 try {
356                         Future<Artifacts> future = aafcon.client(CM_VER)
357                                         .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF,"Authorization","Bearer " + trans.getProperty("oauth_token"));
358         
359                         if(future.get(TIMEOUT)) {
360                                 boolean printed = false;
361                                 for(Artifact a : future.value.getArtifact()) {
362                                         AAFSSO.cons.printf("MechID:          %s\n",a.getMechid()); 
363                                         AAFSSO.cons.printf("  Sponsor:       %s\n",a.getSponsor()); 
364                                         AAFSSO.cons.printf("Machine:         %s\n",a.getMachine()); 
365                                         AAFSSO.cons.printf("CA:              %s\n",a.getCa()); 
366                                         StringBuilder sb = new StringBuilder();
367                                         boolean first = true;
368                                         for(String t : a.getType()) {
369                                                 if(first) {first=false;}
370                                                 else{sb.append(',');}
371                                                 sb.append(t);
372                                         }
373                                         AAFSSO.cons.printf("Types:           %s\n",sb);
374                                         AAFSSO.cons.printf("Namespace:       %s\n",a.getNs()); 
375                                         AAFSSO.cons.printf("Directory:       %s\n",a.getDir());
376                                         AAFSSO.cons.printf("O/S User:        %s\n",a.getOsUser());
377                                         AAFSSO.cons.printf("Renew Days:      %d\n",a.getRenewDays());
378                                         AAFSSO.cons.printf("Notification     %s\n",a.getNotification());
379                                         printed = true;
380                                 }
381                                 if(!printed) {
382                                         AAFSSO.cons.printf("Artifact for %s %s does not exist\n", mechID, machine);
383                                 }
384                         } else {
385                                 trans.error().log(errMsg.toMsg(future));
386                         }
387                 } finally {
388                         tt.done();
389                 }
390         }
391         
392         private static void copyArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
393                 String mechID = fqi(cmds);
394                 String machine = machine(cmds);
395                 String[] newmachs = machines(cmds);
396                 if(machine==null || newmachs == null) {
397                         trans.error().log("No machines listed to copy to");
398                 } else {
399                         TimeTaken tt = trans.start("Copy Artifact", Env.REMOTE);
400                         try {
401                                 Future<Artifacts> future = aafcon.client(CM_VER)
402                                                 .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
403                         
404                                 if(future.get(TIMEOUT)) {
405                                         boolean printed = false;
406                                         for(Artifact a : future.value.getArtifact()) {
407                                                 for(String m : newmachs) {
408                                                         a.setMachine(m);
409                                                         Future<Artifacts> fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, future.value);
410                                                         if(fup.get(TIMEOUT)) {
411                                                                 trans.info().printf("Copy of %s %s successful to %s",mechID,machine,m);
412                                                         } else {
413                                                                 trans.error().printf("Call to AAF Certman failed, %s",
414                                                                         errMsg.toMsg(fup));
415                                                         }
416         
417                                                         printed = true;
418                                                 }
419                                         }
420                                         if(!printed) {
421                                                 AAFSSO.cons.printf("Artifact for %s %s does not exist", mechID, machine);
422                                         }
423                                 } else {
424                                         trans.error().log(errMsg.toMsg(future));
425                                 }
426                         } finally {
427                                 tt.done();
428                         }
429                 }
430         }
431
432         private static void updateArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
433                 String mechID = fqi(cmds);
434                 String machine = machine(cmds);
435
436                 TimeTaken tt = trans.start("Update Artifact", Env.REMOTE);
437                 try {
438                         Future<Artifacts> fread = aafcon.client(CM_VER)
439                                         .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
440         
441                         if(fread.get(TIMEOUT)) {
442                                 Artifacts artifacts = new Artifacts();
443                                 for(Artifact a : fread.value.getArtifact()) {
444                                         Artifact arti = new Artifact();
445                                         artifacts.getArtifact().add(arti);
446                                         
447                                         AAFSSO.cons.printf("For %s on %s\n", a.getMechid(),a.getMachine());
448                                         arti.setMechid(a.getMechid());
449                                         arti.setMachine(a.getMachine());
450                                         arti.setCa(AAFSSO.cons.readLine("CA: (%s): ",a.getCa()));
451                                         StringBuilder sb = new StringBuilder();
452                                         boolean first = true;
453                                         for(String t : a.getType()) {
454                                                 if(first) {first=false;}
455                                                 else{sb.append(',');}
456                                                 sb.append(t);
457                                         }
458         
459                                         String resp = AAFSSO.cons.readLine("Types [file,jks,pkcs12] (%s): ", sb);
460                                         for(String s : Split.splitTrim(',', resp)) {
461                                                 arti.getType().add(s);
462                                         }
463                                         // Always do Script
464                                         if(!resp.contains(SCRIPT)) {
465                                                 arti.getType().add(SCRIPT);
466                                         }
467
468                                         // Note: Sponsor is set on Creation by CM
469                                         arti.setNs(AAFSSO.cons.readLine("Namespace (%s): ",a.getNs()));
470                                         arti.setDir(AAFSSO.cons.readLine("Directory (%s): ", a.getDir()));
471                                         arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", a.getOsUser()));
472                                         arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renew Days (%s):", a.getRenewDays())));
473                                         arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (%s):", a.getNotification())));
474         
475                                 }
476                                 if(artifacts.getArtifact().size()==0) {
477                                         AAFSSO.cons.printf("Artifact for %s %s does not exist", mechID, machine);
478                                 } else {
479                                         Future<Artifacts> fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, artifacts);
480                                         if(fup.get(TIMEOUT)) {
481                                                 trans.info().printf("Call to AAF Certman successful %s, %s",mechID,machine);
482                                         } else {
483                                                 trans.error().printf("Call to AAF Certman failed, %s",
484                                                         errMsg.toMsg(fup));
485                                         }
486                                 }
487                         } else {
488                                 trans.error().printf("Call to AAF Certman failed, %s %s, %s",
489                                                 errMsg.toMsg(fread),mechID,machine);
490                         }
491                 } finally {
492                         tt.done();
493                 }
494         }
495         
496         private static void deleteArtifact(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
497                 String mechid = fqi(cmds);
498                 String machine = machine(cmds);
499                 
500                 TimeTaken tt = trans.start("Delete Artifact", Env.REMOTE);
501                 try {
502                         Future<Void> future = aafcon.client(CM_VER)
503                                         .delete("/cert/artifacts/"+mechid+"/"+machine,"application/json" );
504         
505                         if(future.get(TIMEOUT)) {
506                                 trans.info().printf("Call to AAF Certman successful %s, %s",mechid,machine);
507                         } else {
508                                 trans.error().printf("Call to AAF Certman failed, %s %s, %s",
509                                         errMsg.toMsg(future),mechid,machine);
510                         }
511                 } finally {
512                         tt.done();
513                 }
514         }
515
516         
517
518         private static boolean placeCerts(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
519                 boolean rv = false;
520                 String mechID = fqi(cmds);
521                 String machine = machine(cmds);
522                 String[] fqdns = Split.split(':', machine);
523                 String key;
524                 if(fqdns.length>1) {
525                         key = fqdns[0];
526                         machine = fqdns[1];
527                 } else {
528                         key = machine;
529                 }
530                 
531                 TimeTaken tt = trans.start("Place Artifact", Env.REMOTE);
532                 try {
533                         Future<Artifacts> acf = aafcon.client(CM_VER)
534                                         .read("/cert/artifacts/"+mechID+'/'+key, artifactsDF);
535                         if(acf.get(TIMEOUT)) {
536                                 if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) {
537                                         AAFSSO.cons.printf("===> There are no artifacts for %s on machine '%s'\n", mechID, key);
538                                 } else {
539                                         for(Artifact a : acf.value.getArtifact()) {
540                                                 String osID = System.getProperty("user.name");
541                                                 if(a.getOsUser().equals(osID)) {
542                                                         CertificateRequest cr = new CertificateRequest();
543                                                         cr.setMechid(a.getMechid());
544                                                         cr.setSponsor(a.getSponsor());
545                                                         for(int i=0;i<fqdns.length;++i) {
546                                                                 cr.getFqdns().add(fqdns[i]);
547                                                         }
548                                                         Future<String> f = aafcon.client(CM_VER)
549                                                                         .updateRespondString("/cert/" + a.getCa()+"?withTrust",reqDF, cr);
550                                                         if(f.get(TIMEOUT)) {
551                                                                 CertInfo capi = certDF.newData().in(TYPE.JSON).load(f.body()).asObject();
552                                                                 for(String type : a.getType()) {
553                                                                         PlaceArtifact pa = placeArtifact.get(type);
554                                                                         if(pa!=null) {
555                                                                                 if(rv = pa.place(trans, capi, a,machine)) {
556                                                                                         notifyPlaced(a,rv);
557                                                                                 }
558                                                                         }
559                                                                 }
560                                                                 // Cover for the above multiple pass possibilities with some static Data, then clear per Artifact
561                                                         } else {
562                                                                 trans.error().log(errMsg.toMsg(f));
563                                                         }
564                                                 } else {
565                                                         trans.error().log("You must be OS User \"" + a.getOsUser() +"\" to place Certificates on this box");
566                                                 }
567                                         }
568                                 }
569                         } else {
570                                 trans.error().log(errMsg.toMsg(acf));
571                         }
572                 } finally {
573                         tt.done();
574                 }
575                 return rv;
576         }
577         
578         private static void notifyPlaced(Artifact a, boolean rv) {
579         }
580
581         private static void showPass(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
582                 String mechID = fqi(cmds);
583                 String machine = machine(cmds);
584
585                 TimeTaken tt = trans.start("Show Password", Env.REMOTE);
586                 try {
587                         Future<Artifacts> acf = aafcon.client(CM_VER)
588                                         .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
589                         if(acf.get(TIMEOUT)) {
590                                 // Have to wait for JDK 1.7 source...
591                                 //switch(artifact.getType()) {
592                                 if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) {
593                                         AAFSSO.cons.printf("No Artifacts found for %s on %s", mechID, machine);
594                                 } else {
595                                         String id = aafcon.defID();
596                                         boolean allowed;
597                                         for(Artifact a : acf.value.getArtifact()) {
598                                                 allowed = id!=null && (id.equals(a.getSponsor()) ||
599                                                                 (id.equals(a.getMechid()) 
600                                                                                 && aafcon.securityInfo().defSS.getClass().isAssignableFrom(HBasicAuthSS.class)));
601                                                 if(!allowed) {
602                                                         Future<String> pf = aafcon.client(CM_VER).read("/cert/may/" + 
603                                                                         a.getNs() + ".certman|"+a.getCa()+"|showpass","*/*");
604                                                         if(pf.get(TIMEOUT)) {
605                                                                 allowed = true;
606                                                         } else {
607                                                                 trans.error().log(errMsg.toMsg(pf));
608                                                         }
609                                                 }
610                                                 if(allowed) {
611                                                         File dir = new File(a.getDir());
612                                                         Properties props = new Properties();
613                                                         FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".props"));
614                                                         try {
615                                                                 props.load(fis);
616                                                                 fis.close();
617                                                                 fis = new FileInputStream(new File(dir,a.getNs()+".chal"));
618                                                                 props.load(fis);
619                                                         } finally {
620                                                                 fis.close();
621                                                         }
622                                                         
623                                                         File f = new File(dir,a.getNs()+".keyfile");
624                                                         if(f.exists()) {
625                                                                 Symm symm = Symm.obtain(f);
626                                                                 
627                                                                 for(Iterator<Entry<Object,Object>> iter = props.entrySet().iterator(); iter.hasNext();) {
628                                                                         Entry<Object,Object> en = iter.next();
629                                                                         if(en.getValue().toString().startsWith("enc:")) {
630                                                                                 System.out.printf("%s=%s\n", en.getKey(), symm.depass(en.getValue().toString()));
631                                                                         }
632                                                                 }
633                                                         } else {
634                                                                 trans.error().printf("%s.keyfile must exist to read passwords for %s on %s",
635                                                                                 f.getAbsolutePath(),a.getMechid(), a.getMachine());
636                                                         }
637                                                 }
638                                         }
639                                 }
640                         } else {
641                                 trans.error().log(errMsg.toMsg(acf));
642                         }
643                 } finally {
644                         tt.done();
645                 }
646
647         }
648         
649
650         private static void initConfig(Trans trans, PropAccess pa, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
651                 final String fqi = fqi(cmds);
652                 final String locator = getProperty(pa,aafcon.env,false,Config.AAF_LOCATE_URL,"AAF Locator URL: ");
653                 final String rootFile = FQI.reverseDomain(fqi);
654                 final File dir = new File(pa.getProperty(Config.CADI_ETCDIR, "."));
655                 if(dir.exists()) {
656                         System.out.println("Writing to " + dir.getCanonicalFile());
657                 } else if(dir.mkdirs()) {
658                         System.out.println("Created directory " + dir.getCanonicalFile());
659                 } else {
660                         System.err.println("Unable to create or write to " + dir.getCanonicalPath());
661                         return;
662                 }
663                 
664                 TimeTaken tt = trans.start("Get Configuration", Env.REMOTE);
665                 try {
666                         boolean ok=false;
667                         File fprops = File.createTempFile(rootFile, ".tmp",dir);
668                         PrintStream out = new PrintStream(new FileOutputStream(fprops));
669                         out.println(HASHES);
670                         out.print("# Configuration File generated on ");
671                         out.println(new Date().toString());
672                         out.println(HASHES);
673                         
674                         File fkf = new File(dir,rootFile+".keyfile");
675                         if(!fkf.exists()) {
676                                 CmdLine.main(new String[] {"keygen",fkf.toString()});
677                         }
678                         out.print("cadi_keyfile=");
679                         out.println(fkf.getCanonicalPath());
680                         
681                         out.print(Config.AAF_APPID);
682                         out.print('=');
683                         out.println(fqi);
684                         
685                         Symm filesymm = Symm.obtain(fkf);
686                         out.print(Config.AAF_APPPASS);
687                         out.print("=enc:");
688                         String ps = pa.decrypt(pa.getProperty(Config.AAF_APPPASS), false);
689                         ps = filesymm.enpass(ps);
690                         out.println(ps);
691                         
692                         out.print(Config.CADI_TRUSTSTORE);
693                         out.print("=");
694                         File origTruststore = new File(pa.getProperty(Config.CADI_TRUSTSTORE));
695                         File newTruststore = new File(dir,origTruststore.getName());
696                         if(!newTruststore.exists()) {
697                                 Files.copy(origTruststore.toPath(), newTruststore.toPath());
698                         }
699                         out.println(newTruststore.getCanonicalPath());
700
701                         out.print(Config.CADI_TRUSTSTORE_PASSWORD);
702                         out.print("=enc:");
703                         ps = pa.decrypt(pa.getProperty(Config.CADI_TRUSTSTORE_PASSWORD), false);
704                         ps = filesymm.enpass(ps);
705                         out.println(ps);
706
707                         
708                         try {
709                                 Future<Configuration> acf = aafcon.client(new SingleEndpointLocator(locator))
710                                                 .read("/configure/"+fqi+"/aaf", configDF);
711                                 if(acf.get(TIMEOUT)) {
712 //                                      out.println(acf.value.getName());
713                                         for(Props props : acf.value.getProps()) {
714                                                 out.println(props.getTag() + '=' + props.getValue());                                   
715                                         }
716                                         ok = true;
717                                 } else if(acf.code()==401){
718                                         trans.error().log("Bad Password sent to AAF");
719                                 } else {
720                                         trans.error().log(errMsg.toMsg(acf));
721                                 }
722                         } finally {
723                                 out.close();
724                         }
725                         if(ok) {
726                                 File newFile = new File(dir,rootFile+".common.props");
727                                 fprops.renameTo(newFile);
728                                 System.out.println("Created " + newFile.getCanonicalPath());
729                                 fprops = newFile;
730                         } else {
731                                 fprops.delete();
732                         }
733                 } finally {
734                         tt.done();
735                 }
736         }
737         
738         private static void validate(final AAFSSO aafsso, final AAFCon<?> aafcon) throws LocatorException, CadiException, APIException {
739                 System.out.println("Validating Configuration...");
740                 aafcon.clone(aafsso.access().getProperty(Config.AAF_URL)).best(new Retryable<Void>() {
741                         @Override
742                         public Void code(Rcli<?> client) throws CadiException, ConnectException, APIException {
743                                 Future<Perms> fc = client.read("/authz/perms/user/"+aafsso.user(),permDF);
744                                 if(fc.get(aafcon.timeout)) {
745                                         System.out.print("Success connecting to ");
746                                         System.out.println(client.getURI());
747                                         System.out.print("   Permissions for ");
748                                         System.out.println(aafsso.user());
749                                         for(Perm p : fc.value.getPerm()) {
750                                                 System.out.print('\t');
751                                                 System.out.print(p.getType());
752                                                 System.out.print('|');
753                                                 System.out.print(p.getInstance());
754                                                 System.out.print('|');
755                                                 System.out.println(p.getAction());
756                                         }
757                                 } else {
758                                         System.err.println("Error: " + fc.code() + ' ' + fc.body());
759                                 }
760                                 return null;
761                         }
762                 });
763         }
764
765         /**
766          * Check returns Error Codes, so that Scripts can know what to do
767          * 
768          *   0 - Check Complete, nothing to do
769          *   1 - General Error
770          *   2 - Error for specific Artifact - read check.msg
771          *   10 - Certificate Updated - check.msg is email content
772          *   
773          * @param trans
774          * @param aafcon
775          * @param cmds
776          * @return
777          * @throws Exception
778          */
779         private static int check(Trans trans, AAFCon<?> aafcon, Deque<String> cmds) throws Exception {
780                 int exitCode=1;
781                 String mechID = fqi(cmds);
782                 String machine = machine(cmds);
783                 
784                 TimeTaken tt = trans.start("Check Certificate", Env.REMOTE);
785                 try {
786                 
787                         Future<Artifacts> acf = aafcon.client(CM_VER)
788                                         .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF);
789                         if(acf.get(TIMEOUT)) {
790                                 // Have to wait for JDK 1.7 source...
791                                 //switch(artifact.getType()) {
792                                 if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) {
793                                         AAFSSO.cons.printf("No Artifacts found for %s on %s", mechID, machine);
794                                 } else {
795                                         String id = aafcon.defID();
796                                         GregorianCalendar now = new GregorianCalendar();
797                                         for(Artifact a : acf.value.getArtifact()) {
798                                                 if(id.equals(a.getMechid())) {
799                                                         File dir = new File(a.getDir());
800                                                         Properties props = new Properties();
801                                                         FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".props"));
802                                                         try {
803                                                                 props.load(fis);
804                                                         } finally {
805                                                                 fis.close();
806                                                         }
807                                                         
808                                                         String prop;                                            
809                                                         File f;
810         
811                                                         if((prop=props.getProperty(Config.CADI_KEYFILE))==null ||
812                                                                 !(f=new File(prop)).exists()) {
813                                                                         trans.error().printf("Keyfile must exist to check Certificates for %s on %s",
814                                                                                 a.getMechid(), a.getMachine());
815                                                         } else {
816                                                                 String ksf = props.getProperty(Config.CADI_KEYSTORE);
817                                                                 String ksps = props.getProperty(Config.CADI_KEYSTORE_PASSWORD);
818                                                                 if(ksf==null || ksps == null) {
819                                                                         trans.error().printf("Properties %s and %s must exist to check Certificates for %s on %s",
820                                                                                         Config.CADI_KEYSTORE, Config.CADI_KEYSTORE_PASSWORD,a.getMechid(), a.getMachine());
821                                                                 } else {
822                                                                         KeyStore ks = KeyStore.getInstance("JKS");
823                                                                         Symm symm = Symm.obtain(f);
824                                                                         
825                                                                         fis = new FileInputStream(ksf);
826                                                                         try {
827                                                                                 ks.load(fis,symm.depass(ksps).toCharArray());
828                                                                         } finally {
829                                                                                 fis.close();
830                                                                         }
831                                                                         X509Certificate cert = (X509Certificate)ks.getCertificate(mechID);
832                                                                         String msg = null;
833
834                                                                         if(cert==null) {
835                                                                                 msg = String.format("X509Certificate does not exist for %s on %s in %s",
836                                                                                                 a.getMechid(), a.getMachine(), ksf);
837                                                                                 trans.error().log(msg);
838                                                                                 exitCode = 2;
839                                                                         } else {
840                                                                                 GregorianCalendar renew = new GregorianCalendar();
841                                                                                 renew.setTime(cert.getNotAfter());
842                                                                                 renew.add(GregorianCalendar.DAY_OF_MONTH,-1*a.getRenewDays());
843                                                                                 if(renew.after(now)) {
844                                                                                         msg = String.format("X509Certificate for %s on %s has been checked on %s. It expires on %s; it will not be renewed until %s.\n", 
845                                                                                                         a.getMechid(), a.getMachine(),Chrono.dateOnlyStamp(now),cert.getNotAfter(),Chrono.dateOnlyStamp(renew));
846                                                                                         trans.info().log(msg);
847                                                                                         exitCode = 0; // OK
848                                                                                 } else {
849                                                                                         trans.info().printf("X509Certificate for %s on %s expiration, %s, needs Renewal.\n", 
850                                                                                                         a.getMechid(), a.getMachine(),cert.getNotAfter());
851                                                                                         cmds.offerLast(mechID);
852                                                                                         cmds.offerLast(machine);
853                                                                                         if(placeCerts(trans,aafcon,cmds)) {
854                                                                                                 msg = String.format("X509Certificate for %s on %s has been renewed. Ensure services using are refreshed.\n", 
855                                                                                                                 a.getMechid(), a.getMachine());
856                                                                                                 exitCode = 10; // Refreshed
857                                                                                         } else {
858                                                                                                 msg = String.format("X509Certificate for %s on %s attempted renewal, but failed. Immediate Investigation is required!\n", 
859                                                                                                                 a.getMechid(), a.getMachine());
860                                                                                                 exitCode = 1; // Error Renewing
861                                                                                         }
862                                                                                 }
863                                                                         }
864                                                                         if(msg!=null) {
865                                                                                 FileOutputStream fos = new FileOutputStream(a.getDir()+'/'+a.getNs()+".msg");
866                                                                                 try {
867                                                                                         fos.write(msg.getBytes());
868                                                                                 } finally {
869                                                                                         fos.close();
870                                                                                 }
871                                                                         }
872                                                                 }
873                                                                 
874                                                         }
875                                                 }
876                                         }
877                                 }
878                         } else {
879                                 trans.error().log(errMsg.toMsg(acf));
880                                 exitCode=1;
881                         }
882                 } finally {
883                         tt.done();
884                 }
885                 return exitCode;
886         }
887
888 }
889                         
890                 
891
892