diff options
120 files changed, 2079 insertions, 838 deletions
diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/FutureDAO.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/FutureDAO.java index 7831815f..72c0e98b 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/FutureDAO.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/FutureDAO.java @@ -90,9 +90,9 @@ public class FutureDAO extends CassDAOImpl<AuthzTrans,FutureDAO.Data> { data.memo = row.getString(2); data.start = row.getTimestamp(3); data.expires = row.getTimestamp(4); - data.construct = row.getBytes(5); - data.target_key = row.getString(6); - data.target_date = row.getTimestamp(7); + data.target_key = row.getString(5); + data.target_date = row.getTimestamp(6); + data.construct = row.getBytes(7); return data; } @@ -109,9 +109,9 @@ public class FutureDAO extends CassDAOImpl<AuthzTrans,FutureDAO.Data> { obj[++idx] = data.memo; obj[++idx] = data.start; obj[++idx] = data.expires; - obj[++idx] = data.construct; obj[++idx] = data.target_key; obj[++idx] = data.target_date; + obj[++idx] = data.construct; } } diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/NsDAO.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/NsDAO.java index f769e38c..10e7844c 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/NsDAO.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/NsDAO.java @@ -64,6 +64,7 @@ public class NsDAO extends CassDAOImpl<AuthzTrans,NsDAO.Data> { public static final String TABLE = "ns"; public static final String TABLE_ATTRIB = "ns_attrib"; public static final int CACHE_SEG = 0x40; // yields segment 0x0-0x3F + public static final int USER = 0; public static final int ROOT = 1; public static final int COMPANY=2; public static final int APP = 3; diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/PermDAO.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/PermDAO.java index 6e1057b8..0033f8a1 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/PermDAO.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/PermDAO.java @@ -93,11 +93,31 @@ public class PermDAO extends CassDAOImpl<AuthzTrans,PermDAO.Data> { } public String fullType() { - return ns + '.' + type; + StringBuilder sb = new StringBuilder(); + if(ns==null) { + sb.append('.'); + } else { + sb.append(ns); + sb.append(ns.indexOf('@')<0?'.':':'); + } + sb.append(type); + return sb.toString(); } public String fullPerm() { - return ns + '.' + type + '|' + instance + '|' + action; + StringBuilder sb = new StringBuilder(); + if(ns==null) { + sb.append("null."); + } else { + sb.append(ns); + sb.append(ns.indexOf('@')<0?'.':':'); + } + sb.append(type); + sb.append('|'); + sb.append(instance); + sb.append('|'); + sb.append(action); + return sb.toString(); } public String encode() { @@ -193,17 +213,26 @@ public class PermDAO extends CassDAOImpl<AuthzTrans,PermDAO.Data> { Data rv = new PermDAO.Data(); if (rdns.isOKhasData()) { switch(s.length) { + case 4: + rv.ns=s[0]; + rv.type=s[1]; + rv.instance=s[2]; + rv.action=s[3]; + break; case 3: + rv.ns=s[0]; rv.type=s[1]; rv.instance=s[2]; rv.action=s[3]; break; case 2: + rv.ns=s[0]; rv.type=s[1]; rv.instance=s[2]; rv.action=STAR; break; default: + rv.ns=s[0]; rv.type=s[1]; rv.instance = STAR; rv.action = STAR; diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/RoleDAO.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/RoleDAO.java index 127dd4e2..a5fa7a77 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/RoleDAO.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/cass/RoleDAO.java @@ -106,7 +106,15 @@ public class RoleDAO extends CassDAOImpl<AuthzTrans,RoleDAO.Data> { } public String fullName() { - return ns + '.' + name; + StringBuilder sb = new StringBuilder(); + if(ns==null) { + sb.append('.'); + } else { + sb.append(ns); + sb.append(ns.indexOf('@')<0?'.':':'); + } + sb.append(name); + return sb.toString(); } public String encode() { @@ -122,19 +130,29 @@ public class RoleDAO extends CassDAOImpl<AuthzTrans,RoleDAO.Data> { * @return */ public static Result<Data> decode(AuthzTrans trans, Question q, String r) { - String[] ss = Split.splitTrim('|', r,2); Data data = new Data(); - if (ss[1]==null) { // older 1 part encoding must be evaluated for NS - Result<NsSplit> nss = q.deriveNsSplit(trans, ss[0]); - if (nss.notOK()) { - return Result.err(nss); - } - data.ns=nss.value.ns; - data.name=nss.value.name; - } else { // new 4 part encoding - data.ns=ss[0]; - data.name=ss[1]; - } + if(r.indexOf('@')>=0) { + int colon = r.indexOf(':'); + if(colon<0) { + return Result.err(Result.ERR_BadData, "%s is not a valid Role",r); + } else { + data.ns=r.substring(0, colon); + data.name=r.substring(++colon); + } + } else { + String[] ss = Split.splitTrim('|', r,2); + if (ss[1]==null) { // older 1 part encoding must be evaluated for NS + Result<NsSplit> nss = q.deriveNsSplit(trans, ss[0]); + if (nss.notOK()) { + return Result.err(nss); + } + data.ns=nss.value.ns; + data.name=nss.value.name; + } else { // new 4 part encoding + data.ns=ss[0]; + data.name=ss[1]; + } + } return Result.ok(data); } diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Function.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Function.java index 43e121ac..c59312c0 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Function.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Function.java @@ -1060,8 +1060,8 @@ public class Function { } else if (!fullperm.roles.isEmpty()) { return Result .err(Status.ERR_DependencyExists, - "Permission [%s.%s|%s|%s] cannot be deleted as it is attached to 1 or more roles.", - fullperm.ns, fullperm.type, fullperm.instance, fullperm.action); + "Permission [%s] cannot be deleted as it is attached to 1 or more roles.", + fullperm.fullPerm()); } } diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java index 2c98a9bc..ae6f371b 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/dao/hl/Question.java @@ -187,6 +187,7 @@ public class Question { private final CacheInfoDAO cacheInfoDAO; private final int cldays; + private final boolean alwaysSpecial; public Question(AuthzTrans trans, Cluster cluster, String keyspace) throws APIException, IOException { PERMS = trans.slot("USER_PERMS"); @@ -220,6 +221,8 @@ public class Question { AbsCassDAO.primePSIs(trans); cldays = Integer.parseInt(trans.getProperty(Config.AAF_CRED_WARN_DAYS, Config.AAF_CRED_WARN_DAYS_DFT)); + + alwaysSpecial = Boolean.parseBoolean(trans.getProperty("aaf_always_special", Boolean.FALSE.toString())); } public void startTimers(AuthzEnv env) { @@ -322,13 +325,22 @@ public class Question { return permDAO.readByType(trans, nss.value.ns, nss.value.name); } - public Result<List<PermDAO.Data>> getPermsByName(AuthzTrans trans, - String type, String instance, String action) { - Result<NsSplit> nss = deriveNsSplit(trans, type); - if (nss.notOK()) { - return Result.err(nss); - } - return permDAO.read(trans, nss.value.ns, nss.value.name, instance,action); + public Result<List<PermDAO.Data>> getPermsByName(AuthzTrans trans, String type, String instance, String action) { + if(type.indexOf('@') >= 0) { + int colon = type.indexOf(':'); + if(colon>=0) { + return permDAO.read(trans, type.substring(0, colon),type.substring(colon+1), instance,action); + } else { + return Result.err(Result.ERR_BadData, "%s is malformed",type); + } + } else { + Result<NsSplit> nss = deriveNsSplit(trans, type); + if (nss.notOK()) { + return Result.err(nss); + } + + return permDAO.read(trans, nss.value.ns, nss.value.name, instance,action); + } } public Result<List<PermDAO.Data>> getPermsByRole(AuthzTrans trans, String role, boolean lookup) { @@ -374,8 +386,14 @@ public class Question { return Result.ok(perms); } - public Result<List<RoleDAO.Data>> getRolesByName(AuthzTrans trans, - String role) { + public Result<List<RoleDAO.Data>> getRolesByName(AuthzTrans trans, String role) { + if(role.startsWith(trans.user()) ) { + if(role.endsWith(":user")) { + return roleDAO.read(trans,trans.user(), "user"); + } else { + return Result.err(Result.ERR_BadData,"%s is a badly formatted role",role); + } + } Result<NsSplit> nss = deriveNsSplit(trans, role); if (nss.notOK()) { return Result.err(nss); @@ -412,12 +430,7 @@ public class Question { if (r.isOKhasData()) { return Result.ok(r.value.get(0)); } else { - int dot; - if (child==null) { - return Result.err(Status.ERR_NsNotFound, "No Namespace"); - } else { - dot = child.lastIndexOf('.'); - } + int dot = child.lastIndexOf('.'); if (dot < 0) { return Result.err(Status.ERR_NsNotFound, "No Namespace for [%s]", child); } else { @@ -558,6 +571,9 @@ public class Question { } public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, RoleDAO.Data rdd, Access access) { + if(trans.user().equals(rdd.ns)) { + return Result.ok((NsDAO.Data)null); + } Result<NsDAO.Data> rnsd = deriveNs(trans, rdd.ns); if (rnsd.isOK()) { return mayUser(trans, user, rnsd.value, rdd, access); @@ -612,6 +628,17 @@ public class Question { } public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,PermDAO.Data pdd, Access access) { + if(pdd.ns.indexOf('@')>-1) { + if(user.equals(pdd.ns) || isGranted(trans,user,Define.ROOT_NS(),"access",pdd.instance,READ)) { + NsDAO.Data ndd = new NsDAO.Data(); + ndd.name = user; + ndd.type = NsDAO.USER; + ndd.parent = ""; + return Result.ok(ndd); + } else { + return Result.err(Result.ERR_Security,"Only a User may modify User"); + } + } Result<NsDAO.Data> rnsd = deriveNs(trans, pdd.ns); if (rnsd.isOK()) { return mayUser(trans, user, rnsd.value, pdd, access); @@ -831,6 +858,7 @@ public class Question { byte[] md5=Hash.hashMD5(cred); if (Hash.compareTo(md5,dbcred)==0) { checkLessThanDays(trans,cldays,now,cdd); + trans.setTag(cdd.tag); return Result.ok(cdd.expires); } else if (debug!=null) { load(debug, cdd); @@ -844,6 +872,7 @@ public class Question { if (Hash.compareTo(hash,dbcred)==0) { checkLessThanDays(trans,cldays,now,cdd); + trans.setTag(cdd.tag); return Result.ok(cdd.expires); } else if (debug!=null) { load(debug, cdd); @@ -858,34 +887,41 @@ public class Question { } else { if (expired==null || expired.before(cdd.expires)) { expired = cdd.expires; + trans.setTag(cdd.tag); } } } // end for each - if (debug==null) { - trans.audit().printf("No cred matches ip=%s, user=%s\n",trans.ip(),user); - } else { - trans.audit().printf("No cred matches ip=%s, user=%s %s\n",trans.ip(),user,debug.toString()); - } + if (expired!=null) { // Note: this is only returned if there are no good Credentials rv = Result.err(Status.ERR_Security, - "Credentials %s from %s expired %s",trans.user(), trans.ip(), Chrono.dateTime(expired)); + "Credentials expired %s",Chrono.utcStamp(expired)); + } else { + if (debug==null && alwaysSpecial) { + debug = new StringBuilder(); + } + if (debug!=null) { + debug.append(trans.env().encryptor().encrypt(new String(cred))); + rv = Result.err(Status.ERR_Security,String.format("invalid password - %s",debug.toString())); + } } } } else { return Result.err(result); } - return rv == null ? Result.create((Date) null, Status.ERR_Security, "Wrong credential") : rv; + return rv == null ? Result.err(Status.ERR_Security, "Wrong credential") : rv; } private void load(StringBuilder debug, Data cdd) { - debug.append("DB Entry: user="); + debug.append("\nDB Entry: user="); debug.append(cdd.id); debug.append(",type="); debug.append(cdd.type); debug.append(",expires="); debug.append(Chrono.dateTime(cdd.expires)); + debug.append(",tag="); + debug.append(cdd.tag); debug.append('\n'); } diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFLocator.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFLocator.java index 98459672..2f1d150c 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFLocator.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFLocator.java @@ -73,9 +73,11 @@ public class DirectAAFLocator extends AbsAAFLocator<AuthzTrans> { } try { - String aaf_url = access.getProperty(Config.AAF_URL, null); - if(aaf_url==null) { - aaf_url = "https://"+Config.AAF_LOCATE_URL_TAG+"/%NS."+name; + String aaf_url; + if(name.indexOf('.')>=0) { + aaf_url = "https://"+Config.AAF_LOCATE_URL_TAG+'/'+name+':'+version; + } else { + aaf_url = "https://"+Config.AAF_LOCATE_URL_TAG+"/%NS."+name+':'+version; } RegistrationPropHolder rph = new RegistrationPropHolder(access,0); aaf_url = rph.replacements(getClass().getSimpleName(),aaf_url, null,null); diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFUserPass.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFUserPass.java index 3ef532b4..3c7d873e 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFUserPass.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectAAFUserPass.java @@ -52,28 +52,37 @@ public class DirectAAFUserPass implements CredVal { @Override public boolean validate(String user, Type type, byte[] pass, Object state) { + if(user==null || type==null || pass==null) { + return false; + } + try { AuthzTrans trans; + boolean transfer = false; if (state !=null) { if (state instanceof AuthzTrans) { trans = (AuthzTrans)state; } else { trans = env.newTransNoAvg(); if (state instanceof HttpServletRequest) { - trans.set((HttpServletRequest)state); + trans.set((HttpServletRequest)state,null); + transfer=true; } } } else { trans = env.newTransNoAvg(); } Result<Date> result = question.doesUserCredMatch(trans, user, pass); - trans.logAuditTrail(env.info()); + if(transfer) { + ((HttpServletRequest)state).setAttribute("CRED_TAG", trans.getTag()); + } + trans.logAuditTrail(env.debug()); switch(result.status) { case OK: return true; default: - String ip = trans.ip()==null?"":(", ip="+trans.ip()); - env.warn().log(user, "failed password validation" + ip + ':',result.errorString()); + String ip = trans.ip()==null?"":trans.ip(); + env.audit().printf("user=%s,tag=%s,ip=%s,msg=\"failed password validation: %s\"",user,trans.getTag(),ip,result.errorString()); } } catch (DAOException e) { env.error().log(e,"Cannot validate user/pass from cassandra"); diff --git a/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectRegistrar.java b/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectRegistrar.java index ec5449df..99421097 100644 --- a/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectRegistrar.java +++ b/auth/auth-cass/src/main/java/org/onap/aaf/auth/direct/DirectRegistrar.java @@ -49,7 +49,7 @@ public class DirectRegistrar implements Registrant<AuthzEnv> { ldd.add(convert(me)); } } - + private LocateDAO.Data convert(MgmtEndpoint me) { LocateDAO.Data out = new LocateDAO.Data(); out.name=me.getName(); diff --git a/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/aaf/test/AbsJUCass.java b/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/aaf/test/AbsJUCass.java index dea2ccdd..bb0fcd43 100644 --- a/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/aaf/test/AbsJUCass.java +++ b/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/aaf/test/AbsJUCass.java @@ -104,9 +104,6 @@ public class AbsJUCass { // Load special data here - // WebPhone - env.setProperty("java.naming.provider.url","ldap://ldap.webphone.att.com:389"); - env.setProperty("com.sun.jndi.ldap.connect.pool","true"); iterations = 0; diff --git a/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/cass/JU_RoleDAO.java b/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/cass/JU_RoleDAO.java index 16f05aa3..fa023af3 100644 --- a/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/cass/JU_RoleDAO.java +++ b/auth/auth-cass/src/test/java/org/onap/aaf/auth/dao/cass/JU_RoleDAO.java @@ -430,7 +430,7 @@ public class JU_RoleDAO { } @Test - public void testWasMOdified() { + public void testWasModified() { TimeTaken tt = Mockito.mock(TimeTaken.class); Mockito.doReturn(tt).when(trans).start("RoleDAO CREATE", Env.REMOTE); Mockito.doReturn(tt).when(trans).start("Clear Reset Deque", Env.SUB); diff --git a/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFLur.java b/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFLur.java index 05077438..f0f3c5d0 100644 --- a/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFLur.java +++ b/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFLur.java @@ -237,7 +237,7 @@ public class JU_DirectAAFLur { assertFalse(pp.match(null)); - pond = new AAFPermission("null.test", "name", "instance", "action"); - pp.match(pond); + pond = new AAFPermission("test.test", "test", "test", "test"); + assertTrue(pp.match(pond)); } } diff --git a/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFUserPass.java b/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFUserPass.java index ca0a8917..c767aeb5 100644 --- a/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFUserPass.java +++ b/auth/auth-cass/src/test/java/org/onap/aaf/auth/direct/test/JU_DirectAAFUserPass.java @@ -125,7 +125,7 @@ public class JU_DirectAAFUserPass { } boolean retVal = aafLocatorObj.validate(null, null, null, null); - assertTrue(retVal); + assertFalse(retVal); } @Test diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/AAF_CM.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/AAF_CM.java index 3727e34d..7dea9f07 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/AAF_CM.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/AAF_CM.java @@ -244,11 +244,10 @@ public class AAF_CM extends AbsService<AuthzEnv, AuthzTrans> { try { Log4JLogIt logIt = new Log4JLogIt(args, "cm"); PropAccess propAccess = new PropAccess(logIt,args); - try { - AAF_CM service = new AAF_CM(new AuthzEnv(propAccess)); - JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service); - jss.start(); + new JettyServiceStarter<AuthzEnv,AuthzTrans>( + new AAF_CM(new AuthzEnv(propAccess)),true) + .start(); } catch (Exception e) { propAccess.log(e); } diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java index 881c9bea..10da10d9 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java @@ -47,6 +47,7 @@ public abstract class CA { public static final String ISSUING_CA = "Issuing CA"; public static final String CM_CA_PREFIX = "cm_ca."; public static final String CM_CA_BASE_SUBJECT = ".baseSubject"; + public static final String CM_CA_ENV_TAG = ".env_tag"; protected static final String CM_PUBLIC_DIR = "cm_public_dir"; private static final String CM_TRUST_CAS = "cm_trust_cas"; protected static final String CM_BACKUP_CAS = "cm_backup_cas"; @@ -63,12 +64,15 @@ public abstract class CA { private String[] trustedCAs; private String[] caIssuerDNs; private List<RDN> rdns; + private final boolean env_tag; protected CA(Access access, String caName, String env) throws IOException, CertException { trustedCAs = new String[4]; // starting array this.name = caName; this.env = env; + this.env_tag = env==null || env.isEmpty()?false: + Boolean.parseBoolean(access.getProperty(CM_CA_ENV_TAG, Boolean.FALSE.toString())); permNS = CM_CA_PREFIX + name; permType = access.getProperty(permNS + ".perm_type",null); if (permType==null) { @@ -189,6 +193,10 @@ public abstract class CA { return trustedCAs; } + public boolean shouldAddEnvTag() { + return env_tag; + } + public String getEnv() { return env; } diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java index 18f062d5..1f2b0880 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java @@ -193,7 +193,8 @@ public class CMService { } else if (primary == null) { return Result.err(Result.ERR_Denied, "Request not made from matching IP (%s)", trans.ip()); } else { - host = primary.getHostAddress(); + String thost = primary.getHostName(); + host = thost==null?primary.getHostAddress():thost; } ArtiDAO.Data add = null; @@ -296,6 +297,7 @@ public class CMService { CSRMeta csrMeta; try { csrMeta = BCFactory.createCSRMeta(ca, req.value.mechid, email, fqdns); + csrMeta.environment(ca.getEnv()); X509andChain x509ac = ca.sign(trans, csrMeta); if (x509ac == null) { return Result.err(Result.ERR_ActionNotCompleted, "x509 Certificate not signed by CA"); diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Artifact.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Artifact.java index ab10e66b..4ef85aa2 100644 --- a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Artifact.java +++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Artifact.java @@ -59,8 +59,9 @@ public class JU_API_Artifact { public static void setUp() { AuthzTrans trans = mock(AuthzTrans.class); req = mock(HttpServletRequest.class); + res = mock(HttpServletResponse.class); trans.setProperty("testTag", "UserValue"); - trans.set(req); + trans.set(req,res); } @Rule diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Cert.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Cert.java index 49632975..674e4edf 100644 --- a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Cert.java +++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Cert.java @@ -59,8 +59,9 @@ public class JU_API_Cert { public static void setUp() { AuthzTrans trans = mock(AuthzTrans.class); req = mock(HttpServletRequest.class); + res = mock(HttpServletResponse.class); trans.setProperty("testTag", "UserValue"); - trans.set(req); + trans.set(req,res); } @Rule diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/AAFcli.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/AAFcli.java index edbe2068..8fcea294 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/AAFcli.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/AAFcli.java @@ -94,6 +94,10 @@ public class AAFcli { this(access,new AuthzEnv(access.getProperties()),wtr,hman, si,ss); } + public AuthzEnv env() { + return env; + } + public AAFcli(Access access, AuthzEnv env, Writer wtr, HMangr hman, SecurityInfoC<HttpURLConnection> si, SecuritySetter<HttpURLConnection> ss) throws APIException { this.env = env; this.access = access; @@ -328,7 +332,7 @@ public class AAFcli { Thread.sleep((long)(delay+globalDelay)); } } catch (Exception e) { - if (expect.contains(-1)) { + if (expect.contains(-1)) { pw.println(e.getMessage()); ret = -1; } else { diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Help.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Help.java index 12cf0635..49ffb51b 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Help.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Help.java @@ -31,7 +31,7 @@ public class Help extends Cmd { private List<Cmd> cmds; public Help(AAFcli aafcli, List<Cmd> cmds) { - super(aafcli, "--help", + super(aafcli, "help", new Param("-d (more details)", false), new Param("command",false)); this.cmds = cmds; diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Version.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Version.java index 1b1b1831..d4a82d5d 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Version.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/Version.java @@ -27,17 +27,18 @@ import org.onap.aaf.cadi.config.Config; import org.onap.aaf.misc.env.APIException; public class Version extends Cmd { + private final String version; - - public Version(AAFcli aafcli) { - super(aafcli, "--version"); + public Version(AAFcli aafcli) { + super(aafcli, "version"); + version = aafcli.access.getProperty(Config.AAF_DEPLOYED_VERSION, Config.AAF_DEFAULT_API_VERSION); } @Override protected int _exec(int idx, String... args) throws CadiException, APIException, LocatorException { pw().println("AAF Command Line Tool"); pw().print("Version: "); - pw().println(Config.AAF_DEFAULT_API_VERSION); + pw().println(version); return 200; } } diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersContact.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersContact.java index eadf1c97..d6eb9b30 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersContact.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersContact.java @@ -117,7 +117,7 @@ public class ListUsersContact extends Cmd { indent+=4; detailLine(sb,indent,"Report Users associated with this Namespace's Roles"); sb.append('\n'); - detailLine(sb,indent,"If \"set details=true\" is specified, then all roles are printed "); + detailLine(sb,indent,"If \"details\" is specified, then all roles are printed "); detailLine(sb,indent,"with the associated users and expiration dates"); indent-=4; api(sb,indent,HttpMethods.GET,"authz/nss/<ns>",Nss.class,true); diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersInRole.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersInRole.java index c0838cb7..b33f506d 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersInRole.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/ns/ListUsersInRole.java @@ -117,7 +117,7 @@ public class ListUsersInRole extends Cmd { indent+=4; detailLine(sb,indent,"Report Users associated with this Namespace's Roles"); sb.append('\n'); - detailLine(sb,indent,"If \"set details=true\" is specified, then all roles are printed "); + detailLine(sb,indent,"If \"details\" is specified, then all roles are printed "); detailLine(sb,indent,"with the associated users and expiration dates"); indent-=4; api(sb,indent,HttpMethods.GET,"authz/nss/<ns>",Nss.class,true); diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/Delete.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/Delete.java index 0f0c0011..3edc0e59 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/Delete.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/Delete.java @@ -59,8 +59,12 @@ public class Delete extends Cmd { pk.setInstance(args[idx++]); pk.setAction(args[idx++]); - // Set "Force" if set - setQueryParamsOn(client); + if(pk.getType().contains("@")) { // User Perm deletion... Must remove from hidden role + client.setQueryParams("force"); + } else { + // Set "Force" if set + setQueryParamsOn(client); + } Future<PermRequest> fp = client.delete( "/authz/perm", getDF(PermRequest.class), diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/ListByUser.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/ListByUser.java index 325f45db..00972a18 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/ListByUser.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/perm/ListByUser.java @@ -57,9 +57,9 @@ public class ListByUser extends Cmd { } if (aafcli.isDetailed()) { if (sb==null) { - sb = new StringBuilder('?'); + sb = new StringBuilder("?"); } else { - sb.append('&'); + sb.append("&"); } sb.append("ns"); } diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/Cred.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/Cred.java index d41f0cf3..a1cb3e7a 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/Cred.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/Cred.java @@ -21,30 +21,37 @@ package org.onap.aaf.auth.cmd.user; +import java.util.List; + import org.onap.aaf.auth.cmd.AAFcli; import org.onap.aaf.auth.cmd.Cmd; import org.onap.aaf.auth.cmd.Param; import org.onap.aaf.auth.rserv.HttpMethods; import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.LocatorException; +import org.onap.aaf.cadi.aaf.client.ErrMessage; 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.misc.env.APIException; import aaf.v2_0.CredRequest; +import aaf.v2_0.Error; public class Cred extends Cmd { public static final String ATTEMPT_FAILED_SPECIFICS_WITHELD = "Attempt Failed. Specifics witheld."; private static final String CRED_PATH = "/authn/cred"; private static final String[] options = {"add","del","reset","extend"/*,"clean"*/}; - public Cred(User parent) { + private ErrMessage em; +// private RosettaDF<Error> errDF; + public Cred(User parent) throws APIException { super(parent,"cred", new Param(optionsToString(options),true), new Param("id",true), new Param("password (! D|E)",false), new Param("entry# (if multi)",false) ); + em = new ErrMessage(aafcli.env()); } @Override @@ -59,8 +66,9 @@ public class Cred extends Cmd { if (idx>=args.length) throw new CadiException("Password Required"); cr.setPassword(args[idx++]); } - if (args.length>idx) + if (args.length>idx) { cr.setEntry(args[idx]); + } // Set Start/End commands setStartEnd(cr); @@ -114,6 +122,19 @@ public class Cred extends Cmd { pw().println(']'); } else if (fp.code()==202) { pw().println("Credential Action Accepted, but requires Approvals before actualizing"); + } else if (fp.code()==300) { + Error err = em.getError(fp); + String text = err.getText(); + List<String> vars = err.getVariables(); + + // IMPORTANT! We do this backward, because it is looking for string + // %1 or %13. If we replace %1 first, that messes up %13 + for(int i=vars.size()-1;i>0;--i) { + text = text.replace("%"+(i+1), (i<10?" ":"") + i+") " + vars.get(i)); + } + + text = text.replace("%1",vars.get(0)); + pw().println(text); } else if (fp.code()==406 && option==1) { pw().println("You cannot delete this Credential"); } else { diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/List.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/List.java index 6d993284..7daa51fb 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/List.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/List.java @@ -62,14 +62,12 @@ public class List extends BaseCmd<User> { if (!aafcli.isTest()) { date = Chrono.dateOnlyStamp(user.getExpires()); } - String tag=null; - if(user.getType()<200) { - tag = user.getTag(); - } else { - tag = "\n\tfingerprint: " + user.getTag(); - } + String tag=user.getTag(); + Integer type = user.getType(); if(tag==null) { tag=""; + } else if(type!=null && type>=200) { + tag = "\n\tfingerprint: " + tag; } pw().format(format, count? (Integer.valueOf(++idx) + ") " + user.getId()): user.getId(), diff --git a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/ListForRoles.java b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/ListForRoles.java index b534240b..4e539ac2 100644 --- a/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/ListForRoles.java +++ b/auth/auth-cmd/src/main/java/org/onap/aaf/auth/cmd/user/ListForRoles.java @@ -21,9 +21,6 @@ package org.onap.aaf.auth.cmd.user; -import java.util.Collections; -import java.util.Comparator; - import org.onap.aaf.auth.cmd.AAFcli; import org.onap.aaf.auth.cmd.Cmd; import org.onap.aaf.auth.cmd.Param; @@ -36,7 +33,6 @@ import org.onap.aaf.cadi.client.Retryable; import org.onap.aaf.misc.env.APIException; import aaf.v2_0.Users; -import aaf.v2_0.Users.User; /** * p @@ -61,13 +57,6 @@ public class ListForRoles extends Cmd { getDF(Users.class) ); if (fp.get(AAFcli.timeout())) { - if (aafcli.isTest()) - Collections.sort(fp.value.getUser(), new Comparator<User>() { - @Override - public int compare(User u1, User u2) { - return u1.getId().compareTo(u2.getId()); - } - }); ((org.onap.aaf.auth.cmd.user.List)parent).report(fp.value,false, HEADER,role); if (fp.code()==404)return 200; } else { diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/cache/Cache.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/cache/Cache.java index 9393e143..6a8ccf1e 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/cache/Cache.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/cache/Cache.java @@ -31,7 +31,6 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.Trans; @@ -153,7 +152,7 @@ public class Cache<TRANS extends Trans, DATA> { } if (count>0) { - env.info().log(Level.INFO, "Cache removed",count,"expired Cached Elements out of", total); + env.debug().log("Cache removed",count,"expired Cached Elements out of", total); } // If High (total) is reached during this period, increase the number of expired services removed for next time. diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTrans.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTrans.java index 0256c1bf..1a1e7f24 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTrans.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTrans.java @@ -24,6 +24,7 @@ package org.onap.aaf.auth.env; import java.util.Date; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.onap.aaf.auth.org.Organization; import org.onap.aaf.cadi.Lur; @@ -39,11 +40,13 @@ public interface AuthzTrans extends TransStore { REQD_TYPE(int bit) { this.bit = bit; } - }; - - public abstract AuthzTrans set(HttpServletRequest req); + } + + public abstract AuthzTrans set(HttpServletRequest req, HttpServletResponse resp); public abstract HttpServletRequest hreq(); + + public abstract HttpServletResponse hresp(); public abstract String user(); @@ -76,5 +79,12 @@ public interface AuthzTrans extends TransStore { public abstract void logAuditTrail(LogTarget lt); public abstract Date now(); + + public abstract void setTag(String tag); + + public abstract String getTag(); + + public abstract void clearCache(); + }
\ No newline at end of file diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java index b08e0240..bda23e13 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java @@ -23,8 +23,8 @@ package org.onap.aaf.auth.env; import java.security.Principal; -import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.onap.aaf.auth.rserv.TransFilter; import org.onap.aaf.cadi.CadiException; @@ -63,16 +63,15 @@ public class AuthzTransFilter extends TransFilter<AuthzTrans> { } @Override - protected AuthzTrans newTrans(HttpServletRequest req) { + protected AuthzTrans newTrans(HttpServletRequest req, HttpServletResponse resp) { AuthzTrans at = env.newTrans(); at.setLur(getLur()); - at.set(req); + at.set(req,resp); return at; } @Override - protected TimeTaken start(AuthzTrans trans, ServletRequest request) { - trans.set((HttpServletRequest)request); + protected TimeTaken start(AuthzTrans trans) { return trans.start("Trans " + //(context==null?"n/a":context.toString()) + " IP: " + trans.ip() + " Port: " + trans.port() @@ -85,9 +84,9 @@ public class AuthzTransFilter extends TransFilter<AuthzTrans> { } @Override - protected void tallyHo(AuthzTrans trans) { + protected void tallyHo(AuthzTrans trans, String target) { Boolean b = trans.get(specialLogSlot, false); - LogTarget lt = b?trans.warn():trans.info(); + LogTarget lt = b?trans.warn():trans.debug(); if (lt.isLoggable()) { // Transaction is done, now post full Audit Trail @@ -131,8 +130,11 @@ public class AuthzTransFilter extends TransFilter<AuthzTrans> { sb.append("user="); Principal p = trans.getUserPrincipal(); if (p==null) { - sb.append("n/a"); + lt=trans.warn(); + sb.append(target); + sb.append("[None]"); } else { + lt=trans.info(); sb.append(p.getName()); if (p instanceof TrustPrincipal) { sb.append('('); @@ -148,6 +150,11 @@ public class AuthzTransFilter extends TransFilter<AuthzTrans> { sb.append(']'); } } + String tag = trans.getTag(); + if(tag!=null) { + sb.append(",tag="); + sb.append(tag); + } sb.append(",ip="); sb.append(trans.ip()); sb.append(",port="); @@ -176,7 +183,7 @@ public class AuthzTransFilter extends TransFilter<AuthzTrans> { sb.append('"'); } - trans.warn().log(sb); + lt.log(sb); } } diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransImpl.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransImpl.java index ce947be9..0af760b8 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransImpl.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransImpl.java @@ -24,6 +24,7 @@ package org.onap.aaf.auth.env; import java.util.Date; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.onap.aaf.auth.org.Organization; import org.onap.aaf.auth.org.OrganizationFactory; @@ -37,23 +38,27 @@ public class AuthzTransImpl extends BasicTrans implements AuthzTrans { private static final String N_A = "n/a"; private static final String BLANK = ""; private HttpServletRequest hreq; + private HttpServletResponse hresp; private TaggedPrincipal user; private Lur lur; private Organization org; private int mask; private Date now; + private String tag; public AuthzTransImpl(AuthzEnv env) { super(env); org=null; mask=0; + tag=null; } /** * @see org.onap.aaf.auth.env.test.AuthTrans#set(javax.servlet.http.HttpServletRequest) */ @Override - public AuthzTrans set(HttpServletRequest req) { + public AuthzTrans set(HttpServletRequest req, HttpServletResponse resp) { hreq = req; + hresp = resp; user = (TaggedPrincipal)req.getUserPrincipal(); for (REQD_TYPE rt : REQD_TYPE.values()) { @@ -68,11 +73,17 @@ public class AuthzTransImpl extends BasicTrans implements AuthzTrans { org=null; return this; } + @Override public HttpServletRequest hreq() { return hreq; } - + + @Override + public HttpServletResponse hresp() { + return hresp; + } + @Override public void setUser(TaggedPrincipal p) { user = p; @@ -172,7 +183,7 @@ public class AuthzTransImpl extends BasicTrans implements AuthzTrans { } return false; } - + /* (non-Javadoc) * @see org.onap.aaf.auth.env.test.AuthzTrans#org() */ @@ -213,4 +224,27 @@ public class AuthzTransImpl extends BasicTrans implements AuthzTrans { } return now; } + + /* + * (non-Javadoc) + * @see org.onap.aaf.auth.env.AuthzTrans#setTag(java.lang.String) + */ + @Override + public void setTag(String tag) { + this.tag = tag; + } + + @Override + public String getTag() { + return tag; + } + + @Override + public void clearCache() { + if (lur!=null) { + StringBuilder report = new StringBuilder(); + lur.clear(user, report); + info().log(report); + } + } } diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransOnlyFilter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransOnlyFilter.java index b1111638..5545c7da 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransOnlyFilter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransOnlyFilter.java @@ -21,8 +21,8 @@ package org.onap.aaf.auth.env; -import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.onap.aaf.auth.rserv.TransOnlyFilter; import org.onap.aaf.cadi.principal.TaggedPrincipal; @@ -43,13 +43,14 @@ public class AuthzTransOnlyFilter extends TransOnlyFilter<AuthzTrans> { } @Override - protected AuthzTrans newTrans() { - return env.newTrans(); + protected AuthzTrans newTrans(HttpServletRequest req, HttpServletResponse resp) { + AuthzTrans trans = env.newTrans(); + trans.set(req, resp); + return trans; } @Override - protected TimeTaken start(AuthzTrans trans, ServletRequest request) { - trans.set((HttpServletRequest)request); + protected TimeTaken start(AuthzTrans trans) { return trans.start("Trans " + //(context==null?"n/a":context.toString()) + " IP: " + trans.ip() + " Port: " + trans.port() diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/NullTrans.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/NullTrans.java index 94a6aad5..f0052e5a 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/NullTrans.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/NullTrans.java @@ -24,6 +24,7 @@ package org.onap.aaf.auth.env; import java.util.Date; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.onap.aaf.auth.org.Organization; import org.onap.aaf.cadi.Lur; @@ -130,7 +131,7 @@ public class NullTrans implements AuthzTrans { return null; } @Override - public AuthzTrans set(HttpServletRequest req) { + public AuthzTrans set(HttpServletRequest req, HttpServletResponse resp) { return null; } @@ -138,7 +139,13 @@ public class NullTrans implements AuthzTrans { public HttpServletRequest hreq() { return null; } + + @Override + public HttpServletResponse hresp() { + return null; + } + @Override public String user() { return null; @@ -236,5 +243,15 @@ public class NullTrans implements AuthzTrans { } return now; } + @Override + public void setTag(String tag) { + } + @Override + public String getTag() { + return null; + } + @Override + public void clearCache() { + } } diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/org/OrganizationFactory.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/org/OrganizationFactory.java index 943b92f5..098fb979 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/org/OrganizationFactory.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/org/OrganizationFactory.java @@ -71,7 +71,7 @@ public class OrganizationFactory { String realm = env.getProperty(Config.AAF_DEFAULT_REALM,"people.osaaf.org"); defaultOrg = cnst.newInstance(env,realm); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) { - env.warn().log("Default Organization Module not linked in",e); + env.init().log("Default Organization Module not linked in",e); } } if (defaultOrg == null) { diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java index a269f24b..37f3b088 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/CachingFileAccess.java @@ -131,6 +131,12 @@ public class CachingFileAccess<TRANS extends Trans> extends HttpCode<TRANS, Void typeMap.put("props", "text/plain"); typeMap.put("jks", "application/octet-stream"); + // Fonts + typeMap.put("ttf","font/ttf"); + typeMap.put("woff","font/woff"); + typeMap.put("woff2","font/woff2"); + + timer = new Timer("Caching Cleanup",true); timer.schedule(new Cleanup(content,500),60000,60000); diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java index d0fc1a3f..81e2e619 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java @@ -33,6 +33,7 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.onap.aaf.auth.env.AuthzTrans; import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.CadiWrap; @@ -85,19 +86,20 @@ public abstract class TransFilter<TRANS extends TransStore> implements Filter { return cadi.getLur(); } - protected abstract TRANS newTrans(HttpServletRequest request); - protected abstract TimeTaken start(TRANS trans, ServletRequest request); + protected abstract TRANS newTrans(HttpServletRequest request,HttpServletResponse response); + protected abstract TimeTaken start(TRANS trans); protected abstract void authenticated(TRANS trans, Principal p); - protected abstract void tallyHo(TRANS trans); + protected abstract void tallyHo(TRANS trans, String target); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest)request; HttpServletResponse res = (HttpServletResponse)response; - TRANS trans = newTrans(req); + TRANS trans = newTrans(req,res); - TimeTaken overall = start(trans,request); + TimeTaken overall = start(trans); + String target = "n/a"; try { request.setAttribute(TRANS_TAG, trans); @@ -116,6 +118,10 @@ public abstract class TransFilter<TRANS extends TransStore> implements Filter { CadiWrap cw = null; try { resp = cadi.validate(req,res,trans); + Object tag = req.getAttribute("CRED_TAG"); + if(tag!=null) { + ((AuthzTrans)trans).setTag(tag.toString()); + } switch(r=resp.isAuthenticated()) { case IS_AUTHENTICATED: cw = new CadiWrap(req,resp,cadi.getLur()); @@ -139,7 +145,7 @@ public abstract class TransFilter<TRANS extends TransStore> implements Filter { // use trans.checkpoint(resp.desc(),Env.ALWAYS); if (resp.isFailedAttempt()) { - trans.audit().log(resp.desc()); + target = resp.getTarget(); } } } catch (Exception e) { @@ -148,7 +154,7 @@ public abstract class TransFilter<TRANS extends TransStore> implements Filter { throw new ServletException(e); } finally { overall.done(); - tallyHo(trans); + tallyHo(trans,target); } } diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransOnlyFilter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransOnlyFilter.java index c3514b65..ef91e485 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransOnlyFilter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransOnlyFilter.java @@ -29,6 +29,8 @@ import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.onap.aaf.cadi.principal.TaggedPrincipal; import org.onap.aaf.misc.env.TimeTaken; @@ -52,16 +54,15 @@ public abstract class TransOnlyFilter<TRANS extends TransStore> implements Filte - protected abstract TRANS newTrans(); - protected abstract TimeTaken start(TRANS trans, ServletRequest request); + protected abstract TRANS newTrans(HttpServletRequest req, HttpServletResponse resp); + protected abstract TimeTaken start(TRANS trans); protected abstract void authenticated(TRANS trans, TaggedPrincipal p); protected abstract void tallyHo(TRANS trans); @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - TRANS trans = newTrans(); - - TimeTaken overall = start(trans,request); + TRANS trans = newTrans((HttpServletRequest)request,(HttpServletResponse)response); + TimeTaken overall = start(trans); try { request.setAttribute(TransFilter.TRANS_TAG, trans); chain.doFilter(request, response); diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsService.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsService.java index 02d93512..5fbb951b 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsService.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsService.java @@ -76,7 +76,7 @@ public abstract class AbsService<ENV extends BasicEnv, TRANS extends Trans> exte str = Defaults.AAF_VERSION; env.setProperty(Config.AAF_LOCATOR_VERSION, str); } - app_version = str; + app_version = access.getProperty(Config.AAF_DEPLOYED_VERSION, str); // Print Cipher Suites Available if (access.willLog(Level.DEBUG)) { diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsServiceStarter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsServiceStarter.java index 0e8cb78d..11ba6562 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsServiceStarter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/AbsServiceStarter.java @@ -43,9 +43,11 @@ public abstract class AbsServiceStarter<ENV extends RosettaEnv, TRANS extends Tr private boolean do_register; protected AbsService<ENV,TRANS> service; protected String hostname; + protected final boolean secure; - public AbsServiceStarter(final AbsService<ENV,TRANS> service) { + public AbsServiceStarter(final AbsService<ENV,TRANS> service, boolean secure) { + this.secure = secure; this.service = service; try { OrganizationFactory.init(service.env); @@ -56,7 +58,6 @@ public abstract class AbsServiceStarter<ENV extends RosettaEnv, TRANS extends Tr // do_register - this is used for specialty Debug Situations. Developer can create an Instance for a remote system // for Debugging purposes without fear that real clients will start to call your debug instance do_register = !"TRUE".equalsIgnoreCase(access().getProperty("aaf_locate_no_register",null)); - _propertyAdjustment(); hostname = access().getProperty(Config.HOSTNAME, null); if (hostname==null) { try { @@ -65,6 +66,7 @@ public abstract class AbsServiceStarter<ENV extends RosettaEnv, TRANS extends Tr hostname= "cannotBeDetermined"; } } + _propertyAdjustment(); } @@ -96,12 +98,14 @@ public abstract class AbsServiceStarter<ENV extends RosettaEnv, TRANS extends Tr }); if(System.getProperty("ECLIPSE", null)!=null) { Thread.sleep(2000); - System.out.println("Service Started in Eclipse: "); - System.out.print(" Hit <enter> to end:"); - try { - System.in.read(); - System.exit(0); - } catch (IOException e) { + if(!app.isCancelled()) { + System.out.println("Service Started in Eclipse: "); + System.out.print(" Hit <enter> to end:\n"); + try { + System.in.read(); + System.exit(0); + } catch (IOException e) { + } } } } @@ -124,6 +128,7 @@ public abstract class AbsServiceStarter<ENV extends RosettaEnv, TRANS extends Tr _start(service); } catch (Exception e) { e.printStackTrace(); + shutdown(); } } diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java index bcc071a2..8d49720b 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java @@ -54,23 +54,11 @@ import org.onap.aaf.misc.rosetta.env.RosettaEnv; public class JettyServiceStarter<ENV extends RosettaEnv, TRANS extends Trans> extends AbsServiceStarter<ENV,TRANS> { - private boolean secure; - public JettyServiceStarter(final AbsService<ENV,TRANS> service) throws OrganizationException { - super(service); - secure = true; + public JettyServiceStarter(final AbsService<ENV,TRANS> service, boolean secure) throws OrganizationException { + super(service, secure); } - /** - * Specifically set this Service starter to Insecure (HTTP) Mode. - * @return - */ - public JettyServiceStarter<ENV,TRANS> insecure() { - secure = false; - return this; - } - - @Override public void _propertyAdjustment() { // System.setProperty("com.sun.management.jmxremote.port", "8081"); diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/validation/Validator.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/validation/Validator.java index 7e861eda..98c09076 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/validation/Validator.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/validation/Validator.java @@ -143,6 +143,21 @@ public class Validator { return this; } + public final Validator permTypeWithUser(String user, String type) { + if (type==null) { + msg("Perm Type is null"); + } else if (user==null) { + msg("User is null"); + } else { + if(!(type.startsWith(user) && type.endsWith(":id"))) { + if(nob(type,NAME_CHARS)) { + msg("Perm Type [" + type + "] is invalid."); + } + } + } + return this; + } + public final Validator permType(String type, String ns) { if (type==null) { msg("Perm Type is null"); @@ -169,6 +184,29 @@ public class Validator { return this; } + public final Validator role(String user, String role) { + boolean quit = false; + if(role==null) { + msg("Role is null"); + quit = true; + } + if(user==null) { + msg("User is null"); + quit = true; + } + if(!quit) { + if(role.startsWith(user) && role.endsWith(":user")) { + if(!(role.length() == user.length() + 5)) { + msg("Role [" + role + "] is invalid."); + } + } else if (nob(role, NAME_CHARS)) { + msg("Role [" + role + "] is invalid."); + } + } + return this; + } + + public final Validator role(String role) { if (nob(role, NAME_CHARS)) { msg("Role [" + role + "] is invalid."); diff --git a/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransImpl.java b/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransImpl.java index f4481ed4..af92e372 100644 --- a/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransImpl.java +++ b/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransImpl.java @@ -66,11 +66,12 @@ public class JU_AuthzTransImpl { public void setUp(){ authzTransImpl = new AuthzTransImpl(authzEnvMock); req = mock(HttpServletRequest.class); - authzTransImpl.set(req); + res = mock(HttpServletResponse.class); + authzTransImpl.set(req,res); when(req.getParameter("request")).thenReturn("NotNull"); - authzTransImpl.set(req); + authzTransImpl.set(req,res); when(req.getParameter("request")).thenReturn(""); - authzTransImpl.set(req); + authzTransImpl.set(req,res); } @Test diff --git a/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransOnlyFilter.java b/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransOnlyFilter.java index 091a3aa6..346ca48f 100644 --- a/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransOnlyFilter.java +++ b/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_AuthzTransOnlyFilter.java @@ -76,10 +76,7 @@ public class JU_AuthzTransOnlyFilter { public void testStart() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { AuthzTransOnlyFilter aTF = new AuthzTransOnlyFilter(authzEnvMock); Class c = aTF.getClass(); - Class[] cArg = new Class[2]; - cArg[0] = AuthzTrans.class; - cArg[1] = ServletRequest.class; //Steps to test a protected method - Method startMethod = c.getDeclaredMethod("start", cArg); + Method startMethod = c.getDeclaredMethod("start", new Class[] {AuthzTrans.class}); startMethod.setAccessible(true); //startMethod.invoke(aTF, authzTransMock, servletRequestMock); } diff --git a/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_NullTrans.java b/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_NullTrans.java index f67716fa..9c7212c2 100644 --- a/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_NullTrans.java +++ b/auth/auth-core/src/test/java/org/onap/aaf/auth/env/test/JU_NullTrans.java @@ -27,6 +27,7 @@ import static org.mockito.Mockito.mock; import java.security.Principal; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.junit.Assert; import org.junit.Before; @@ -157,7 +158,8 @@ public class JU_NullTrans { @Test public void testSet() { HttpServletRequest req = mock(HttpServletRequest.class); - AuthzTrans set = nullTrans.set(req); + HttpServletResponse res = mock(HttpServletResponse.class); + AuthzTrans set = nullTrans.set(req,res); Assert.assertNull(set); } diff --git a/auth/auth-core/src/test/java/org/onap/aaf/auth/server/test/JU_AbsServiceStarter.java b/auth/auth-core/src/test/java/org/onap/aaf/auth/server/test/JU_AbsServiceStarter.java index 9b49216d..4972b572 100644 --- a/auth/auth-core/src/test/java/org/onap/aaf/auth/server/test/JU_AbsServiceStarter.java +++ b/auth/auth-core/src/test/java/org/onap/aaf/auth/server/test/JU_AbsServiceStarter.java @@ -49,8 +49,8 @@ public class JU_AbsServiceStarter { private class AbsServiceStarterStub extends AbsServiceStarter { - public AbsServiceStarterStub(AbsService service) { - super(service); + public AbsServiceStarterStub(AbsService service, boolean secure) { + super(service,secure); // TODO Auto-generated constructor stub } @@ -110,7 +110,7 @@ public class JU_AbsServiceStarter { prop.setLogLevel(Level.DEBUG); absServiceStub = new AbsServiceStub(prop, bEnv); - absServiceStarterStub = new AbsServiceStarterStub(absServiceStub); + absServiceStarterStub = new AbsServiceStarterStub(absServiceStub,true); } // @Test diff --git a/auth/auth-fs/src/main/java/org/onap/aaf/auth/fs/AAF_FS.java b/auth/auth-fs/src/main/java/org/onap/aaf/auth/fs/AAF_FS.java index b56fc03e..67952001 100644 --- a/auth/auth-fs/src/main/java/org/onap/aaf/auth/fs/AAF_FS.java +++ b/auth/auth-fs/src/main/java/org/onap/aaf/auth/fs/AAF_FS.java @@ -106,10 +106,13 @@ public class AAF_FS extends AbsService<AuthzEnv, AuthzTrans> { try { Log4JLogIt logIt = new Log4JLogIt(args, "fs"); PropAccess propAccess = new PropAccess(logIt,args); - - AAF_FS service = new AAF_FS(new AuthzEnv(propAccess)); - JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service); - jss.insecure().start(); + try { + new JettyServiceStarter<AuthzEnv,AuthzTrans>( + new AAF_FS(new AuthzEnv(propAccess)),false) + .start(); + } catch (Exception e) { + propAccess.log(e); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java index 7859b7cc..f2d7522e 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/cui/CUI.java @@ -24,15 +24,17 @@ package org.onap.aaf.auth.cui; import java.io.PrintWriter; +import java.util.regex.Pattern; import javax.servlet.ServletInputStream; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.onap.aaf.auth.cmd.AAFcli; import org.onap.aaf.auth.env.AuthzTrans; -import org.onap.aaf.auth.env.AuthzEnv; import org.onap.aaf.auth.gui.AAF_GUI; +import org.onap.aaf.auth.gui.Page; import org.onap.aaf.auth.rserv.HttpCode; import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp; import org.onap.aaf.cadi.http.HTransferSS; @@ -43,6 +45,7 @@ import org.onap.aaf.misc.env.TimeTaken; public class CUI extends HttpCode<AuthzTrans, Void> { private final AAF_GUI gui; + private final static Pattern userPerm = Pattern.compile("perm (create|delete).*@.*:id.*aaf.gui.*"); public CUI(AAF_GUI gui) { @@ -84,6 +87,13 @@ public class CUI extends HttpCode<AuthzTrans, Void> { } try { aafcli.eval(cmdStr); + if(userPerm.matcher(cmdStr).matches()) { + trans.clearCache(); + Cookie cookie = new Cookie(Page.AAF_THEME,trans.getProperty(Page.AAF_THEME)); + cookie.setMaxAge(-1); + cookie.setComment("Remove AAF GUI Theme"); + trans.hresp().addCookie(cookie); + } pw.flush(); } catch (Exception e) { pw.flush(); diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java index f8aeb11b..17916c24 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/AAF_GUI.java @@ -26,6 +26,9 @@ import static org.onap.aaf.auth.rserv.HttpMethods.POST; import static org.onap.aaf.auth.rserv.HttpMethods.PUT; import javax.servlet.Filter; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.onap.aaf.auth.cmd.Cmd; import org.onap.aaf.auth.cui.CUI; @@ -40,6 +43,7 @@ import org.onap.aaf.auth.gui.pages.CMArtiChangeAction; import org.onap.aaf.auth.gui.pages.CMArtiChangeForm; import org.onap.aaf.auth.gui.pages.CMArtifactShow; import org.onap.aaf.auth.gui.pages.CredDetail; +import org.onap.aaf.auth.gui.pages.CredHistory; import org.onap.aaf.auth.gui.pages.Home; import org.onap.aaf.auth.gui.pages.LoginLanding; import org.onap.aaf.auth.gui.pages.LoginLandingAction; @@ -66,6 +70,7 @@ import org.onap.aaf.auth.gui.pages.UserRoleExtend; import org.onap.aaf.auth.gui.pages.UserRoleRemove; import org.onap.aaf.auth.gui.pages.WebCommand; import org.onap.aaf.auth.rserv.CachingFileAccess; +import org.onap.aaf.auth.rserv.HttpCode; import org.onap.aaf.auth.server.AbsService; import org.onap.aaf.auth.server.JettyServiceStarter; import org.onap.aaf.auth.server.Log4JLogIt; @@ -114,21 +119,21 @@ public class AAF_GUI extends AbsService<AuthzEnv, AuthzTrans> implements State<E protected final String deployedVersion; private StaticSlot sThemeWebPath; private StaticSlot sDefaultTheme; -// public final String theme; public AAF_GUI(final AuthzEnv env) throws Exception { super(env.access(), env); sDefaultTheme = env.staticSlot(AAF_GUI_THEME); - env.put(sDefaultTheme, env.getProperty(AAF_GUI_THEME,"onap")); + String defTheme = env.getProperty(AAF_GUI_THEME,"onap"); + env.put(sDefaultTheme, defTheme); sThemeWebPath = env.staticSlot(CachingFileAccess.CFA_WEB_PATH); if(env.get(sThemeWebPath)==null) { env.put(sThemeWebPath,"theme"); } - + slot_httpServletRequest = env.slot(HTTP_SERVLET_REQUEST); - deployedVersion = access.getProperty(Config.AAF_RELEASE, "N/A:2.x"); + deployedVersion = app_version; // Certificate Manager String aaf_url_cm = env.getProperty(Config.AAF_URL_CM,Config.AAF_URL_CM_DEF); @@ -157,8 +162,9 @@ public class AAF_GUI extends AbsService<AuthzEnv, AuthzTrans> implements State<E // MyNameSpace final Page myNamespaces = new Display(this, GET, new NssShow(this, start)).page(); Page nsDetail = new Display(this, GET, new NsDetail(this, start, myNamespaces)).page(); - new Display(this, GET, new NsHistory(this, start,myNamespaces,nsDetail)); + new Display(this, GET, new NsHistory(this, start,myNamespaces,nsDetail)); Page crdDetail = new Display(this, GET, new CredDetail(this, start, myNamespaces, nsDetail)).page(); + new Display(this, GET, new CredHistory(this,start,myNamespaces,nsDetail,crdDetail)); Page artiShow = new Display(this, GET, new CMArtifactShow(this, start, myNamespaces, nsDetail, crdDetail)).page(); Page artiCForm = new Display(this, GET, new CMArtiChangeForm(this, start, myNamespaces, nsDetail, crdDetail,artiShow)).page(); new Display(this, POST, new CMArtiChangeAction(this, start,artiShow,artiCForm)); @@ -204,6 +210,23 @@ public class AAF_GUI extends AbsService<AuthzEnv, AuthzTrans> implements State<E // Command line Mechanism route(env, PUT, "/gui/cui", new CUI(this),"text/plain;charset=utf-8","*/*"); + route(env, GET, "/gui/clear", new HttpCode<AuthzTrans, Void>(null, "Clear"){ + @Override + public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception { + trans.clearCache(); + Cookie cookies[] = req.getCookies(); + if(cookies!=null) { + for(Cookie c : cookies) { + if(c.getName().startsWith("aaf.gui.")) { + c.setMaxAge(0); + resp.addCookie(c); + } + } + } + resp.sendRedirect("/gui/home"); + } + }, "text/plain;charset=utf-8","*/*"); + /////////////////////// // WebContent Handler /////////////////////// @@ -262,9 +285,13 @@ public class AAF_GUI extends AbsService<AuthzEnv, AuthzTrans> implements State<E Log4JLogIt logIt = new Log4JLogIt(args, "gui"); PropAccess propAccess = new PropAccess(logIt,args); - AAF_GUI service = new AAF_GUI(new AuthzEnv(propAccess)); - JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service); - jss.start(); + try { + new JettyServiceStarter<AuthzEnv,AuthzTrans>( + new AAF_GUI(new AuthzEnv(propAccess)),true) + .start(); + } catch (Exception e) { + propAccess.log(e); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java index 5b6eb016..9abd5ee0 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/Page.java @@ -46,7 +46,6 @@ import org.onap.aaf.auth.env.AuthzTrans; import org.onap.aaf.auth.gui.pages.Home; import org.onap.aaf.cadi.Permission; import org.onap.aaf.cadi.aaf.AAFPermission; -import org.onap.aaf.cadi.client.Holder; import org.onap.aaf.cadi.config.Config; import org.onap.aaf.cadi.principal.TaggedPrincipal; import org.onap.aaf.misc.env.APIException; @@ -70,6 +69,7 @@ import org.onap.aaf.misc.xgen.html.Imports; * */ public class Page extends HTMLCacheGen { + public static final String AAF_THEME = "aaf_theme"; public static final String AAFURL_TOOLS = "aaf_url.tools"; public static final String AAF_URL_TOOL_DOT = "aaf_url.tool."; public static final String AAF_URL_CUIGUI = "aaf_url.cuigui"; // link to help @@ -92,6 +92,23 @@ public class Page extends HTMLCacheGen { // Note: Only access is synchronized in "getPerm" private final static Map<String,Map<String,Permission>> perms = new HashMap<>(); + + /* + * Relative path, Menu Name, Full Path + */ + protected static final String[][] MENU_ITEMS = new String[][] { + {"myperms","My Permissions","/gui/myperms"}, + {"myroles","My Roles","/gui/myroles"}, + {"ns","My Namespaces","/gui/ns"}, + {"approve","My Approvals","/gui/approve"}, + {"myrequests","My Pending Requests","/gui/myrequests"}, + // Enable later + // {"onboard","Onboarding"}, + {"passwd","Password Management","/gui/passwd"}, + {"cui","Command Prompt","/gui/cui"}, + {"api","AAF API","/gui/api"}, + {"clear","Clear Preferences","/gui/clear"} + }; public String name() { return bcName; @@ -151,7 +168,8 @@ public class Page extends HTMLCacheGen { private static class PageCode implements Code<HTMLGen> { - private static final String AAF_GUI_TITLE = "aaf_gui_title"; + private static final String AAF_GUI_THEME = "aaf.gui.theme"; + private static final String AAF_GUI_TITLE = "aaf_gui_title"; private final ContentCode[] content; private final Slot browserSlot; @@ -167,6 +185,7 @@ public class Page extends HTMLCacheGen { browserSlot = env.slot(BROWSER_TYPE); sTheme = env.staticSlot(AAF_GUI.AAF_GUI_THEME); this.env = env; + getThemeFiles(env,""); // } private static synchronized List<String> getThemeFiles(Env env, String theme) { @@ -185,11 +204,11 @@ public class Page extends HTMLCacheGen { themeProps = new TreeMap<>(); props = null; } else { - props = themeProps.get(theme); + props = themeProps.get(t.getName()); } if(props==null) { props = new Properties(); - themeProps.put(theme, props); + themeProps.put(t.getName(), props); } try { @@ -215,13 +234,10 @@ public class Page extends HTMLCacheGen { return themes.get(theme); } - protected Imports getImports(Env env, Holder<String> theme, String defaultTheme, int backdots, BROWSER browser) { - List<String> ls = getThemeFiles(env,theme.get()); + protected Imports getImports(Env env, String theme, int backdots, BROWSER browser) { + List<String> ls = getThemeFiles(env,theme); Imports imp = new Imports(backdots); - if(ls==null) { - theme.set(defaultTheme); - } - String prefix = "theme/" + theme.get() + '/'; + String prefix = "theme/" + theme + '/'; for(String f : ls) { if(f.endsWith(".js")) { imp.js(prefix + f); @@ -262,7 +278,6 @@ public class Page extends HTMLCacheGen { hgen.html(); final String title = env.getProperty(AAF_GUI_TITLE,"Authentication/Authorization Framework"); final String defaultTheme = env.get(sTheme,"onap"); - final Holder<String> hTheme = new Holder<>(defaultTheme); Mark head = hgen.head(); hgen.leaf(TITLE).text(title).end(); @@ -270,15 +285,37 @@ public class Page extends HTMLCacheGen { @Override public void code(AAF_GUI state, AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException { BROWSER browser = browser(trans,browserSlot); + String theme = null; Cookie[] cookies = trans.hreq().getCookies(); if(cookies!=null) { for(Cookie c : cookies) { - if("aaf_theme".equals(c.getName())) { - hTheme.set(c.getValue()); + if(AAF_GUI_THEME.equals(c.getName())) { + theme=c.getValue(); + if(!(themes.containsKey(theme))) { + theme = defaultTheme; + } + break; } } } - hgen.imports(getImports(env,hTheme,defaultTheme,backdots,browser)); + + if(theme==null) { + for(String t : themes.keySet()) { + if(!t.equals(defaultTheme) && trans.fish(new AAFPermission(null,trans.user()+":id", AAF_GUI_THEME, t))) { + theme=t; + break; + } + } + if(theme==null) { + theme = defaultTheme; + } + Cookie cookie = new Cookie(AAF_GUI_THEME,theme); + cookie.setMaxAge(604_800); // one week + trans.hresp().addCookie(cookie); + } + trans.setProperty(Page.AAF_THEME, theme); + + hgen.imports(getImports(env,theme,backdots,browser)); switch(browser) { case ie: case ieOld: @@ -350,7 +387,8 @@ public class Page extends HTMLCacheGen { } hgen.end(header); - + + hgen.divID("pageContent"); Mark inner = hgen.divID("inner"); // Content for (int i=cIdx;i<content.length;++i) { @@ -361,39 +399,65 @@ public class Page extends HTMLCacheGen { } hgen.end(inner); + + cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() { + @Override + public void code(AAF_GUI state, AuthzTrans trans,Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException { + String theme = trans.getProperty(Page.AAF_THEME); + Properties props; + if(theme==null) { + props = null; + } else { + props = themeProps==null?null:themeProps.get(theme); + } + + if(props!=null && "TRUE".equalsIgnoreCase(props.getProperty("enable_nav_btn"))) { + xgen.leaf("button", "id=navBtn").end(); + } + } + }); + // Adding "nav Hamburger button" // Navigation - Using older Nav to work with decrepit IE versions - Mark nav = hgen.divID("nav"); cache.dynamic(hgen, new DynamicCode<HTMLGen,AAF_GUI,AuthzTrans>() { @Override public void code(AAF_GUI state, AuthzTrans trans,Cache<HTMLGen> cache, HTMLGen xgen) throws APIException, IOException { - Properties props = themeProps==null?null:themeProps.get(hTheme.get()); - if(props!=null && "TRUE".equalsIgnoreCase(props.getProperty("main_menu_in_nav"))) { - xgen.incr("h2").text("Navigation").end(); - Mark mark = new Mark(); - boolean selected = isSelected(trans.path(),Home.HREF); - //trans.path().endsWith("home"); - xgen.incr(mark,HTMLGen.UL) - .incr(HTMLGen.LI,selected?"class=selected":"") - .incr(HTMLGen.A, "href=home") - .text("Home") - .end(2); - boolean noSelection = !selected; - for(String[] mi : Home.MENU_ITEMS) { - //selected = trans.path().endsWith(mi[0]); - if(noSelection) { - selected = isSelected(trans.path(),mi[2]); - noSelection = !selected; - } else { - selected = false; - } - xgen.incr(HTMLGen.LI,selected?"class=selected":"") - .incr(HTMLGen.A, "href="+mi[0]) - .text(mi[1]) - .end(2); - } - xgen.end(mark); + String theme = trans.getProperty(Page.AAF_THEME); + Properties props; + if(theme==null) { + props = null; + } else { + props = themeProps==null?null:themeProps.get(theme); + } + + if(props!=null) { + if("TRUE".equalsIgnoreCase(props.getProperty("main_menu_in_nav"))) { + xgen.incr("h2").text("Navigation").end(); + Mark mark = new Mark(); + boolean selected = isSelected(trans.path(),Home.HREF); + //trans.path().endsWith("home"); + xgen.incr(mark,HTMLGen.UL) + .incr(HTMLGen.LI,selected?"class=selected":"") + .incr(HTMLGen.A, "href=home") + .text("Home") + .end(2); + boolean noSelection = !selected; + for(String[] mi : MENU_ITEMS) { + //selected = trans.path().endsWith(mi[0]); + if(noSelection) { + selected = isSelected(trans.path(),mi[2]); + noSelection = !selected; + } else { + selected = false; + } + xgen.incr(HTMLGen.LI,selected?"class=selected":"") + .incr(HTMLGen.A, "href="+mi[2]) + .text(mi[1]) + .end(2); + } + xgen.end(mark); + } } } diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java index 969505bb..106c3889 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/ApiDocs.java @@ -43,6 +43,7 @@ import org.onap.aaf.cadi.Symm; 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.misc.env.APIException; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.TimeTaken; @@ -82,7 +83,7 @@ public class ApiDocs extends Page { public Preamble(AAF_GUI gui) { super(false, "preamble"); - fsUrl = gui.access.getProperty("fs_url", ""); + fsUrl = gui.access.getProperty(Config.AAF_URL_FS, "/theme"); } @Override diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java index d32c7dc3..1e06b109 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtiChangeAction.java @@ -82,32 +82,36 @@ trans.info().log("Step 1"); arti.getSans().add(s); } } - // Disallow IP entries, except by special Permission - if (!trans.fish(getPerm(ca,"ip"))) { - boolean ok=true; - if (IPValidator.ip(machine)) { - ok=false; - } - if (ok) { - for (String s: arti.getSans()) { - if (IPValidator.ip(s)) { - ok=false; - break; - } - } - } - if (!ok) { - hgen.p("Policy Failure: IPs in certificates are only allowed by Exception."); - return; - } - } - // Disallow Domain based Definitions without exception - if (machine.startsWith("*")) { // Domain set - if (!trans.fish(getPerm(ca, "domain"))) { - hgen.p("Policy Failure: Domain Artifact Declarations are only allowed by Exception."); - return; - } + // These checks to not apply to deletions + if(!CMArtiChangeForm.DELETE.equals(trans.get(sCmd, ""))) { + // Disallow IP entries, except by special Permission + if (!trans.fish(getPerm(ca,"ip"))) { + boolean ok=true; + if (IPValidator.ip(machine)) { + ok=false; + } + if (ok) { + for (String s: arti.getSans()) { + if (IPValidator.ip(s)) { + ok=false; + break; + } + } + } + if (!ok) { + hgen.p("Policy Failure: IPs in certificates are only allowed by Exception."); + return; + } + } + + // Disallow Domain based Definitions without exception + if (machine.startsWith("*")) { // Domain set + if (!trans.fish(getPerm(ca, "domain"))) { + hgen.p("Policy Failure: Domain Artifact Declarations are only allowed by Exception."); + return; + } + } } arti.setMechid((String)trans.get(sID,null)); diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java index 00e58c87..70d86933 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredDetail.java @@ -214,6 +214,7 @@ public class CredDetail extends Page { StringWriter buttons = new StringWriter(); HTMLGen hgen = cd.clone(buttons); hgen.leaf("button","onclick=divVisibility('"+key+"');","class=button").text("Expand").end(); + hgen.leaf(HTMLGen.A,"class=button","class=greenbutton","href="+CredHistory.HREF+"?user="+ulm.getKey()).text("History").end(); StringWriter creds = new StringWriter(); hgen = cd.clone(creds); @@ -302,8 +303,9 @@ public class CredDetail extends Page { Chrono.niceDateStamp(oldest), Chrono.niceDateStamp(newest))) .end(uRow); - + } + } hgen.end(utable); } @@ -316,6 +318,7 @@ public class CredDetail extends Page { new TextCell(creds.toString(),STYLE_WIDTH_70) }); } + for (String missing : lns) { StringWriter buttons = new StringWriter(); HTMLGen hgen = cd.clone(buttons); diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredHistory.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredHistory.java new file mode 100644 index 00000000..7e3962ec --- /dev/null +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CredHistory.java @@ -0,0 +1,224 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * 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. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.auth.gui.pages; + + +import java.io.IOException; +import java.net.ConnectException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Comparator; +import java.util.List; + +import org.onap.aaf.auth.env.AuthzEnv; +import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.gui.AAF_GUI; +import org.onap.aaf.auth.gui.BreadCrumbs; +import org.onap.aaf.auth.gui.NamedCode; +import org.onap.aaf.auth.gui.Page; +import org.onap.aaf.auth.gui.Table; +import org.onap.aaf.auth.gui.Table.Cells; +import org.onap.aaf.auth.gui.table.AbsCell; +import org.onap.aaf.auth.gui.table.TableData; +import org.onap.aaf.auth.gui.table.TextCell; +import org.onap.aaf.cadi.CadiException; +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.misc.env.APIException; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.Slot; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.xgen.Cache; +import org.onap.aaf.misc.xgen.DynamicCode; +import org.onap.aaf.misc.xgen.html.HTMLGen; + +import aaf.v2_0.History; +import aaf.v2_0.History.Item; + + +public class CredHistory extends Page { + static final String NAME="CredHistory"; + static final String HREF = "/gui/credHistory"; + static final String FIELDS[] = {"user","dates"}; + + + public CredHistory(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException { + super(gui.env,NAME,HREF, FIELDS, + new BreadCrumbs(breadcrumbs), + new Table<AAF_GUI,AuthzTrans>("History", gui.env.newTransNoAvg(),new Model(gui.env),"class=std"), + new NamedCode(true, "content") { + @Override + public void code(final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException { + final Slot user = gui.env.slot(NAME+".user"); + cache.dynamic(hgen, new DynamicCode<HTMLGen, AAF_GUI, AuthzTrans>() { + @Override + public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) throws APIException, IOException { + String obUser = trans.get(user, null); + + // Use Javascript to make the table title more descriptive + hgen.js() + .text("var caption = document.querySelector(\".title\");") + .text("caption.innerHTML='History for User [ " + obUser + " ]';") + .done(); + + // Use Javascript to change Link Target to our last visited Detail page + String lastPage = CredDetail.HREF + "?role=" + obUser; + hgen.js() + .text("alterLink('roledetail', '"+lastPage + "');") + .done(); + + hgen.br(); + hgen.leaf("a", "href=#advanced_search","onclick=divVisibility('advanced_search');","class=greenbutton").text("Advanced Search").end() + .divID("advanced_search", "style=display:none"); + hgen.incr("table"); + + addDateRow(hgen,"Start Date"); + addDateRow(hgen,"End Date"); + hgen.incr("tr").incr("td"); + hgen.tagOnly("input", "type=button","value=Get History", + "onclick=datesURL('"+HREF+"?user=" + obUser+"');","class=greenbutton"); + hgen.end().end(); + hgen.end(); + hgen.end(); + } + }); + } + } + + ); + + } + + private static void addDateRow(HTMLGen hgen, String s) { + hgen + .incr("tr") + .incr("td") + .incr("label", "for=month", "required").text(s+"*").end() + .end() + .incr("td") + .incr("select", "name=month"+s.substring(0, s.indexOf(' ')), "id=month"+s.substring(0, s.indexOf(' ')), "required") + .incr("option", "value=").text("Month").end(); + for(NsHistory.Month m : NsHistory.Month.values()) { + if (Calendar.getInstance().get(Calendar.MONTH) == m.ordinal()) { + hgen.incr("option", "selected", "value="+(m.ordinal()+1)).text(m.name()).end(); + } else { + hgen.incr("option", "value="+(m.ordinal()+1)).text(m.name()).end(); + } + } + hgen.end() + .end() + .incr("td") + .tagOnly("input","type=number","id=year"+s.substring(0, s.indexOf(' ')),"required", + "value="+Calendar.getInstance().get(Calendar.YEAR), "min=1900", + "max="+Calendar.getInstance().get(Calendar.YEAR), + "placeholder=Year").end() + .end(); + } + + + /** + * Implement the Table Content for History + * + * @author Jonathan + * + */ + private static class Model extends TableData<AAF_GUI,AuthzTrans> { + private static final String[] headers = new String[] {"Date","User","Memo"}; + private Slot user; + private Slot dates; + + public Model(AuthzEnv env) { + user = env.slot(NAME+".user"); + dates = env.slot(NAME+".dates"); + } + + @Override + public String[] headers() { + return headers; + } + + @Override + public Cells get(final AuthzTrans trans, final AAF_GUI gui) { + final String oName = trans.get(user,null); + final String oDates = trans.get(dates,null); + + Cells rv = Cells.EMPTY; + if (oName!=null) { + + try { + rv = gui.clientAsUser(trans.getUserPrincipal(), new Retryable<Cells>() { + @Override + public Cells code(Rcli<?> client) throws CadiException, ConnectException, APIException { + ArrayList<AbsCell[]> rv = new ArrayList<>(); + TimeTaken tt = trans.start("AAF Get History for credential ["+oName+"]",Env.REMOTE); + String msg = null; + try { + if (oDates != null) { + client.setQueryParams("yyyymm="+oDates); + } + Future<History> fh = client.read("/authz/hist/subject/"+oName + "/cred",gui.getDF(History.class)); + if (fh.get(AAF_GUI.TIMEOUT)) { + tt.done(); + tt = trans.start("Load History Data", Env.SUB); + List<Item> histItems = fh.value.getItem(); + + java.util.Collections.sort(histItems, new Comparator<Item>() { + @Override + public int compare(Item o1, Item o2) { + return o2.getTimestamp().compare(o1.getTimestamp()); + } + }); + + for (Item i : histItems) { + String user = i.getUser(); + AbsCell userCell = new TextCell(user); + + String memo = i.getMemo().replace("<script>", "<script>").replace("</script>", "</script>"); + rv.add(new AbsCell[] { + new TextCell(i.getTimestamp().toGregorianCalendar().getTime().toString()), + userCell, + new TextCell(memo) + }); + } + } else { + if (fh.code()==403) { + rv.add(new AbsCell[] {new TextCell("You may not view History of Credentiol[" + oName + "]", "colspan = 3", "class=center")}); + } else { + rv.add(new AbsCell[] {new TextCell("*** Data Unavailable ***", "colspan = 3", "class=center")}); + } + } + } finally { + tt.done(); + } + return new Cells(rv,msg); + } + }); + } catch (Exception e) { + trans.error().log(e); + } + } + return rv; + } + } + +} diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java index 6fc4b5c1..73e118a2 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/Home.java @@ -37,21 +37,6 @@ import org.onap.aaf.misc.xgen.html.HTMLGen; public class Home extends Page { public static final String HREF = "/gui/home"; - /* - * Relative path, Menu Name, Full Path - */ - public static final String[][] MENU_ITEMS = new String[][] { - {"myperms","My Permissions","/gui/myperms"}, - {"myroles","My Roles","/gui/myroles"}, - {"ns","My Namespaces","/gui/ns"}, - {"approve","My Approvals","/gui/approve"}, - {"myrequests","My Pending Requests","/gui/myrequests"}, - // Enable later - // {"onboard","Onboarding"}, - {"passwd","Password Management","/gui/passwd"}, - {"cui","Command Prompt","/gui/cui"}, - {"api","AAF API","/gui/api"} - }; public Home(final AAF_GUI gui) throws APIException, IOException { super(gui.env,"Home",HREF, NO_FIELDS, new NamedCode(false,"content") { diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java index 16a6c940..6b1c6120 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsDetail.java @@ -168,7 +168,7 @@ public class NsDetail extends Page { } String historyLink = NsHistory.HREF + "?name=" + nsName; - rv.add(new AbsCell[] {new RefCell("See History",historyLink,false)}); + rv.add(new AbsCell[] {new RefCell("See History",historyLink,false,"class=greenbutton")}); } finally { tt.done(); } diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java index bca6c92c..dc9119bf 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/NsHistory.java @@ -58,7 +58,6 @@ public class NsHistory extends Page { static final String NAME="NsHistory"; static final String HREF = "/gui/nsHistory"; static final String FIELDS[] = {"name","dates"}; - static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id="; static enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER }; @@ -88,7 +87,7 @@ public class NsHistory extends Page { .done(); hgen.br(); - hgen.leaf("a","href=#advanced_search","onclick=divVisibility('advanced_search');").text("Advanced Search").end() + hgen.leaf("a","href=#advanced_search","onclick=divVisibility('advanced_search');","class=greenbutton").text("Advanced Search").end() .divID("advanced_search", "style=display:none"); hgen.incr("table"); @@ -96,7 +95,7 @@ public class NsHistory extends Page { addDateRow(hgen,"End Date"); hgen.incr("tr").incr("td"); hgen.tagOnly("input", "type=button","value=Get History", - "onclick=datesURL('"+HREF+"?name=" + obName+"');"); + "onclick=datesURL('"+HREF+"?name=" + obName+"');","class=greenbutton"); hgen.end().end(); hgen.end(); hgen.end(); diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java index 41711db2..ae5fe375 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PendingRequestsShow.java @@ -60,8 +60,7 @@ import aaf.v2_0.Approvals; public class PendingRequestsShow extends Page { public static final String HREF = "/gui/myrequests"; public static final String NAME = "MyRequests"; - static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id="; - static final String[] FIELDS = new String[] {"as_user"}; // as_user Checked in Display + private static final String[] FIELDS = new String[] {"as_user"}; // as_user Checked in Display private static final String AS_USER=NAME+".as_user"; public PendingRequestsShow(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException { diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java index 7d31d0e4..4a5a940a 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermDetail.java @@ -88,7 +88,7 @@ public class PermDetail extends Page { final String pInstance = trans.get(instance, null); final String pAction = trans.get(action, null); Validator v = new Validator(); - v.permType(pType) + v.permTypeWithUser(trans.user(),pType) .permInstance(pInstance) .permAction(pAction); @@ -135,7 +135,7 @@ public class PermDetail extends Page { String historyLink = PermHistory.HREF + "?type=" + pType + "&instance=" + pInstance + "&action=" + pAction; - rv.add(new AbsCell[] {new RefCell("See History",historyLink,false)}); + rv.add(new AbsCell[] {new RefCell("See History",historyLink,false,"class=greenbutton")}); } else { rv.add(new AbsCell[] {new TextCell( fp.code()==HttpStatus.NOT_FOUND_404? diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java index bbaf419f..4c3bd32e 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/PermHistory.java @@ -60,9 +60,6 @@ public class PermHistory extends Page { static final String NAME="PermHistory"; static final String HREF = "/gui/permHistory"; static final String FIELDS[] = {"type","instance","action","dates"}; - static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id="; - static enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, - AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER }; public PermHistory(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException { super(gui.env,NAME,HREF, FIELDS, @@ -96,7 +93,7 @@ public class PermHistory extends Page { .done(); hgen.br(); - hgen.leaf("a", "href=#advanced_search", "onclick=divVisibility('advanced_search');").text("Advanced Search").end() + hgen.leaf("a", "href=#advanced_search", "onclick=divVisibility('advanced_search');","class=greenbutton").text("Advanced Search").end() .divID("advanced_search", "style=display:none"); hgen.incr("table"); @@ -106,7 +103,7 @@ public class PermHistory extends Page { hgen.tagOnly("input", "type=button","value=Get History", "onclick=datesURL('"+HREF+"?type=" + type + "&instance=" + instance - + "&action=" + action+"');"); + + "&action=" + action+"');","class=greenbutton"); hgen.end().end(); hgen.end(); hgen.end(); @@ -128,7 +125,7 @@ public class PermHistory extends Page { .incr("td") .incr("select", "name=month"+s.substring(0, s.indexOf(' ')), "id=month"+s.substring(0, s.indexOf(' ')), "required") .incr("option", "value=").text("Month").end(); - for (Month m : Month.values()) { + for (NsHistory.Month m : NsHistory.Month.values()) { if (Calendar.getInstance().get(Calendar.MONTH) == m.ordinal()) { hgen.incr("option", "selected", "value="+(m.ordinal()+1)).text(m.name()).end(); } else { diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java index bfc258bc..6588de54 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleDetail.java @@ -106,7 +106,11 @@ public class RoleDetail extends Page { public void prefix(final AAF_GUI gui, final AuthzTrans trans, final Cache<HTMLGen> cache, final HTMLGen hgen) { final String pRole = trans.get(sRoleName, null); Validator v = new Validator(); - v.role(pRole); + if(!v.isNull("Role",pRole).err()) { + if(!pRole.startsWith(trans.user())) { + v.role(pRole); + } + } if (v.err()) { trans.warn().printf("Error in PermDetail Request: %s", v.errs()); return; @@ -266,7 +270,7 @@ public class RoleDetail extends Page { // History rv.add(new AbsCell[] { - new RefCell("See History",RoleHistory.HREF + "?role=" + pRole,false) + new RefCell("See History",RoleHistory.HREF + "?role=" + pRole,false,"class=greenbutton") }); } else { rv.add(new AbsCell[]{ diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java index fdf6f9e3..a9f0eeb0 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/RoleHistory.java @@ -60,9 +60,7 @@ public class RoleHistory extends Page { static final String NAME="RoleHistory"; static final String HREF = "/gui/roleHistory"; static final String FIELDS[] = {"role","dates"}; - static final String WEBPHONE = "http://webphone.att.com/cgi-bin/webphones.pl?id="; - static enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, - AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER }; + public RoleHistory(final AAF_GUI gui, final Page ... breadcrumbs) throws APIException, IOException { super(gui.env,NAME,HREF, FIELDS, @@ -90,7 +88,7 @@ public class RoleHistory extends Page { .done(); hgen.br(); - hgen.leaf("a", "href=#advanced_search","onclick=divVisibility('advanced_search');").text("Advanced Search").end() + hgen.leaf("a", "href=#advanced_search","onclick=divVisibility('advanced_search');","class=greenbutton").text("Advanced Search").end() .divID("advanced_search", "style=display:none"); hgen.incr("table"); @@ -98,7 +96,7 @@ public class RoleHistory extends Page { addDateRow(hgen,"End Date"); hgen.incr("tr").incr("td"); hgen.tagOnly("input", "type=button","value=Get History", - "onclick=datesURL('"+HREF+"?role=" + obRole+"');"); + "onclick=datesURL('"+HREF+"?role=" + obRole+"');","class=greenbutton"); hgen.end().end(); hgen.end(); hgen.end(); @@ -120,7 +118,7 @@ public class RoleHistory extends Page { .incr("td") .incr("select", "name=month"+s.substring(0, s.indexOf(' ')), "id=month"+s.substring(0, s.indexOf(' ')), "required") .incr("option", "value=").text("Month").end(); - for (Month m : Month.values()) { + for (NsHistory.Month m : NsHistory.Month.values()) { if (Calendar.getInstance().get(Calendar.MONTH) == m.ordinal()) { hgen.incr("option", "selected", "value="+(m.ordinal()+1)).text(m.name()).end(); } else { diff --git a/auth/auth-gui/theme/onap/aaf5.css b/auth/auth-gui/theme/onap/aaf5.css index 67f03b27..ca9b3a77 100644 --- a/auth/auth-gui/theme/onap/aaf5.css +++ b/auth/auth-gui/theme/onap/aaf5.css @@ -350,7 +350,7 @@ div.detail caption { color: white; font-family: "Lucida Console", Monaco, monospace; overflow-y: scroll; - height: 300px; + height: 600px; min-width: 600px; padding: 5px; resize: vertical; diff --git a/auth/auth-gui/theme/onap/console.js b/auth/auth-gui/theme/onap/console.js index f65c17b4..fe4f6494 100644 --- a/auth/auth-gui/theme/onap/console.js +++ b/auth/auth-gui/theme/onap/console.js @@ -29,7 +29,7 @@ function getCommand() { cmds = document.querySelector("#command_field").value.split(" "); var cleanCmd = ""; if (document.querySelector("#details_img").getAttribute("class") == "selected") - cleanCmd += "set details=true "; + cleanCmd += "details "; for (var i = 0; i < cmds.length;i++) { var trimmed = cmds[i].trim(); if (trimmed != "") @@ -286,7 +286,7 @@ function maximizeConsole(img) { content.removeAttribute("class"); footer.style.display=""; console_area.style.resize="vertical"; - console_area.style.height="300px"; + console_area.style.height="600px"; } selectOption(img,0); } diff --git a/auth/auth-hello/src/main/java/org/onap/aaf/auth/hello/AAF_Hello.java b/auth/auth-hello/src/main/java/org/onap/aaf/auth/hello/AAF_Hello.java index 6aee85d3..d88ed097 100644 --- a/auth/auth-hello/src/main/java/org/onap/aaf/auth/hello/AAF_Hello.java +++ b/auth/auth-hello/src/main/java/org/onap/aaf/auth/hello/AAF_Hello.java @@ -122,9 +122,13 @@ public class AAF_Hello extends AbsService<AuthzEnv,AuthzTrans> { Log4JLogIt logIt = new Log4JLogIt(args, "hello"); PropAccess propAccess = new PropAccess(logIt,args); - AAF_Hello service = new AAF_Hello(new AuthzEnv(propAccess)); - JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service); - jss.start(); + try { + new JettyServiceStarter<AuthzEnv,AuthzTrans>( + new AAF_Hello(new AuthzEnv(propAccess)),true) + .start(); + } catch (Exception e) { + propAccess.log(e); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/AAF_Locate.java b/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/AAF_Locate.java index 26bdb695..5ebabed7 100644 --- a/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/AAF_Locate.java +++ b/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/AAF_Locate.java @@ -199,8 +199,8 @@ public class AAF_Locate extends AbsService<AuthzEnv, AuthzTrans> { } catch (UnknownHostException | CadiException e) { throw new LocatorException(e); } - gui_locator = AbsAAFLocator.create(rph.getPublicEntryName("gui", rph.default_container), - Config.AAF_DEFAULT_API_VERSION); + String url = rph.getPublicEntryName("gui", rph.default_container); + gui_locator = AbsAAFLocator.create(url,Config.AAF_DEFAULT_API_VERSION); } return gui_locator; } @@ -241,9 +241,13 @@ public class AAF_Locate extends AbsService<AuthzEnv, AuthzTrans> { Log4JLogIt logIt = new Log4JLogIt(args, "locate"); PropAccess propAccess = new PropAccess(logIt,args); - AAF_Locate service = new AAF_Locate(new AuthzEnv(propAccess)); - JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service); - jss.start(); + try { + new JettyServiceStarter<AuthzEnv,AuthzTrans>( + new AAF_Locate(new AuthzEnv(propAccess)),true) + .start(); + } catch (Exception e) { + propAccess.log(e); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/service/LocateServiceImpl.java b/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/service/LocateServiceImpl.java index 6d96ded3..829335c0 100644 --- a/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/service/LocateServiceImpl.java +++ b/auth/auth-locate/src/main/java/org/onap/aaf/auth/locate/service/LocateServiceImpl.java @@ -22,7 +22,6 @@ package org.onap.aaf.auth.locate.service; import java.util.List; -import java.util.UUID; import org.onap.aaf.auth.dao.cass.ConfigDAO; import org.onap.aaf.auth.dao.cass.ConfigDAO.Data; @@ -72,27 +71,31 @@ public class LocateServiceImpl<IN,OUT,ERROR> return Result.err(Result.ERR_BadData,v.errs()); } int count = 0; + StringBuilder denied = null; for (MgmtEndpoint me : meps.getMgmtEndpoint()) { if (permToRegister) { int dot = me.getName().lastIndexOf('.'); // Note: Validator checks for NS for getName() - AAFPermission p = new AAFPermission(me.getName().substring(0,dot),"locator",me.getName(),"write"); - if (trans.fish(p)) { - LocateDAO.Data data = mapper.locateData(me); - locateDAO.update(trans, data, true); - ++count; - } else { - return Result.err(Result.ERR_Denied,"May not register service (needs " + p.getKey() + ')'); + AAFPermission p = new AAFPermission(me.getName().substring(0,dot),"locator",me.getHostname(),"write"); + if (!trans.fish(p)) { + if(denied==null) { + denied = new StringBuilder("May not register service(s):"); + } + + denied.append("\n\t"); + denied.append(p.getKey()); + denied.append(')'); + continue; } - } else { //TODO if (MechID is part of Namespace) { - LocateDAO.Data data = mapper.locateData(me); - locateDAO.update(trans, data, true); - ++count; } + LocateDAO.Data data = mapper.locateData(me); + locateDAO.update(trans, data, true); + ++count; } if (count>0) { return Result.ok(); } else { - return Result.err(Result.ERR_NotFound, "No endpoints found"); + return denied==null?Result.err(Result.ERR_NotFound, "No endpoints found") + :Result.err(Result.ERR_Security,denied.toString()); } } @@ -106,28 +109,39 @@ public class LocateServiceImpl<IN,OUT,ERROR> return Result.err(Result.ERR_BadData,v.errs()); } int count = 0; + StringBuilder denied = null; for (MgmtEndpoint me : meps.getMgmtEndpoint()) { - int dot = me.getName().lastIndexOf('.'); // Note: Validator checks for NS for getName() - AAFPermission p = new AAFPermission(me.getName().substring(0,dot),"locator",me.getHostname(),"write"); - if (trans.fish(p)) { - LocateDAO.Data data = mapper.locateData(me); - data.port_key = UUID.randomUUID(); - locateDAO.delete(trans, data, false); - ++count; - } else { - return Result.err(Result.ERR_Denied,"May not register service (needs " + p.getKey() + ')'); - } + if (permToRegister) { + int dot = me.getName().lastIndexOf('.'); // Note: Validator checks for NS for getName() + AAFPermission p = new AAFPermission(me.getName().substring(0,dot),"locator",me.getHostname(),"write"); + if (!trans.fish(p)) { + if(denied==null) { + denied = new StringBuilder("May not deregister service(s):"); + } + + denied.append("\n\t"); + denied.append(p.getKey()); + denied.append(')'); + continue; + } + } + LocateDAO.Data data = mapper.locateData(me); + locateDAO.delete(trans, data, true); + ++count; } if (count>0) { return Result.ok(); } else { - return Result.err(Result.ERR_NotFound, "No endpoints found"); + return denied==null?Result.err(Result.ERR_NotFound, "No endpoints found") + :Result.err(Result.ERR_Security,denied.toString()); } } ///// ADDED v1_1 /* (non-Javadoc) * @see org.onap.aaf.auth.locate.service.LocateService#getConfig(org.onap.aaf.auth.env.AuthzTrans, java.lang.String, java.lang.String) + * + * Note: "id" is put in, in case we need to filter, or direct data change in the future by Permission */ @Override public Result<Configuration> getConfig(AuthzTrans trans, String id, String type) { @@ -145,7 +159,6 @@ public class LocateServiceImpl<IN,OUT,ERROR> } } return Result.ok(c); - //return Result.err(Result.ERR_NotImplemented,"not done yet"); } diff --git a/auth/auth-oauth/src/main/java/org/onap/aaf/auth/oauth/AAF_OAuth.java b/auth/auth-oauth/src/main/java/org/onap/aaf/auth/oauth/AAF_OAuth.java index d5a6615f..7f38b65a 100644 --- a/auth/auth-oauth/src/main/java/org/onap/aaf/auth/oauth/AAF_OAuth.java +++ b/auth/auth-oauth/src/main/java/org/onap/aaf/auth/oauth/AAF_OAuth.java @@ -192,9 +192,13 @@ public class AAF_OAuth extends AbsService<AuthzEnv,AuthzTrans> { Log4JLogIt logIt = new Log4JLogIt(args, "oauth"); PropAccess propAccess = new PropAccess(logIt,args); - AAF_OAuth service = new AAF_OAuth(new AuthzEnv(propAccess)); - JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service); - jss.start(); + try { + new JettyServiceStarter<AuthzEnv,AuthzTrans>( + new AAF_OAuth(new AuthzEnv(propAccess)),true) + .start(); + } catch (Exception e) { + propAccess.log(e); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AAF_Service.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AAF_Service.java index 6a63907d..333c0fc1 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AAF_Service.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AAF_Service.java @@ -239,9 +239,13 @@ public class AAF_Service extends AbsService<AuthzEnv,AuthzTrans> { Log4JLogIt logIt = new Log4JLogIt(args, "authz"); PropAccess propAccess = new PropAccess(logIt,args); - AbsService<AuthzEnv, AuthzTrans> service = new AAF_Service(new AuthzEnv(propAccess)); - JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service); - jss.start(); + try { + new JettyServiceStarter<AuthzEnv,AuthzTrans>( + new AAF_Service(new AuthzEnv(propAccess)),true) + .start(); + } catch (Exception e) { + propAccess.log(e); + } } catch (Exception e) { e.printStackTrace(); } diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java index e311513e..37ca509a 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzCassServiceImpl.java @@ -47,6 +47,9 @@ import javax.servlet.http.HttpServletRequest; import org.onap.aaf.auth.common.Define; import org.onap.aaf.auth.dao.DAOException; +import org.onap.aaf.auth.dao.cached.CachedPermDAO; +import org.onap.aaf.auth.dao.cached.CachedRoleDAO; +import org.onap.aaf.auth.dao.cached.CachedUserRoleDAO; import org.onap.aaf.auth.dao.cass.ApprovalDAO; import org.onap.aaf.auth.dao.cass.CertDAO; import org.onap.aaf.auth.dao.cass.CredDAO; @@ -70,6 +73,7 @@ import org.onap.aaf.auth.dao.hl.Function.OP_STATUS; import org.onap.aaf.auth.dao.hl.Question; import org.onap.aaf.auth.dao.hl.Question.Access; import org.onap.aaf.auth.env.AuthzTrans; +import org.onap.aaf.auth.env.AuthzTrans.REQD_TYPE; import org.onap.aaf.auth.layer.Result; import org.onap.aaf.auth.org.Executor; import org.onap.aaf.auth.org.Organization; @@ -82,7 +86,9 @@ import org.onap.aaf.auth.service.mapper.Mapper; import org.onap.aaf.auth.service.mapper.Mapper.API; import org.onap.aaf.auth.service.validation.ServiceValidator; import org.onap.aaf.auth.validation.Validator; +import org.onap.aaf.cadi.aaf.Defaults; import org.onap.aaf.cadi.principal.BasicPrincipal; +import org.onap.aaf.cadi.util.FQI; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.TimeTaken; import org.onap.aaf.misc.env.util.Chrono; @@ -109,7 +115,8 @@ import aaf.v2_0.CredRequest; public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> implements AuthzService <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> { - private Mapper <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> mapper; + private static final String TWO_SPACE = " "; + private Mapper <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> mapper; @Override public Mapper <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERTS,KEYS,REQUEST,HISTORY,ERR,APPROVALS> mapper() {return mapper;} @@ -799,62 +806,129 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE @Override public Result<Void> createPerm(final AuthzTrans trans,REQUEST rreq) { final Result<PermDAO.Data> newPd = mapper.perm(trans, rreq); - // Does Perm Type exist as a Namespace? - if(newPd.value.type.isEmpty() || ques.nsDAO().read(trans, newPd.value.fullType()).isOKhasData()) { - return Result.err(Status.ERR_ConflictAlreadyExists, - "Permission Type exists as a Namespace"); - } - + final ServiceValidator v = new ServiceValidator(); if (v.perm(newPd).err()) { return Result.err(Status.ERR_BadData,v.errs()); } - - Result<FutureDAO.Data> fd = mapper.future(trans, PermDAO.TABLE, rreq, newPd.value,false, - new Mapper.Memo() { - @Override - public String get() { - return "Create Permission [" + - newPd.value.fullType() + '|' + - newPd.value.instance + '|' + - newPd.value.action + ']'; - } - }, - new MayChange() { - private Result<NsDAO.Data> nsd; - @Override - public Result<?> mayChange() { - if (nsd==null) { - nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write); - } - return nsd; - } - }); - Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, newPd.value.ns); - if (nsr.notOKorIsEmpty()) { - return Result.err(nsr); + + // User Permission mechanism + if(newPd.value.ns.indexOf('@')>0) { + PermDAO.Data pdd = newPd.value; + if(trans.user().equals(newPd.value.ns)) { + CachedPermDAO permDAO = ques.permDAO(); + Result<List<PermDAO.Data>> rlpdd = permDAO.read(trans, pdd); + if(rlpdd.notOK()) { + return Result.err(rlpdd); + } + if(!rlpdd.isEmpty()) { + return Result.err(Result.ERR_ConflictAlreadyExists,"Permission already exists"); + } + + RoleDAO.Data rdd = new RoleDAO.Data(); + rdd.ns = pdd.ns; + rdd.name = "user"; + + pdd.roles(true).add(rdd.fullName()); + Result<PermDAO.Data> rpdd = permDAO.create(trans, pdd); + if(rpdd.notOK()) { + return Result.err(rpdd); + } + + CachedRoleDAO roleDAO = ques.roleDAO(); + Result<List<RoleDAO.Data>> rlrdd = roleDAO.read(trans, rdd); + if(rlrdd.notOK()) { + return Result.err(rlrdd); + } else { + if(!rlrdd.isEmpty()) { + rdd = rlrdd.value.get(0); + } + } + + String eperm = pdd.encode(); + rdd.perms(true).add(eperm); + Result<Void> rv = roleDAO.update(trans, rdd); + if(rv.notOK()) { + return rv; + } + + CachedUserRoleDAO urDAO = ques.userRoleDAO(); + UserRoleDAO.Data urdd = new UserRoleDAO.Data(); + urdd.user = trans.user(); + urdd.ns = rdd.ns; + urdd.rname = rdd.name; + urdd.role = rdd.fullName(); + Result<List<UserRoleDAO.Data>> rlurdd = urDAO.read(trans, urdd); + if(rlurdd.notOK()) { + return Result.err(rlrdd); + } else if(rlurdd.isEmpty()) { + GregorianCalendar gc = trans.org().expiration(null, Expiration.UserInRole); + if(gc==null) { + return Result.err(Result.ERR_Policy,"Organzation does not grant Expiration for UserRole"); + } else { + urdd.expires = gc.getTime(); + } + Result<UserRoleDAO.Data> rurdd = urDAO.create(trans, urdd); + return Result.err(rurdd); + } + return rv; + } else { + return Result.err(Result.ERR_Security,"Only the User can create User Permissions"); + } + } else { + // Does Perm Type exist as a Namespace? + if(newPd.value.type.isEmpty() || ques.nsDAO().read(trans, newPd.value.fullType()).isOKhasData()) { + return Result.err(Status.ERR_ConflictAlreadyExists, + "Permission Type exists as a Namespace"); + } + + Result<FutureDAO.Data> fd = mapper.future(trans, PermDAO.TABLE, rreq, newPd.value,false, + new Mapper.Memo() { + @Override + public String get() { + return "Create Permission [" + + newPd.value.fullType() + '|' + + newPd.value.instance + '|' + + newPd.value.action + ']'; + } + }, + new MayChange() { + private Result<NsDAO.Data> nsd; + @Override + public Result<?> mayChange() { + if (nsd==null) { + nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write); + } + return nsd; + } + }); + + Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, newPd.value.ns); + if (nsr.notOKorIsEmpty()) { + return Result.err(nsr); + } + switch(fd.status) { + case OK: + Result<String> rfc = func.createFuture(trans,fd.value, + newPd.value.fullType() + '|' + newPd.value.instance + '|' + newPd.value.action, + trans.user(), + nsr.value.get(0), + FUTURE_OP.C); + if (rfc.isOK()) { + return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", + newPd.value.ns, + newPd.value.type, + newPd.value.instance, + newPd.value.action); + } else { + return Result.err(rfc); + } + case Status.ACC_Now: + return func.createPerm(trans, newPd.value, true); + default: + return Result.err(fd); + } } - switch(fd.status) { - case OK: - Result<String> rfc = func.createFuture(trans,fd.value, - newPd.value.fullType() + '|' + newPd.value.instance + '|' + newPd.value.action, - trans.user(), - nsr.value.get(0), - FUTURE_OP.C); - if (rfc.isOK()) { - return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", - newPd.value.ns, - newPd.value.type, - newPd.value.instance, - newPd.value.action); - } else { - return Result.err(rfc); - } - case Status.ACC_Now: - return func.createPerm(trans, newPd.value, true); - default: - return Result.err(fd); - } } @ApiDoc( @@ -1392,7 +1466,7 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE return Result.err(Status.ERR_PermissionNotFound, "Permission [%s.%s|%s|%s] does not exist", perm.ns,perm.type,perm.instance,perm.action ); } - + Result<FutureDAO.Data> fd = mapper.future(trans,PermDAO.TABLE,from,perm,false, new Mapper.Memo() { @Override @@ -1917,6 +1991,9 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE public Result<?> mayChange() { if (nsd==null) { nsd = ques.mayUser(trans, trans.user(), rpd.value, Access.write); + if(nsd.notOK()) { + trans.requested(REQD_TYPE.future,true); + } } return nsd; } @@ -1926,32 +2003,32 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE return Result.err(nsr); } switch(fd.status) { - case OK: - Result<String> rfc = func.createFuture(trans,fd.value, - rpd.value.fullPerm(), - trans.user(), - nsr.value.get(0), - FUTURE_OP.G); - if (rfc.isOK()) { - return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", - rpd.value.ns, - rpd.value.type, - rpd.value.instance, - rpd.value.action); - } else { - return Result.err(rfc); - } - case Status.ACC_Now: - Result<Void> rv = null; - if (createPerm!=null) {// has been validated for creating - rv = func.createPerm(trans, createPerm, false); - } - if (rv==null || rv.isOK()) { - rv = func.addPermToRole(trans, rrd.value, rpd.value, false); - } - return rv; - default: - return Result.err(fd); + case OK: + Result<String> rfc = func.createFuture(trans,fd.value, + rpd.value.fullPerm(), + trans.user(), + nsr.value.get(0), + FUTURE_OP.G); + if (rfc.isOK()) { + return Result.err(Status.ACC_Future, "Perm [%s.%s|%s|%s] is saved for future processing", + rpd.value.ns, + rpd.value.type, + rpd.value.instance, + rpd.value.action); + } else { + return Result.err(rfc); + } + case Status.ACC_Now: + Result<Void> rv = null; + if (createPerm!=null) {// has been validated for creating + rv = func.createPerm(trans, createPerm, false); + } + if (rv==null || rv.isOK()) { + rv = func.addPermToRole(trans, rrd.value, rpd.value, false); + } + return rv; + default: + return Result.err(fd); } } @@ -2229,40 +2306,59 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } private class MayChangeCred implements MayChange { - - private Result<NsDAO.Data> nsd; + private static final String EXTEND = "extend"; + private static final String RESET = "reset"; + private static final String DELETE = "delete"; + private Result<NsDAO.Data> nsd; private AuthzTrans trans; private CredDAO.Data cred; - public MayChangeCred(AuthzTrans trans, CredDAO.Data cred) { + private String action; + public MayChangeCred(AuthzTrans trans, CredDAO.Data cred, String action) { this.trans = trans; this.cred = cred; + this.action = action; } @Override public Result<?> mayChange() { // User can change himself (but not create) - if (trans.user().equals(cred.id)) { - return Result.ok(); - } if (nsd==null) { nsd = ques.validNSOfDomain(trans, cred.id); } // Get the Namespace if (nsd.isOK()) { - if (ques.mayUser(trans, trans.user(), nsd.value,Access.write).isOK()) { - return Result.ok(); - } - String user[] = Split.split('.',trans.user()); - if (user.length>2) { - String company = user[user.length-1] + '.' + user[user.length-2]; - if (ques.isGranted(trans, trans.user(), ROOT_NS,"password",company,"reset")) { - return Result.ok(); - } - } + String ns = nsd.value.name; + String user = trans.user(); + String company; + String temp[] = Split.split('.',ns); + switch(temp.length) { + case 0: + company = Defaults.AAF_NS; + break; + case 1: + company = temp[0]; + break; + default: + company = temp[0] + '.' + temp[1]; + } + switch(action) { + case DELETE: + if(ques.isOwner(trans, user,ns) || + ques.isAdmin(trans, user,ns) || + ques.isGranted(trans, user, ROOT_NS,"password",company,DELETE)) { + return Result.ok(); + } + break; + case RESET: + case EXTEND: + if (ques.isGranted(trans, trans.user(), ROOT_NS,"password",company,action)) { + return Result.ok(); + } + break; + } } - return Result.err(Status.ERR_Denied,"%s is not allowed to change %s in %s",trans.user(),cred.id,cred.ns); + return Result.err(Status.ERR_Denied,"%s is not allowed to %s %s in %s",trans.user(),action,cred.id,cred.ns); } - } private final long DAY_IN_MILLIS = 24*3600*1000L; @@ -2561,7 +2657,7 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } ) @Override - public Result<Void> changeUserCred(final AuthzTrans trans, REQUEST from) { + public Result<Void> resetUserCred(final AuthzTrans trans, REQUEST from) { final String cmdDescription = "Update User Credential"; TimeTaken tt = trans.start(cmdDescription, Env.SUB); try { @@ -2579,13 +2675,15 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); } - MayChange mc = new MayChangeCred(trans, rcred.value); + MayChange mc = new MayChangeCred(trans, rcred.value,MayChangeCred.RESET); Result<?> rmc = mc.mayChange(); if (rmc.notOK()) { return Result.err(rmc); } - Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, rlcd.value); + List<CredDAO.Data> lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256); + + Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, lcdd, MayChangeCred.RESET); if (ri.notOK()) { return Result.err(ri); } @@ -2668,27 +2766,6 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } } - /* - * Codify the way to get Either Choice Needed or actual Integer from Credit Request - */ - private Result<Integer> selectEntryIfMultiple(final CredRequest cr, List<CredDAO.Data> lcd) { - int entry = 0; - if (lcd.size() > 1) { - String inputOption = cr.getEntry(); - if (inputOption == null) { - String message = selectCredFromList(lcd, false); - Object[] variables = buildVariables(lcd); - return Result.err(Status.ERR_ChoiceNeeded, message, variables); - } else { - entry = Integer.parseInt(inputOption) - 1; - } - if (entry < 0 || entry >= lcd.size()) { - return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); - } - } - return Result.ok(entry); - } - @ApiDoc( method = PUT, path = "/authn/cred/:days", @@ -2730,14 +2807,18 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE if (rlcd.notOKorIsEmpty()) { return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); } + + // Only Passwords can be extended + List<CredDAO.Data> lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256); //Need to do the "Pick Entry" mechanism - Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, rlcd.value); + // Note, this sorts + Result<Integer> ri = selectEntryIfMultiple((CredRequest)from, lcdd, "extend"); if (ri.notOK()) { return Result.err(ri); } - CredDAO.Data found = rlcd.value.get(ri.value); + CredDAO.Data found = lcdd.get(ri.value); CredDAO.Data cd = cred.value; // Copy over the cred cd.id = found.id; @@ -2759,29 +2840,204 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } } - private String[] buildVariables(List<CredDAO.Data> value) { + @ApiDoc( + method = DELETE, + path = "/authn/cred", + params = {}, + expectedCode = 200, + errorCodes = {300,403,404,406}, + text = { "Delete a Credential. If multiple credentials exist for this", + "ID, you will need to specify which entry you are deleting in the", + "CredRequest object." + } + ) + @Override + public Result<Void> deleteUserCred(AuthzTrans trans, REQUEST from) { + final Result<CredDAO.Data> cred = mapper.cred(trans, from, false); + final Validator v = new ServiceValidator(); + if (v.nullOrBlank("cred", cred.value.id).err()) { + return Result.err(Status.ERR_BadData,v.errs()); + } + + MayChange mc = new MayChangeCred(trans,cred.value,MayChangeCred.DELETE); + Result<?> rmc = mc.mayChange(); + if (rmc.notOK()) { + return Result.err(rmc); + } + + Result<List<CredDAO.Data>> rlcd = ques.credDAO().readID(trans, cred.value.id); + if (rlcd.notOKorIsEmpty()) { + // Empty Creds should have no user_roles. + Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); + if (rlurd.isOK()) { + for (UserRoleDAO.Data data : rlurd.value) { + ques.userRoleDAO().delete(trans, data, false); + } + } + return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); + } + boolean isLastCred = rlcd.value.size()==1; + + + int entry = 0; + if (!trans.requested(force)) { + if (rlcd.value.size() > 1) { + CredRequest cr = (CredRequest)from; + String inputOption = cr.getEntry(); + if (inputOption == null) { + List<CredDAO.Data> list = filterList(rlcd.value,CredDAO.BASIC_AUTH,CredDAO.BASIC_AUTH_SHA256,CredDAO.CERT_SHA256_RSA); + String message = selectCredFromList(list, MayChangeCred.DELETE); + Object[] variables = buildVariables(list); + return Result.err(Status.ERR_ChoiceNeeded, message, variables); + } else { + try { + if (inputOption.length()>5) { // should be a date + Date d = Chrono.xmlDatatypeFactory.newXMLGregorianCalendar(inputOption).toGregorianCalendar().getTime(); + entry = 0; + for (CredDAO.Data cd : rlcd.value) { + if (cd.type.equals(cr.getType()) && cd.expires.equals(d)) { + break; + } + ++entry; + } + } else { + entry = Integer.parseInt(inputOption) - 1; + } + } catch (NullPointerException e) { + return Result.err(Status.ERR_BadData, "Invalid Date Format for Entry"); + } catch (NumberFormatException e) { + return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); + } + } + isLastCred = (entry==-1)?true:false; + } else { + isLastCred = true; + } + if (entry < -1 || entry >= rlcd.value.size()) { + return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); + } + } + + Result<FutureDAO.Data> fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false, + () -> "Delete Credential [" + + cred.value.id + + ']', + mc); + + Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, cred.value.ns); + if (nsr.notOKorIsEmpty()) { + return Result.err(nsr); + } + + switch(fd.status) { + case OK: + Result<String> rfc = func.createFuture(trans, fd.value, cred.value.id, + trans.user(), nsr.value.get(0), FUTURE_OP.D); + + if (rfc.isOK()) { + return Result.err(Status.ACC_Future, "Credential Delete [%s] is saved for future processing",cred.value.id); + } else { + return Result.err(rfc); + } + case Status.ACC_Now: + Result<?>udr = null; + if (!trans.requested(force)) { + if (entry<0 || entry >= rlcd.value.size()) { + return Result.err(Status.ERR_BadData,"Invalid Choice [" + entry + "] chosen for Delete [%s] is saved for future processing",cred.value.id); + } + udr = ques.credDAO().delete(trans, rlcd.value.get(entry),false); + } else { + for (CredDAO.Data curr : rlcd.value) { + udr = ques.credDAO().delete(trans, curr, false); + if (udr.notOK()) { + return Result.err(udr); + } + } + } + if (isLastCred) { + Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); + if (rlurd.isOK()) { + for (UserRoleDAO.Data data : rlurd.value) { + ques.userRoleDAO().delete(trans, data, false); + } + } + } + if (udr==null) { + return Result.err(Result.ERR_NotFound,"No User Data found"); + } + if (udr.isOK()) { + return Result.ok(); + } + return Result.err(udr); + default: + return Result.err(fd); + } + + } + + /* + * Codify the way to get Either Choice Needed or actual Integer from Credit Request + */ + private Result<Integer> selectEntryIfMultiple(final CredRequest cr, List<CredDAO.Data> lcd, String action) { + int entry = 0; + if (lcd.size() > 1) { + String inputOption = cr.getEntry(); + if (inputOption == null) { + String message = selectCredFromList(lcd, action); + Object[] variables = buildVariables(lcd); + return Result.err(Status.ERR_ChoiceNeeded, message, variables); + } else { + entry = Integer.parseInt(inputOption) - 1; + } + if (entry < 0 || entry >= lcd.size()) { + return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); + } + } + return Result.ok(entry); + } + + private List<CredDAO.Data> filterList(List<CredDAO.Data> orig, Integer ... types) { + List<CredDAO.Data> rv = new ArrayList<>(); + for(CredDAO.Data cdd : orig) { + if(cdd!=null) { + for(int t : types) { + if(t==cdd.type) { + rv.add(cdd); + } + } + } + } + return rv; + } + + private String[] buildVariables(List<CredDAO.Data> value) { // ensure credentials are sorted so we can fully automate Cred regression test - Collections.sort(value, (cred1, cred2) -> cred1.expires.compareTo(cred2.expires)); + Collections.sort(value, (cred1, cred2) -> + cred1.type==cred2.type?cred2.expires.compareTo(cred1.expires): + cred1.type<cred2.type?-1:1); String [] vars = new String[value.size()+1]; vars[0]="Choice"; + CredDAO.Data cdd; for (int i = 0; i < value.size(); i++) { - vars[i+1] = value.get(i).id + " " + value.get(i).type - + " |" + value.get(i).expires; + cdd = value.get(i); + vars[i+1] = cdd.id + TWO_SPACE + cdd.type + TWO_SPACE + (cdd.type<10?TWO_SPACE:"")+ cdd.expires + TWO_SPACE + cdd.tag; } return vars; } - private String selectCredFromList(List<CredDAO.Data> value, boolean isDelete) { + private String selectCredFromList(List<CredDAO.Data> value, String action) { StringBuilder errMessage = new StringBuilder(); - String userPrompt = isDelete?"Select which cred to delete (set force=true to delete all):":"Select which cred to update:"; + String userPrompt = MayChangeCred.DELETE.equals(action)? + "Select which cred to delete (set force=true to delete all):": + "Select which cred to " + action + ':'; int numSpaces = value.get(0).id.length() - "Id".length(); errMessage.append(userPrompt + '\n'); - errMessage.append(" Id"); + errMessage.append(" ID"); for (int i = 0; i < numSpaces; i++) { errMessage.append(' '); } - errMessage.append(" Type Expires" + '\n'); + errMessage.append(" Type Expires Tag " + '\n'); for (int i=0;i<value.size();++i) { errMessage.append(" %s\n"); } @@ -2791,140 +3047,6 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } - @ApiDoc( - method = DELETE, - path = "/authn/cred", - params = {}, - expectedCode = 200, - errorCodes = {300,403,404,406}, - text = { "Delete a Credential. If multiple credentials exist for this", - "ID, you will need to specify which entry you are deleting in the", - "CredRequest object." - } - ) - @Override - public Result<Void> deleteUserCred(AuthzTrans trans, REQUEST from) { - final Result<CredDAO.Data> cred = mapper.cred(trans, from, false); - final Validator v = new ServiceValidator(); - if (v.nullOrBlank("cred", cred.value.id).err()) { - return Result.err(Status.ERR_BadData,v.errs()); - } - - Result<List<CredDAO.Data>> rlcd = ques.credDAO().readID(trans, cred.value.id); - if (rlcd.notOKorIsEmpty()) { - // Empty Creds should have no user_roles. - Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); - if (rlurd.isOK()) { - for (UserRoleDAO.Data data : rlurd.value) { - ques.userRoleDAO().delete(trans, data, false); - } - } - return Result.err(Status.ERR_UserNotFound, "Credential does not exist"); - } - boolean isLastCred = rlcd.value.size()==1; - - MayChange mc = new MayChangeCred(trans,cred.value); - Result<?> rmc = mc.mayChange(); - if (rmc.notOK()) { - return Result.err(rmc); - } - - int entry = 0; - if (!trans.requested(force)) { - if (rlcd.value.size() > 1) { - CredRequest cr = (CredRequest)from; - String inputOption = cr.getEntry(); - if (inputOption == null) { - String message = selectCredFromList(rlcd.value, true); - Object[] variables = buildVariables(rlcd.value); - return Result.err(Status.ERR_ChoiceNeeded, message, variables); - } else { - try { - if (inputOption.length()>5) { // should be a date - Date d = Chrono.xmlDatatypeFactory.newXMLGregorianCalendar(inputOption).toGregorianCalendar().getTime(); - entry = 0; - for (CredDAO.Data cd : rlcd.value) { - if (cd.type.equals(cr.getType()) && cd.expires.equals(d)) { - break; - } - ++entry; - } - } else { - entry = Integer.parseInt(inputOption) - 1; - } - } catch (NullPointerException e) { - return Result.err(Status.ERR_BadData, "Invalid Date Format for Entry"); - } catch (NumberFormatException e) { - return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); - } - } - isLastCred = (entry==-1)?true:false; - } else { - isLastCred = true; - } - if (entry < -1 || entry >= rlcd.value.size()) { - return Result.err(Status.ERR_BadData, "User chose invalid credential selection"); - } - } - - Result<FutureDAO.Data> fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false, - () -> "Delete Credential [" + - cred.value.id + - ']', - mc); - - Result<List<NsDAO.Data>> nsr = ques.nsDAO().read(trans, cred.value.ns); - if (nsr.notOKorIsEmpty()) { - return Result.err(nsr); - } - - switch(fd.status) { - case OK: - Result<String> rfc = func.createFuture(trans, fd.value, cred.value.id, - trans.user(), nsr.value.get(0), FUTURE_OP.D); - - if (rfc.isOK()) { - return Result.err(Status.ACC_Future, "Credential Delete [%s] is saved for future processing",cred.value.id); - } else { - return Result.err(rfc); - } - case Status.ACC_Now: - Result<?>udr = null; - if (!trans.requested(force)) { - if (entry<0 || entry >= rlcd.value.size()) { - return Result.err(Status.ERR_BadData,"Invalid Choice [" + entry + "] chosen for Delete [%s] is saved for future processing",cred.value.id); - } - udr = ques.credDAO().delete(trans, rlcd.value.get(entry),false); - } else { - for (CredDAO.Data curr : rlcd.value) { - udr = ques.credDAO().delete(trans, curr, false); - if (udr.notOK()) { - return Result.err(udr); - } - } - } - if (isLastCred) { - Result<List<UserRoleDAO.Data>> rlurd = ques.userRoleDAO().readByUser(trans, cred.value.id); - if (rlurd.isOK()) { - for (UserRoleDAO.Data data : rlurd.value) { - ques.userRoleDAO().delete(trans, data, false); - } - } - } - if (udr==null) { - return Result.err(Result.ERR_NotFound,"No User Data found"); - } - if (udr.isOK()) { - return Result.ok(); - } - return Result.err(udr); - default: - return Result.err(fd); - } - - } - - @Override public Result<Date> doesCredentialMatch(AuthzTrans trans, REQUEST credReq) { TimeTaken tt = trans.start("Does Credential Match", Env.SUB); @@ -2950,22 +3072,6 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } @ApiDoc( - method = GET, - path = "/authn/basicAuth", - params = {}, - expectedCode = 200, - errorCodes = { 403 }, - text = { "!!!! DEPRECATED without X509 Authentication STOP USING THIS API BY DECEMBER 2017, or use Certificates !!!!\n" - + "Use /authn/validate instead\n" - + "Note: Validate a Password using BasicAuth Base64 encoded Header. This HTTP/S call is intended as a fast" - + " User/Password lookup for Security Frameworks, and responds 200 if it passes BasicAuth " - + "security, and 403 if it does not." } - ) - private void basicAuth() { - // This is a place holder for Documentation. The real BasicAuth API does not call Service. - } - - @ApiDoc( method = POST, path = "/authn/validate", params = {}, @@ -2995,6 +3101,22 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE return Result.err(Status.ERR_Denied,"Bad Basic Auth"); } +@ApiDoc( + method = GET, + path = "/authn/basicAuth", + params = {}, + expectedCode = 200, + errorCodes = { 403 }, + text = { "!!!! DEPRECATED without X509 Authentication STOP USING THIS API BY DECEMBER 2017, or use Certificates !!!!\n" + + "Use /authn/validate instead\n" + + "Note: Validate a Password using BasicAuth Base64 encoded Header. This HTTP/S call is intended as a fast" + + " User/Password lookup for Security Frameworks, and responds 200 if it passes BasicAuth " + + "security, and 403 if it does not." } + ) + private void basicAuth() { + // This is a place holder for Documentation. The real BasicAuth API does not call Service. + } + /*********************************** * USER-ROLE ***********************************/ @@ -3022,7 +3144,7 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE final UserRoleDAO.Data userRole = urr.value; final ServiceValidator v = new ServiceValidator(); - if (v.user_role(userRole).err() || + if (v.user_role(trans.user(),userRole).err() || v.user(trans.org(), userRole.user).err()) { return Result.err(Status.ERR_BadData,v.errs()); } @@ -3038,6 +3160,9 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE private Result<NsDAO.Data> nsd; @Override public Result<?> mayChange() { + if(urr.value.role.startsWith(urr.value.user)) { + return Result.ok((NsDAO.Data)null); + } if (nsd==null) { RoleDAO.Data r = RoleDAO.Data.decode(userRole); nsd = ques.mayUser(trans, trans.user(), r, Access.write); @@ -3045,15 +3170,24 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE return nsd; } }); - Result<NsDAO.Data> nsr = ques.deriveNs(trans, userRole.role); - if (nsr.notOKorIsEmpty()) { - return Result.err(nsr); + + NsDAO.Data ndd; + if(userRole.role.startsWith(userRole.user)) { + userRole.ns=userRole.user; + userRole.rname="user"; + ndd = null; + } else { + Result<NsDAO.Data> nsr = ques.deriveNs(trans, userRole.role); + if (nsr.notOK()) { + return Result.err(nsr); + } + ndd = nsr.value; } switch(fd.status) { case OK: Result<String> rfc = func.createFuture(trans, fd.value, userRole.user+'|'+userRole.ns + '.' + userRole.rname, - userRole.user, nsr.value, FUTURE_OP.C); + userRole.user, ndd, FUTURE_OP.C); if (rfc.isOK()) { return Result.err(Status.ACC_Future, "UserRole [%s - %s.%s] is saved for future processing", userRole.user, @@ -3519,7 +3653,7 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE return Result.ok(users); } - /*********************************** +/*********************************** * HISTORY ***********************************/ @Override @@ -3593,16 +3727,21 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } // May user see Namespace of Permission (since it's only one piece... we can't check for "is permission part of") - Result<NsDAO.Data> rnd = ques.deriveNs(trans,type); - if (rnd.notOK()) { - return Result.err(rnd); + Result<List<HistoryDAO.Data>> resp; + if(type.startsWith(trans.user())) { + resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); + } else { + Result<NsDAO.Data> rnd = ques.deriveNs(trans,type); + if (rnd.notOK()) { + return Result.err(rnd); + } + rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read); + if (rnd.notOK()) { + return Result.err(rnd); + } + resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); } - rnd = ques.mayUser(trans, trans.user(), rnd.value, Access.read); - if (rnd.notOK()) { - return Result.err(rnd); - } - Result<List<HistoryDAO.Data>> resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); if (resp.notOK()) { return Result.err(resp); } @@ -3612,8 +3751,7 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE @Override public Result<HISTORY> getHistoryByNS(AuthzTrans trans, String ns, int[] yyyymm, final int sort) { final Validator v = new ServiceValidator(); - if (v.nullOrBlank("NS",ns) - .err()) { + if (v.nullOrBlank("NS",ns).err()) { return Result.err(Status.ERR_BadData,v.errs()); } @@ -3633,6 +3771,22 @@ public class AuthzCassServiceImpl <NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE return mapper.history(trans, resp.value,sort); } + @Override + public Result<HISTORY> getHistoryBySubject(AuthzTrans trans, String subject, String target, int[] yyyymm, final int sort) { + NsDAO.Data ndd = new NsDAO.Data(); + ndd.name = FQI.reverseDomain(subject); + Result<Data> rnd = ques.mayUser(trans, trans.user(), ndd, Access.read); + if (rnd.notOK()) { + return Result.err(rnd); + } + + Result<List<HistoryDAO.Data>> resp = ques.historyDAO().readBySubject(trans, subject, target, yyyymm); + if (resp.notOK()) { + return Result.err(resp); + } + return mapper.history(trans, resp.value,sort); + } + /*********************************** * DELEGATE ***********************************/ diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzService.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzService.java index a89f64ed..80d317f0 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzService.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/AuthzService.java @@ -447,7 +447,7 @@ public interface AuthzService<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERT * @param from * @return */ - Result<Void> changeUserCred(AuthzTrans trans, REQUEST from); + Result<Void> resetUserCred(AuthzTrans trans, REQUEST from); /** * @@ -636,6 +636,16 @@ public interface AuthzService<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERT */ public Result<HISTORY> getHistoryByNS(AuthzTrans trans, String subj, int[] yyyymm, int sort); + /** + * + * @param trans + * @param target + * @param yyyymm + * @param sort + * @return + */ + public Result<HISTORY> getHistoryBySubject(AuthzTrans trans, String subject, String target, int[] yyyymm, int sort); + /*********************************** * DELEGATE ***********************************/ @@ -753,7 +763,4 @@ public interface AuthzService<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DELGS,CERT */ public void dbReset(AuthzTrans trans); - - - } diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/api/API_History.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/api/API_History.java index 2c868d3d..ce730cec 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/api/API_History.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/api/API_History.java @@ -170,6 +170,33 @@ public class API_History { } } }); + + /** + * Get History by Subject + */ + authzAPI.route(GET,"/authz/hist/subject/:type/:subject",API.HISTORY,new Code(facade,"Get History by Perm Type", true) { + @Override + public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception { + int[] years; + int descend; + try { + years = getYears(req); + descend = decending(req); + } catch (Exception e) { + context.error(trans, resp, Result.err(Status.ERR_BadData, e.getMessage())); + return; + } + + Result<Void> r = context.getHistoryBySubject(trans, resp, pathParam(req,":type"), pathParam(req,":subject"),years,descend); + switch(r.status) { + case OK: + resp.setStatus(HttpStatus.OK_200); + break; + default: + context.error(trans,resp,r); + } + } + }); } // Check if Ascending diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacade.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacade.java index 463de35f..80e02264 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacade.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacade.java @@ -235,13 +235,15 @@ public interface AuthzFacade { */ public abstract Result<Void> getHistoryByUser(AuthzTrans trans, HttpServletResponse resp, String user, int[] yyyymm, final int sort); - public abstract Result<Void> getHistoryByRole(AuthzTrans trans, HttpServletResponse resp, String subject, int[] yyyymm, final int sort); + public abstract Result<Void> getHistoryByRole(AuthzTrans trans, HttpServletResponse resp, String role, int[] yyyymm, final int sort); - public abstract Result<Void> getHistoryByPerm(AuthzTrans trans, HttpServletResponse resp, String subject, int[] yyyymm, final int sort); + public abstract Result<Void> getHistoryByPerm(AuthzTrans trans, HttpServletResponse resp, String perm, int[] yyyymm, final int sort); - public abstract Result<Void> getHistoryByNS(AuthzTrans trans, HttpServletResponse resp, String subject, int[] yyyymm, final int sort); + public abstract Result<Void> getHistoryByNS(AuthzTrans trans, HttpServletResponse resp, String ns, int[] yyyymm, final int sort); - /* + public abstract Result<Void> getHistoryBySubject(AuthzTrans trans, HttpServletResponse resp, String type, String subject, int[] yyyymm, int sort); + + /* * Cache */ public abstract Result<Void> cacheClear(AuthzTrans trans, String pathParam); diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacadeImpl.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacadeImpl.java index 02fa842f..e85e52ec 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacadeImpl.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/facade/AuthzFacadeImpl.java @@ -44,7 +44,9 @@ import static org.onap.aaf.auth.layer.Result.OK; import java.io.IOException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Date; +import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -172,9 +174,15 @@ public abstract class AuthzFacadeImpl<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE if (result.variables==null) { detail = new String[1]; } else { - int l = result.variables.length; - detail=new String[l+1]; - System.arraycopy(result.variables, 0, detail, 1, l); + List<String> dlist = new ArrayList<String>(); + String os; + for(Object s : result.variables) { + if(s!=null && (os=s.toString()).length()>0) { + dlist.add(os); + } + } + detail = new String[dlist.size()]; + dlist.toArray(detail); } //int httpstatus; @@ -280,10 +288,6 @@ public abstract class AuthzFacadeImpl<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE break; case ERR_ChoiceNeeded: msgId = "SVC1300"; - detail = new String[result.variables.length]; - for(int i=0; i<result.variables.length;++i) { - detail[i]=result.variables[i].toString(); - } response.setStatus(/*httpstatus=*/300); break; case ERR_Backend: @@ -1623,7 +1627,7 @@ public abstract class AuthzFacadeImpl<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE Question.logEncryptTrace(trans,data.asString()); } - return service.changeUserCred(trans, data.asObject()); + return service.resetUserCred(trans, data.asObject()); } catch (APIException e) { trans.error().log(e,"Bad Input data"); return Result.err(Status.ERR_BadData, e.getLocalizedMessage()); @@ -2274,6 +2278,7 @@ public abstract class AuthzFacadeImpl<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE public static final String GET_HISTORY_ROLE = "getHistoryByRole"; public static final String GET_HISTORY_PERM = "getHistoryByPerm"; public static final String GET_HISTORY_NS = "getHistoryByNS"; + public static final String GET_HISTORY_SUBJECT = "getHistoryBySubject"; /* (non-Javadoc) * @see com.att.authz.facade.AuthzFacade#getHistoryByUser(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ @@ -2447,6 +2452,50 @@ public abstract class AuthzFacadeImpl<NSS,PERMS,PERMKEY,ROLES,USERS,USERROLES,DE } } + /* (non-Javadoc) + * @see com.att.authz.facade.AuthzFacade#getHistoryByUser(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public Result<Void> getHistoryBySubject(AuthzTrans trans, HttpServletResponse resp, String subject, String target, int[] yyyymm, final int sort) { + StringBuilder sb = new StringBuilder(); + sb.append(GET_HISTORY_SUBJECT); + sb.append(' '); + sb.append(subject); + sb.append(" for "); + boolean first = true; + for (int i : yyyymm) { + if (first) { + first = false; + } else { + sb.append(','); + } + sb.append(i); + } + TimeTaken tt = trans.start(sb.toString(), Env.SUB|Env.ALWAYS); + + try { + Result<HISTORY> rh = service.getHistoryBySubject(trans,subject,target,yyyymm,sort); + switch(rh.status) { + case OK: + RosettaData<HISTORY> data = historyDF.newData(trans).load(rh.value); + if (Question.willSpecialLog(trans, trans.user())) { + Question.logEncryptTrace(trans,data.asString()); + } + + data.to(resp.getOutputStream()); + setContentType(resp,historyDF.getOutType()); + return Result.ok(); + default: + return Result.err(rh); + } + } catch (Exception e) { + trans.error().log(e,IN,GET_HISTORY_USER); + return Result.err(e); + } finally { + tt.done(); + } + } + public final static String CACHE_CLEAR = "cacheClear "; // public final static String CACHE_VALIDATE = "validateCache"; diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/mapper/Mapper_2_0.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/mapper/Mapper_2_0.java index 187f4e39..44ad7fcb 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/mapper/Mapper_2_0.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/mapper/Mapper_2_0.java @@ -38,6 +38,7 @@ import org.onap.aaf.auth.dao.cass.ApprovalDAO; import org.onap.aaf.auth.dao.cass.CertDAO; import org.onap.aaf.auth.dao.cass.CredDAO; import org.onap.aaf.auth.dao.cass.DelegateDAO; +import org.onap.aaf.auth.dao.cass.DelegateDAO.Data; import org.onap.aaf.auth.dao.cass.FutureDAO; import org.onap.aaf.auth.dao.cass.HistoryDAO; import org.onap.aaf.auth.dao.cass.Namespace; @@ -47,7 +48,6 @@ import org.onap.aaf.auth.dao.cass.PermDAO; import org.onap.aaf.auth.dao.cass.RoleDAO; import org.onap.aaf.auth.dao.cass.Status; import org.onap.aaf.auth.dao.cass.UserRoleDAO; -import org.onap.aaf.auth.dao.cass.DelegateDAO.Data; import org.onap.aaf.auth.dao.hl.Question; import org.onap.aaf.auth.dao.hl.Question.Access; import org.onap.aaf.auth.env.AuthzTrans; @@ -58,6 +58,7 @@ import org.onap.aaf.auth.org.Organization.Expiration; import org.onap.aaf.auth.rserv.Pair; import org.onap.aaf.auth.service.MayChange; import org.onap.aaf.cadi.aaf.marshal.CertsMarshal; +import org.onap.aaf.cadi.util.Split; import org.onap.aaf.cadi.util.Vars; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.TimeTaken; @@ -364,18 +365,32 @@ public class Mapper_2_0 implements Mapper<Nss, Perms, Pkey, Roles, Users, UserRo @Override public Result<PermDAO.Data> perm(AuthzTrans trans, Request req) { PermRequest from = (PermRequest)req; - Result<NsSplit> nss = q.deriveNsSplit(trans, from.getType()); + String type = from.getType(); + if(type==null) { + return Result.err(Result.ERR_BadData, "Invalid Perm Type"); + } PermDAO.Data pd = new PermDAO.Data(); - if (nss.isOK()) { - pd.ns=nss.value.ns; - pd.type = nss.value.name; - pd.instance = from.getInstance(); - pd.action = from.getAction(); - pd.description = from.getDescription(); - trans.checkpoint(pd.fullPerm(), Env.ALWAYS); - return Result.ok(pd); - } else { - return Result.err(nss); + if(type.contains("@")) { + String[] split = Split.splitTrim(':', type); + pd.ns = split[0]; + pd.type=split.length>1?split[1]:""; + pd.instance = from.getInstance(); + pd.action = from.getAction(); + pd.description = from.getDescription(); + return Result.ok(pd); + } else { + Result<NsSplit> nss = q.deriveNsSplit(trans, from.getType()); + if (nss.isOK()) { + pd.ns=nss.value.ns; + pd.type = nss.value.name; + pd.instance = from.getInstance(); + pd.action = from.getAction(); + pd.description = from.getDescription(); + trans.checkpoint(pd.fullPerm(), Env.ALWAYS); + return Result.ok(pd); + } else { + return Result.err(nss); + } } } diff --git a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/validation/ServiceValidator.java b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/validation/ServiceValidator.java index adff4612..df8bde8b 100644 --- a/auth/auth-service/src/main/java/org/onap/aaf/auth/service/validation/ServiceValidator.java +++ b/auth/auth-service/src/main/java/org/onap/aaf/auth/service/validation/ServiceValidator.java @@ -57,7 +57,9 @@ public class ServiceValidator extends Validator { if (pd==null) { msg("Perm Data is null."); } else { - ns(pd.ns); + if(!pd.ns.contains("@")) { + ns(pd.ns); + } permType(pd.type,pd.ns); permInstance(pd.instance); permAction(pd.action); @@ -84,7 +86,7 @@ public class ServiceValidator extends Validator { } return this; } - + public ServiceValidator role(RoleDAO.Data pd) { if (pd==null) { msg("Role Data is null."); @@ -217,6 +219,16 @@ public class ServiceValidator extends Validator { return this; } + public ServiceValidator user_role(String user, UserRoleDAO.Data urdd) { + role(user,urdd.role); + if(!urdd.role.startsWith(user)) { + nullOrBlank("UserRole.ns",urdd.ns); + nullOrBlank("UserRole.rname",urdd.rname); + } + return this; + } + + public ServiceValidator user_role(UserRoleDAO.Data urdd) { if (urdd==null) { msg("UserRole is null"); diff --git a/auth/docker/dbash.sh b/auth/docker/dbash.sh index a9c90f99..81e96b4d 100644 --- a/auth/docker/dbash.sh +++ b/auth/docker/dbash.sh @@ -20,4 +20,4 @@ # . ./d.props -${DOCKER:=docker} exec -it aaf-$1 bash -c "cd /opt/app/osaaf/logs && exec bash" +${DOCKER:=docker} exec -it aaf-$1 bash -c "cd /opt/app && exec bash" diff --git a/auth/docker/dinstall.sh b/auth/docker/dinstall.sh new file mode 100644 index 00000000..22ea4c91 --- /dev/null +++ b/auth/docker/dinstall.sh @@ -0,0 +1,29 @@ +#!/bin/bash +######### +# ============LICENSE_START==================================================== +# org.onap.aaf +# =========================================================================== +# Copyright (c) 2017 AT&T Intellectual Property. All rights reserved. +# =========================================================================== +# 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. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END==================================================== +# +# This is only called from HEAT, as it needs a single check and wait for Cassandra to be ready +# +cd ../auth-cass/docker +. dinstall.sh $@ +cd - +if [ "$1" = "publish" ]; then + shift +fi +. drun.sh diff --git a/auth/docker/drun.sh b/auth/docker/drun.sh index 648c497a..1910f4a2 100644 --- a/auth/docker/drun.sh +++ b/auth/docker/drun.sh @@ -106,6 +106,7 @@ for AAF_COMPONENT in ${AAF_COMPONENTS}; do --env aaf_locator_container_ns=${NAMESPACE} \ --env aaf_locator_fqdn=${HOSTNAME} \ --env aaf_locator_public_fqdn=${HOSTNAME} \ + --env aaf_deployed_version=${VERSION} \ --env LATITUDE=${LATITUDE} \ --env LONGITUDE=${LONGITUDE} \ --env CASSANDRA_CLUSTER=${CASSANDRA_CLUSTER} \ diff --git a/auth/helm/aaf-hello/aaf.sh b/auth/helm/aaf-hello/aaf.sh index 5bb83515..b1c8e639 100644 --- a/auth/helm/aaf-hello/aaf.sh +++ b/auth/helm/aaf-hello/aaf.sh @@ -1,4 +1,4 @@ -. ../../docker/d.props +. ../../docker/aaf.props IMAGE=onap/aaf/aaf_agent:$VERSION kubectl -n onap run -it --rm aaf-agent-$USER --image=$IMAGE --overrides=' diff --git a/auth/helm/aaf-hello/values.yaml b/auth/helm/aaf-hello/values.yaml index 8d43070e..3a0a377c 100644 --- a/auth/helm/aaf-hello/values.yaml +++ b/auth/helm/aaf-hello/values.yaml @@ -54,7 +54,7 @@ image: # When using Docker Repo, add, and include trailing "/" # repository: nexus3.onap.org:10003/ # repository: localhost:5000/ - version: 2.1.12-SNAPSHOT + version: 2.1.14-SNAPSHOT resources: {} # We usually recommend not to specify default resources and to leave this as a conscious diff --git a/auth/helm/aaf/Chart.yaml b/auth/helm/aaf/Chart.yaml index 0f0f2761..d0a1d286 100644 --- a/auth/helm/aaf/Chart.yaml +++ b/auth/helm/aaf/Chart.yaml @@ -22,4 +22,4 @@ apiVersion: v1 appVersion: "1.0" description: AAF Helm Chart name: aaf -version: 2.1.12-SNAPSHOT +version: 2.1.14-SNAPSHOT diff --git a/auth/helm/aaf/templates/aaf-gui.yaml b/auth/helm/aaf/templates/aaf-gui.yaml index c31496fc..4c540778 100644 --- a/auth/helm/aaf/templates/aaf-gui.yaml +++ b/auth/helm/aaf/templates/aaf-gui.yaml @@ -90,6 +90,8 @@ spec: value: "{{.Values.services.aaf_locator_name}}" - name: aaf_locator_name_helm value: "{{.Values.services.aaf_locator_name_helm}}" + - name: aaf_deployed_version + value: "{{ .Values.image.version }}" - name: CASSANDRA_CLUSTER value: "{{.Values.services.cass.fqdn}}.{{.Values.services.ns}}" # - name: CASSANDRA_USER diff --git a/auth/sample/bin/service.sh b/auth/sample/bin/service.sh index 29d9f967..c14754ae 100644 --- a/auth/sample/bin/service.sh +++ b/auth/sample/bin/service.sh @@ -33,7 +33,7 @@ echo "# Properties passed in" # Set from CAP Based PROPS, if necessary aaf_env=${aaf_env:-"${AAF_ENV}"} -aaf_release=${aaf_release:-"${VERSION}"} +aaf_deployed_version=${aaf_deployed_version:-"${VERSION}"} cadi_latitude=${cadi_latitude:-"${LATITUDE}"} cadi_longitude=${cadi_longitude:-"${LONGITUDE}"} cadi_x509_issuers=${cadi_x509_issuers:-"${CADI_X509_ISSUERS}"} diff --git a/auth/sample/cass_data/config.dat b/auth/sample/cass_data/config.dat index 83976192..cf70164b 100644 --- a/auth/sample/cass_data/config.dat +++ b/auth/sample/cass_data/config.dat @@ -1,9 +1,12 @@ -aaf|aaf_env|DEV -aaf|aaf_oauth2_introspect_url|https://AAF_LOCATE_URL/%CNS.%AAF_NS.introspect:2.1/introspect -aaf|aaf_oauth2_token_url|https://AAF_LOCATE_URL/%CNS.%AAF_NS.token:2.1/token -aaf|aaf_url|https://AAF_LOCATE_URL/%CNS.%AAF_NS.service:2.1 -aaf|cadi_protocols|TLSv1.1,TLSv1.2 -aaf|cadi_x509_issuers|CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US -aaf|cm_url|https://AAF_LOCATE_URL/%CNS.%AAF_NS.cm:2.1 -aaf|fs_url|https://AAF_LOCATE_URL/%CNS.%AAF_NS.fs:2.1 -aaf|gui_url|https://AAF_LOCATE_URL/%CNS.%AAF_NS.gui:2.1 +aaf,aaf_cm_url,https://AAF_LOCATE_URL/%CNS.%AAF_NS.cm:2.1
+aaf,aaf_env,DEV
+aaf,aaf_fs_url,https://AAF_LOCATE_URL/%CNS.%AAF_NS.fs:2.1
+aaf,aaf_gui_url,https://AAF_LOCATE_URL/%CNS.%AAF_NS.gui:2.1
+aaf,aaf_locate_url,https://aaf.dev.att.com:8095
+aaf,aaf_oauth2_introspect_url,https://AAF_LOCATE_URL/%CNS.%AAF_NS.introspect:2.1/introspect
+aaf,aaf_oauth2_token_url,https://AAF_LOCATE_URL/%CNS.%AAF_NS.token:2.1/token
+aaf,aaf_oauth_url,https://AAF_LOCATE_URL/%CNS.%AAF_NS.oauth:2.1
+aaf,aaf_root_ns,com.att.aaf
+aaf,aaf_url,https://AAF_LOCATE_URL/%CNS.%AAF_NS.service:2.1
+aaf,cadi_protocols,"TLSv1.1,TLSv1.2"
+aaf,cadi_x509_issuers,"CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US"
diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/AAFPermission.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/AAFPermission.java index be1d3922..037ee8be 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/AAFPermission.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/AAFPermission.java @@ -83,6 +83,9 @@ public class AAFPermission implements Permission { * If you want a simple field comparison, it is faster without REGEX */ public boolean match(Permission p) { + if(p==null) { + return false; + } String aafNS; String aafType; String aafInstance; diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/TestConnectivity.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/TestConnectivity.java index e5a0a28c..f02c17f8 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/TestConnectivity.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/TestConnectivity.java @@ -76,7 +76,7 @@ public class TestConnectivity { List<SecuritySetter<HttpURLConnection>> lss = loadSetters(access,si); ///////// String directAAFURL = aaf_urls.get(Config.AAF_URL); - if(directAAFURL!=null && !directAAFURL.contains("/locate/")) { + if(directAAFURL!=null && !directAAFURL.contains("/locate/") || !directAAFURL.contains("AAF_LOCATE_URL")) { print(true,"Test Connections by non-located aaf_url"); Locator<URI> locator = new SingleEndpointLocator(directAAFURL); connectTest(locator,new URI(directAAFURL)); diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/client/ErrMessage.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/client/ErrMessage.java index 55421262..42efd89b 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/client/ErrMessage.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/client/ErrMessage.java @@ -88,9 +88,13 @@ public class ErrMessage { public StringBuilder toMsg(StringBuilder sb, Error err) { sb.append(err.getMessageId()); sb.append(' '); - String[] vars = new String[err.getVariables().size()]; + Object[] vars = new String[err.getVariables().size()]; err.getVariables().toArray(vars); Vars.convert(sb, err.getText(),vars); return sb; } + + public Error getError(Future<?> future) throws APIException { + return errDF.newData().in(TYPE.JSON).load(future.body()).asObject(); + } } diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFAuthn.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFAuthn.java index 606638a4..ec0875c1 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFAuthn.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFAuthn.java @@ -117,7 +117,7 @@ public class AAFAuthn<CLIENT> extends AbsUserCache<AAFPermission> { return "AAF Inaccessible"; case UNVALIDATED: addUser(new User<AAFPermission>(user,bytes,con.timeout)); - return "User/Pass combo invalid for " + user; + return "user/pass combo invalid for " + user; case DENIED: return "AAF denies API for " + user; default: diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFTaf.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFTaf.java index 99c3c3fc..a25d2502 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFTaf.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFTaf.java @@ -106,6 +106,7 @@ public class AAFTaf<CLIENT> extends AbsUserCache<AAFPermission> implements HttpT // Note: Either Carbon or Silicon based LifeForms ok String authz = req.getHeader("Authorization"); + String target = "invalid"; if (authz != null && authz.startsWith("Basic ")) { if (warn&&!req.isSecure()) { aaf.access.log(Level.WARN,"WARNING! BasicAuth has been used over an insecure channel"); @@ -131,7 +132,7 @@ public class AAFTaf<CLIENT> extends AbsUserCache<AAFPermission> implements HttpT Miss miss = missed(bp.getName(), bp.getCred()); if (miss!=null && !miss.mayContinue()) { - return new BasicHttpTafResp(aaf.access,null,buildMsg(bp,req, + return new BasicHttpTafResp(aaf.access,bp.getName(),buildMsg(bp,req, "User/Pass Retry limit exceeded"), RESP.TRY_AUTHENTICATING,resp,aaf.getRealm(),true); } @@ -157,11 +158,11 @@ public class AAFTaf<CLIENT> extends AbsUserCache<AAFPermission> implements HttpT // Note: AddMiss checks for miss==null, and is part of logic boolean rv= addMiss(bp.getName(),bp.getCred()); if (rv) { - return new BasicHttpTafResp(aaf.access,null,buildMsg(bp,req, + return new BasicHttpTafResp(aaf.access,bp.getName(),buildMsg(bp,req, "user/pass combo invalid via AAF from " + req.getRemoteAddr()), RESP.TRY_AUTHENTICATING,resp,aaf.getRealm(),true); } else { - return new BasicHttpTafResp(aaf.access,null,buildMsg(bp,req, + return new BasicHttpTafResp(aaf.access,bp.getName(),buildMsg(bp,req, "user/pass combo invalid via AAF from " + req.getRemoteAddr() + " - Retry limit exceeded"), RESP.FAIL,resp,aaf.getRealm(),true); } @@ -172,7 +173,7 @@ public class AAFTaf<CLIENT> extends AbsUserCache<AAFPermission> implements HttpT } catch (IOException e) { String msg = buildMsg(null,req,"Invalid Auth Token"); aaf.access.log(Level.WARN,msg,'(', e.getMessage(), ')'); - return new BasicHttpTafResp(aaf.access,null,msg, RESP.TRY_AUTHENTICATING, resp, aaf.getRealm(),true); + return new BasicHttpTafResp(aaf.access,target,msg, RESP.TRY_AUTHENTICATING, resp, aaf.getRealm(),true); } catch (Exception e) { String msg = buildMsg(null,req,"Authenticating Service unavailable"); try { @@ -181,10 +182,10 @@ public class AAFTaf<CLIENT> extends AbsUserCache<AAFPermission> implements HttpT aaf.access.log(e1, "Error Invalidating Client"); } aaf.access.log(Level.WARN,msg,'(', e.getMessage(), ')'); - return new BasicHttpTafResp(aaf.access,null,msg, RESP.FAIL, resp, aaf.getRealm(),false); + return new BasicHttpTafResp(aaf.access,target,msg, RESP.FAIL, resp, aaf.getRealm(),false); } } - return new BasicHttpTafResp(aaf.access,null,"Requesting HTTP Basic Authorization",RESP.TRY_AUTHENTICATING,resp,aaf.getRealm(),false); + return new BasicHttpTafResp(aaf.access,target,"Requesting HTTP Basic Authorization",RESP.TRY_AUTHENTICATING,resp,aaf.getRealm(),false); } private String buildMsg(Principal pr, HttpServletRequest req, Object... msg) { diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AbsAAFLocator.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AbsAAFLocator.java index ac8168b9..e43250a0 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AbsAAFLocator.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AbsAAFLocator.java @@ -122,6 +122,9 @@ public abstract class AbsAAFLocator<TRANS extends Trans> implements Locator<URI> } public static Locator<URI> create(final String name, final String version) throws LocatorException { + if(locatorCreator==null) { + throw new LocatorException("LocatorCreator is not set"); + } return locatorCreator.create(name, version); } @@ -234,7 +237,7 @@ public abstract class AbsAAFLocator<TRANS extends Trans> implements Locator<URI> @Override public Item best() throws LocatorException { if (!hasItems()) { - throw new LocatorException("No Entries found for '" + aaf_locator_uri.toString() + "/locate/" + name + ':' + version + '\''); + throw new LocatorException("No Entries found for '" + aaf_locator_uri.toString() + '/' + name + ':' + version + '\''); } List<EP> lep = new ArrayList<>(); EP first = null; 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 e50b52d8..98abfbf9 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 @@ -28,12 +28,14 @@ import java.io.IOException; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.InetAddress; +import java.net.URISyntaxException; import java.net.UnknownHostException; import java.nio.file.Files; 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.Deque; import java.util.GregorianCalendar; @@ -84,7 +86,8 @@ import locate.v1_1.Configuration; import locate.v1_1.Configuration.Props; public class Agent { - private static final String HASHES = "################################################################"; + 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"; @@ -233,8 +236,7 @@ public class Agent { aafsso.setLogDefault(); aafsso.setStdErrDefault(); - Map<String, String> aaf_urls = loadURLs(access); - aafsso.addProp(Config.AAF_URL_CM, aaf_urls.get(Config.AAF_URL_CM)); + /*urls=*/loadURLs(access); aafsso.writeFiles(); } @@ -310,29 +312,41 @@ public class Agent { 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[] {"aaf","locate","oauth","cm","gui","fs","hello","token","introspect"}) { - String proto = "fs".equals(u)?"http://":"https://"; - String lhost; - if("locate".equals(u)) { - lhost=rph.default_fqdn; - } else { - lhost=Config.AAF_LOCATE_URL_TAG; - } - String value = rph.replacements("Agent:loadURLs", - proto + lhost + "/%CNS.%AAF_NS." + ("aaf".equals(u)?"service":u) + ':' + version, - null,dot_le); + for(String u : new String[] {"locate","aaf","oauth","cm","gui","fs","hello","token","introspect"}) { + String tag; + String append=null; switch(u) { - case "aaf": rv.put(Config.AAF_URL, value); break; - case "locate": rv.put(Config.getAAFLocateUrl(access), value); break; - case "token": rv.put(Config.AAF_OAUTH2_TOKEN_URL, value); break; - case "introspect": rv.put(Config.AAF_OAUTH2_INTROSPECT_URL, value); break; - case "cm": rv.put(Config.AAF_URL_CM, value); break; - case "gui": rv.put(Config.AAF_URL_GUI, value); break; - case "fs": rv.put(Config.AAF_URL_FS, value); break; - case "hello": rv.put(Config.AAF_URL_HELLO, value); break; + 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: - rv.put("aaf_url_" + u, value); + 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; } @@ -379,6 +393,9 @@ public class Agent { private static String fqi(Deque<String> 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(); @@ -825,9 +842,12 @@ public class Agent { app.add(Config.AAF_LOCATE_URL, Config.getAAFLocateUrl(propAccess)); app.add(Config.AAF_ENV,propAccess, "DEV"); - String release = propAccess.getProperty(Config.AAF_RELEASE); + 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_RELEASE, release); + app.add(Config.AAF_DEPLOYED_VERSION, release); } for(Entry<Object, Object> aaf_loc_prop : propAccess.getProperties().entrySet()) { String key = aaf_loc_prop.getKey().toString(); @@ -910,26 +930,15 @@ public class Agent { } else { aafcon = aafcon(propAccess); if (aafcon!=null) { // get Properties from Remote AAF - final String locator = getProperty(propAccess,aafcon.env,false,Config.AAF_LOCATE_URL,"AAF Locator URL: "); - - Future<Configuration> acf = aafcon.client(new SingleEndpointLocator(locator)) - .read("/configure/"+fqi+"/aaf", configDF); - if (acf.get(TIMEOUT)) { - for (Props props : acf.value.getProps()) { - 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()); - } - } - } 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)); + 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()); + } } + } } } @@ -940,6 +949,20 @@ public class Agent { } } + public static List<Props> aafProps(Trans trans, AAFCon<?> aafcon, String locator, String fqi) throws CadiException, APIException, URISyntaxException { + Future<Configuration> 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 { System.out.println("Validating Configuration..."); diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java index 7256af40..67b3df09 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java @@ -66,17 +66,26 @@ public class PlaceArtifactInKeystore extends ArtifactDir { X509Certificate x509; List<X509Certificate> chainList = new ArrayList<>(); Set<X509Certificate> caSet = new HashSet<>(); + X509Certificate curr = null; for (Certificate c : certColl) { x509 = (X509Certificate)c; // Is a Root (self-signed, anyway) if (x509.getSubjectDN().equals(x509.getIssuerDN())) { caSet.add(x509); } else { - chainList.add(x509); + // Expect Certs in Trust Chain Order. + if(curr==null) { + chainList.add(x509); + curr=x509; + } else { + // Only Add Cert next on the list + if(curr.getIssuerDN().equals(x509.getSubjectDN())) { + chainList.add(x509); + curr=x509; + } + } } } -// chainList.addAll(caSet); - //Collections.reverse(chainList); // Properties, etc // Add CADI Keyfile Entry to Properties diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/oauth/TokenClientFactory.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/oauth/TokenClientFactory.java index 772040c3..b3cf266e 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/oauth/TokenClientFactory.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/oauth/TokenClientFactory.java @@ -29,6 +29,8 @@ import java.nio.file.Path; import java.security.GeneralSecurityException; import java.security.NoSuchAlgorithmException; import java.util.Map; +import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; @@ -55,6 +57,7 @@ import aafoauth.v2_0.Token; public class TokenClientFactory extends Persist<Token,TimedToken> { private static TokenClientFactory instance; + private final Set<String> alts; private Map<String,AAFConHttp> aafcons = new ConcurrentHashMap<>(); private SecurityInfoC<HttpURLConnection> hsi; // Package on purpose @@ -62,14 +65,26 @@ public class TokenClientFactory extends Persist<Token,TimedToken> { private TokenClientFactory(Access pa) throws APIException, GeneralSecurityException, IOException, CadiException { super(pa, new RosettaEnv(pa.getProperties()),Token.class,"outgoing"); + Map<String, String> aaf_urls = Agent.loadURLs(pa); + alts = new TreeSet<>(); + if (access.getProperty(Config.AAF_OAUTH2_TOKEN_URL,null)==null) { access.getProperties().put(Config.AAF_OAUTH2_TOKEN_URL, aaf_urls.get(Config.AAF_OAUTH2_TOKEN_URL)); // Default to AAF } + if (access.getProperty(Config.AAF_OAUTH2_INTROSPECT_URL,null)==null) { access.getProperties().put(Config.AAF_OAUTH2_INTROSPECT_URL, aaf_urls.get(Config.AAF_OAUTH2_INTROSPECT_URL)); // Default to AAF); } - + + for(String tag : new String[] {Config.AAF_ALT_OAUTH2_TOKEN_URL, Config.AAF_ALT_OAUTH2_INTROSPECT_URL}) { + String value = access.getProperty(tag, null); + if(value!=null) { + alts.add(tag); + alts.add(value); + } + } + symm = Symm.encrypt.obtain(); hsi = SecurityInfoC.instance(access, HttpURLConnection.class); } @@ -105,15 +120,11 @@ public class TokenClientFactory extends Persist<Token,TimedToken> { } } char okind; - if ( Config.AAF_OAUTH2_TOKEN_URL.equals(tagOrURL) || - Config.AAF_OAUTH2_INTROSPECT_URL.equals(tagOrURL) || - tagOrURL.equals(access.getProperty(Config.AAF_OAUTH2_TOKEN_URL, null)) || - tagOrURL.equals(access.getProperty(Config.AAF_OAUTH2_INTROSPECT_URL, null)) - ) { - okind = Kind.AAF_OAUTH; - } else { - okind = Kind.OAUTH; - } + if (alts.contains(tagOrURL)) { + okind = Kind.OAUTH; + } else { + okind = Kind.AAF_OAUTH; + } TokenClient tci = new TokenClient( okind, this, diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/obasic/OBasicHttpTaf.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/obasic/OBasicHttpTaf.java index 8c2cc82d..4ae8ba5f 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/obasic/OBasicHttpTaf.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/obasic/OBasicHttpTaf.java @@ -84,7 +84,7 @@ public class OBasicHttpTaf extends AbsOTafLur implements HttpTaf { */ public TafResp validate(Taf.LifeForm reading, HttpServletRequest req, HttpServletResponse resp) { // See if Request implements BasicCred (aka CadiWrap or other), and if User/Pass has already been set separately - final String user; + String user = "invalid"; String password=null; byte[] cred=null; if (req instanceof BasicCred) { @@ -106,18 +106,18 @@ public class OBasicHttpTaf extends AbsOTafLur implements HttpTaf { } else { access.printf(Level.AUDIT,"Malformed BasicAuth entry ip=%s, entry=%s",req.getRemoteAddr(), access.encrypt(temp)); - return new BasicHttpTafResp(access,null,"Malformed BasicAuth entry",RESP.FAIL,resp,realm,false); + return new BasicHttpTafResp(access,user,"Malformed BasicAuth entry",RESP.FAIL,resp,realm,false); } if (!rbac.validate(user,Type.PASSWORD,password.getBytes(),req)) { - return new BasicHttpTafResp(access,null,buildMsg(null,req,"user/pass combo invalid for ",user,"from",req.getRemoteAddr()), + return new BasicHttpTafResp(access,user,buildMsg(null,req,"user/pass combo invalid for ",user,"from",req.getRemoteAddr()), RESP.TRY_AUTHENTICATING,resp,realm,true); } } catch (IOException e) { access.log(e, ERROR_GETTING_TOKEN_CLIENT); - return new BasicHttpTafResp(access,null,ERROR_GETTING_TOKEN_CLIENT,RESP.FAIL,resp,realm,false); + return new BasicHttpTafResp(access,user,ERROR_GETTING_TOKEN_CLIENT,RESP.FAIL,resp,realm,false); } } else { - return new BasicHttpTafResp(access,null,"Not a Basic Auth",RESP.TRY_ANOTHER_TAF,resp,realm,false); + return new BasicHttpTafResp(access,user,"Not a Basic Auth",RESP.TRY_ANOTHER_TAF,resp,realm,false); } } @@ -135,25 +135,25 @@ public class OBasicHttpTaf extends AbsOTafLur implements HttpTaf { Result<TimedToken> rtt = pclient.content.getToken('B',scope); if (rtt.isOK()) { if (rtt.value.expired()) { - return new BasicHttpTafResp(access,null,"BasicAuth/OAuth Token: Token Expired",RESP.FAIL,resp,realm,true); + return new BasicHttpTafResp(access,user,"BasicAuth/OAuth Token: Token Expired",RESP.FAIL,resp,realm,true); } else { TimedToken tt = rtt.value; Result<OAuth2Principal> prin = tkMgr.toPrincipal(tt.getAccessToken(), cred); if (prin.isOK()) { return new BasicHttpTafResp(access,prin.value,"BasicAuth/OAuth Token Authentication",RESP.IS_AUTHENTICATED,resp,realm,true); } else { - return new BasicHttpTafResp(access,null,"BasicAuth/OAuth Token: " + prin.code + ' ' + prin.error,RESP.FAIL,resp,realm,true); + return new BasicHttpTafResp(access,user,"BasicAuth/OAuth Token: " + prin.code + ' ' + prin.error,RESP.FAIL,resp,realm,true); } } } else { - return new BasicHttpTafResp(access,null,"BasicAuth/OAuth Token: " + rtt.code + ' ' + rtt.error,RESP.FAIL,resp,realm,true); + return new BasicHttpTafResp(access,user,"BasicAuth/OAuth Token: " + rtt.code + ' ' + rtt.error,RESP.FAIL,resp,realm,true); } } finally { pclient.done(); } } catch (APIException | CadiException | LocatorException | NoSuchAlgorithmException e) { access.log(e, ERROR_GETTING_TOKEN_CLIENT); - return new BasicHttpTafResp(access,null,ERROR_GETTING_TOKEN_CLIENT,RESP.TRY_ANOTHER_TAF,resp,realm,false); + return new BasicHttpTafResp(access,user,ERROR_GETTING_TOKEN_CLIENT,RESP.TRY_ANOTHER_TAF,resp,realm,false); } } diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/register/RegistrationCreator.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/register/RegistrationCreator.java index cbf0339b..8b879e4f 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/register/RegistrationCreator.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/register/RegistrationCreator.java @@ -90,10 +90,11 @@ public class RegistrationCreator { } if(specificVersion!=null) { String split[] = Split.splitTrim('.', specificVersion); - locate.setPkg(split.length>3?Integer.parseInt(split[3]):0); - locate.setPatch(split.length>2?Integer.parseInt(split[2]):0); - locate.setMinor(split.length>1?Integer.parseInt(split[1]):0); - locate.setMajor(split.length>0?Integer.parseInt(split[0]):0); + String deply[]= Split.splitTrim('.', access.getProperty(Config.AAF_DEPLOYED_VERSION, "")); + locate.setMajor(best(split,deply,0)); + locate.setMinor(best(split,deply,1)); + locate.setPatch(best(split,deply,2)); + locate.setPkg(best(split,deply,3)); } String protocol = access.getProperty(Config.AAF_LOCATOR_PROTOCOL + dot_le, defProtocol); @@ -131,7 +132,39 @@ public class RegistrationCreator { return me; } - private StringBuilder print(StringBuilder sb, List<MgmtEndpoint> lme) { + /* + * Find the best version between Actual Interface and Deployed version + */ + private int best(String[] split, String[] deploy, int i) { + StringBuilder sb = new StringBuilder(); + char c; + String s; + if(split.length>i) { + s=split[i]; + for(int j=0;j<s.length();++j) { + if(Character.isDigit(c=s.charAt(j))) { + sb.append(c); + } else { + break; + } + } + } + + if(sb.length()==0 && deploy.length>i) { + s=deploy[i]; + for(int j=0;j<s.length();++j) { + if(Character.isDigit(c=s.charAt(j))) { + sb.append(c); + } else { + break; + } + } + } + + return sb.length()==0?0:Integer.parseInt(sb.toString()); + } + + private StringBuilder print(StringBuilder sb, List<MgmtEndpoint> lme) { int cnt = 0; for(MgmtEndpoint m : lme) { print(sb,cnt++,m); @@ -155,9 +188,9 @@ public class RegistrationCreator { out.append('.'); out.append(mep.getMinor()); out.append('.'); - out.append(mep.getPkg()); - out.append('.'); out.append(mep.getPatch()); + out.append('.'); + out.append(mep.getPkg()); out.append("\n\tPort: "); out.append(mep.getPort()); out.append("\n\tProtocol: "); @@ -201,8 +234,8 @@ public class RegistrationCreator { out.setLongitude(mep.getLongitude()); out.setMajor(mep.getMajor()); out.setMinor(mep.getMinor()); - out.setPkg(mep.getPkg()); out.setPatch(mep.getPatch()); + out.setPkg(mep.getPkg()); out.setPort(mep.getPort()); out.setProtocol(mep.getProtocol()); out.getSpecialPorts().addAll(mep.getSpecialPorts()); diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/sso/AAFSSO.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/sso/AAFSSO.java index 10acc887..de31e661 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/sso/AAFSSO.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/sso/AAFSSO.java @@ -29,6 +29,7 @@ import java.io.InputStream; import java.io.PrintStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; @@ -36,14 +37,24 @@ import java.util.Properties; import org.onap.aaf.cadi.Access.Level; import org.onap.aaf.cadi.CadiException; +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.v2_0.AAFCon; +import org.onap.aaf.cadi.client.Future; import org.onap.aaf.cadi.config.Config; import org.onap.aaf.cadi.configure.ArtifactDir; +import org.onap.aaf.cadi.locator.SingleEndpointLocator; import org.onap.aaf.cadi.util.MyConsole; import org.onap.aaf.cadi.util.SubStandardConsole; import org.onap.aaf.cadi.util.TheConsole; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.rosetta.env.RosettaDF; +import org.onap.aaf.misc.rosetta.env.RosettaEnv; + +import locate.v1_1.Configuration; +import locate.v1_1.Configuration.Props; public class AAFSSO { public static final MyConsole cons = TheConsole.implemented() ? new TheConsole() : new SubStandardConsole(); @@ -179,16 +190,20 @@ public class AAFSSO { appID=null; } + String aaf_container_ns = ""; if (appID!=null) { - diskprops.setProperty(Config.AAF_APPID,appID); if( access.getProperty(Config.AAF_APPPASS)==null) { - char[] password = cons.readPassword("Password for %s: ", appID); + appID = user = cons.readLine("Deployer ID [%s]: ", user); + access.setProperty(Config.AAF_APPID,appID); + char[] password = cons.readPassword("Password for %s: ", user); if(password.length>0) { String app_pass = access.encrypt(new String(password)); access.setProperty(Config.AAF_APPPASS,app_pass); diskprops.setProperty(Config.AAF_APPPASS,app_pass); } + aaf_container_ns = cons.readLine("Container Namespace (blank if none)? [\"\"]: ", aaf_container_ns); } + diskprops.setProperty(Config.AAF_APPID,appID); } String keystore=access.getProperty(Config.CADI_KEYSTORE); @@ -298,36 +313,6 @@ public class AAFSSO { err.append("-D" + Config.AAF_APPPASS + "=<passwd> "); } - String locateUrl = Config.getAAFLocateUrl(access); - if (locateUrl==null) { - locateUrl=AAFSSO.cons.readLine("AAF Locator URL=https://"); - if (locateUrl==null || locateUrl.length()==0) { - err = new StringBuilder(Config.AAF_LOCATE_URL); - err.append(" is required."); - ok = false; - return; - } else { - locateUrl="https://"+locateUrl; - } - access.setProperty(Config.AAF_LOCATE_URL, locateUrl); - addProp(Config.AAF_LOCATE_URL, locateUrl); - } - - final String apiVersion = access.getProperty(Config.AAF_API_VERSION, Config.AAF_DEFAULT_API_VERSION); - final String aaf_root_ns = access.getProperty(Config.AAF_ROOT_NS); - String locateRoot; - if(aaf_root_ns==null) { - locateRoot=Defaults.AAF_ROOT; - } else { - locateRoot = Defaults.AAF_LOCATE_CONST + "/%CNS." + aaf_root_ns; - } - if(access.getProperty(Config.AAF_URL)==null) { - - access.setProperty(Config.AAF_URL, locateRoot+".service:"+apiVersion); - } - if(access.getProperty(Config.AAF_URL_CM)==null) { - access.setProperty(Config.AAF_URL_CM, locateRoot+".cm:"+apiVersion); - } String cadiLatitude = access.getProperty(Config.CADI_LATITUDE); if (cadiLatitude==null) { System.out.println("# If you do not know your Global Coordinates, we suggest bing.com/maps"); @@ -381,6 +366,55 @@ public class AAFSSO { } ok = err==null; } + String locateUrl = Config.getAAFLocateUrl(access); + if (locateUrl==null) { + locateUrl=AAFSSO.cons.readLine("AAF Locator URL=https://"); + if (locateUrl==null || locateUrl.length()==0) { + err = new StringBuilder(Config.AAF_LOCATE_URL); + err.append(" is required."); + ok = false; + return; + } else { + locateUrl="https://"+locateUrl; + } + access.setProperty(Config.AAF_LOCATE_URL, locateUrl); + addProp(Config.AAF_LOCATE_URL, locateUrl); + try { + if(access.getProperty(Config.AAF_URL)==null) { + access.setProperty(Config.AAF_URL, "https://AAF_LOCATE/AAF_NS.service:2.1"); + } + AAFCon<?> aafCon = AAFCon.newInstance(access); + Future<Configuration> acf; + RosettaDF<Configuration> configDF = new RosettaEnv().newDataFactory(Configuration.class); + acf = aafCon.client(new SingleEndpointLocator(locateUrl)) + .read("/configure/"+user+"/aaf", configDF); + if (acf.get(aafCon.connTimeout)) { + for(Props p : acf.value.getProps()) { + addProp(p.getTag(),p.getValue()); + if(access.getProperty(p.getTag())==null) { + access.setProperty(p.getTag(), p.getValue()); + } + } + } else { + access.log(Level.INFO,acf.body()); + } + } catch (LocatorException | APIException | URISyntaxException e) { + access.log(e); + } + } + + final String apiVersion = access.getProperty(Config.AAF_API_VERSION, Config.AAF_DEFAULT_API_VERSION); + final String aaf_root_ns = access.getProperty(Config.AAF_ROOT_NS); + String locateRoot; + if(aaf_root_ns==null) { + locateRoot=Defaults.AAF_ROOT; + } else { + locateRoot = Defaults.AAF_LOCATE_CONST + "/%CNS." + aaf_root_ns; + } + if(access.getProperty(Config.AAF_URL)==null) { + access.setProperty(Config.AAF_URL, locateRoot+".service:"+apiVersion); + } + writeFiles(); } diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/aaf/v2_0/JU_AAFAuthn.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/aaf/v2_0/JU_AAFAuthn.java index 41b519b1..962397cc 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/aaf/v2_0/JU_AAFAuthn.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/aaf/v2_0/JU_AAFAuthn.java @@ -87,7 +87,7 @@ public class JU_AAFAuthn { Future<String> futureObj = Mockito.mock(Future.class); Mockito.doReturn(futureObj).when(rcliObj).read( "/authn/basicAuth","text/plain"); realm = authnObj.validate("test", "test","test"); - assertTrue(realm.contains("User/Pass combo invalid")); + assertTrue(realm.contains("user/pass combo invalid")); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/cadi/aaf/src/test/resources/cadi.properties b/cadi/aaf/src/test/resources/cadi.properties index ee0b719f..d0862909 100644 --- a/cadi/aaf/src/test/resources/cadi.properties +++ b/cadi/aaf/src/test/resources/cadi.properties @@ -23,7 +23,7 @@ AFT_LATITUDE=32.780140 AFT_LONGITUDE=-96.800451 AFT_ENVIRONMENT=AFTUAT -DEPLOYED_VERSION=2.0.MITHRIL +aaf_deployed_version=2.0.MITHRIL cadi_prop_files=/opt/app/aaf/common/com.att.aaf.props #cadi_keystore=/Volumes/Data/src/authz/common/cadiaaf.jks diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java b/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java index d6b8d56d..fac6a3f1 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/PropAccess.java @@ -42,7 +42,11 @@ import org.onap.aaf.cadi.util.Split; public class PropAccess implements Access { // Sonar says cannot be static... it's ok. not too many PropAccesses created. - private final SimpleDateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + private final SimpleDateFormat iso8601 = newISO8601(); + + public static SimpleDateFormat newISO8601() { + return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + } public static final Level DEFAULT = Level.AUDIT; @@ -101,7 +105,7 @@ public class PropAccess implements Access { init(nprops); } - protected void init(Properties p) { + protected synchronized void init(Properties p) { // Make sure these two are set before any changes in Logging name = "cadi"; level=DEFAULT.maskOf(); @@ -258,10 +262,13 @@ public class PropAccess implements Access { } } - protected StringBuilder buildMsg(Level level, Object[] elements) { + public StringBuilder buildMsg(Level level, Object[] elements) { return buildMsg(name,iso8601,level,elements); } - + + /* + * Need to pass in DateFormat per thread, because not marked as thread safe + */ public static StringBuilder buildMsg(final String name, final DateFormat sdf, Level level, Object[] elements) { final StringBuilder sb; int end = elements.length; diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java b/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java index 66fbe847..2655b4ce 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java @@ -157,6 +157,7 @@ public class Config { public static final String AAF_LOCATE_URL = "aaf_locate_url"; //URL for AAF locator public static final String AAF_LOCATE_URL_TAG = "AAF_LOCATE_URL"; // Name of Above for use in Config Variables. public static final String AAF_DEFAULT_API_VERSION = "2.1"; + public static final String AAF_DEPLOYED_VERSION="aaf_deployed_version"; public static final String AAF_API_VERSION = "aaf_api_version"; public static final String AAF_URL = "aaf_url"; //URL for AAF... Use to trigger AAF configuration public static final String AAF_LOCATOR_CLASS = "aaf_locator_class"; @@ -219,8 +220,8 @@ public class Config { public static final String AAF_CERT_IDS = "aaf_cert_ids"; public static final String AAF_DEBUG_IDS = "aaf_debug_ids"; // comma delimited public static final String AAF_DATA_DIR = "aaf_data_dir"; // AAF processes and Components only. - public static final String AAF_RELEASE = "aaf_release"; + public static final String AAF_URL_OAUTH = "aaf_url_oauth"; public static final String AAF_URL_GUI="aaf_url_gui"; public static final String AAF_URL_FS="aaf_url_fs"; public static final String AAF_URL_CM = "aaf_url_cm"; @@ -564,7 +565,7 @@ public class Config { } access.log(Level.INIT, sb); - Locator<URI> locator = loadLocator(si, logProp(rph, Config.getAAFLocateUrl(access), null)); + Locator<URI> locator = loadLocator(si, aafURL); taf = new HttpEpiTaf(access,locator, tc, htarray); // ok to pass locator == null String level = logProp(access, CADI_LOGLEVEL, null); @@ -849,6 +850,36 @@ public class Config { if (_url==null) { access.log(Level.INIT,"No URL passed to 'loadLocator'. Disabled"); } else { + try { + Class<?> aalCls = Class.forName("org.onap.aaf.cadi.aaf.v2_0.AbsAAFLocator"); + Method aalMth = aalCls.getMethod("create", String.class,String.class); + int colon = _url.lastIndexOf(':'); + if(colon>=0) { + int slash = _url.indexOf('/',colon); + String version; + if(slash<0) { + version = _url.substring(colon+1); + } else { + version = _url.substring(colon+1,slash); + } + slash = _url.lastIndexOf('/',colon); + if(slash>=0) { + Object aal = aalMth.invoke(null/*static*/, _url.substring(slash+1, colon),version); + return (Locator<URI>)aal; + } + } + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + String msg; + char quote; + if(e.getCause()!=null) { + msg=e.getCause().getMessage(); + quote='"'; + } else { + msg = "-"; + quote=' '; + } + access.printf(Level.DEBUG, "Configured AbsAAFLocator not found%c%s%cContinuing Locator creation ",quote,msg,quote); + } // String url = _url.replace("/AAF_NS.", "/%C%CID%AAF_NS."); // String root_ns = access.getProperty(Config.AAF_ROOT_NS, null); String url; @@ -877,7 +908,7 @@ public class Config { Method meth = lcls.getMethod("create",Access.class,String.class); locator = (Locator<URI>)meth.invoke(null,access,url); } catch (Exception e) { - access.log(Level.TRACE, "(Not fatal) Cannot load by create(String)", e); + access.log(Level.NONE, "(Not fatal) Cannot load by create(String)", e); } if (locator==null) { URI locatorURI = new URI(url); diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/config/RegistrationPropHolder.java b/cadi/core/src/main/java/org/onap/aaf/cadi/config/RegistrationPropHolder.java index 50f17e88..2a8760f4 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/config/RegistrationPropHolder.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/config/RegistrationPropHolder.java @@ -263,9 +263,10 @@ public class RegistrationPropHolder { if(value.indexOf("%NS")>=0) { str = getNS(dot_le); if(str==null || str.isEmpty()) { - value = value.replace("%NS"+'.', str); + value = value.replace("%NS"+'.', ""); + } else { + value = value.replace("%NS", str); } - value = value.replace("%NS", str); } // aaf_root_ns diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfo.java b/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfo.java index 285c45ec..5d1d23fa 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfo.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfo.java @@ -91,12 +91,6 @@ public class SecurityInfo { this.access = access; // reuse DME2 Properties for convenience if specific Properties don't exist - msgHelp = String.format(INITIALIZING_ERR_FMT,"Keystore", access.getProperty(Config.CADI_KEYSTORE, "")); - initializeKeyManager(); - - msgHelp = String.format(INITIALIZING_ERR_FMT,"Truststore", access.getProperty(Config.CADI_TRUSTSTORE, "")); - initializeTrustManager(); - String str = access.getProperty(Config.CADI_ALIAS, null); if(str==null || str.isEmpty()) { defaultAlias = null; @@ -113,7 +107,14 @@ public class SecurityInfo { } else { defaultClientAlias = str; } + + msgHelp = String.format(INITIALIZING_ERR_FMT,"Keystore", access.getProperty(Config.CADI_KEYSTORE, "")); + initializeKeyManager(); + msgHelp = String.format(INITIALIZING_ERR_FMT,"Truststore", access.getProperty(Config.CADI_TRUSTSTORE, "")); + initializeTrustManager(); + + msgHelp = String.format(INITIALIZING_ERR_FMT,"Trustmasks", access.getProperty(Config.CADI_TRUST_MASKS, "")); initializeTrustMasks(); @@ -239,13 +240,51 @@ public class SecurityInfo { } } } + + StringBuilder sb = null; for (KeyManager keyManager : keyManagerFactory.getKeyManagers()) { if (keyManager instanceof X509KeyManager) { - keyManagers.add((X509KeyManager)keyManager); + X509KeyManager xkm = (X509KeyManager)keyManager; + keyManagers.add(xkm); + if(defaultAlias!=null) { + sb=new StringBuilder("X509 Chain\n"); + x509Info(sb,xkm.getCertificateChain(defaultAlias)); + } + if(defaultClientAlias!=null && !defaultClientAlias.equals(defaultAlias)) { + if(sb==null) { + sb = new StringBuilder(); + } else { + sb.append('\n'); + } + sb.append("X509 Client Chain\n"); + x509Info(sb,xkm.getCertificateChain(defaultAlias)); + } } } x509KeyManager = new X509KeyManager[keyManagers.size()]; keyManagers.toArray(x509KeyManager); + + if(sb!=null) { + access.log(Level.INIT, sb); + } + } + + private void x509Info(StringBuilder sb, X509Certificate[] chain) { + if(chain!=null) { + int i=0; + for(X509Certificate x : chain) { + sb.append(" "); + sb.append(i++); + sb.append(')'); + sb.append("\n Subject: "); + sb.append(x.getSubjectDN()); + sb.append("\n Issuer : "); + sb.append(x.getIssuerDN()); + sb.append("\n Expires: "); + sb.append(x.getNotAfter()); + sb.append('\n'); + } + } } protected void initializeTrustManager() throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, CadiException { diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java index bab758ec..5920a260 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java @@ -55,7 +55,13 @@ import org.onap.aaf.cadi.util.UserChainManip; * */ public class CadiHTTPManip { - private static final String ACCESS_CADI_CONTROL = ".access|cadi|control"; + private static final String ACCESS_DENIED = "Access Denied"; + private static final String NO_TAF_WILL_AUTHORIZE = "No TAF will authorize"; + private static final String AUTHENTICATION_FAILURE = "Authentication Failure"; + private static final String AUTHENTICATING_VIA_REDIRECTION = "Authenticating via redirection"; + private static final String MSG_FMT = "user=%s,ip=%s:%d,msg=\"%s: %s\""; + private static final String AUTHENTICATED = "Authenticated"; + private static final String ACCESS_CADI_CONTROL = ".access|cadi|control"; private static final String METH = "OPTIONS"; private static final String CADI = "/cadi/"; private static final String CADI_CACHE_PRINT = "/cadi/cache/print"; @@ -120,40 +126,42 @@ public class CadiHTTPManip { TafResp tresp = taf.validate(Taf.LifeForm.LFN, hreq, hresp); switch(tresp.isAuthenticated()) { case IS_AUTHENTICATED: - access.printf(Level.INFO,"Authenticated: %s from %s:%d", - tresp.desc(), hreq.getRemoteAddr(), hreq.getRemotePort()); + access.printf(Level.DEBUG,MSG_FMT,tresp.getTarget(),hreq.getRemoteAddr(), + hreq.getRemotePort(),AUTHENTICATED,tresp.desc()); break; case TRY_AUTHENTICATING: switch (tresp.authenticate()) { case IS_AUTHENTICATED: - access.printf(Level.INFO,"Authenticated: %s from %s:%d", - tresp.desc(), hreq.getRemoteAddr(), hreq.getRemotePort()); + access.printf(Level.DEBUG,MSG_FMT,tresp.getTarget(),hreq.getRemoteAddr(), + hreq.getRemotePort(),AUTHENTICATED,tresp.desc()); break; case HTTP_REDIRECT_INVOKED: - access.log(Level.INFO,"Authenticating via redirection: ", tresp.desc()); + access.printf(Level.DEBUG,MSG_FMT,tresp.getTarget(),hreq.getRemoteAddr(), + hreq.getRemotePort(),AUTHENTICATING_VIA_REDIRECTION,tresp.desc()); break; case NO_FURTHER_PROCESSING: - access.printf(Level.AUDIT,"Authentication Failure: %s from %s:%d" - , tresp.desc(), hreq.getRemoteAddr(), hreq.getRemotePort()); + access.printf(Level.AUDIT,MSG_FMT,tresp.getTarget(),hreq.getRemoteAddr(), + hreq.getRemotePort(),AUTHENTICATION_FAILURE,tresp.desc()); hresp.sendError(403, tresp.desc()); // Forbidden break; default: - access.printf(Level.AUDIT,"No TAF will authorize for request from %s:%d" - , hreq.getRemoteAddr(), hreq.getRemotePort()); + access.printf(Level.AUDIT,MSG_FMT,tresp.getTarget(),hreq.getRemoteAddr(), + hreq.getRemotePort(),NO_TAF_WILL_AUTHORIZE,tresp.desc()); hresp.sendError(403, tresp.desc()); // Forbidden } break; case NO_FURTHER_PROCESSING: - access.printf(Level.AUDIT,"Authentication Failure: %s from %s:%d", - tresp.desc(), hreq.getRemoteAddr(), hreq.getRemotePort()); - hresp.sendError(403, "Access Denied"); // FORBIDDEN + access.printf(Level.AUDIT,MSG_FMT, tresp.getTarget(),hreq.getRemoteAddr(), + hreq.getRemotePort(),NO_TAF_WILL_AUTHORIZE,tresp.desc()); + hresp.sendError(403, ACCESS_DENIED); // FORBIDDEN break; default: - access.printf(Level.AUDIT,"No TAF will authorize for request from %s:%d" - , hreq.getRemoteAddr(), hreq.getRemotePort()); - hresp.sendError(403, "Access Denied"); // FORBIDDEN + access.printf(Level.AUDIT,MSG_FMT, tresp.getTarget(),hreq.getRemoteAddr(), + hreq.getRemotePort(),NO_TAF_WILL_AUTHORIZE,tresp.desc()); + hresp.sendError(403, ACCESS_DENIED); // FORBIDDEN } + return tresp; } @@ -193,7 +201,7 @@ public class CadiHTTPManip { } return true; } - + public Lur getLur() { return lur; } diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/AbsTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/AbsTafResp.java index b3ac0945..364a0728 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/AbsTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/AbsTafResp.java @@ -37,7 +37,9 @@ public abstract class AbsTafResp implements TafResp { protected final Access access; protected final String tafName; + // Note: Valid Resp is based on Principal being non-null protected final TaggedPrincipal principal; + protected final String target; protected final String desc; private float timing; @@ -58,6 +60,28 @@ public abstract class AbsTafResp implements TafResp { this.access = access; this.tafName = tafname; this.principal = principal; + this.target = principal==null?"unknown":principal.getName(); + this.desc = description; + } + + /** + * AbsTafResp + * + * Set and hold + * Description (for logging) + * Principal (as created by derived class) + * Access (for access to underlying container, i.e. for Logging, auditing, ClassLoaders, etc) + * + * @param access + * @param tafname + * @param principal + * @param description + */ + public AbsTafResp(Access access, String tafname, String target, String description) { + this.access = access; + this.tafName = tafname; + this.principal = null; + this.target = target; this.desc = description; } @@ -102,7 +126,15 @@ public abstract class AbsTafResp implements TafResp { return principal; } - /** + /* (non-Javadoc) + * @see org.onap.aaf.cadi.taf.TafResp#getTarget() + */ + @Override + public String getTarget() { + return target; + } + + /** * getAccess() * * Get the Access object from the TAF, so that appropriate Logging, etc can be coordinated. diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/LoginPageTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/LoginPageTafResp.java index a5ce45b7..d64fbe0d 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/LoginPageTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/LoginPageTafResp.java @@ -37,7 +37,7 @@ public class LoginPageTafResp extends AbsTafResp { private final String loginPageURL; private LoginPageTafResp(Access access, final HttpServletResponse resp, String loginPageURL) { - super(access, "LoginPage", null, "Multiple Possible HTTP Logins available. Redirecting to Login Choice Page"); + super(access, "LoginPage","unknown", "Multiple Possible HTTP Logins available. Redirecting to Login Choice Page"); httpResp = resp; this.loginPageURL = loginPageURL; } diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/NullTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/NullTafResp.java index a3c8f5bb..fb66ec08 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/NullTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/NullTafResp.java @@ -60,7 +60,15 @@ class NullTafResp implements TafResp { return null; } - public Access getAccess() { + /* (non-Javadoc) + * @see org.onap.aaf.cadi.taf.TafResp#getTarget() + */ + @Override + public String getTarget() { + return "unknown"; + } + + public Access getAccess() { return Access.NULL; } diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/PuntTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/PuntTafResp.java index e6555051..3bc278e5 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/PuntTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/PuntTafResp.java @@ -63,7 +63,15 @@ public class PuntTafResp implements TafResp { return null; } - public Access getAccess() { + /* (non-Javadoc) + * @see org.onap.aaf.cadi.taf.TafResp#getTarget() + */ + @Override + public String getTarget() { + return "punt"; + } + + public Access getAccess() { return NullTafResp.singleton().getAccess(); } diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TafResp.java index f3afde72..6850a372 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TafResp.java @@ -81,6 +81,11 @@ public interface TafResp { * @return */ public TaggedPrincipal getPrincipal(); + + /** Target - when Authentication Fails, need to know what ID was being attempted + * @return + */ + public String getTarget(); /** * get the Access object which created this object, allowing the responder to appropriate Log, etc diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustNotTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustNotTafResp.java index 6b8adeb8..f397cbab 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustNotTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustNotTafResp.java @@ -62,7 +62,15 @@ public class TrustNotTafResp implements TafResp { return delegate.getPrincipal(); } - @Override + /* (non-Javadoc) + * @see org.onap.aaf.cadi.taf.TafResp#getTarget() + */ + @Override + public String getTarget() { + return delegate.getTarget(); + } + + @Override public Access getAccess() { return delegate.getAccess(); } diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustTafResp.java index 91f9f8c4..061d4e2f 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/TrustTafResp.java @@ -64,7 +64,15 @@ public class TrustTafResp implements TafResp { return principal; } - @Override + /* (non-Javadoc) + * @see org.onap.aaf.cadi.taf.TafResp#getTarget() + */ + @Override + public String getTarget() { + return delegate.getTarget(); + } + + @Override public Access getAccess() { return delegate.getAccess(); } diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTaf.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTaf.java index d5c88464..dcd27d63 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTaf.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTaf.java @@ -120,13 +120,15 @@ public class BasicHttpTaf implements HttpTaf { return new BasicHttpTafResp(access,bp,bp.getName()+" authenticated by password",RESP.IS_AUTHENTICATED,resp,realm,false); } else { //TODO may need timed retries in a given time period - return new BasicHttpTafResp(access,null,buildMsg(bp,req,"user/pass combo invalid for ",bc.getUser(),"from",req.getRemoteAddr()), + return new BasicHttpTafResp(access,bc.getUser(),buildMsg(bp,req,"user/pass combo invalid for ",bc.getUser(),"from",req.getRemoteAddr()), RESP.TRY_AUTHENTICATING,resp,realm,true); } } } // Get User/Password from Authorization Header value String authz = req.getHeader("Authorization"); + String target="unknown"; + if (authz != null && authz.startsWith("Basic ")) { if (warn&&!req.isSecure()) { access.log(Level.WARN,"WARNING! BasicAuth has been used over an insecure channel"); @@ -136,6 +138,7 @@ public class BasicHttpTaf implements HttpTaf { } try { CachedBasicPrincipal ba = new CachedBasicPrincipal(this,authz,realm,timeToLive); + target=ba.getName(); if (DenialOfServiceTaf.isDeniedID(ba.getName())!=null) { return DenialOfServiceTaf.respDenyID(access,ba.getName()); } @@ -152,16 +155,16 @@ public class BasicHttpTaf implements HttpTaf { return new BasicHttpTafResp(access,ba, ba.getName()+" authenticated by BasicAuth password",RESP.IS_AUTHENTICATED,resp,realm,false); } else { //TODO may need timed retries in a given time period - return new BasicHttpTafResp(access,null,buildMsg(ba,req,"user/pass combo invalid"), + return new BasicHttpTafResp(access,target,buildMsg(ba,req,"user/pass combo invalid"), RESP.TRY_AUTHENTICATING,resp,realm,true); } } catch (IOException e) { String msg = buildMsg(null,req,"Failed HTTP Basic Authorization (", e.getMessage(), ')'); access.log(Level.INFO,msg); - return new BasicHttpTafResp(access,null,msg, RESP.TRY_AUTHENTICATING, resp, realm,true); + return new BasicHttpTafResp(access,target,msg, RESP.TRY_AUTHENTICATING, resp, realm,true); } } - return new BasicHttpTafResp(access,null,"Requesting HTTP Basic Authorization",RESP.TRY_AUTHENTICATING,resp,realm,false); + return new BasicHttpTafResp(access,target,"Requesting HTTP Basic Authorization",RESP.TRY_AUTHENTICATING,resp,realm,false); } protected String buildMsg(Principal pr, HttpServletRequest req, Object ... msg) { diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTafResp.java index d1acf5fe..e2174493 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/basic/BasicHttpTafResp.java @@ -45,6 +45,14 @@ public class BasicHttpTafResp extends AbsTafResp implements TafResp { this.wasFailed = wasFailed; } + public BasicHttpTafResp(Access access, String target, String description, RESP status, HttpServletResponse resp, String realm, boolean wasFailed) { + super(access, tafName, target, description); + httpResp = resp; + this.realm = realm; + this.status = status; + this.wasFailed = wasFailed; + } + public RESP authenticate() throws IOException { httpResp.setStatus(401); // Unauthorized httpResp.setHeader("WWW-Authenticate", "Basic realm=\""+realm+'"'); diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/cert/X509Taf.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/cert/X509Taf.java index fca99a31..5f5ff574 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/cert/X509Taf.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/cert/X509Taf.java @@ -266,6 +266,7 @@ public class X509Taf implements HttpTaf { // if Principal is found, check for "AS_USER" and whether this entity is trusted to declare if (prin!=null) { + // Note: Tag for Certs is Fingerprint, but that takes computation... leaving off return new X509HttpTafResp( access, prin, diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/dos/DenialOfServiceTafResp.java b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/dos/DenialOfServiceTafResp.java index 2fcd1553..2215a6f9 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/taf/dos/DenialOfServiceTafResp.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/taf/dos/DenialOfServiceTafResp.java @@ -32,7 +32,7 @@ public class DenialOfServiceTafResp extends AbsTafResp { private RESP ect; // Homage to Arethra Franklin public DenialOfServiceTafResp(Access access, RESP resp, String description ) { - super(access, tafName, null, description); + super(access, tafName, "dos", description); ect = resp; } diff --git a/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_AbsTafResp.java b/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_AbsTafResp.java index bf5a15fb..4dba8edb 100644 --- a/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_AbsTafResp.java +++ b/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_AbsTafResp.java @@ -73,7 +73,7 @@ public class JU_AbsTafResp { assertThat(tafResp.getAccess(), is(access)); assertThat(tafResp.isFailedAttempt(), is(false)); - tafResp = new AbsTafResp(null, JUNIT, null, null) { + tafResp = new AbsTafResp(null, JUNIT, "unknown", null) { @Override public RESP authenticate() throws IOException { return null; } @@ -82,6 +82,7 @@ public class JU_AbsTafResp { assertThat(tafResp.isValid(), is(false)); assertThat(tafResp.isAuthenticated(), is(RESP.TRY_ANOTHER_TAF)); assertThat(tafResp.getPrincipal(), is(nullValue())); + assertThat(tafResp.getTarget(), is("unknown")); assertThat(tafResp.getAccess(), is(nullValue())); assertThat(tafResp.taf(), is(JUNIT)); assertThat(tafResp.isFailedAttempt(), is(false)); diff --git a/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_EpiTaf.java b/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_EpiTaf.java index 08602cb0..8e103893 100644 --- a/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_EpiTaf.java +++ b/cadi/core/src/test/java/org/onap/aaf/cadi/taf/test/JU_EpiTaf.java @@ -76,6 +76,7 @@ public class JU_EpiTaf { @Override public RESP isAuthenticated() { return RESP.TRY_ANOTHER_TAF; } @Override public RESP authenticate() throws IOException { return null; } @Override public TaggedPrincipal getPrincipal() { return null; } + @Override public String getTarget() {return "unknown";} @Override public Access getAccess() { return null; } @Override public boolean isFailedAttempt() { return false; } @Override public float timing() { return 0; } @@ -93,6 +94,7 @@ public class JU_EpiTaf { @Override public RESP isAuthenticated() { return RESP.TRY_AUTHENTICATING; } @Override public RESP authenticate() throws IOException { return null; } @Override public TaggedPrincipal getPrincipal() { return null; } + @Override public String getTarget() {return "unknown";} @Override public Access getAccess() { return null; } @Override public boolean isFailedAttempt() { return false; } @Override public float timing() { return 0; } diff --git a/docs/sections/installation/AAF_6_running.rst b/docs/sections/installation/AAF_6_running.rst new file mode 100644 index 00000000..a57da6d7 --- /dev/null +++ b/docs/sections/installation/AAF_6_running.rst @@ -0,0 +1,54 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 +.. Copyright © 2017 AT&T Intellectual Property. All rights reserved. + +Running AAF +========================= + +The default methodology for running AAF for ONAP is to run as on of the ONAP OOM charts. This allows AAF to be starting in the right order, be available, etc for ONAP Components. + +AAF is very effective as Standalone Java processes, Docker or non OOM Helm Charts, because AAF is an infrastructure component used by ONAP. It is not an integral ONAP Component, +which means that it can be run independently in a number way. From someone's home computer to the extreme Scale and Resilency requirements of Class A Enterprises. + +OOM +--- + +Please see OOM Documentation to run AAF with other ONAP Components + +Helm +---- + +Use git to pull down "authz" code set. Build if desired. + + - Ensure Docker and K8s is install (Minikube is very useful for local machines, see internet) + - Ensure Helm is installed an configured (see internet) + - cd authz/auth/helm + - helm --namespace onap -n dublin install aaf + - Control with kubectl (see K8S/Minikub docs) + + - A sample App that generates all its certificates and configurations automatically is available as "aaf-hello + - helm --namespace onap -n hello install aaf-hello + +Docker +------ + +Use git to pull down "authz" code set. See Build info for Docker. + + - cd authz/auth/docker + - if you need Docker Container, cd ../cass/docker + - bash dinstall.sh + - (note: if you add the word "publish", cqlsh is available for your local apps at port 9042) + + - bash dcqlsh.sh (puts you into CQLSH inside Docker) + - docker container exec -it aaf-cass bash -c "cqlsh -k authz --request-timeout=60" + - bash dbash.sh (short cut to get you a Shell in the "cass" container) + + - all the d...sh scripts utilize short-cut names. + - "cass" is actually aaf-cass in Docker, "service" is actually aaf-service in Docker + + - dbuild.sh (builds new Docker Containers, see Build) + - dclean.sh (cleans out Docker Containers, getting ready for a new build) + - drun.sh <blank|shortcut name> (Creates and Starts Container for all or one AAF components) + - dstop.sh <blank|shortcut name> (Stops Container for all or one AAF Components) + - dstart.sh <blank|shortcut name> (Use when container exists for all or one AAF Components) + diff --git a/docs/sections/release-notes.rst b/docs/sections/release-notes.rst index 4e6fcbd0..a6b4806c 100644 --- a/docs/sections/release-notes.rst +++ b/docs/sections/release-notes.rst @@ -2,11 +2,10 @@ .. http://creativecommons.org/licenses/by/4.0 .. Copyright © 2017 AT&T Intellectual Property. All rights reserved. - Release Notes ============= -Version: 2.1.13 (Dublin, 3.1.0-ONAP) +Version: 2.1.13 (Dublin, 4.0.0-ONAP) --------------------------------------- :Release Date: 2019-06-06 @@ -38,6 +37,15 @@ Note: In general, Infrastructure must be accomplished in the release PRIOR to ge - `AAF-785 <https://jira.onap.org/browse/AAF-785>`_ non STAGING version on master - `AAF-822 <https://jira.onap.org/browse/AAF-822>`_ Startup issues with K8S, Certs +**Usage Notes** + - AAF Core and SMS elements have consistently started from scratch. The one case where this didn't happen for SMS, + it was found that incompatible data was left in volume. Removal of old data for SMS (See SMS notes) should resolve + - On the same instance, one AAF Core component had a similar scenario. A simple bounce of aaf-locator resolved. + - Existing Cassandra + - For each release, AAF maintains the authz/auth/auth-cass/cass_init/init.cql which is used to setup Keyspaces from scratch + - Any changes are also done in small CQL files, you MIGHT need authz/auth/auth-cass/cass_init/init2_10.cql for Dublin + + Version: 2.1.8 (Casablanca, 3.0.0-ONAP, Casablanca Maintenance Release) -------------------------------------------------------------------------- @@ -130,3 +138,5 @@ Version: 2.1.1 (Beijing, 2.0.0-ONAP) - `CII Best Practices Passing Badge information for AAF <https://bestpractices.coreinfrastructure.org/en/projects/2303?criteria_level=0>`_ - `Project Vulnerability Review Table for AAF <https://wiki.onap.org/pages/viewpage.action?pageId=43385140>`_ + + diff --git a/misc/log4j/src/main/java/org/onap/aaf/misc/env/log4j/LogFileNamer.java b/misc/log4j/src/main/java/org/onap/aaf/misc/env/log4j/LogFileNamer.java index 9a615fb8..85aae6f0 100644 --- a/misc/log4j/src/main/java/org/onap/aaf/misc/env/log4j/LogFileNamer.java +++ b/misc/log4j/src/main/java/org/onap/aaf/misc/env/log4j/LogFileNamer.java @@ -57,14 +57,20 @@ public class LogFileNamer { */
public String setAppender(String appender) throws IOException {
File f = new File(String.format(FIRST_FILE_FORMAT_STR, dir, root, appender));
+ File lock = new File(f.getAbsoluteFile()+".lock");
if(f.exists()) {
- int i = 0;
- while ((f = new File(String.format(FILE_FORMAT_STR, dir, root, appender, i))).exists()) {
- ++i;
- }
+ if(lock.exists()) {
+ int i = 0;
+ while ((f = new File(String.format(FILE_FORMAT_STR, dir, root, appender, i))).exists() &&
+ (lock = new File(f.getAbsoluteFile()+".lock")).exists()) {
+ ++i;
+ }
+ }
}
try {
+ lock.createNewFile();
+ lock.deleteOnExit();
f.createNewFile();
} catch (IOException e) {
throw new IOException("Cannot create file '" + f.getCanonicalPath() + '\'', e);
|