X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=cadi%2Faaf%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Faaf%2Fcadi%2Fconfigure%2FAgent.java;h=74f0916d3239edab07e5ccc0d2ae9aabcfdb506c;hb=be1edcb6830745015f5de72e820f40f36dd571ad;hp=a26422213c0593c1b05da381ba54a3f1a80f0f39;hpb=7e966914050e66219689001ff4ab601a49eef0ac;p=aaf%2Fauthz.git diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java index a2642221..74f0916d 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,7 +25,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.io.PrintStream; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.InetAddress; @@ -35,8 +34,8 @@ import java.security.KeyPair; import java.security.KeyStore; import java.security.cert.X509Certificate; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; import java.util.Deque; import java.util.GregorianCalendar; import java.util.HashMap; @@ -45,14 +44,14 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; -import java.util.TreeMap; +import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.CmdLine; import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.PropAccess; import org.onap.aaf.cadi.Symm; -import org.onap.aaf.cadi.aaf.Defaults; +import org.onap.aaf.cadi.aaf.TestConnectivity; import org.onap.aaf.cadi.aaf.client.ErrMessage; import org.onap.aaf.cadi.aaf.v2_0.AAFCon; import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp; @@ -60,6 +59,7 @@ import org.onap.aaf.cadi.client.Future; import org.onap.aaf.cadi.client.Rcli; import org.onap.aaf.cadi.client.Retryable; import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.config.RegistrationPropHolder; import org.onap.aaf.cadi.config.SecurityInfoC; import org.onap.aaf.cadi.http.HBasicAuthSS; import org.onap.aaf.cadi.locator.SingleEndpointLocator; @@ -86,17 +86,18 @@ import locate.v1_1.Configuration; import locate.v1_1.Configuration.Props; public class Agent { + private static final String AGENT_LOAD_URLS = "Agent:loadURLs"; private static final String HASHES = "################################################################"; private static final String PRINT = "print"; private static final String FILE = "file"; public static final String PKCS12 = "pkcs12"; public static final String JKS = "jks"; private static final String SCRIPT="script"; - + private static final String CM_VER = "1.0"; public static final int PASS_SIZE = 24; private static int TIMEOUT; - + private static RosettaDF reqDF; private static RosettaDF certDF; private static RosettaDF artifactsDF; @@ -105,10 +106,25 @@ public class Agent { private static ErrMessage errMsg; private static Map placeArtifact; private static RosettaEnv env; - + private static boolean doExit; private static AAFCon aafcon; + private static List CRED_TAGS = Arrays.asList(new String[] { + Config.CADI_KEYFILE, + Config.AAF_APPID, Config.AAF_APPPASS, + Config.CADI_KEYSTORE, Config.CADI_KEYSTORE_PASSWORD, Config.CADI_KEY_PASSWORD, + Config.CADI_TRUSTSTORE,Config.CADI_TRUSTSTORE_PASSWORD, + Config.CADI_ALIAS, Config.CADI_X509_ISSUERS + }); + private static List LOC_TAGS = Arrays.asList(new String[] { + Config.CADI_LATITUDE, Config.CADI_LONGITUDE + }); + // Note: This is set by loadURLs. Use that function as singleton, not directly. + private static Map aaf_urls = null; + private static boolean configNoPasswd = false; + + public static void main(String[] args) { int exitCode = 0; doExit = true; @@ -122,33 +138,89 @@ public class Agent { System.out.println(HASHES); } CmdLine.main(newArgs); + } else if(args.length>0 && "connectivity".equals(args[0])) { + String[] newArgs = new String[args.length-1]; + System.arraycopy(args, 1, newArgs, 0, newArgs.length); + if(newArgs.length>0 && newArgs[0].indexOf('@')>=0) { + newArgs[0]=FQI.reverseDomain(newArgs[0])+".props"; + } + TestConnectivity.main(newArgs); } else { try { AAFSSO aafsso=null; - PropAccess access; - - if (args.length>1 && args[0].equals("validate") ) { - int idx = args[1].indexOf('='); - aafsso = null; - access = new PropAccess( - (idx<0?Config.CADI_PROP_FILES:args[1].substring(0, idx))+ - '='+ - (idx<0?args[1]:args[1].substring(idx+1))); - } else { - aafsso= new AAFSSO(args, new AAFSSO.ProcessArgs() { - @Override - public Properties process(String[] args, Properties props) { - if (args.length>1) { - if (!args[0].equals("keypairgen")) { - props.put("aaf_id", args[1]); - } + PropAccess access=null; + + String hasEtc = null; + for(String a : args) { + if(a.startsWith(Config.CADI_PROP_FILES)) { + access = new PropAccess(args); + break; + } else if(a.startsWith(Config.CADI_ETCDIR)) { + int idx = a.indexOf('='); + if(idx>=0 && idx1 && args[1].contains("@")) { + String domain = FQI.reverseDomain(args[1]); + if(domain!=null) { + if(hasEtc==null) { + hasEtc = "."; + } + File etc = new File(hasEtc); + if(etc.exists()) { + File nsprops = new File(etc,domain+".props"); + if(nsprops.exists()) { + access = new PropAccess(new String[] {Config.CADI_PROP_FILES+'='+nsprops.getAbsolutePath()}); + } } - return props; } - }); - access = aafsso.access(); + } + } + + if(access==null) { + for(Entry es : System.getProperties().entrySet()) { + if(Config.CADI_PROP_FILES.equals(es.getKey())) { + access = new PropAccess(); + } + } + } + + // When using Config file, check if Cred Exists, and if not, work with Deployer. + if(access!=null && !"config".equals(args[0]) && access.getProperty(Config.AAF_APPPASS)==null && access.getProperty(Config.CADI_ALIAS)==null) { + // not enough credentials to use Props. Use AAFSSO + access = null; } - + + if(access==null) { + if (args.length>1 && args[0].equals("validate") ) { + int idx = args[1].indexOf('='); + aafsso = null; + access = new PropAccess( + (idx<0?Config.CADI_PROP_FILES:args[1].substring(0, idx))+ + '='+ + (idx<0?args[1]:args[1].substring(idx+1))); + } else { + aafsso= new AAFSSO(args, new AAFSSO.ProcessArgs() { + @Override + public Properties process(String[] args, Properties props) { + if (args.length>1) { + if (!args[0].equals("keypairgen")) { + props.put(Config.AAF_APPID, args[1]); + } + } + return props; + } + }); + access = aafsso.access(); + } + } + if (aafsso!=null && aafsso.loginOnly()) { aafsso.setLogDefault(); aafsso.writeFiles(); @@ -157,56 +229,60 @@ public class Agent { env = new RosettaEnv(access.getProperties()); Deque cmds = new ArrayDeque(); for (String p : args) { + int eq; if ("-noexit".equalsIgnoreCase(p)) { doExit = false; - } else if (p.indexOf('=') < 0) { + } else if ((eq=p.indexOf('=')) < 0) { cmds.add(p); + } else { + access.setProperty(p.substring(0,eq), p.substring(eq+1)); } } - + if (cmds.size()==0) { if (aafsso!=null) { aafsso.setLogDefault(); } // NOTE: CHANGE IN CMDS should be reflected in AAFSSO constructor, to get FQI->aaf-id or not System.out.println("Usage: java -jar cmd []*"); - System.out.println(" create []"); - System.out.println(" read []"); - System.out.println(" update []"); - System.out.println(" delete []"); - System.out.println(" copy [,]*"); - System.out.println(" place []"); - System.out.println(" showpass []"); - System.out.println(" check []"); - System.out.println(" keypairgen "); - System.out.println(" config "); - System.out.println(" validate .props>"); + System.out.println(" create []"); + System.out.println(" read []"); + System.out.println(" update []"); + System.out.println(" delete []"); + System.out.println(" copy [,]*"); + System.out.println(" place [[,]*"); + System.out.println(" showpass []"); + System.out.println(" check []"); + System.out.println(" keypairgen "); + System.out.println(" config [--nopasswd]"); + System.out.println(" validate .props>"); + System.out.println(" connectivity .props>"); System.out.println(" --- Additional Tool Access ---"); System.out.println(" ** Type with no params for Tool Help"); System.out.println(" ** If using with Agent, preface with \"cadi\""); System.out.println(" cadi "); - + if (doExit) { System.exit(1); } } - + TIMEOUT = Integer.parseInt(env.getProperty(Config.AAF_CONN_TIMEOUT, "5000")); - + reqDF = env.newDataFactory(CertificateRequest.class); artifactsDF = env.newDataFactory(Artifacts.class); certDF = env.newDataFactory(CertInfo.class); configDF = env.newDataFactory(Configuration.class); permDF = env.newDataFactory(Perms.class); errMsg = new ErrMessage(env); - + placeArtifact = new HashMap<>(); placeArtifact.put(JKS, new PlaceArtifactInKeystore(JKS)); placeArtifact.put(PKCS12, new PlaceArtifactInKeystore(PKCS12)); placeArtifact.put(FILE, new PlaceArtifactInFiles()); placeArtifact.put(PRINT, new PlaceArtifactOnStream(System.out)); placeArtifact.put(SCRIPT, new PlaceArtifactScripts()); - + Trans trans = env.newTrans(); String token; if ((token=access.getProperty("oauth_token"))!=null) { @@ -217,17 +293,13 @@ public class Agent { // show Std out again aafsso.setLogDefault(); aafsso.setStdErrDefault(); - - // if CM_URL can be obtained, add to sso.props, if written - String cm_url = getProperty(access,env,false, Config.CM_URL,Config.CM_URL+": "); - if (cm_url!=null) { - aafsso.addProp(Config.CM_URL, cm_url); - } + + /*urls=*/loadURLs(access); aafsso.writeFiles(); } - - - + + + String cmd = cmds.removeFirst(); switch(cmd) { case "place": @@ -255,13 +327,7 @@ public class Agent { keypairGen(trans, access, cmds); break; case "config": - if (access.getProperty(Config.CADI_PROP_FILES)!=null) { - // Get Properties from initialization Prop Files - config(trans,access,null,cmds); - } else { - // Get Properties from existing AAF Instance - config(trans,access,aafcon(access),cmds); - } + config(trans,access,args,cmds); break; case "validate": validate(access); @@ -297,9 +363,65 @@ public class Agent { } } - private static synchronized AAFCon aafcon(PropAccess access) throws APIException, CadiException, LocatorException { + public synchronized static Map loadURLs(Access access) throws UnknownHostException, CadiException { + if(aaf_urls==null) { + Map rv = new HashMap<>(); + RegistrationPropHolder rph = new RegistrationPropHolder(access, 0); + String dot_le = access.getProperty(Config.AAF_LOCATOR_CONTAINER,null); + dot_le=dot_le==null?"":'.'+dot_le; + String version = access.getProperty(Config.AAF_API_VERSION,Config.AAF_DEFAULT_API_VERSION); + for(String u : new String[] {"locate","aaf","oauth","cm","gui","fs","hello","token","introspect"}) { + String tag; + String append=null; + switch(u) { + case "aaf": tag = Config.AAF_URL; break; + case "locate":tag = Config.AAF_LOCATE_URL; break; + case "oauth": tag = Config.AAF_URL_OAUTH; break; + case "token": tag = Config.AAF_OAUTH2_TOKEN_URL; append="/token"; break; + case "introspect": tag = Config.AAF_OAUTH2_INTROSPECT_URL; append="/introspect"; break; + case "cm": tag = Config.AAF_URL_CM; break; + case "gui": tag = Config.AAF_URL_GUI; break; + case "fs": tag = Config.AAF_URL_FS; break; + case "hello": tag = Config.AAF_URL_HELLO; break; + default: + tag = "aaf_url_" + u; + } + String value; + if((value=access.getProperty(tag,null))==null) { + String proto = "fs".equals(u)?"http://":"https://"; + String lhost; + if("locate".equals(u)) { + lhost=rph.default_fqdn; + } else { + lhost=Config.AAF_LOCATE_URL_TAG; + } + value = rph.replacements(AGENT_LOAD_URLS, + proto + lhost + "/%CNS.%AAF_NS." + ("aaf".equals(u)?"service":u) + ':' + version, + null,dot_le); + if(append!=null) { + value+=append; + } + } else { + value = rph.replacements(AGENT_LOAD_URLS, value,null,dot_le); + } + rv.put(tag, value); + }; + aaf_urls = rv; + } + return aaf_urls; + } + + public static void fillMissing(PropAccess access, Map map) { + for(Entry es : map.entrySet()) { + if(access.getProperty(es.getKey())==null) { + access.setProperty(es.getKey(),es.getValue()); + } + } + } + + private static synchronized AAFCon aafcon(Access access) throws APIException, CadiException, LocatorException { if (aafcon==null) { - aafcon = new AAFConHttp(access,Config.CM_URL); + aafcon = new AAFConHttp(access,Config.AAF_URL_CM); } return aafcon; } @@ -329,9 +451,12 @@ public class Agent { private static String fqi(Deque cmds) { if (cmds.size()<1) { String alias = env.getProperty(Config.CADI_ALIAS); + if(alias==null) { + alias = env.getProperty(Config.AAF_APPID); + } return alias!=null?alias:AAFSSO.cons.readLine("AppID: "); } - return cmds.removeFirst(); + return cmds.removeFirst(); } private static String machine(Deque cmds) throws UnknownHostException { @@ -363,7 +488,7 @@ public class Agent { arti.setMechid(mechID!=null?mechID:AAFSSO.cons.readLine("AppID: ")); arti.setMachine(machine!=null?machine:AAFSSO.cons.readLine("Machine (%s): ",InetAddress.getLocalHost().getHostName())); arti.setCa(AAFSSO.cons.readLine("CA: (%s): ","aaf")); - + String resp = AAFSSO.cons.readLine("Types [file,pkcs12,jks,script] (%s): ", PKCS12); for (String s : Split.splitTrim(',', resp)) { arti.getType().add(s); @@ -380,7 +505,7 @@ public class Agent { arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", System.getProperty("user.name"))); arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renewal Days (%s):", "30"))); arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (mailto owner):", ""))); - + TimeTaken tt = trans.start("Create Artifact", Env.REMOTE); try { Future future = aafcon.client(CM_VER).create("/cert/artifacts", artifactsDF, artifacts); @@ -405,7 +530,7 @@ public class Agent { } return notification; } - + private static void readArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { String mechID = fqi(cmds); @@ -415,14 +540,14 @@ public class Agent { try { Future future = aafcon.client(CM_VER) .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF,"Authorization","Bearer " + trans.getProperty("oauth_token")); - + if (future.get(TIMEOUT)) { boolean printed = false; for (Artifact a : future.value.getArtifact()) { - AAFSSO.cons.printf("AppID: %s\n",a.getMechid()); - AAFSSO.cons.printf(" Sponsor: %s\n",a.getSponsor()); - AAFSSO.cons.printf("Machine: %s\n",a.getMachine()); - AAFSSO.cons.printf("CA: %s\n",a.getCa()); + AAFSSO.cons.printf("AppID: %s\n",a.getMechid()); + AAFSSO.cons.printf(" Sponsor: %s\n",a.getSponsor()); + AAFSSO.cons.printf("Machine: %s\n",a.getMachine()); + AAFSSO.cons.printf("CA: %s\n",a.getCa()); StringBuilder sb = new StringBuilder(); boolean first = true; for (String t : a.getType()) { @@ -431,7 +556,7 @@ public class Agent { sb.append(t); } AAFSSO.cons.printf("Types: %s\n",sb); - AAFSSO.cons.printf("Namespace: %s\n",a.getNs()); + AAFSSO.cons.printf("Namespace: %s\n",a.getNs()); AAFSSO.cons.printf("Directory: %s\n",a.getDir()); AAFSSO.cons.printf("O/S User: %s\n",a.getOsUser()); AAFSSO.cons.printf("Renew Days: %d\n",a.getRenewDays()); @@ -448,7 +573,7 @@ public class Agent { tt.done(); } } - + private static void copyArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { String mechID = fqi(cmds); String machine = machine(cmds); @@ -460,7 +585,7 @@ public class Agent { try { Future future = aafcon.client(CM_VER) .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); - + if (future.get(TIMEOUT)) { boolean printed = false; for (Artifact a : future.value.getArtifact()) { @@ -473,7 +598,7 @@ public class Agent { trans.error().printf("Call to AAF Certman failed, %s", errMsg.toMsg(fup)); } - + printed = true; } } @@ -497,13 +622,13 @@ public class Agent { try { Future fread = aafcon.client(CM_VER) .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); - + if (fread.get(TIMEOUT)) { Artifacts artifacts = new Artifacts(); for (Artifact a : fread.value.getArtifact()) { Artifact arti = new Artifact(); artifacts.getArtifact().add(arti); - + AAFSSO.cons.printf("For %s on %s\n", a.getMechid(),a.getMachine()); arti.setMechid(a.getMechid()); arti.setMachine(a.getMachine()); @@ -515,7 +640,7 @@ public class Agent { else{sb.append(',');} sb.append(t); } - + String resp = AAFSSO.cons.readLine("Types [file,jks,pkcs12] (%s): ", sb); for (String s : Split.splitTrim(',', resp)) { arti.getType().add(s); @@ -531,7 +656,7 @@ public class Agent { arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", a.getOsUser())); arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renew Days (%s):", a.getRenewDays()))); arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (%s):", a.getNotification()))); - + } if (artifacts.getArtifact().size()==0) { AAFSSO.cons.printf("Artifact for %s %s does not exist", mechID, machine); @@ -552,16 +677,16 @@ public class Agent { tt.done(); } } - + private static void deleteArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { String mechid = fqi(cmds); String machine = machine(cmds); - + TimeTaken tt = trans.start("Delete Artifact", Env.REMOTE); try { Future future = aafcon.client(CM_VER) .delete("/cert/artifacts/"+mechid+"/"+machine,"application/json" ); - + if (future.get(TIMEOUT)) { trans.info().printf("Call to AAF Certman successful %s, %s",mechid,machine); } else { @@ -573,7 +698,7 @@ public class Agent { } } - + private static boolean placeCerts(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { boolean rv = false; @@ -586,8 +711,9 @@ public class Agent { machine = fqdns[1]; } else { key = machine; + fqdns = machines(cmds); } - + TimeTaken tt = trans.start("Place Artifact", Env.REMOTE); try { Future acf = aafcon.client(CM_VER) @@ -602,8 +728,11 @@ public class Agent { CertificateRequest cr = new CertificateRequest(); cr.setMechid(a.getMechid()); cr.setSponsor(a.getSponsor()); + cr.getFqdns().add(machine); for (int i=0;i f = aafcon.client(CM_VER) .updateRespondString("/cert/" + a.getCa()+"?withTrust",reqDF, cr); @@ -626,6 +755,7 @@ public class Agent { } } } + PropHolder.writeAll(); } else { trans.error().log(errMsg.toMsg(acf)); } @@ -634,7 +764,7 @@ public class Agent { } return rv; } - + private static void notifyPlaced(Artifact a, boolean rv) { } @@ -656,10 +786,10 @@ public class Agent { boolean allowed; for (Artifact a : acf.value.getArtifact()) { allowed = id!=null && (id.equals(a.getSponsor()) || - (id.equals(a.getMechid()) + (id.equals(a.getMechid()) && aafcon.securityInfo().defSS.getClass().isAssignableFrom(HBasicAuthSS.class))); if (!allowed) { - Future pf = aafcon.client(CM_VER).read("/cert/may/" + + Future pf = aafcon.client(CM_VER).read("/cert/may/" + a.getNs()+"|certman|"+a.getCa()+"|showpass","*/*"); if (pf.get(TIMEOUT)) { allowed = true; @@ -673,17 +803,20 @@ public class Agent { FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".cred.props")); try { props.load(fis); - fis.close(); - fis = new FileInputStream(new File(dir,a.getNs()+".chal")); - props.load(fis); + File chalFile = new File(dir,a.getNs()+".chal"); + if(chalFile.exists()) { + fis.close(); + fis = new FileInputStream(chalFile); + props.load(fis); + } } finally { fis.close(); } - + File f = new File(dir,a.getNs()+".keyfile"); if (f.exists()) { - Symm symm = Symm.obtain(f); - + Symm symm = ArtifactDir.getSymm(f); + for (Iterator> iter = props.entrySet().iterator(); iter.hasNext();) { Entry en = iter.next(); if (en.getValue().toString().startsWith("enc:")) { @@ -705,13 +838,13 @@ public class Agent { } } - + private static void keypairGen(final Trans trans, final PropAccess access, final Deque cmds) throws IOException { final String fqi = fqi(cmds); final String ns = FQI.reverseDomain(fqi); File dir = new File(access.getProperty(Config.CADI_ETCDIR,".")); // default to current Directory File f = new File(dir,ns+".key"); - + if (f.exists()) { String line = AAFSSO.cons.readLine("%s exists. Overwrite? (y/n): ", f.getCanonicalPath()); if (!"Y".equalsIgnoreCase(line)) { @@ -719,7 +852,7 @@ public class Agent { return; } } - + KeyPair kp = Factory.generateKeyPair(trans); ArtifactDir.write(f, Chmod.to400, Factory.toString(trans, kp.getPrivate())); System.out.printf("Wrote %s\n", f.getCanonicalFile()); @@ -728,219 +861,178 @@ public class Agent { ArtifactDir.write(f, Chmod.to644, Factory.toString(trans, kp.getPublic())); System.out.printf("Wrote %s\n", f.getCanonicalFile()); } - - private static void config(Trans trans, PropAccess pa, AAFCon aafcon, Deque cmds) throws Exception { - final String fqi = fqi(cmds); - final String rootFile = FQI.reverseDomain(fqi); - final File dir = new File(pa.getProperty(Config.CADI_ETCDIR, ".")); - if (dir.exists()) { - System.out.println("Writing to " + dir.getCanonicalFile()); - } else if (dir.mkdirs()) { - System.out.println("Created directory " + dir.getCanonicalFile()); - } else { - System.err.println("Unable to create or write to " + dir.getCanonicalPath()); - return; - } - + + private static void config(Trans trans, PropAccess propAccess, String[] args, Deque cmds) throws Exception { TimeTaken tt = trans.start("Get Configuration", Env.REMOTE); try { - boolean ok=false; - File fProps = File.createTempFile(rootFile, ".tmp",dir); - File fSecureTempProps = File.createTempFile(rootFile, ".cred.tmp",dir); - File fSecureProps = new File(dir,rootFile+".cred.props"); - PrintStream psProps; - - File fLocProps = new File(dir,rootFile + ".location.props"); - if (!fLocProps.exists()) { - psProps = new PrintStream(new FileOutputStream(fLocProps)); - try { - psProps.println(HASHES); - psProps.print("# Configuration File generated on "); - psProps.println(new Date().toString()); - psProps.println(HASHES); - for (String tag : LOC_TAGS) { - psProps.print(tag); - psProps.print('='); - psProps.println(getProperty(pa, trans, false, tag, "%s: ",tag)); - } - } finally { - psProps.close(); + final String fqi = fqi(cmds); + Artifact arti = new Artifact(); + arti.setDir(propAccess.getProperty(Config.CADI_ETCDIR, System.getProperty("user.dir"))); + arti.setNs(FQI.reverseDomain(fqi)); + PropHolder loc = PropHolder.get(arti, "location.props"); + PropHolder cred = PropHolder.get(arti,"cred.props"); + PropHolder app= PropHolder.get(arti,"props"); + for(String c : args) { + int idx = c.indexOf('='); + if(idx>0) { + app.add(c.substring(0,idx), c.substring(idx+1)); } } + app.add(Config.CADI_PROP_FILES, loc.getPath()+':'+cred.getPath()); - psProps = new PrintStream(new FileOutputStream(fProps)); - try { - PrintStream psCredProps = new PrintStream(new FileOutputStream(fSecureTempProps)); - try { - psCredProps.println(HASHES); - psCredProps.print("# Configuration File generated on "); - psCredProps.println(new Date().toString()); - psCredProps.println(HASHES); - - psProps.println(HASHES); - psProps.print("# Configuration File generated on "); - psProps.println(new Date().toString()); - psProps.println(HASHES); - - psProps.print(Config.CADI_PROP_FILES); - psProps.print('='); - psProps.print(fSecureProps.getCanonicalPath()); - psProps.print(File.pathSeparatorChar); - psProps.println(fLocProps.getCanonicalPath()); - - File fkf = new File(dir,rootFile+".keyfile"); - if (!fkf.exists()) { - CmdLine.main(new String[] {"keygen",fkf.toString()}); + for (String tag : LOC_TAGS) { + loc.add(tag, getProperty(propAccess, trans, false, tag, "%s: ",tag)); + } + + String keyfile = cred.getKeyPath(); + if(keyfile!=null) { + File fkeyfile = new File(keyfile); + if(!fkeyfile.exists()) { + ArtifactDir.write(fkeyfile,Chmod.to400,Symm.keygen()); + } + } + cred.add(Config.CADI_KEYFILE, cred.getKeyPath()); + final String ssoAppID = propAccess.getProperty(Config.AAF_APPID); + if(fqi!=null && fqi.equals(ssoAppID)) { + cred.addEnc(Config.AAF_APPPASS, propAccess, null); + // only Ask for Password when starting scratch + } else if(propAccess.getProperty(Config.CADI_PROP_FILES)==null) { + if(!configNoPasswd) { + char[] pwd = AAFSSO.cons.readPassword("Password for %s (leave blank for NO password): ", fqi); + if(pwd.length>0) { + cred.addEnc(Config.AAF_APPPASS, new String(pwd)); } - Symm filesymm = Symm.obtain(fkf); - Map normal = new TreeMap<>(); - Map creds = new TreeMap<>(); - - directedPut(pa, filesymm, normal,creds, Config.CADI_KEYFILE, fkf.getCanonicalPath()); - directedPut(pa, filesymm, normal,creds, Config.AAF_APPID,fqi); - directedPut(pa, filesymm, normal,creds, Config.AAF_APPPASS,null); - directedPut(pa, filesymm, normal,creds, Config.AAF_URL, Defaults.AAF_URL); - - - String cts = pa.getProperty(Config.CADI_TRUSTSTORE); - if (cts!=null) { - File origTruststore = new File(cts); - if (!origTruststore.exists()) { - // Try same directory as cadi_prop_files - String cpf = pa.getProperty(Config.CADI_PROP_FILES); - if (cpf!=null) { - for (String f : Split.split(File.pathSeparatorChar, cpf)) { - File fcpf = new File(f); - if (fcpf.exists()) { - int lastSep = cts.lastIndexOf(File.pathSeparator); - origTruststore = new File(fcpf.getParentFile(),lastSep>=0?cts.substring(lastSep):cts); - if (origTruststore.exists()) { - break; - } + } + } + + // load all properties that are already setup. + Map aaf_urls = loadURLs(propAccess); + for(Entry es : aaf_urls.entrySet()) { + app.add(es.getKey(), es.getValue()); + } + + app.add(Config.AAF_LOCATE_URL, Config.getAAFLocateUrl(propAccess)); + app.add(Config.AAF_ENV,propAccess, "DEV"); + String release = propAccess.getProperty(Config.AAF_DEPLOYED_VERSION); + if(release==null) { + release = System.getProperty(Config.AAF_DEPLOYED_VERSION,null); + } + if(release!=null) { + app.add(Config.AAF_DEPLOYED_VERSION, release); + } + for(Entry aaf_loc_prop : propAccess.getProperties().entrySet()) { + String key = aaf_loc_prop.getKey().toString(); + if(key.startsWith("aaf_locator")) { + app.add(key, aaf_loc_prop.getValue().toString()); + } + } + + app.add(Config.AAF_APPID, fqi); + + String cts = propAccess.getProperty(Config.CADI_TRUSTSTORE); + System.out.println("Passed in Truststore is " + cts); + if (cts!=null) { + File origTruststore = new File(cts); + File newTruststore = new File(app.getDir(),origTruststore.getName()); + if(!newTruststore.exists()) { + if (!origTruststore.exists()) { + // Try same directory as cadi_prop_files + String cpf = propAccess.getProperty(Config.CADI_PROP_FILES); + if (cpf!=null) { + for (String f : Split.split(File.pathSeparatorChar, cpf)) { + File fcpf = new File(f); + if (fcpf.exists()) { + int lastSep = cts.lastIndexOf(File.pathSeparator); + origTruststore = new File(fcpf.getParentFile(),lastSep>=0?cts.substring(lastSep):cts); + if (origTruststore.exists()) { + break; } } - if (!origTruststore.exists()) { - throw new CadiException(cts + " does not exist"); - } } - - } - File newTruststore = new File(dir,origTruststore.getName()); - if (!newTruststore.exists()) { - Files.copy(origTruststore.toPath(), newTruststore.toPath()); + if (!origTruststore.exists()) { + throw new CadiException(cts + " does not exist"); + } } - - directedPut(pa, filesymm, normal,creds, Config.CADI_TRUSTSTORE,newTruststore.getCanonicalPath()); - directedPut(pa, filesymm, normal,creds, Config.CADI_TRUSTSTORE_PASSWORD,null); + } - - if (aafcon!=null) { // get Properties from Remote AAF - final String locator = getProperty(pa,aafcon.env,false,Config.AAF_LOCATE_URL,"AAF Locator URL: "); + if (!newTruststore.exists() && origTruststore.exists()) { + Files.copy(origTruststore.toPath(), newTruststore.toPath()); + } + } - Future acf = aafcon.client(new SingleEndpointLocator(locator)) - .read("/configure/"+fqi+"/aaf", configDF); - if (acf.get(TIMEOUT)) { - for (Props props : acf.value.getProps()) { - directedPut(pa, filesymm, normal,creds, props.getTag(),props.getValue()); - } - ok = true; - } else if (acf.code()==401){ - trans.error().log("Bad Password sent to AAF"); - } else { - trans.error().log(errMsg.toMsg(acf)); - } - } else { - String cpf = pa.getProperty(Config.CADI_PROP_FILES); - if (cpf!=null){ - for (String f : Split.split(File.pathSeparatorChar, cpf)) { - System.out.format("Reading %s\n",f); - FileInputStream fis = new FileInputStream(f); - try { - Properties props = new Properties(); - props.load(fis); - for (Entry prop : props.entrySet()) { - directedPut(pa, filesymm, normal,creds, prop.getKey().toString(),prop.getValue().toString()); + System.out.println("New Truststore is " + newTruststore); + cred.add(Config.CADI_TRUSTSTORE, newTruststore.getCanonicalPath()); + cred.add(Config.CADI_TRUSTSTORE_PASSWORD, "changeit" /* Java default */); + + String cpf = propAccess.getProperty(Config.CADI_PROP_FILES); + if (cpf!=null){ + String[] propFiles = Split.splitTrim(File.pathSeparatorChar, cpf); + for (int pfi = propFiles.length-1;pfi>=0;--pfi) { + String f = propFiles[pfi]; + System.out.format("Reading %s\n",f); + FileInputStream fis = new FileInputStream(f); + try { + Properties props = new Properties(); + props.load(fis); + for (Entry prop : props.entrySet()) { + boolean lower = true; + String key = prop.getKey().toString(); + if(LOC_TAGS.contains(key)) { + break; + } + for(int i=0;lower && i es : normal.entrySet()) { - psProps.print(es.getKey()); - psProps.print('='); - psProps.println(es.getValue()); - } - - for (Entry es : creds.entrySet()) { - psCredProps.print(es.getKey()); - psCredProps.print('='); - psCredProps.println(es.getValue()); - } - - File newFile = new File(dir,rootFile+".props"); - if (newFile.exists()) { - File backup = new File(dir,rootFile+".props.backup"); - newFile.renameTo(backup); - System.out.println("Backed up to " + backup.getCanonicalPath()); - } - fProps.renameTo(newFile); - System.out.println("Created " + newFile.getCanonicalPath()); - fProps = newFile; - - if (fSecureProps.exists()) { - File backup = new File(dir,fSecureProps.getName()+".backup"); - fSecureProps.renameTo(backup); - System.out.println("Backed up to " + backup.getCanonicalPath()); + } else { + aafcon = aafcon(propAccess); + if (aafcon!=null) { // get Properties from Remote AAF + for (Props props : aafProps(trans,aafcon,getProperty(propAccess,aafcon.env,false,Config.AAF_LOCATE_URL,"AAF Locator URL: "),fqi)) { + PropHolder ph = CRED_TAGS.contains(props.getTag())?cred:app; + if(props.getTag().endsWith("_password")) { + ph.addEnc(props.getTag(), props.getValue()); + } else { + ph.add(props.getTag(), props.getValue()); + } } - fSecureTempProps.renameTo(fSecureProps); - System.out.println("Created " + fSecureProps.getCanonicalPath()); - fProps = newFile; - } else { - fProps.delete(); - fSecureTempProps.delete(); + } - } finally { - psCredProps.close(); } - } finally { - psProps.close(); } + + PropHolder.writeAll(); } finally { tt.done(); } } - private static List CRED_TAGS = Arrays.asList(new String[] { - Config.CADI_KEYFILE, - Config.AAF_APPID, Config.AAF_APPPASS, - Config.CADI_KEYSTORE, Config.CADI_KEYSTORE_PASSWORD, Config.CADI_KEY_PASSWORD, - Config.CADI_TRUSTSTORE,Config.CADI_TRUSTSTORE_PASSWORD, - Config.CADI_ALIAS, Config.CADI_X509_ISSUERS - }); - - private static List LOC_TAGS = Arrays.asList(new String[] {Config.CADI_LATITUDE, Config.CADI_LONGITUDE}); - - private static void directedPut(final PropAccess orig, final Symm symm, final Map main, final Map secured, final String tag, final String value) throws IOException { - if (!LOC_TAGS.contains(tag)) { // Location already covered - String val = value==null?orig.getProperty(tag):value; - if (tag.endsWith("_password")) { - if (val.length()>4) { - if (val.startsWith("enc:")) { - val = orig.decrypt(val, true); - } - val = "enc:" + symm.enpass(val); - } - } - if (CRED_TAGS.contains(tag)) { - secured.put(tag, val); - } else { - main.put(tag, val); - } + public static List aafProps(Trans trans, AAFCon aafcon, String locator, String fqi) throws CadiException, APIException, LocatorException { + Future acf = aafcon.client(new SingleEndpointLocator(locator)) + .read("/configure/"+fqi+"/aaf", configDF); + if (acf.get(TIMEOUT)) { + return acf.value.getProps(); + } else if (acf.code()==401){ + trans.error().log("Bad Password sent to AAF"); + } else if (acf.code()==404){ + trans.error().log("This version of AAF does not support remote Properties"); + } else { + trans.error().log(errMsg.toMsg(acf)); } + return new ArrayList<>(); } private static void validate(final PropAccess pa) throws LocatorException, CadiException, APIException { @@ -973,12 +1065,12 @@ public class Agent { /** * Check returns Error Codes, so that Scripts can know what to do - * + * * 0 - Check Complete, nothing to do * 1 - General Error * 2 - Error for specific Artifact - read check.msg * 10 - Certificate Updated - check.msg is email content - * + * * @param trans * @param aafcon * @param cmds @@ -989,10 +1081,10 @@ public class Agent { int exitCode=1; String mechID = fqi(cmds); String machine = machine(cmds); - + TimeTaken tt = trans.start("Check Certificate", Env.REMOTE); try { - + Future acf = aafcon.client(CM_VER) .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); if (acf.get(TIMEOUT)) { @@ -1013,10 +1105,10 @@ public class Agent { } finally { fis.close(); } - - String prop; + + String prop; File f; - + if ((prop=trans.getProperty(Config.CADI_KEYFILE))==null || !(f=new File(prop)).exists()) { trans.error().printf("Keyfile must exist to check Certificates for %s on %s", @@ -1028,9 +1120,10 @@ public class Agent { trans.error().printf("Properties %s and %s must exist to check Certificates for %s on %s", Config.CADI_KEYSTORE, Config.CADI_KEYSTORE_PASSWORD,a.getMechid(), a.getMachine()); } else { + Symm symm = ArtifactDir.getSymm(f); + KeyStore ks = KeyStore.getInstance("JKS"); - Symm symm = Symm.obtain(f); - + fis = new FileInputStream(ksf); try { ks.load(fis,symm.depass(ksps).toCharArray()); @@ -1050,21 +1143,21 @@ public class Agent { renew.setTime(cert.getNotAfter()); renew.add(GregorianCalendar.DAY_OF_MONTH,-1*a.getRenewDays()); if (renew.after(now)) { - 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", + 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", a.getMechid(), a.getMachine(),Chrono.dateOnlyStamp(now),cert.getNotAfter(),Chrono.dateOnlyStamp(renew)); trans.info().log(msg); exitCode = 0; // OK } else { - trans.info().printf("X509Certificate for %s on %s expiration, %s, needs Renewal.\n", + trans.info().printf("X509Certificate for %s on %s expiration, %s, needs Renewal.\n", a.getMechid(), a.getMachine(),cert.getNotAfter()); cmds.offerLast(mechID); cmds.offerLast(machine); if (placeCerts(trans,aafcon,cmds)) { - msg = String.format("X509Certificate for %s on %s has been renewed. Ensure services using are refreshed.\n", + msg = String.format("X509Certificate for %s on %s has been renewed. Ensure services using are refreshed.\n", a.getMechid(), a.getMachine()); exitCode = 10; // Refreshed } else { - msg = String.format("X509Certificate for %s on %s attempted renewal, but failed. Immediate Investigation is required!\n", + msg = String.format("X509Certificate for %s on %s attempted renewal, but failed. Immediate Investigation is required!\n", a.getMechid(), a.getMachine()); exitCode = 1; // Error Renewing } @@ -1079,7 +1172,7 @@ public class Agent { } } } - + } } } @@ -1095,7 +1188,7 @@ public class Agent { } } - - + +