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