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