1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\r
4 * * ===========================================================================
\r
5 * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
\r
6 * * ===========================================================================
\r
7 * * Licensed under the Apache License, Version 2.0 (the "License");
\r
8 * * you may not use this file except in compliance with the License.
\r
9 * * You may obtain a copy of the License at
\r
11 * * http://www.apache.org/licenses/LICENSE-2.0
\r
13 * * Unless required by applicable law or agreed to in writing, software
\r
14 * * distributed under the License is distributed on an "AS IS" BASIS,
\r
15 * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
16 * * See the License for the specific language governing permissions and
\r
17 * * limitations under the License.
\r
18 * * ============LICENSE_END====================================================
\r
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
23 package org.onap.aaf.cadi.config;
\r
25 import java.io.IOException;
\r
26 import java.lang.reflect.Constructor;
\r
27 import java.lang.reflect.Field;
\r
28 import java.lang.reflect.Method;
\r
29 import java.net.InetAddress;
\r
30 import java.net.URI;
\r
31 import java.net.UnknownHostException;
\r
32 import java.security.NoSuchAlgorithmException;
\r
33 import java.security.cert.CertificateException;
\r
34 import java.util.ArrayList;
\r
35 import java.util.List;
\r
36 import java.util.Map.Entry;
\r
38 import org.onap.aaf.cadi.AbsUserCache;
\r
39 import org.onap.aaf.cadi.Access;
\r
40 import org.onap.aaf.cadi.CachingLur;
\r
41 import org.onap.aaf.cadi.CadiException;
\r
42 import org.onap.aaf.cadi.CredVal;
\r
43 import org.onap.aaf.cadi.Locator;
\r
44 import org.onap.aaf.cadi.Lur;
\r
45 import org.onap.aaf.cadi.PropAccess;
\r
46 import org.onap.aaf.cadi.Symm;
\r
47 import org.onap.aaf.cadi.TrustChecker;
\r
48 import org.onap.aaf.cadi.Access.Level;
\r
49 import org.onap.aaf.cadi.lur.EpiLur;
\r
50 import org.onap.aaf.cadi.lur.LocalLur;
\r
51 import org.onap.aaf.cadi.lur.NullLur;
\r
52 import org.onap.aaf.cadi.taf.HttpEpiTaf;
\r
53 import org.onap.aaf.cadi.taf.HttpTaf;
\r
54 import org.onap.aaf.cadi.taf.basic.BasicHttpTaf;
\r
55 import org.onap.aaf.cadi.taf.cert.X509Taf;
\r
56 import org.onap.aaf.cadi.taf.dos.DenialOfServiceTaf;
\r
58 import java.util.Properties;
\r
59 import java.util.TimerTask;
\r
62 * Create a Consistent Configuration mechanism, even when configuration styles are as vastly different as
\r
63 * Properties vs JavaBeans vs FilterConfigs...
\r
67 public class Config {
\r
69 private static final String HIDE_PASS = "***************";
\r
71 public static final String UTF_8 = "UTF-8";
\r
73 // Property Names associated with configurations.
\r
74 // As of 1.0.2, these have had the dots removed so as to be compatible with JavaBean style
\r
75 // configurations as well as property list style.
\r
76 public static final String HOSTNAME = "hostname";
\r
77 public static final String CADI_PROP_FILES = "cadi_prop_files"; // Additional Properties files (separate with ;)
\r
78 public static final String CADI_LOGLEVEL = "cadi_loglevel";
\r
79 public static final String CADI_LOGNAME = "cadi_logname";
\r
80 public static final String CADI_KEYFILE = "cadi_keyfile";
\r
81 public static final String CADI_KEYSTORE = "cadi_keystore";
\r
82 public static final String CADI_KEYSTORE_PASSWORD = "cadi_keystore_password";
\r
83 public static final String CADI_ALIAS = "cadi_alias";
\r
84 public static final String CADI_LOGINPAGE_URL = "cadi_loginpage_url";
\r
86 public static final String CADI_KEY_PASSWORD = "cadi_key_password";
\r
87 public static final String CADI_TRUSTSTORE = "cadi_truststore";
\r
88 public static final String CADI_TRUSTSTORE_PASSWORD = "cadi_truststore_password";
\r
89 public static final String CADI_X509_ISSUERS = "cadi_x509_issuers";
\r
90 public static final String CADI_TRUST_MASKS="cadi_trust_masks";
\r
91 public static final String CADI_TRUST_PERM="cadi_trust_perm"; // IDs with this perm can utilize the "AS " user concept
\r
92 public static final String CADI_PROTOCOLS = "cadi_protocols";
\r
93 public static final String CADI_NOAUTHN = "cadi_noauthn";
\r
94 public static final String CADI_LOC_LIST = "cadi_loc_list";
\r
96 public static final String CADI_USER_CHAIN_TAG = "cadi_user_chain";
\r
97 public static final String CADI_USER_CHAIN = "USER_CHAIN";
\r
101 public static final String CSP_DOMAIN = "csp_domain";
\r
102 public static final String CSP_HOSTNAME = "csp_hostname";
\r
103 public static final String CSP_DEVL_LOCALHOST = "csp_devl_localhost";
\r
104 public static final String CSP_USER_HEADER = "CSP_USER";
\r
105 public static final String CSP_SYSTEMS_CONF = "CSPSystems.conf";
\r
106 public static final String CSP_SYSTEMS_CONF_FILE = "csp_systems_conf_file";
\r
109 public static final String TGUARD_ENV="tguard_env";
\r
110 public static final String TGUARD_DOMAIN = "tguard_domain";
\r
111 public static final String TGUARD_TIMEOUT = "tguard_timeout";
\r
112 public static final String TGUARD_TIMEOUT_DEF = "5000";
\r
113 public static final String TGUARD_CERTS = "tguard_certs"; // comma delimited SHA-256 finger prints
\r
114 // public static final String TGUARD_DEVL_LOCALHOST = "tguard_devl_localhost";
\r
115 // public static final String TGUARD_USER_HEADER = "TGUARD_USER";
\r
117 public static final String LOCALHOST_ALLOW = "localhost_allow";
\r
118 public static final String LOCALHOST_DENY = "localhost_deny";
\r
120 public static final String BASIC_REALM = "basic_realm"; // what is sent to the client
\r
121 public static final String BASIC_WARN = "basic_warn"; // Warning of insecure channel
\r
122 public static final String USERS = "local_users";
\r
123 public static final String GROUPS = "local_groups";
\r
124 public static final String WRITE_TO = "local_writeto"; // dump RBAC to local file in Tomcat Style (some apps use)
\r
126 public static final String AAF_ENV = "aaf_env";
\r
127 public static final String AAF_ROOT_NS = "aaf_root_ns";
\r
128 public static final String AAF_ROOT_COMPANY = "aaf_root_company";
\r
129 public static final String AAF_URL = "aaf_url"; //URL for AAF... Use to trigger AAF configuration
\r
130 public static final String AAF_MECHID = "aaf_id";
\r
131 public static final String AAF_MECHPASS = "aaf_password";
\r
132 public static final String AAF_LUR_CLASS = "aaf_lur_class";
\r
133 public static final String AAF_TAF_CLASS = "aaf_taf_class";
\r
134 public static final String AAF_CONNECTOR_CLASS = "aaf_connector_class";
\r
135 public static final String AAF_LOCATOR_CLASS = "aaf_locator_class";
\r
136 public static final String AAF_CONN_TIMEOUT = "aaf_conn_timeout";
\r
137 public static final String AAF_CONN_TIMEOUT_DEF = "3000";
\r
138 public static final String AAF_READ_TIMEOUT = "aaf_timeout";
\r
139 public static final String AAF_READ_TIMEOUT_DEF = "5000";
\r
140 public static final String AAF_USER_EXPIRES = "aaf_user_expires";
\r
141 public static final String AAF_USER_EXPIRES_DEF = "600000"; // Default is 10 mins
\r
142 public static final String AAF_CLEAN_INTERVAL = "aaf_clean_interval";
\r
143 public static final String AAF_CLEAN_INTERVAL_DEF = "30000"; // Default is 30 seconds
\r
144 public static final String AAF_REFRESH_TRIGGER_COUNT = "aaf_refresh_trigger_count";
\r
145 public static final String AAF_REFRESH_TRIGGER_COUNT_DEF = "3"; // Default is 10 mins
\r
147 public static final String AAF_HIGH_COUNT = "aaf_high_count";
\r
148 public static final String AAF_HIGH_COUNT_DEF = "1000"; // Default is 1000 entries
\r
149 public static final String AAF_PERM_MAP = "aaf_perm_map";
\r
150 public static final String AAF_DEPLOYED_VERSION = "DEPLOYED_VERSION";
\r
151 public static final String AAF_CERT_IDS = "aaf_cert_ids";
\r
152 public static final String AAF_DEBUG_IDS = "aaf_debug_ids"; // comma delimited
\r
154 public static final String GW_URL = "gw_url";
\r
155 public static final String CM_URL = "cm_url";
\r
156 public static final String CM_TRUSTED_CAS = "cm_trusted_cas";
\r
158 public static final String PATHFILTER_URLPATTERN = "pathfilter_urlpattern";
\r
159 public static final String PATHFILTER_STACK = "pathfilter_stack";
\r
160 public static final String PATHFILTER_NS = "pathfilter_ns";
\r
161 public static final String PATHFILTER_NOT_AUTHORIZED_MSG = "pathfilter_not_authorized_msg";
\r
163 public static final String AFT_DME2_TRUSTSTORE_PASSWORD = "AFT_DME2_TRUSTSTORE_PASSWORD";
\r
164 public static final String AFT_DME2_TRUSTSTORE = "AFT_DME2_TRUSTSTORE";
\r
165 public static final String AFT_DME2_KEYSTORE_PASSWORD = "AFT_DME2_KEYSTORE_PASSWORD";
\r
166 public static final String AFT_DME2_KEY_PASSWORD = "AFT_DME2_KEY_PASSWORD";
\r
167 public static final String AFT_DME2_KEYSTORE = "AFT_DME2_KEYSTORE";
\r
168 public static final String AFT_DME2_SSL_TRUST_ALL = "AFT_DME2_SSL_TRUST_ALL";
\r
169 public static final String AFT_DME2_SSL_INCLUDE_PROTOCOLS = "AFT_DME2_SSL_INCLUDE_PROTOCOLS";
\r
172 // DME2 Client. First property must be set to "false", and the others set in order to use SSL Client
\r
173 public static final String AFT_DME2_CLIENT_IGNORE_SSL_CONFIG="AFT_DME2_CLIENT_IGNORE_SSL_CONFIG";
\r
174 public static final String AFT_DME2_CLIENT_KEYSTORE = "AFT_DME2_CLIENT_KEYSTORE";
\r
175 public static final String AFT_DME2_CLIENT_KEYSTORE_PASSWORD = "AFT_DME2_CLIENT_KEYSTORE_PASSWORD";
\r
176 public static final String AFT_DME2_CLIENT_TRUSTSTORE = "AFT_DME2_CLIENT_TRUSTSTORE";
\r
177 public static final String AFT_DME2_CLIENT_TRUSTSTORE_PASSWORD = "AFT_DME2_CLIENT_TRUSTSTORE_PASSWORD";
\r
178 public static final String AFT_DME2_CLIENT_SSL_CERT_ALIAS = "AFT_DME2_CLIENT_SSL_CERT_ALIAS";
\r
179 public static final String AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS = "AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS";
\r
182 // This one should go unpublic
\r
183 public static final String AAF_DEFAULT_REALM = "aaf_default_realm";
\r
184 private static String defaultRealm="none";
\r
186 public static final String AAF_DOMAIN_SUPPORT = "aaf_domain_support";
\r
187 //public static final String AAF_DOMAIN_SUPPORT_DEF = ".com";
\r
188 public static final String AAF_DOMAIN_SUPPORT_DEF = ".org";
\r
191 public static void setDefaultRealm(Access access) throws CadiException {
\r
195 Class.forName("com.att.cadi.taf.csp.CSPTaf");
\r
197 } catch(ClassNotFoundException e) {
\r
198 hasCSP = logProp(access,Config.CSP_DOMAIN, null)!=null;
\r
200 defaultRealm = logProp(access,Config.AAF_DEFAULT_REALM,
\r
201 hasCSP?"csp.att.com":
\r
202 logProp(access,Config.BASIC_REALM,
\r
203 logProp(access,HOSTNAME,InetAddress.getLocalHost().getHostName())
\r
206 } catch (UnknownHostException e) {
\r
207 //defaultRealm="none";
\r
212 public static HttpTaf configHttpTaf(Access access, TrustChecker tc, CredVal up, Lur lur, Object ... additionalTafLurs) throws CadiException {
\r
213 /////////////////////////////////////////////////////
\r
214 // Setup AAFCon for any following
\r
215 /////////////////////////////////////////////////////
\r
216 Object aafcon = null;
\r
220 f = lur.getClass().getField("aaf");
\r
221 aafcon = f.get(lur);
\r
222 } catch (Exception nsfe) {
\r
225 // IMPORTANT! Don't attempt to load AAF Connector if there is no AAF URL
\r
226 String aafURL = access.getProperty(AAF_URL,null);
\r
227 if(aafcon==null && aafURL!=null) {
\r
228 aafcon = loadAAFConnector(access, aafURL);
\r
232 // Setup Host, in case Network reports an unusable Hostname (i.e. VTiers, VPNs, etc)
\r
233 String hostname = logProp(access, HOSTNAME,null);
\r
234 if(hostname==null) {
\r
236 hostname = InetAddress.getLocalHost().getHostName();
\r
237 } catch (UnknownHostException e1) {
\r
238 throw new CadiException("Unable to determine Hostname",e1);
\r
242 access.log(Level.INIT, "Hostname set to",hostname);
\r
243 // Get appropriate TAFs
\r
244 ArrayList<HttpTaf> htlist = new ArrayList<HttpTaf>();
\r
246 /////////////////////////////////////////////////////
\r
247 // Add a Denial of Service TAF
\r
248 // Note: how IPs and IDs are added are up to service type.
\r
249 // They call "DenialOfServiceTaf.denyIP(String) or denyID(String)
\r
250 /////////////////////////////////////////////////////
\r
251 htlist.add(new DenialOfServiceTaf(access));
\r
253 /////////////////////////////////////////////////////
\r
254 // Configure LocalHost
\r
255 /////////////////////////////////////////////////////
\r
257 String truststore = logProp(access, CADI_TRUSTSTORE, access.getProperty("AFT_DME2_TRUSTSTORE", null));
\r
258 if(truststore!=null) {
\r
259 String truststore_pwd = access.getProperty(CADI_TRUSTSTORE_PASSWORD, access.getProperty("AFT_DME2_TRUSTSTORE_PASSWORD",null));
\r
260 if(truststore_pwd!=null) {
\r
261 if(truststore_pwd.startsWith(Symm.ENC)) {
\r
263 truststore_pwd = access.decrypt(truststore_pwd,false);
\r
264 } catch (IOException e) {
\r
265 throw new CadiException(CADI_TRUSTSTORE_PASSWORD + " cannot be decrypted",e);
\r
269 htlist.add(new X509Taf(access,lur));
\r
270 access.log(Level.INIT,"Certificate Authorization enabled");
\r
271 } catch (SecurityException e) {
\r
272 access.log(Level.INIT,"AAFListedCertIdentity cannot be instantiated. Certificate Authorization is now disabled",e);
\r
273 } catch (IllegalArgumentException e) {
\r
274 access.log(Level.INIT,"AAFListedCertIdentity cannot be instantiated. Certificate Authorization is now disabled",e);
\r
275 } catch (CertificateException e) {
\r
276 access.log(Level.INIT,"Certificate Authorization failed, it is disabled",e);
\r
277 } catch (NoSuchAlgorithmException e) {
\r
278 access.log(Level.INIT,"Certificate Authorization failed, wrong Security Algorithm",e);
\r
282 access.log(Level.INIT,"Certificate Authorization not enabled");
\r
285 /////////////////////////////////////////////////////
\r
286 // Configure Basic Auth (local content)
\r
287 /////////////////////////////////////////////////////
\r
288 String basic_realm = logProp(access, BASIC_REALM,null);
\r
289 boolean basic_warn = "TRUE".equals(access.getProperty(BASIC_WARN,"FALSE"));
\r
290 if(basic_realm!=null && up!=null) {
\r
291 access.log(Level.INIT,"Basic Authorization is enabled using realm",basic_realm);
\r
292 // Allow warning about insecure channel to be turned off
\r
293 if(!basic_warn)access.log(Level.INIT,"WARNING! The basic_warn property has been set to false.",
\r
294 " There will be no additional warning if Basic Auth is used on an insecure channel"
\r
296 String aafCleanup = logProp(access, AAF_USER_EXPIRES,AAF_USER_EXPIRES_DEF); // Default is 10 mins
\r
297 long userExp = Long.parseLong(aafCleanup);
\r
299 htlist.add(new BasicHttpTaf(access, up, basic_realm, userExp, basic_warn));
\r
301 access.log(Level.INIT,"Local Basic Authorization is disabled. Enable by setting basic_realm=<appropriate realm, i.e. my.att.com>");
\r
304 /////////////////////////////////////////////////////
\r
305 // Configure AAF Driven Basic Auth
\r
306 /////////////////////////////////////////////////////
\r
307 boolean getRemoteAAF = true;
\r
308 if(additionalTafLurs!=null) {
\r
309 for(Object o : additionalTafLurs) {
\r
310 if(o.getClass().getSimpleName().equals("DirectAAFLur")) {
\r
311 getRemoteAAF = false;
\r
316 HttpTaf aaftaf=null;
\r
319 access.log(Level.INIT,"AAF Connection (AAFcon) is null. Cannot create an AAF TAF");
\r
320 } else if(aafURL==null) {
\r
321 access.log(Level.INIT,"No AAF URL in properties, Cannot create an AAF TAF");
\r
322 } else {// There's an AAF_URL... try to configure an AAF
\r
323 String defName = aafURL.contains("version=2.0")?"com.att.cadi.aaf.v2_0.AAFTaf":"";
\r
324 String aafTafClassName = logProp(access, AAF_TAF_CLASS,defName);
\r
325 // Only 2.0 available at this time
\r
326 if("com.att.cadi.aaf.v2_0.AAFTaf".equals(aafTafClassName)) {
\r
328 Class<?> aafTafClass = loadClass(access,aafTafClassName);
\r
329 Class<?> aafConClass = loadClass(access,"com.att.cadi.aaf.v2_0.AAFCon");
\r
331 Constructor<?> cstr = aafTafClass.getConstructor(aafConClass,boolean.class,AbsUserCache.class);
\r
333 aaftaf = (HttpTaf)cstr.newInstance(aafcon,basic_warn,lur);
\r
335 access.log(Level.INIT,"ERROR! AAF TAF Failed construction. NOT Configured");
\r
337 access.log(Level.INIT,"AAF TAF Configured to ",aafURL);
\r
338 // Note: will add later, after all others configured
\r
341 } catch(Exception e) {
\r
342 access.log(Level.INIT,"ERROR! AAF TAF Failed construction. NOT Configured");
\r
349 String alias = logProp(access, CADI_ALIAS,null);
\r
351 /////////////////////////////////////////////////////
\r
352 // Configure tGuard... (AT&T Client Repo)
\r
353 /////////////////////////////////////////////////////
\r
354 // TGUARD Environment, translated to any other remote Environment validation mechanism...
\r
355 String tGuard_domain = logProp(access, TGUARD_DOMAIN,null);
\r
356 String tGuard_env = logProp(access, TGUARD_ENV, null);
\r
358 if(!("PROD".equals(tGuard_env) || "STAGE".equals(tGuard_env))) {
\r
359 access.log(Level.INIT, "tGuard Authorization is disabled. Enable by setting", TGUARD_ENV, "to \"PROD\" or \"STAGE\"");
\r
360 } else if(tGuard_domain==null) {
\r
361 access.log(Level.INIT,TGUARD_DOMAIN + " must be set: tGuard Authorization is disabled.");
\r
362 } else if(alias == null) {
\r
363 access.log(Level.INIT,CADI_ALIAS + " must be set: tGuard Authorization is disabled.");
\r
366 Class<?> tGuardClass = loadClass(access,"com.att.cadi.tguard.TGuardHttpTaf");
\r
368 Constructor<?> tGuardCnst = tGuardClass.getConstructor(new Class[]{Access.class, AbsUserCache.class});
\r
369 htlist.add((HttpTaf)tGuardCnst.newInstance(new Object[] {access,aaftaf}));
\r
370 access.log(Level.INIT,"tGuard Authorization is enabled on",tGuard_env,"on the",tGuard_domain," tGuard Domain");
\r
372 Constructor<?> tGuardCnst = tGuardClass.getConstructor(new Class[]{Access.class, int.class, int.class, int.class});
\r
373 htlist.add((HttpTaf)tGuardCnst.newInstance(new Object[] {
\r
375 Integer.parseInt(logProp(access, AAF_CLEAN_INTERVAL,AAF_CLEAN_INTERVAL_DEF)),
\r
376 Integer.parseInt(logProp(access, AAF_HIGH_COUNT, AAF_HIGH_COUNT_DEF)),
\r
377 Integer.parseInt(logProp(access, AAF_REFRESH_TRIGGER_COUNT, AAF_REFRESH_TRIGGER_COUNT_DEF))
\r
379 access.log(Level.INIT,"tGuard Authorization is enabled on",tGuard_env,"on the",tGuard_domain," tGuard Domain");
\r
381 } catch(Exception e) {
\r
382 access.log(e, Level.INIT,"tGuard Class cannot be loaded: tGuard Authorization is disabled.");
\r
386 /////////////////////////////////////////////////////
\r
387 // Adding BasicAuth (AAF) last, after other primary Cookie Based
\r
388 // Needs to be before Cert... see below
\r
389 /////////////////////////////////////////////////////
\r
391 htlist.add(aaftaf);
\r
395 /////////////////////////////////////////////////////
\r
396 // Any Additional Lurs passed in Constructor
\r
397 /////////////////////////////////////////////////////
\r
398 if(additionalTafLurs!=null) {
\r
399 for(Object additional : additionalTafLurs) {
\r
400 if(additional instanceof HttpTaf) {
\r
401 htlist.add((HttpTaf)additional);
\r
402 access.log(Level.INIT,additional);
\r
407 /////////////////////////////////////////////////////
\r
408 // Create EpiTaf from configured TAFs
\r
409 /////////////////////////////////////////////////////
\r
410 if(htlist.size()==1) {
\r
411 // just return the one
\r
412 taf = htlist.get(0);
\r
414 HttpTaf[] htarray = new HttpTaf[htlist.size()];
\r
415 htlist.toArray(htarray);
\r
416 Locator<URI> locator = loadLocator(access, logProp(access, CADI_LOGINPAGE_URL, null));
\r
418 taf = new HttpEpiTaf(access,locator, tc, htarray); // ok to pass locator == null
\r
419 String level = logProp(access, CADI_LOGLEVEL, null);
\r
421 access.setLogLevel(Level.valueOf(level));
\r
428 public static String logProp(Access access,String tag, String def) {
\r
429 String rv = access.getProperty(tag, def);
\r
431 access.log(Level.INIT,tag,"is not set");
\r
433 access.log(Level.INIT,tag,"is set to",rv);
\r
438 public static Lur configLur(Access access, Object ... additionalTafLurs) throws CadiException {
\r
439 List<Lur> lurs = new ArrayList<Lur>();
\r
441 /////////////////////////////////////////////////////
\r
442 // Configure a Local Property Based RBAC/LUR
\r
443 /////////////////////////////////////////////////////
\r
445 String users = access.getProperty(USERS,null);
\r
446 String groups = access.getProperty(GROUPS,null);
\r
448 if(groups!=null || users!=null) {
\r
450 lurs.add(ll = new LocalLur(access, users, groups)); // note b64==null is ok.. just means no encryption.
\r
452 String writeto = access.getProperty(WRITE_TO,null);
\r
453 if(writeto!=null) {
\r
454 String msg = UsersDump.updateUsers(writeto, ll);
\r
455 if(msg!=null) access.log(Level.INIT,"ERROR! Error Updating ",writeto,"with roles and users:",msg);
\r
458 } catch (IOException e) {
\r
459 throw new CadiException(e);
\r
462 /////////////////////////////////////////////////////
\r
463 // Configure the AAF Lur (if any)
\r
464 /////////////////////////////////////////////////////
\r
465 String aafURL = logProp(access,AAF_URL,null); // Trigger Property
\r
466 String aaf_env = access.getProperty(AAF_ENV,null);
\r
467 if(aaf_env == null && aafURL!=null && access instanceof PropAccess) { // set AAF_ENV from AAF_URL
\r
468 int ec = aafURL.indexOf("envContext=");
\r
470 ec += 11; // length of envContext=
\r
471 int slash = aafURL.indexOf('/', ec);
\r
473 aaf_env = aafURL.substring(ec, slash);
\r
474 ((PropAccess)access).setProperty(AAF_ENV, aaf_env);
\r
475 access.printf(Level.INIT, "Setting aaf_env to %s from aaf_url value",aaf_env);
\r
481 access.log(Level.INIT,"No AAF LUR properties, AAF will not be loaded");
\r
482 } else {// There's an AAF_URL... try to configure an AAF
\r
483 String aafLurClassStr = logProp(access,AAF_LUR_CLASS,"com.att.cadi.aaf.v2_0.AAFLurPerm");
\r
484 ////////////AAF Lur 2.0 /////////////
\r
485 if(aafLurClassStr.startsWith("com.att.cadi.aaf.v2_0")) {
\r
487 Object aafcon = loadAAFConnector(access, aafURL);
\r
489 access.log(Level.INIT,"AAF LUR class,",aafLurClassStr,"cannot be constructed without valid AAFCon object.");
\r
491 Class<?> aafAbsAAFCon = loadClass(access, "com.att.cadi.aaf.v2_0.AAFCon");
\r
492 Method mNewLur = aafAbsAAFCon.getMethod("newLur");
\r
493 Object aaflur = mNewLur.invoke(aafcon);
\r
496 access.log(Level.INIT,"ERROR! AAF LUR Failed construction. NOT Configured");
\r
498 access.log(Level.INIT,"AAF LUR Configured to ",aafURL);
\r
499 lurs.add((Lur)aaflur);
\r
500 String debugIDs = logProp(access,Config.AAF_DEBUG_IDS, null);
\r
501 if(debugIDs !=null && aaflur instanceof CachingLur) {
\r
502 ((CachingLur<?>)aaflur).setDebug(debugIDs);
\r
506 } catch (Exception e) {
\r
507 access.log(e,"AAF LUR class,",aafLurClassStr,"could not be constructed with given Constructors.");
\r
512 /////////////////////////////////////////////////////
\r
513 // Any Additional passed in Constructor
\r
514 /////////////////////////////////////////////////////
\r
515 if(additionalTafLurs!=null) {
\r
516 for(Object additional : additionalTafLurs) {
\r
517 if(additional instanceof Lur) {
\r
518 lurs.add((Lur)additional);
\r
519 access.log(Level.INIT, additional);
\r
524 /////////////////////////////////////////////////////
\r
525 // Return a Lur based on how many there are...
\r
526 /////////////////////////////////////////////////////
\r
527 switch(lurs.size()) {
\r
529 access.log(Level.INIT,"WARNING! No CADI LURs configured");
\r
530 // Return a NULL Lur that does nothing.
\r
531 return new NullLur();
\r
533 return lurs.get(0); // Only one, just return it, save processing
\r
535 // Multiple Lurs, use EpiLUR to handle
\r
536 Lur[] la = new Lur[lurs.size()];
\r
538 return new EpiLur(la);
\r
542 private static final String COM_ATT_CADI_AAF_V2_0_AAF_CON_DME2 = "com.att.cadi.aaf.v2_0.AAFConDME2";
\r
543 private static final String COM_ATT_CADI_AAF_V2_0_AAF_CON_HTTP = "com.att.cadi.aaf.v2_0.AAFConHttp";
\r
544 public static Object loadAAFConnector(Access access, String aafURL) {
\r
545 Object aafcon = null;
\r
546 Class<?> aafConClass = null;
\r
550 String aafConnector = access.getProperty(AAF_CONNECTOR_CLASS, COM_ATT_CADI_AAF_V2_0_AAF_CON_HTTP);
\r
551 if(COM_ATT_CADI_AAF_V2_0_AAF_CON_DME2.equals(aafConnector) || aafURL.contains("/service=")) {
\r
552 aafConClass = loadClass(access, COM_ATT_CADI_AAF_V2_0_AAF_CON_DME2);
\r
553 if(aafConClass!=null) {
\r
554 Constructor<?> cons = aafConClass.getConstructor(PropAccess.class);
\r
555 aafcon = cons.newInstance(access);
\r
557 access.log(Level.ERROR, "URL contains '/service=', which requires DME2");
\r
559 } else if(COM_ATT_CADI_AAF_V2_0_AAF_CON_HTTP.equals(aafConnector)) {
\r
560 aafConClass = loadClass(access, COM_ATT_CADI_AAF_V2_0_AAF_CON_HTTP);
\r
561 for(Constructor<?> c : aafConClass.getConstructors()) {
\r
562 List<Object> lo = new ArrayList<Object>();
\r
563 for(Class<?> pc : c.getParameterTypes()) {
\r
564 if(pc.equals(PropAccess.class)) {
\r
566 } else if(pc.equals(Locator.class)) {
\r
567 lo.add(loadLocator(access, aafURL));
\r
572 if(c.getParameterTypes().length!=lo.size()) {
\r
573 continue; // back to another Constructor
\r
575 aafcon = c.newInstance(lo.toArray());
\r
581 String mechid = logProp(access,Config.AAF_MECHID, null);
\r
582 String pass = access.getProperty(Config.AAF_MECHPASS, null);
\r
583 if(mechid!=null && pass!=null) {
\r
585 Method basicAuth = aafConClass.getMethod("basicAuth", String.class, String.class);
\r
586 basicAuth.invoke(aafcon, mechid,pass);
\r
587 } catch (NoSuchMethodException nsme) {
\r
588 // it's ok, don't use
\r
593 } catch (Exception e) {
\r
594 access.log(e,"AAF Connector could not be constructed with given Constructors.");
\r
600 public static Class<?> loadClass(Access access, String className) {
\r
603 cls = access.classLoader().loadClass(className);
\r
604 } catch (ClassNotFoundException cnfe) {
\r
606 cls = access.getClass().getClassLoader().loadClass(className);
\r
607 } catch (ClassNotFoundException cnfe2) {
\r
608 // just return null
\r
614 @SuppressWarnings("unchecked")
\r
615 public static Locator<URI> loadLocator(Access access, String url) {
\r
616 Locator<URI> locator = null;
\r
618 access.log(Level.INIT,"No URL for AAF Login Page. Disabled");
\r
620 if(url.contains("DME2RESOLVE")) {
\r
622 Class<?> lcls = loadClass(access,"com.att.cadi.locator.DME2Locator");
\r
623 Class<?> dmcls = loadClass(access,"com.att.aft.dme2.api.DME2Manager");
\r
624 Constructor<?> cnst = lcls.getConstructor(new Class[] {Access.class,dmcls,String.class});
\r
625 locator = (Locator<URI>)cnst.newInstance(new Object[] {access,null,url});
\r
626 access.log(Level.INFO, "DME2Locator enabled with " + url);
\r
627 } catch (Exception e) {
\r
628 access.log(Level.INIT,"AAF Login Page accessed by " + url + " requires DME2. It is now disabled",e);
\r
632 Class<?> cls = loadClass(access,"com.att.cadi.locator.PropertyLocator");
\r
633 Constructor<?> cnst = cls.getConstructor(new Class[] {String.class});
\r
634 locator = (Locator<URI>)cnst.newInstance(new Object[] {url});
\r
635 access.log(Level.INFO, "PropertyLocator enabled with " + url);
\r
636 } catch (Exception e) {
\r
637 access.log(Level.INIT,"AAF Login Page accessed by " + url + " requires PropertyLocator. It is now disabled",e);
\r
645 * DME2 can only read Passwords as clear text properties. Leaving in "System Properties" un-encrypted exposes these passwords
\r
647 public static class PasswordRemoval extends TimerTask {
\r
648 private Access access;
\r
650 private final List<String> pws;
\r
652 public PasswordRemoval(Access access) {
\r
653 this.access = access;
\r
654 pws = new ArrayList<String>();
\r
658 public void run() {
\r
659 for(String key:pws) {
\r
660 access.log(Level.INIT, "Scrubbing " + key);
\r
661 System.clearProperty(key);
\r
664 public void add(String key) {
\r
669 private static final String Y = "Y";
\r
671 private static String[][] CONVERTER_STRINGS=new String[][] {
\r
672 {AFT_DME2_KEYSTORE,CADI_KEYSTORE,null},
\r
673 {AFT_DME2_KEYSTORE_PASSWORD,CADI_KEYSTORE_PASSWORD,null},
\r
674 {AFT_DME2_KEY_PASSWORD,CADI_KEY_PASSWORD,null},
\r
675 {AFT_DME2_TRUSTSTORE,CADI_TRUSTSTORE,null},
\r
676 {AFT_DME2_TRUSTSTORE_PASSWORD,CADI_TRUSTSTORE_PASSWORD,null},
\r
677 {AFT_DME2_CLIENT_KEYSTORE,CADI_KEYSTORE,null},
\r
678 {AFT_DME2_CLIENT_KEYSTORE_PASSWORD,CADI_KEYSTORE_PASSWORD,null},
\r
679 {AFT_DME2_CLIENT_TRUSTSTORE,CADI_TRUSTSTORE,null},
\r
680 {AFT_DME2_CLIENT_TRUSTSTORE_PASSWORD,CADI_TRUSTSTORE_PASSWORD,null},
\r
681 {AFT_DME2_CLIENT_SSL_CERT_ALIAS,CADI_ALIAS,null},
\r
682 {AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS,CADI_PROTOCOLS,null},
\r
683 {"AFT_DME2_HOSTNAME",HOSTNAME,null},
\r
684 {"AFT_LATITUDE",null,Y},
\r
685 {"AFT_LONGITUDE",null,Y},
\r
686 {"AFT_ENVIRONMENT",null,Y},
\r
687 {"SCLD_PLATFORM",null,Y},
\r
688 {"DME2_EP_REGISTRY_CLASS",null,Y},// for Developer local access
\r
689 {"AFT_DME2_EP_REGISTRY_FS_DIR",null,Y},
\r
690 {"DME2.DEBUG",null,null},
\r
691 {"AFT_DME2_HTTP_EXCHANGE_TRACE_ON",null,null},
\r
692 {"AFT_DME2_SSL_ENABLE",null,null},
\r
693 {"AFT_DME2_SSL_WANT_CLIENT_AUTH",null,null},
\r
694 {AFT_DME2_SSL_INCLUDE_PROTOCOLS,CADI_PROTOCOLS,null},
\r
695 {"AFT_DME2_SSL_VALIDATE_CERTS",null,null},
\r
696 {AFT_DME2_CLIENT_IGNORE_SSL_CONFIG,null,null},
\r
697 {"https.protocols",CADI_PROTOCOLS,Y},
\r
702 public static Properties getDME2Props(PropAccess access) {
\r
703 Properties dprops = new Properties();
\r
704 String value = null;
\r
705 boolean reqClientConfig = false;
\r
706 for(String[] row : CONVERTER_STRINGS) {
\r
707 value = access.getProperty(row[0],null);
\r
709 value = System.getProperty(row[0]);
\r
710 if(value==null && row[1]!=null) {
\r
711 value = access.getProperty(row[1],null);
\r
712 if(value == null) {
\r
713 value = System.getProperty(row[1]);
\r
718 if(row[0].contains("_SSL_")) {
\r
719 reqClientConfig = true;
\r
721 if(row[0].startsWith("AFT") || row[0].startsWith("SCLD") || row[0].contains("DME2")) {
\r
722 if(value.startsWith("enc:")) {
\r
724 value = access.decrypt(value, true);
\r
725 } catch (IOException e) {
\r
726 access.log(Level.ERROR, e);
\r
728 System.setProperty(row[0], value);
\r
729 } else if(Y.equals(row[2])) {
\r
730 System.setProperty(row[0], value);
\r
731 dprops.setProperty(row[0], value);
\r
732 } else if(row[0].contains("PASSWORD") || row[0].contains("STORE")) {
\r
733 System.setProperty(row[0], value);
\r
735 dprops.setProperty(row[0], value);
\r
743 Properties sprops = System.getProperties();
\r
744 if(reqClientConfig && sprops.getProperty(AFT_DME2_CLIENT_IGNORE_SSL_CONFIG)==null) {
\r
745 sprops.put(AFT_DME2_CLIENT_IGNORE_SSL_CONFIG, "false");
\r
746 replaceKeyWithTrust(sprops,AFT_DME2_KEYSTORE,AFT_DME2_TRUSTSTORE);
\r
747 replaceKeyWithTrust(sprops,AFT_DME2_KEYSTORE_PASSWORD,AFT_DME2_TRUSTSTORE_PASSWORD);
\r
748 replaceKeyWithTrust(sprops,AFT_DME2_CLIENT_KEYSTORE,AFT_DME2_CLIENT_TRUSTSTORE);
\r
749 replaceKeyWithTrust(sprops,AFT_DME2_CLIENT_KEYSTORE_PASSWORD,AFT_DME2_CLIENT_TRUSTSTORE_PASSWORD);
\r
752 if(sprops.getProperty(AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS)==null) {
\r
753 sprops.setProperty(AFT_DME2_CLIENT_SSL_INCLUDE_PROTOCOLS, access.getProperty(CADI_PROTOCOLS,SecurityInfo.HTTPS_PROTOCOLS_DEFAULT));
\r
756 if(sprops.getProperty(AFT_DME2_SSL_INCLUDE_PROTOCOLS)==null) {
\r
757 sprops.setProperty(AFT_DME2_SSL_INCLUDE_PROTOCOLS, access.getProperty(CADI_PROTOCOLS,SecurityInfo.HTTPS_PROTOCOLS_DEFAULT));
\r
760 if(access.willLog(Level.DEBUG)) {
\r
761 if(access instanceof PropAccess) {
\r
762 access.log(Level.DEBUG,"Access Properties");
\r
763 for(Entry<Object, Object> es : ((PropAccess)access).getProperties().entrySet()) {
\r
764 access.printf(Level.DEBUG," %s=%s",es.getKey().toString(),es.getValue().toString());
\r
767 access.log(Level.DEBUG,"DME2 Properties()");
\r
768 for(Entry<Object, Object> es : dprops.entrySet()) {
\r
769 value = es.getValue().toString();
\r
770 if(es.getKey().toString().contains("PASS")) {
\r
771 if(value==null || !value.contains("enc:")) {
\r
775 access.printf(Level.DEBUG," %s=%s",es.getKey().toString(),value);
\r
778 access.log(Level.DEBUG,"System (AFT) Properties");
\r
779 for(Entry<Object, Object> es : System.getProperties().entrySet()) {
\r
780 if(es.getKey().toString().startsWith("AFT")) {
\r
781 value = es.getValue().toString();
\r
782 if(es.getKey().toString().contains("PASS")) {
\r
783 if(value==null || !value.contains("enc:")) {
\r
787 access.printf(Level.DEBUG," %s=%s",es.getKey().toString(),value);
\r
791 // Cover any not specific AFT props
\r
793 for(Entry<Object, Object> es : access.getProperties().entrySet()) {
\r
794 if((key=es.getKey().toString()).startsWith("AFT_") &&
\r
795 !key.contains("PASSWORD") &&
\r
796 dprops.get(key)==null) {
\r
797 dprops.put(key, es.getValue());
\r
803 private static void replaceKeyWithTrust(Properties props, String ks, String ts) {
\r
805 if(props.get(ks)==null && (value=props.getProperty(ts))!=null) {
\r
806 props.put(ks,value);
\r
810 // Set by CSP, or is hostname.
\r
811 public static String getDefaultRealm() {
\r
812 return defaultRealm;
\r