From: Jonathan Gathman Date: Wed, 3 Jul 2019 14:10:52 +0000 (+0000) Subject: Merge "Moved null ref check to line before dereferencing" X-Git-Tag: 2.1.15~22 X-Git-Url: https://gerrit.onap.org/r/gitweb?p=aaf%2Fauthz.git;a=commitdiff_plain;h=9f1388eb5ac3f9aab5fe617eae55b08fd2a57059;hp=8a400f444aa99722505a6219142ffb5588983cc1 Merge "Moved null ref check to line before dereferencing" --- 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 { 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 { 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 { 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 { } 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 { 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 { } 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 { * @return */ public static Result 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 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 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> getPermsByName(AuthzTrans trans, - String type, String instance, String action) { - Result 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> 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 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> getPermsByRole(AuthzTrans trans, String role, boolean lookup) { @@ -374,8 +386,14 @@ public class Question { return Result.ok(perms); } - public Result> getRolesByName(AuthzTrans trans, - String role) { + public Result> 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 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 mayUser(AuthzTrans trans, String user, RoleDAO.Data rdd, Access access) { + if(trans.user().equals(rdd.ns)) { + return Result.ok((NsDAO.Data)null); + } Result 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 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 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 { } 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 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 { 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 { try { Log4JLogIt logIt = new Log4JLogIt(args, "cm"); PropAccess propAccess = new PropAccess(logIt,args); - try { - AAF_CM service = new AAF_CM(new AuthzEnv(propAccess)); - JettyServiceStarter jss = new JettyServiceStarter(service); - jss.start(); + new JettyServiceStarter( + 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 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 si, SecuritySetter 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 cmds; public Help(AAFcli aafcli, List 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/",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/",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 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 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 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 { 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() { - @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 { } 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 { } @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 { } @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 { 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 { 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 { 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 { } @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 extends HttpCode 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 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 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 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 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 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 service; protected String hostname; + protected final boolean secure; - public AbsServiceStarter(final AbsService service) { + public AbsServiceStarter(final AbsService service, boolean secure) { + this.secure = secure; this.service = service; try { OrganizationFactory.init(service.env); @@ -56,7 +58,6 @@ public abstract class AbsServiceStarter 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 to end:\n"); + try { + System.in.read(); + System.exit(0); + } catch (IOException e) { + } } } } @@ -124,6 +128,7 @@ public abstract class AbsServiceStarter extends AbsServiceStarter { - private boolean secure; - public JettyServiceStarter(final AbsService service) throws OrganizationException { - super(service); - secure = true; + public JettyServiceStarter(final AbsService service, boolean secure) throws OrganizationException { + super(service, secure); } - /** - * Specifically set this Service starter to Insecure (HTTP) Mode. - * @return - */ - public JettyServiceStarter 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 { try { Log4JLogIt logIt = new Log4JLogIt(args, "fs"); PropAccess propAccess = new PropAccess(logIt,args); - - AAF_FS service = new AAF_FS(new AuthzEnv(propAccess)); - JettyServiceStarter jss = new JettyServiceStarter(service); - jss.insecure().start(); + try { + new JettyServiceStarter( + 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 { 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 { } 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 implements State implements State implements State(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 implements State jss = new JettyServiceStarter(service); - jss.start(); + try { + new JettyServiceStarter( + 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> 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 { - 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 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 theme, String defaultTheme, int backdots, BROWSER browser) { - List ls = getThemeFiles(env,theme.get()); + protected Imports getImports(Env env, String theme, int backdots, BROWSER browser) { + List 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 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 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() { + @Override + public void code(AAF_GUI state, AuthzTrans trans,Cache 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() { @Override public void code(AAF_GUI state, AuthzTrans trans,Cache 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("History", gui.env.newTransNoAvg(),new Model(gui.env),"class=std"), + new NamedCode(true, "content") { + @Override + public void code(final Cache cache, final HTMLGen hgen) throws APIException, IOException { + final Slot user = gui.env.slot(NAME+".user"); + cache.dynamic(hgen, new DynamicCode() { + @Override + public void code(final AAF_GUI gui, final AuthzTrans trans, final Cache 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 { + 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() { + @Override + public Cells code(Rcli client) throws CadiException, ConnectException, APIException { + ArrayList 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 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 histItems = fh.value.getItem(); + + java.util.Collections.sort(histItems, new Comparator() { + @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>"); + 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 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 { Log4JLogIt logIt = new Log4JLogIt(args, "hello"); PropAccess propAccess = new PropAccess(logIt,args); - AAF_Hello service = new AAF_Hello(new AuthzEnv(propAccess)); - JettyServiceStarter jss = new JettyServiceStarter(service); - jss.start(); + try { + new JettyServiceStarter( + 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 { } 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 { Log4JLogIt logIt = new Log4JLogIt(args, "locate"); PropAccess propAccess = new PropAccess(logIt,args); - AAF_Locate service = new AAF_Locate(new AuthzEnv(propAccess)); - JettyServiceStarter jss = new JettyServiceStarter(service); - jss.start(); + try { + new JettyServiceStarter( + 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 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 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 getConfig(AuthzTrans trans, String id, String type) { @@ -145,7 +159,6 @@ public class LocateServiceImpl } } 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 { Log4JLogIt logIt = new Log4JLogIt(args, "oauth"); PropAccess propAccess = new PropAccess(logIt,args); - AAF_OAuth service = new AAF_OAuth(new AuthzEnv(propAccess)); - JettyServiceStarter jss = new JettyServiceStarter(service); - jss.start(); + try { + new JettyServiceStarter( + 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 { Log4JLogIt logIt = new Log4JLogIt(args, "authz"); PropAccess propAccess = new PropAccess(logIt,args); - AbsService service = new AAF_Service(new AuthzEnv(propAccess)); - JettyServiceStarter jss = new JettyServiceStarter(service); - jss.start(); + try { + new JettyServiceStarter( + 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 implements AuthzService { - private Mapper mapper; + private static final String TWO_SPACE = " "; + private Mapper mapper; @Override public Mapper mapper() {return mapper;} @@ -799,62 +806,129 @@ public class AuthzCassServiceImpl createPerm(final AuthzTrans trans,REQUEST rreq) { final Result 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 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 nsd; - @Override - public Result mayChange() { - if (nsd==null) { - nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write); - } - return nsd; - } - }); - Result> 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> 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 rpdd = permDAO.create(trans, pdd); + if(rpdd.notOK()) { + return Result.err(rpdd); + } + + CachedRoleDAO roleDAO = ques.roleDAO(); + Result> 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 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> 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 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 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 nsd; + @Override + public Result mayChange() { + if (nsd==null) { + nsd = ques.mayUser(trans, trans.user(), newPd.value, Access.write); + } + return nsd; + } + }); + + Result> nsr = ques.nsDAO().read(trans, newPd.value.ns); + if (nsr.notOKorIsEmpty()) { + return Result.err(nsr); + } + switch(fd.status) { + case OK: + Result 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 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 fd = mapper.future(trans,PermDAO.TABLE,from,perm,false, new Mapper.Memo() { @Override @@ -1917,6 +1991,9 @@ public class AuthzCassServiceImpl 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 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 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 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 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 nsd; + private static final String EXTEND = "extend"; + private static final String RESET = "reset"; + private static final String DELETE = "delete"; + private Result 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 changeUserCred(final AuthzTrans trans, REQUEST from) { + public Result 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 rmc = mc.mayChange(); if (rmc.notOK()) { return Result.err(rmc); } - Result ri = selectEntryIfMultiple((CredRequest)from, rlcd.value); + List lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256); + + Result ri = selectEntryIfMultiple((CredRequest)from, lcdd, MayChangeCred.RESET); if (ri.notOK()) { return Result.err(ri); } @@ -2668,27 +2766,6 @@ public class AuthzCassServiceImpl selectEntryIfMultiple(final CredRequest cr, List 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 lcdd = filterList(rlcd.value,CredDAO.BASIC_AUTH, CredDAO.BASIC_AUTH_SHA256); //Need to do the "Pick Entry" mechanism - Result ri = selectEntryIfMultiple((CredRequest)from, rlcd.value); + // Note, this sorts + Result 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 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 deleteUserCred(AuthzTrans trans, REQUEST from) { + final Result 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> rlcd = ques.credDAO().readID(trans, cred.value.id); + if (rlcd.notOKorIsEmpty()) { + // Empty Creds should have no user_roles. + Result> 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 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 fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false, + () -> "Delete Credential [" + + cred.value.id + + ']', + mc); + + Result> nsr = ques.nsDAO().read(trans, cred.value.ns); + if (nsr.notOKorIsEmpty()) { + return Result.err(nsr); + } + + switch(fd.status) { + case OK: + Result 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: + Resultudr = 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> 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 selectEntryIfMultiple(final CredRequest cr, List 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 filterList(List orig, Integer ... types) { + List 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 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 value, boolean isDelete) { + private String selectCredFromList(List 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 deleteUserCred(AuthzTrans trans, REQUEST from) { - final Result 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> rlcd = ques.credDAO().readID(trans, cred.value.id); - if (rlcd.notOKorIsEmpty()) { - // Empty Creds should have no user_roles. - Result> 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 fd = mapper.future(trans,CredDAO.TABLE,from,cred.value,false, - () -> "Delete Credential [" + - cred.value.id + - ']', - mc); - - Result> nsr = ques.nsDAO().read(trans, cred.value.ns); - if (nsr.notOKorIsEmpty()) { - return Result.err(nsr); - } - - switch(fd.status) { - case OK: - Result 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: - Resultudr = 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> 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 doesCredentialMatch(AuthzTrans trans, REQUEST credReq) { TimeTaken tt = trans.start("Does Credential Match", Env.SUB); @@ -2949,22 +3071,6 @@ public class AuthzCassServiceImpl 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 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 nsr = ques.deriveNs(trans, userRole.role); + if (nsr.notOK()) { + return Result.err(nsr); + } + ndd = nsr.value; } switch(fd.status) { case OK: Result 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 rnd = ques.deriveNs(trans,type); - if (rnd.notOK()) { - return Result.err(rnd); + Result> resp; + if(type.startsWith(trans.user())) { + resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); + } else { + Result 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> resp = ques.historyDAO().readBySubject(trans, type, "perm", yyyymm); if (resp.notOK()) { return Result.err(resp); } @@ -3612,8 +3751,7 @@ public class AuthzCassServiceImpl 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 getHistoryBySubject(AuthzTrans trans, String subject, String target, int[] yyyymm, final int sort) { + NsDAO.Data ndd = new NsDAO.Data(); + ndd.name = FQI.reverseDomain(subject); + Result rnd = ques.mayUser(trans, trans.user(), ndd, Access.read); + if (rnd.notOK()) { + return Result.err(rnd); + } + + Result> 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 changeUserCred(AuthzTrans trans, REQUEST from); + Result resetUserCred(AuthzTrans trans, REQUEST from); /** * @@ -636,6 +636,16 @@ public interface AuthzService getHistoryByNS(AuthzTrans trans, String subj, int[] yyyymm, int sort); + /** + * + * @param trans + * @param target + * @param yyyymm + * @param sort + * @return + */ + public Result getHistoryBySubject(AuthzTrans trans, String subject, String target, int[] yyyymm, int sort); + /*********************************** * DELEGATE ***********************************/ @@ -753,7 +763,4 @@ public interface AuthzService 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 getHistoryByUser(AuthzTrans trans, HttpServletResponse resp, String user, int[] yyyymm, final int sort); - public abstract Result getHistoryByRole(AuthzTrans trans, HttpServletResponse resp, String subject, int[] yyyymm, final int sort); + public abstract Result getHistoryByRole(AuthzTrans trans, HttpServletResponse resp, String role, int[] yyyymm, final int sort); - public abstract Result getHistoryByPerm(AuthzTrans trans, HttpServletResponse resp, String subject, int[] yyyymm, final int sort); + public abstract Result getHistoryByPerm(AuthzTrans trans, HttpServletResponse resp, String perm, int[] yyyymm, final int sort); - public abstract Result getHistoryByNS(AuthzTrans trans, HttpServletResponse resp, String subject, int[] yyyymm, final int sort); + public abstract Result getHistoryByNS(AuthzTrans trans, HttpServletResponse resp, String ns, int[] yyyymm, final int sort); - /* + public abstract Result getHistoryBySubject(AuthzTrans trans, HttpServletResponse resp, String type, String subject, int[] yyyymm, int sort); + + /* * Cache */ public abstract Result 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 dlist = new ArrayList(); + 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 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 rh = service.getHistoryBySubject(trans,subject,target,yyyymm,sort); + switch(rh.status) { + case OK: + RosettaData 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 perm(AuthzTrans trans, Request req) { PermRequest from = (PermRequest)req; - Result 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 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> 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 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 extends AbsUserCache { return "AAF Inaccessible"; case UNVALIDATED: addUser(new User(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 extends AbsUserCache 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 extends AbsUserCache 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 extends AbsUserCache 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 extends AbsUserCache 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 extends AbsUserCache 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 implements Locator } public static Locator 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 implements Locator @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 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 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 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 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 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 aafProps(Trans trans, AAFCon aafcon, String locator, String fqi) throws CadiException, APIException, URISyntaxException { + Future acf = aafcon.client(new SingleEndpointLocator(locator)) + .read("/configure/"+fqi+"/aaf", configDF); + if (acf.get(TIMEOUT)) { + return acf.value.getProps(); + } else if (acf.code()==401){ + trans.error().log("Bad Password sent to AAF"); + } else if (acf.code()==404){ + trans.error().log("This version of AAF does not support remote Properties"); + } else { + trans.error().log(errMsg.toMsg(acf)); + } + return new ArrayList<>(); + } private static void validate(final PropAccess pa) throws LocatorException, CadiException, APIException { 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 chainList = new ArrayList<>(); Set 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 b0c32942..14cf0f62 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 { private static TokenClientFactory instance; + private final Set alts; private Map aafcons = new ConcurrentHashMap<>(); private SecurityInfoC hsi; // Package on purpose @@ -62,14 +65,26 @@ public class TokenClientFactory extends Persist { private TokenClientFactory(Access pa) throws APIException, GeneralSecurityException, IOException, CadiException { super(pa, new RosettaEnv(pa.getProperties()),Token.class,"outgoing"); + Map 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 { } } 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 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 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 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;ji) { + s=deploy[i]; + for(int j=0;j 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 + "= "); } - 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 acf; + RosettaDF 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 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 locator = loadLocator(si, logProp(rph, Config.getAAFLocateUrl(access), null)); + Locator 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)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)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 (Creates and Starts Container for all or one AAF components) + - dstop.sh (Stops Container for all or one AAF Components) + - dstart.sh (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 `_ non STAGING version on master - `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 `_ - `Project Vulnerability Review Table for AAF `_ + + 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);