package org.onap.aaf.auth.batch.helpers;
+import org.onap.aaf.cadi.Access;
import org.onap.aaf.misc.env.LogTarget;
import com.datastax.driver.core.ResultSet;
private StringBuilder sb;
private int hasAdded;
private LogTarget log;
+ private long sleep;
+ private long last;
public CQLBatch(LogTarget log, Session session) {
this.log = log;
this.session = session;
sb = new StringBuilder();
hasAdded = 0;
+ sleep = 0L;
}
public StringBuilder begin() {
sb.setLength(0);
public ResultSet execute() {
if(end()) {
+ if(sleep>0) {
+ long left = last - System.currentTimeMillis();
+ if(left>0) {
+ try {
+ Thread.sleep(left);
+ } catch (InterruptedException e) {
+ Access.NULL.log(e); // Keep code check idiocy at bay
+ }
+ }
+ last = System.currentTimeMillis()+sleep;
+ }
return session.execute(sb.toString());
} else {
return null;
public ResultSet execute(boolean dryRun) {
ResultSet rv = null;
if(dryRun) {
+ if(sleep>0) {
+ long left = last - System.currentTimeMillis();
+ if(left>0) {
+ try {
+ Thread.sleep(left);
+ } catch (InterruptedException e) {
+ Access.NULL.log(e); // Keep code check idiocy at bay
+ }
+ }
+ last = System.currentTimeMillis()+sleep;
+ }
end();
} else {
rv = execute();
execute(dryRun);
}
+ public void sleep(int j) {
+ sleep = j*1000;
+ }
+
public String toString() {
return sb.toString();
}
private int batches;
private final StringBuilder current;
private boolean showProgress;
-
+
public CQLBatchLoop(CQLBatch cb, int max, boolean dryRun) {
cqlBatch = cb;
i=0;
package org.onap.aaf.auth.batch.helpers;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
}
public static void loadOneNS(Trans trans, Session session, String ns,int ... types ) {
- load(trans, session,"select id, type, expires, other, writetime(cred), tag from authz.cred WHERE ns='" + ns + "';");
+ load(trans, session,"select id, type, expires, other, writetime(cred), tag from authz.cred WHERE ns='" + ns + "';", types);
}
private static void load(Trans trans, Session session, String query, int ...types) {
inst.expires.getTime(),inst.tag,reason);
}
-
+ static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+SSSS");
public static void batchDelete(StringBuilder sb, List<String> row) {
+ Long l = Long.parseLong(row.get(5));
+ String date = sdf.format(new Date(l));
sb.append("DELETE from authz.cred WHERE id='");
sb.append(row.get(1));
sb.append("' AND type=");
sb.append(Integer.parseInt(row.get(3)));
// Note: We have to work with long, because Expires is part of Key... can't easily do date.
- sb.append(" AND expires=dateof(maxtimeuuid(");
- sb.append(row.get(5));
- sb.append("));\n");
+ sb.append(" AND expires='");
+ sb.append(date);
+ sb.append("';\n");
+// sb.append(" AND expires=dateof(maxtimeuuid(");
+// sb.append(row.get(5));
+// sb.append("));\n");
+
}
public String toString() {
public static void load(Trans trans, Session session, Visitor<X509> visitor) {
- load(trans,session,"select ca, id, x500, x509, serial from authz.x509;", visitor);
+ load(trans,session, "" , visitor);
}
+
+ public static void load(Trans trans, Session session, String where, Visitor<X509> visitor) {
+ load(trans,session, visitor,"select ca, id, x500, x509, serial from authz.x509 " + where +';');
+ }
+
- private static void load(Trans trans, Session session, String query, Visitor<X509> visitor) {
+ private static void load(Trans trans, Session session, Visitor<X509> visitor, String query) {
trans.info().log( "query: " + query );
TimeTaken tt = trans.start("Read X509", Env.REMOTE);
return Result.ok();
}
- protected interface Getter<D> {
+ public interface Getter<D> {
public abstract Result<List<D>> get();
};
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Cluster.Builder;
+import com.datastax.driver.core.SocketOptions;
import com.datastax.driver.core.policies.DCAwareRoundRobinPolicy;
import com.datastax.driver.core.policies.TokenAwarePolicy;
env.init().printf("Cassandra is using Default Policy, which is not DC aware");
}
}
+ cb.withSocketOptions(new SocketOptions().setReadTimeoutMillis(6500000));
return cb.build();
}
import org.onap.aaf.auth.dao.CIDAO;
import org.onap.aaf.auth.dao.CachedDAO;
import org.onap.aaf.auth.dao.cass.CredDAO;
+import org.onap.aaf.auth.dao.cass.CredDAO.Data;
import org.onap.aaf.auth.dao.cass.Status;
import org.onap.aaf.auth.env.AuthzTrans;
import org.onap.aaf.auth.layer.Result;
public class CachedCredDAO extends CachedDAO<AuthzTrans, CredDAO, CredDAO.Data> {
+ private final ReadID readID;
+ private final ReadID readIDBath;
+
public CachedCredDAO(CredDAO dao, CIDAO<AuthzTrans> info, long expiresIn) {
super(dao, info, CredDAO.CACHE_SEG, expiresIn);
+ if(FileGetter.isLoaded) {
+ readID = new ReadID() {
+ @Override
+ public Result<List<Data>> read(AuthzTrans trans, final String id) {
+ return FileGetter.singleton(null).getter(id).get();
+ }
+ };
+ // Both are the same... File read in only does BAth
+ readIDBath = readID;
+ } else {
+ readID = new ReadID() {
+ @Override
+ public Result<List<Data>> read(AuthzTrans trans, final String id) {
+ DAOGetter getter = new DAOGetter(trans,dao()) {
+ public Result<List<CredDAO.Data>> call() {
+ return dao().readID(trans, id);
+ }
+ };
+
+ Result<List<CredDAO.Data>> lurd = get(trans, id, getter);
+ if (lurd.isOK() && lurd.isEmpty()) {
+ return Result.err(Status.ERR_UserNotFound,"No User Cred found");
+ }
+ return lurd;
+ }
+ };
+
+ readIDBath = new ReadID() {
+ @Override
+ public Result<List<Data>> read(AuthzTrans trans, final String id) {
+ DAOGetter getter = new DAOGetter(trans,dao()) {
+ public Result<List<CredDAO.Data>> call() {
+ return dao().readIDBAth(trans, id);
+ }
+ };
+
+ Result<List<CredDAO.Data>> lurd = get(trans, id, getter);
+ if (lurd.isOK() && lurd.isEmpty()) {
+ return Result.err(Status.ERR_UserNotFound,"No User Cred found");
+ }
+ return lurd;
+ }
+ };
+ }
}
/**
return dao().readNS(trans, ns);
}
-
+
public Result<List<CredDAO.Data>> readID(AuthzTrans trans, final String id) {
- DAOGetter getter = new DAOGetter(trans,dao()) {
- public Result<List<CredDAO.Data>> call() {
- return dao().readID(trans, id);
- }
- };
-
- Result<List<CredDAO.Data>> lurd = get(trans, id, getter);
- if (lurd.isOK() && lurd.isEmpty()) {
- return Result.err(Status.ERR_UserNotFound,"No User Cred found");
- }
- return lurd;
+ return readID.read(trans, id);
+ }
+
+ public Result<List<Data>> readIDBAth(AuthzTrans trans, String id) {
+ return readIDBath.read(trans,id);
}
+ private interface ReadID {
+ public Result<List<CredDAO.Data>> read(final AuthzTrans trans, final String id);
+ }
}
--- /dev/null
+/**
+ * ============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.dao.cached;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.onap.aaf.auth.dao.Cached.Getter;
+import org.onap.aaf.auth.dao.cass.CredDAO;
+import org.onap.aaf.auth.dao.cass.CredDAO.Data;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.Hash;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.util.CSV;
+
+public class FileGetter {
+ private static final String AAF_FILEGETTER = "aaf_filegetter";
+ public static boolean isLoaded = false;
+ private static FileGetter singleton;
+
+ private Map<String,List<CredDAO.Data>> data;
+ private SimpleDateFormat sdf;
+ private FileGetter(Access access) {
+ if(access!=null) {
+ String filename = access.getProperty(AAF_FILEGETTER,null);
+ if(filename!=null) {
+ if(!isLoaded) {
+ data = new TreeMap<>();
+ sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+SSSS");
+ CSV csv = new CSV(access, filename).setDelimiter('|');
+ try {
+ access.log(Level.INIT, "Loading Filebased Cred from",filename);
+ csv.visit(row -> {
+ if(row.size()<1) {
+ access.log(Level.INIT, "Bad Row");
+ }
+ int type;
+ try {
+ type =Integer.parseInt(row.get(1));
+ } catch(Exception e) {
+ access.log(Level.INIT, e, "skipping ", row.get(0));
+ return;
+ }
+ if(CredDAO.CERT_SHA256_RSA == type) {
+ return;
+ }
+ CredDAO.Data cdd = new CredDAO.Data();
+ cdd.id=row.get(0);
+ cdd.type = type;
+ try {
+ cdd.expires = sdf.parse(row.get(2));
+ cdd.cred = ByteBuffer.wrap(Hash.fromHex(row.get(3)));
+ cdd.notes= row.get(4);
+ cdd.ns = row.get(5);
+ cdd.other = Integer.parseInt(row.get(6));
+ if(row.size()>8) {
+ cdd.tag = row.get(8);
+ } else {
+ cdd.tag = "";
+ }
+ List<CredDAO.Data> lcdd = data.get(cdd.id);
+ if(lcdd == null) {
+ lcdd = new ArrayList<>();
+ data.put(cdd.id, lcdd);
+ }
+ lcdd.add(cdd);
+
+ } catch (ParseException e) {
+ access.log(Level.INIT, e);
+ }
+
+ });
+ access.printf(Level.INIT, "Filebased Cred finished...");
+ isLoaded = true;
+ } catch( CadiException | IOException e) {
+ access.log(Level.ERROR, e);
+ }
+ }
+ }
+ }
+ }
+
+ public static synchronized FileGetter singleton(Access access) {
+ if(singleton==null) {
+ singleton = new FileGetter(access);
+ }
+ return singleton;
+
+ }
+ public Getter<CredDAO.Data> getter(String id) {
+ return new FGetter(id);
+ }
+ private static List<CredDAO.Data> EMPTY = new ArrayList<>();
+ public class FGetter implements Getter<CredDAO.Data> {
+ private final List<CredDAO.Data> lcdd;
+ public FGetter(final String id) {
+ lcdd = data.get(id);
+ }
+ @Override
+ public Result<List<Data>> get() {
+ return Result.ok(lcdd==null?EMPTY:lcdd);
+ }
+ }
+
+ public static void main(String[] args) {
+ PropAccess access = new PropAccess(args);
+ access.setProperty(AAF_FILEGETTER,"/Users/jg1555/cred.dat");
+ FileGetter fg = FileGetter.singleton(access);
+
+ for(String id : new String[] {"m01891@aaf.att.com","bogus"}) {
+ Getter<CredDAO.Data> g = fg.getter(id);
+ Result<List<CredDAO.Data>> r = g.get();
+ if(r.isOKhasData()) {
+ for(CredDAO.Data cdd : r.value) {
+ System.out.println(cdd);
+ }
+ }
+ }
+ }
+}
+
private CIDAO<AuthzTrans> infoDAO;
private PSInfo psNS;
private PSInfo psID;
+ private PSInfo psIDBath;
public CredDAO(AuthzTrans trans, Cluster cluster, String keyspace) throws APIException, IOException {
super(trans, CredDAO.class.getSimpleName(),cluster, keyspace, Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
psID = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE +
" WHERE id = ?", CredLoader.deflt,readConsistency);
+
+ // NOTE: (type) in ((1),(2)) is valid for Cass 2.1.14. After 2.1.14, more obvious
+ // syntax of type in (1,2) is available
+ // ALSO, 1 & 2 STAND FOR BASIC_AUTH (MD5) AND BASIC_AUTH_SHA256(with salt).
+ // If more Basic Auth Protocols become available, add here but do NOT
+ // add X509, and there can be man Certs, and we don't need to read them every time, or
+ // as discovered, or provide CASS Outage due to too many Certs to read.
+ psIDBath = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE +
+ " WHERE id = ? and (type) in ((1),(2))", CredLoader.deflt,readConsistency);
}
/* (non-Javadoc)
return psID.read(trans, R_TEXT, new Object[]{id});
}
+ public Result<List<Data>> readIDBAth(AuthzTrans trans, String id) {
+ return psIDBath.read(trans, R_TEXT, new Object[] {id});
+ }
+
/**
* Log Modification statements to History
*
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
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.cached.FileGetter;
import org.onap.aaf.auth.dao.cass.ApprovalDAO;
import org.onap.aaf.auth.dao.cass.CacheInfoDAO;
import org.onap.aaf.auth.dao.cass.CertDAO;
static Slot PERMS;
private static Set<String> specialLog = null;
- public static final Random random = new SecureRandom();
+ public static final SecureRandom random = new SecureRandom();
private static long traceID = random.nextLong();
private static Slot specialLogSlot = null;
private static Slot transIDSlot = null;
permDAO = new CachedPermDAO(new PermDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
roleDAO = new CachedRoleDAO(new RoleDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
userRoleDAO = new CachedUserRoleDAO(new UserRoleDAO(trans, historyDAO,cacheInfoDAO), cacheInfoDAO, expiresIn);
+ // Create if aaf_file_cred exists with file
+ FileGetter.singleton(trans.env().access());
credDAO = new CachedCredDAO(new CredDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
certDAO = new CachedCertDAO(new CertDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO, expiresIn);
public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, Access access) {
// <ns>.access|:role:<role name>|<read|write>
String ns = ndd.name;
+ boolean isRoot = ns.startsWith(Define.ROOT_NS());
int last;
do {
if (isGranted(trans, user, ns, ACCESS, ":ns", access.name())) {
return Result.ok(ndd);
}
+ if(isRoot) {
+ break;
+ }
if ((last = ns.lastIndexOf('.')) >= 0) {
ns = ns.substring(0, last);
}
} while (last >= 0);
- // com.att.aaf.ns|:<client ns>:ns|<access>
- // AAF-724 - Make consistent response for May User", and not take the
- // last check... too confusing.
- Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + ndd.name + ":ns", access.name());
- if (rv.isOK()) {
- return rv;
- } else if (rv.status==Result.ERR_Backend) {
- return Result.err(rv);
- } else {
- return Result.err(Status.ERR_Denied, "[%s] may not %s in NS [%s]",
- user, access.name(), ndd.name);
- }
+
+ // SAFETY - Do not allow these when NS is Root
+ if(!isRoot) {
+ // com.att.aaf.ns|:<client ns>:ns|<access>
+ // AAF-724 - Make consistent response for May User", and not take the
+ // last check... too confusing.
+ Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + ndd.name + ":ns", access.name());
+ if (rv.isOK()) {
+ return rv;
+ } else if (rv.status==Result.ERR_Backend) {
+ return Result.err(rv);
+ }
+ }
+ return Result.err(Status.ERR_Denied, "[%s] may not %s in NS [%s]",
+ user, access.name(), ndd.name);
+
}
public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, RoleDAO.Data rdd, Access access) {
}
public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, NsDAO.Data ndd, RoleDAO.Data rdd, Access access) {
- // 1) Is User in the Role?
- Result<List<UserRoleDAO.Data>> rurd = userRoleDAO.readUserInRole(trans, user, rdd.fullName());
- if (rurd.isOKhasData()) {
- return Result.ok(ndd);
+ // 1) For "read", Is User in the Role is enough
+ if(Access.read.equals(access)) {
+ Result<List<UserRoleDAO.Data>> rurd = userRoleDAO.readUserInRole(trans, user, rdd.fullName());
+ if (rurd.isOKhasData()) {
+ return Result.ok(ndd);
+ }
}
String roleInst = ":role:" + rdd.name;
// <ns>.access|:role:<role name>|<read|write>
String ns = rdd.ns;
+ boolean isRoot = ns.startsWith(Define.ROOT_NS());
int last;
do {
if (isGranted(trans, user, ns,ACCESS, roleInst, access.name())) {
return Result.ok(ndd);
}
+ if(isRoot) {
+ break;
+ }
if ((last = ns.lastIndexOf('.')) >= 0) {
ns = ns.substring(0, last);
}
} while (last >= 0);
- // Check if Access by Global Role perm
- // com.att.aaf.ns|:<client ns>:role:name|<access>
- Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":"
- + rdd.ns + roleInst, access.name());
- if (rnsd.isOK()) {
- return rnsd;
- } else if (rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- }
+ // SAFETY - Do not allow these when NS is Root
+ if(!isRoot) {
+ // Check if Access by Global Role perm
+ // com.att.aaf.ns|:<client ns>:role:name|<access>
+ Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":"
+ + rdd.ns + roleInst, access.name());
+ if (rnsd.isOK()) {
+ return rnsd;
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ }
- // Check if Access to Whole NS
- // AAF-724 - Make consistent response for May User", and not take the
- // last check... too confusing.
- Result<org.onap.aaf.auth.dao.cass.NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd,
- ":" + rdd.ns + ":ns", access.name());
- if (rv.isOK()) {
- return rv;
- } else if (rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- } else {
- return Result.err(Status.ERR_Denied, "[%s] may not %s Role [%s]",
- user, access.name(), rdd.fullName());
+ // Check if Access to Whole NS
+ // AAF-724 - Make consistent response for May User", and not take the
+ // last check... too confusing.
+ Result<org.onap.aaf.auth.dao.cass.NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd,
+ ":" + rdd.ns + ":ns", access.name());
+ if (rv.isOK()) {
+ return rv;
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ }
}
-
+ return Result.err(Status.ERR_Denied, "[%s] may not %s Role [%s]",
+ user, access.name(), rdd.fullName());
}
public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,PermDAO.Data pdd, Access access) {
}
public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, PermDAO.Data pdd, Access access) {
+ // Most common occurrence... if granted Permission
if (isGranted(trans, user, pdd.ns, pdd.type, pdd.instance, pdd.action)) {
return Result.ok(ndd);
}
+
String permInst = ":perm:" + pdd.type + ':' + pdd.instance + ':' + pdd.action;
// <ns>.access|:role:<role name>|<read|write>
String ns = ndd.name;
+ boolean isRoot = ns.startsWith(Define.ROOT_NS());
int last;
do {
if (isGranted(trans, user, ns, ACCESS, permInst, access.name())) {
return Result.ok(ndd);
}
+ if(isRoot) {
+ break;
+ }
if ((last = ns.lastIndexOf('.')) >= 0) {
ns = ns.substring(0, last);
}
} while (last >= 0);
- // Check if Access by NS perm
- // com.att.aaf.ns|:<client ns>:role:name|<access>
- Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + permInst, access.name());
- if (rnsd.isOK()) {
- return rnsd;
- } else if (rnsd.status==Result.ERR_Backend) {
- return Result.err(rnsd);
- }
+ // SAFETY - Do not allow these when NS is Root
+ if(!isRoot) {
+ // Check if Access by NS perm
+ // com.att.aaf.ns|:<client ns>:role:name|<access>
+ Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + permInst, access.name());
+ if (rnsd.isOK()) {
+ return rnsd;
+ } else if (rnsd.status==Result.ERR_Backend) {
+ return Result.err(rnsd);
+ }
- // Check if Access to Whole NS
- // AAF-724 - Make consistent response for May User", and not take the
- // last check... too confusing.
- Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + ":ns", access.name());
- if (rv.isOK()) {
- return rv;
- } else {
- return Result.err(Status.ERR_Denied,
- "[%s] may not %s Perm [%s|%s|%s]", user, access.name(),
- pdd.fullType(), pdd.instance, pdd.action);
+ // Check if Access to Whole NS
+ // AAF-724 - Make consistent response for May User", and not take the
+ // last check... too confusing.
+ Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + ":ns", access.name());
+ if (rv.isOK()) {
+ return rv;
+ }
}
-
+ return Result.err(Status.ERR_Denied,
+ "[%s] may not %s Perm [%s|%s|%s]", user, access.name(),
+ pdd.fullType(), pdd.instance, pdd.action);
}
public Result<Void> mayUser(AuthzTrans trans, DelegateDAO.Data dd, Access access) {
Result<List<CredDAO.Data>> result;
TimeTaken tt = trans.start("Read DB Cred", Env.REMOTE);
try {
- result = credDAO.readID(trans, user);
+ result = credDAO.readIDBAth(trans, user);
} finally {
tt.done();
}
private Mapper<REQ, CERT, ARTIFACTS, ERROR> mapper;
// private Slot sCertAuth;
private final String voidResp;
+
public FacadeImpl(AAF_CM certman,
CMService service,
Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper,
import org.onap.aaf.auth.dao.cass.CertDAO;
import org.onap.aaf.auth.env.AuthzTrans;
import org.onap.aaf.auth.layer.Result;
-import org.onap.aaf.cadi.util.FQI;
import org.onap.aaf.cadi.util.Vars;
import aaf.v2_0.Error;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.onap.aaf.auth.cm.data.CertReq;
import org.onap.aaf.auth.cm.data.CertResp;
import org.onap.aaf.auth.cm.validation.CertmanValidator;
+import org.onap.aaf.auth.common.Define;
import org.onap.aaf.auth.dao.CassAccess;
import org.onap.aaf.auth.dao.cass.ArtiDAO;
import org.onap.aaf.auth.dao.cass.CacheInfoDAO;
import org.onap.aaf.auth.org.Organization;
import org.onap.aaf.auth.org.Organization.Identity;
import org.onap.aaf.auth.org.OrganizationException;
+import org.onap.aaf.cadi.Access.Level;
import org.onap.aaf.cadi.Hash;
import org.onap.aaf.cadi.Permission;
-import org.onap.aaf.cadi.Access.Level;
import org.onap.aaf.cadi.aaf.AAFPermission;
import org.onap.aaf.cadi.config.Config;
import org.onap.aaf.cadi.configure.Factory;
private static final int STD_RENEWAL = 30;
private static final int MAX_RENEWAL = 60;
private static final int MIN_RENEWAL = 10;
-
+ // Limit total requests
+ private static final int MAX_X509s = 200; // Need a "LIMIT Exception" DB.
+ private static final String MAX_X509S_TAG = "cm_max_x509s"; // be able to adjust limit in future
+
public static final String REQUEST = "request";
public static final String IGNORE_IPS = "ignoreIPs";
public static final String RENEW = "renew";
public static final String DROP = "drop";
public static final String DOMAIN = "domain";
+ public static final String DYNAMIC_SANS="dynamic_sans";
private static final String CERTMAN = "certman";
private static final String ACCESS = "access";
private final ArtiDAO artiDAO;
private AAF_CM certManager;
private Boolean allowIgnoreIPs;
- private Boolean alwaysIgnoreIPs;
+ private AAFPermission limitOverridePerm;
+ private int max_509s;
// @SuppressWarnings("unchecked")
public CMService(final AuthzTrans trans, AAF_CM certman) throws APIException, IOException {
"*",
"read"
);
- alwaysIgnoreIPs = Boolean.valueOf(certman.access.getProperty(Config.CM_ALWAYS_IGNORE_IPS, "false"));
- if(alwaysIgnoreIPs) {
- trans.env().access().log(Level.INIT, "DNS Evaluation for Cert Creation is turned off with " + Config.CM_ALWAYS_IGNORE_IPS );
- } else {
- allowIgnoreIPs = Boolean.valueOf(certman.access.getProperty(Config.CM_ALLOW_IGNORE_IPS, "false"));
- if(allowIgnoreIPs) {
- trans.env().access().log(Level.INIT, "Allowing DNS Evaluation to be turned off with <ns>.certman|<ca name>|"+IGNORE_IPS);
- }
+ try {
+ max_509s = Integer.parseInt(trans.env().getProperty(MAX_X509S_TAG,Integer.toString(MAX_X509s)));
+ } catch (Exception e) {
+ trans.env().log(e, "");
+ max_509s = MAX_X509s;
+ }
+ limitOverridePerm = new AAFPermission(Define.ROOT_NS(),"certman","quantity","override");
+ allowIgnoreIPs = Boolean.valueOf(certman.access.getProperty(Config.CM_ALLOW_IGNORE_IPS, "false"));
+ if(allowIgnoreIPs) {
+ trans.env().access().log(Level.INIT, "Allowing DNS Evaluation to be turned off with <ns>.certman|<ca name>|"+IGNORE_IPS);
}
}
public Result<CertResp> requestCert(final AuthzTrans trans, final Result<CertReq> req, final CA ca) {
if (req.isOK()) {
-
if (req.value.fqdns.isEmpty()) {
return Result.err(Result.ERR_BadData, "No Machines passed in Request");
}
}
List<String> notes = null;
- List<String> fqdns = new ArrayList<>(req.value.fqdns);
+ List<String> fqdns;
+ boolean domain_based = false;
+ boolean dynamic_sans = false;
+
+ if(req.value.fqdns.isEmpty()) {
+ fqdns = new ArrayList<>();
+ } else {
+ // Only Template or Dynamic permitted to pass in FQDNs
+ if (req.value.fqdns.get(0).startsWith("*")) { // Domain set
+ if (trans.fish(new AAFPermission(null,ca.getPermType(), ca.getName(), DOMAIN))) {
+ domain_based = true;
+ } else {
+ return Result.err(Result.ERR_Denied,
+ "Domain based Authorizations (" + req.value.fqdns.get(0) + ") requires Exception");
+ }
+ } else {
+ if(trans.fish(new AAFPermission(null, ca.getPermType(), ca.getName(),DYNAMIC_SANS))) {
+ dynamic_sans = true;
+ } else {
+ return Result.err(Result.ERR_Denied,
+ "Dynamic SANs for (" + req.value.mechid + ") requires Permission");
+ }
+ }
+ fqdns = new ArrayList<>(req.value.fqdns);
+ }
String email = null;
Organization org = trans.org();
boolean ignoreIPs;
- if(alwaysIgnoreIPs) {
- ignoreIPs=true;
- } else if(allowIgnoreIPs) {
+ if(allowIgnoreIPs) {
ignoreIPs = trans.fish(new AAFPermission(mechNS,CERTMAN, ca.getName(), IGNORE_IPS));
} else {
ignoreIPs = false;
InetAddress primary = null;
// Organize incoming information to get to appropriate Artifact
- if (!fqdns.isEmpty()) {
+ if (!fqdns.isEmpty()) { // Passed in FQDNS, validated above
// Accept domain wild cards, but turn into real machines
// Need *domain.com:real.machine.domain.com:san.machine.domain.com:...
- if (fqdns.get(0).startsWith("*")) { // Domain set
- if (!trans.fish(new AAFPermission(null,ca.getPermType(), ca.getName(), DOMAIN))) {
- return Result.err(Result.ERR_Denied,
- "Domain based Authorizations (" + fqdns.get(0) + ") requires Exception");
- }
-
+ if (domain_based) { // Domain set
// check for Permission in Add Artifact?
- String domain = fqdns.get(0).substring(1);
+ String domain = fqdns.get(0).substring(1); // starts with *, see above
fqdns.remove(0);
if (fqdns.isEmpty()) {
- return Result.err(Result.ERR_Denied, "Requests using domain require machine declaration");
+ return Result.err(Result.ERR_Denied,
+ "Requests using domain require machine declaration");
}
if (!ignoreIPs) {
InetAddress ia = InetAddress.getByName(fqdns.get(0));
if (ia == null) {
return Result.err(Result.ERR_Denied,
- "Request not made from matching IP matching domain");
+ "Request not made from matching IP matching domain");
} else if (ia.getHostName().endsWith(domain)) {
primary = ia;
}
}
} else {
+ // Passed in FQDNs, but not starting with *
if (!ignoreIPs) {
for (String cn : req.value.fqdns) {
try {
if (ignoreIPs) {
host = req.value.fqdns.get(0);
} else if (primary == null) {
- return Result.err(Result.ERR_Denied, "Request not made from matching IP (%s)", trans.ip());
+ return Result.err(Result.ERR_Denied, "Request not made from matching IP (%s)", req.value.fqdns.get(0));
} else {
String thost = primary.getHostName();
host = thost==null?primary.getHostAddress():thost;
ArtiDAO.Data add = null;
Result<List<ArtiDAO.Data>> ra = artiDAO.read(trans, req.value.mechid, host);
if (ra.isOKhasData()) {
- if (add == null) {
- add = ra.value.get(0); // single key
+ add = ra.value.get(0); // single key
+ if(dynamic_sans && (add.sans!=null && !add.sans.isEmpty())) { // do not allow both Dynamic and Artifact SANS
+ return Result.err(Result.ERR_Denied,"Authorization must not include SANS when doing Dynamic SANS (%s, %s)", req.value.mechid, key);
}
} else {
- ra = artiDAO.read(trans, req.value.mechid, key);
- if (ra.isOKhasData()) { // is the Template available?
- add = ra.value.get(0);
- add.machine = host;
- for (String s : fqdns) {
- if (!s.equals(add.machine)) {
- add.sans(true).add(s);
- }
- }
- Result<ArtiDAO.Data> rc = artiDAO.create(trans, add); // Create new Artifact from Template
- if (rc.notOK()) {
- return Result.err(rc);
- }
- } else {
- add = ra.value.get(0);
- }
+ if(domain_based) {
+ ra = artiDAO.read(trans, req.value.mechid, key);
+ if (ra.isOKhasData()) { // is the Template available?
+ add = ra.value.get(0);
+ add.machine = host;
+ for (String s : fqdns) {
+ if (!s.equals(add.machine)) {
+ add.sans(true).add(s);
+ }
+ }
+ Result<ArtiDAO.Data> rc = artiDAO.create(trans, add); // Create new Artifact from Template
+ if (rc.notOK()) {
+ return Result.err(rc);
+ }
+ } else {
+ return Result.err(Result.ERR_Denied,"No Authorization Template for %s, %s", req.value.mechid, key);
+ }
+ } else {
+ return Result.err(Result.ERR_Denied,"No Authorization found for %s, %s", req.value.mechid, key);
+ }
}
// Add Artifact listed FQDNs
- if (add.sans != null) {
- for (String s : add.sans) {
- if (!fqdns.contains(s)) {
- fqdns.add(s);
- }
- }
+ if(!dynamic_sans) {
+ if (add.sans != null) {
+ for (String s : add.sans) {
+ if (!fqdns.contains(s)) {
+ fqdns.add(s);
+ }
+ }
+ }
}
// Policy 2: If Config marked as Expired, do not create or renew
try {
csrMeta = BCFactory.createCSRMeta(ca, req.value.mechid, email, fqdns);
csrMeta.environment(ca.getEnv());
+
+ // Before creating, make sure they don't have too many
+ if(!trans.fish(limitOverridePerm)) {
+ Result<List<CertDAO.Data>> existing = certDAO.readID(trans, req.value.mechid);
+ if(existing.isOK()) {
+ String cn = "CN=" + csrMeta.cn();
+ int count = 0;
+ Date now = new Date();
+ for (CertDAO.Data cdd : existing.value) {
+ Collection<? extends Certificate> certs = Factory.toX509Certificate(cdd.x509);
+ for(Iterator<? extends Certificate> iter = certs.iterator(); iter.hasNext();) {
+ X509Certificate x509 = (X509Certificate)iter.next();
+ if(x509.getNotAfter().after(now) && x509.getSubjectDN().getName().contains(cn)) {
+ if(++count>MAX_X509s) {
+ break;
+ }
+ }
+ }
+ }
+ if(count>max_509s) {
+ return Result.err(Result.ERR_Denied, "There are too many Certificates generated for " + cn + " for " + req.value.mechid);
+ }
+ }
+ }
+ // Here is where we send off to CA for Signing.
X509andChain x509ac = ca.sign(trans, csrMeta);
if (x509ac == null) {
return Result.err(Result.ERR_ActionNotCompleted, "x509 Certificate not signed by CA");
cdd.id = req.value.mechid;
cdd.x500 = x509.getSubjectDN().getName();
cdd.x509 = Factory.toString(trans, x509);
+
certDAO.create(trans, cdd);
CredDAO.Data crdd = new CredDAO.Data();
crdd.id = req.value.mechid;
crdd.ns = Question.domain2ns(crdd.id);
crdd.type = CredDAO.CERT_SHA256_RSA;
- crdd.tag = cdd.serial.toString(16);
+ crdd.tag = cdd.ca + '|' + cdd.serial.toString();
credDAO.create(trans, crdd);
CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), compileNotes(notes));
byte[] hash = Hash.hashSHA256(bb.array());
return ByteBuffer.wrap(hash);
}
-}
\ No newline at end of file
+}
public abstract class Code extends HttpCode<AuthzTrans,Facade1_0> implements Cloneable {
public Code(AAF_CM cma, String description, String ... roles) {
- super(cma.facade1_0, description, roles);
+ super(AAF_CM.facade1_0, description, roles);
// Note, the first "Code" will be created with default Facade, "JSON".
// use clone for another Code with XML
}
pw.println("Press <Return> to continue...");
++idx;
// Sonar insists we do something with the string, though it's only a pause. Not very helpful...
- String sonar = new BufferedReader(new InputStreamReader(System.in)).readLine();
+ BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+ String sonar;
+ try {
+ sonar = br.readLine();
+ } finally {
+ br.close();
+ }
sonar=""; // this useless code brought to you by Sonar.
pw.print(sonar);
continue;
}
} else if (rdr != null) {
BufferedReader br = new BufferedReader(rdr);
- String line;
- while ((line = br.readLine()) != null) {
- if (!aafcli.eval(line) && exitOnFailure) {
- rv = 1;
- break;
+ try {
+ String line;
+ while ((line = br.readLine()) != null) {
+ if (!aafcli.eval(line) && exitOnFailure) {
+ rv = 1;
+ break;
+ }
}
+ } finally {
+ br.close();
}
} else { // just run the command line
aafcli.verbose(false);
package org.onap.aaf.auth.cmd.perm;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
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.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 aaf.v2_0.PermRequest;
// Set Start/End commands
setStartEnd(pr);
- Future<PermRequest> fp = client.update(
- "/authz/perm/"+origType+"/"+origInstance+"/"+origAction,
- getDF(PermRequest.class),
- pr
- );
- int rv;
- if (fp.get(AAFcli.timeout())) {
- rv = fp.code();
- pw().println("Updated Permission");
- } else {
- rv = fp.code();
- if (rv==202) {
- pw().println("Permission Update Accepted, but requires Approvals before actualizing");
+ try {
+ Future<PermRequest> fp = client.update(
+ "/authz/perm/"+
+ origType+ '/' +
+ URLEncoder.encode(origInstance,Config.UTF_8) + '/' +
+ origAction,
+ getDF(PermRequest.class),
+ pr
+ );
+ int rv;
+ if (fp.get(AAFcli.timeout())) {
+ rv = fp.code();
+ pw().println("Updated Permission");
} else {
- error(fp);
+ rv = fp.code();
+ if (rv==202) {
+ pw().println("Permission Update Accepted, but requires Approvals before actualizing");
+ } else {
+ error(fp);
+ }
}
+ return rv;
+ } catch (UnsupportedEncodingException e) {
+ throw new CadiException(e);
}
- return rv;
}
});
package org.onap.aaf.auth.cmd.role;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
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.LocatorException;
import org.onap.aaf.cadi.client.Future;
import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.config.Config;
import org.onap.aaf.misc.env.APIException;
import aaf.v2_0.Roles;
@Override
public int _exec(int idx0, final String ... args) throws CadiException, APIException, LocatorException {
- int idx = idx0;
+ int idx = idx0;
final String type=args[idx];
final String instance=args[++idx];
- final String action=args[++idx];
-
+ final String action = args[++idx];
+
return same(((List)parent).new ListRoles() {
@Override
public Integer code(Rcli<?> client) throws CadiException, APIException {
-
- Future<Roles> fp = client.read(
- "/authz/roles/perm/"+type+'/'+instance+'/'+action,
- getDF(Roles.class)
- );
- return list(fp,client, HEADER+type+'|'+instance+'|'+action);
+ try {
+ Future<Roles> fp = client.read(
+ "/authz/roles/perm/"+type+'/' +
+ URLEncoder.encode(instance,Config.UTF_8)+'/'+
+ action,
+ getDF(Roles.class)
+ );
+ return list(fp,client, HEADER+type+'|'+instance+'|'+action);
+ } catch (UnsupportedEncodingException e) {
+ throw new CadiException(e);
+ }
}
});
}
package org.onap.aaf.auth.cmd.user;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
import java.util.Collections;
import java.util.Comparator;
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 aaf.v2_0.Users;
if ("\\*".equals(instance))instance="*";
String action = args[idx++];
if ("\\*".equals(action))action="*";
- Future<Users> fp = client.read(
- "/authz/users/perm/"+type+'/'+instance+'/'+action,
- getDF(Users.class)
- );
- if (fp.get(AAFcli.timeout())) {
- if (aafcli.isTest())
- Collections.sort(fp.value.getUser(), (Comparator<User>) (u1, u2) -> u1.getId().compareTo(u2.getId()));
- ((org.onap.aaf.auth.cmd.user.List)parent).report(fp.value,false,HEADER,type+"|"+instance+"|"+action);
- if (fp.code()==404)return 200;
- } else {
- error(fp);
+ try {
+ Future<Users> fp = client.read(
+ "/authz/users/perm/" +
+ type + '/' +
+ URLEncoder.encode(instance,Config.UTF_8) + '/' +
+ action,
+ getDF(Users.class)
+ );
+ if (fp.get(AAFcli.timeout())) {
+ if (aafcli.isTest())
+ Collections.sort(fp.value.getUser(), (Comparator<User>) (u1, u2) -> u1.getId().compareTo(u2.getId()));
+ ((org.onap.aaf.auth.cmd.user.List)parent).report(fp.value,false,HEADER,type+"|"+instance+"|"+action);
+ if (fp.code()==404)return 200;
+ } else {
+ error(fp);
+ }
+ return fp.code();
+ } catch (UnsupportedEncodingException e) {
+ throw new CadiException(e);
}
- return fp.code();
}
});
}
public abstract AuthzEnv env();
public abstract void setLur(Lur lur);
+
+ public abstract Lur getLur();
public abstract boolean fish(Permission ... p);
this.lur = lur;
}
+ @Override
+ public Lur getLur() {
+ return lur;
+ }
+
@Override
public boolean fish(Permission ... pond) {
if (lur!=null) {
public void setLur(Lur lur) {
}
+ @Override
+ public Lur getLur() {
+ return null;
+ }
+
@Override
public boolean fish(Permission ... p) {
return false;
if(theme==null) {
theme = defaultTheme;
}
+ List<String> ls = getThemeFiles(trans, theme);
+ if(ls==null) {
+ throw new APIException("Theme " + theme + " does not exist.");
+ }
Cookie cookie = new Cookie(AAF_GUI_THEME,theme);
cookie.setMaxAge(604_800); // one week
trans.hresp().addCookie(cookie);
HttpServletRequest req,
HttpServletResponse resp) throws Exception {
- Result<Void> r = context.renamePerm(trans, req, resp, pathParam(req, "type"),
- pathParam(req, "instance"), pathParam(req, "action"));
+ Result<Void> r = context.renamePerm(trans, req, resp,
+ pathParam(req, "type"),
+ URLDecoder.decode(pathParam(req, "instance"),Config.UTF_8),
+ pathParam(req, "action"));
switch(r.status) {
case OK:
resp.setStatus(HttpStatus.OK_200);
import static org.onap.aaf.auth.rserv.HttpMethods.POST;
import static org.onap.aaf.auth.rserv.HttpMethods.PUT;
+import java.net.URLDecoder;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.onap.aaf.auth.service.Code;
import org.onap.aaf.auth.service.facade.AuthzFacade;
import org.onap.aaf.auth.service.mapper.Mapper.API;
+import org.onap.aaf.cadi.config.Config;
public class API_Roles {
public static void init(AAF_Service authzAPI, AuthzFacade facade) throws Exception {
Result<Void> r = context.getRolesByPerm(trans, resp,
pathParam(req, "type"),
- pathParam(req, "instance"),
+ URLDecoder.decode(pathParam(req, "instance"),Config.UTF_8),
pathParam(req, "action"));
switch(r.status) {
case OK:
import static org.onap.aaf.auth.layer.Result.OK;
import static org.onap.aaf.auth.rserv.HttpMethods.GET;
+import java.net.URLDecoder;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.onap.aaf.auth.service.Code;
import org.onap.aaf.auth.service.facade.AuthzFacade;
import org.onap.aaf.auth.service.mapper.Mapper.API;
+import org.onap.aaf.cadi.config.Config;
/**
* User Role APIs
//
Result<Void> r = context.getUsersByPermission(trans, resp,
pathParam(req, ":type"),
- pathParam(req, ":instance"),
+ URLDecoder.decode(pathParam(req, ":instance"),Config.UTF_8),
pathParam(req, ":action"));
switch(r.status) {
case OK:
import static org.onap.aaf.auth.layer.Result.ERR_BadData;
import static org.onap.aaf.auth.layer.Result.ERR_General;
-import aaf.v2_0.Certs;
-import aaf.v2_0.Certs.Cert;
-import aaf.v2_0.History;
-import aaf.v2_0.History.Item;
-import aaf.v2_0.Users;
-import aaf.v2_0.Users.User;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.UUID;
import java.util.stream.Collectors;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.onap.aaf.misc.env.Env;
import org.onap.aaf.misc.env.TimeTaken;
+import aaf.v2_0.Certs;
+import aaf.v2_0.Certs.Cert;
import aaf.v2_0.CredRequest;
+import aaf.v2_0.History;
+import aaf.v2_0.History.Item;
import aaf.v2_0.NsRequest;
import aaf.v2_0.Nss;
import aaf.v2_0.Nss.Ns;
import aaf.v2_0.UserRole;
import aaf.v2_0.UserRoleRequest;
import aaf.v2_0.UserRoles;
+import aaf.v2_0.Users;
+import aaf.v2_0.Users.User;
@RunWith(MockitoJUnitRunner.class)
public class JU_Mapper_2_0 {
public void cred_shouldReturnError_whenGivenPasswordDoesNotFulfillPolicy() {
//given
String id = "aaf@aaf.osaaf.org";
- String password = "invalid";
- given(org.isValidPassword(transaction, id, password)).willReturn("Password does not match org.osaaf Password Standards");
+ String strp = "invalid";
+ given(org.isValidPassword(transaction, id, strp)).willReturn("Password does not match org.osaaf Password Standards");
//when
- Result<CredDAO.Data> result = mapper.cred(transaction, createCredRequest(id, password), true);
+ Result<CredDAO.Data> result = mapper.cred(transaction, createCredRequest(id, strp), true);
//then
assertFalse(result.isOK());
//given
String ns = "org.osaaf.aaf";
String id = "aaf@aaf.osaaf.org";
- String password = "SomeValidPassword123!";
+ String strp = "SomeValidPassword123!";
GregorianCalendar expiration = new GregorianCalendar();
given(org.expiration(isA(GregorianCalendar.class), eq(Expiration.Password), eq(id))).willReturn(expiration);
- given(org.isValidPassword(transaction, id, password)).willReturn("");
+ given(org.isValidPassword(transaction, id, strp)).willReturn("");
//when
- Result<CredDAO.Data> result = mapper.cred(transaction, createCredRequest(id, password), true);
+ Result<CredDAO.Data> result = mapper.cred(transaction, createCredRequest(id, strp), true);
//then
assertTrue(result.isOK());
*
*/
public static class ImmutableMap {
+ @SuppressWarnings("unchecked")
public static <T,U> Map<T,U> of(Object ... tag_value) {
Map<T,U> rv = new HashMap<>();
for(int i=0;i<tag_value.length-1;i+=2) {
*
*/
public static class Lists {
- @SuppressWarnings("unchecked")
+ @SafeVarargs
public static <T> List<T> newArrayList(Collection<T> ... init ) {
List<T> rv = new ArrayList<>();
for(Collection<T> o : init) {
import java.util.List;
import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Access.Level;
import org.onap.aaf.cadi.CadiException;
import org.onap.aaf.cadi.LocatorException;
import org.onap.aaf.cadi.SecuritySetter;
import org.onap.aaf.cadi.config.Config;
import org.onap.aaf.cadi.config.SecurityInfoC;
import org.onap.aaf.cadi.http.HClient;
+import org.onap.aaf.cadi.locator.DNSLocator;
import org.onap.aaf.cadi.util.FixURIinfo;
import org.onap.aaf.cadi.util.Split;
import org.onap.aaf.misc.env.APIException;
public class AAFLocator extends AbsAAFLocator<BasicTrans> {
private static RosettaEnv env;
- HClient client;
+ private HClient client;
+ private HClient lclient;
private RosettaDF<Endpoints> epsDF;
+ private DNSLocator locatorLocator;
+ private Item locatorItem;
+
public AAFLocator(SecurityInfoC<HttpURLConnection> si, URI locatorURI) throws LocatorException {
super(si.access, nameFromLocatorURI(locatorURI), 10000L /* Wait at least 10 seconds between refreshes */);
sb.append(path[i]);
}
setPathInfo(sb.toString());
-// URI uri = new URI(
-// locatorURI.getScheme(),
-// locatorURI.getAuthority(),
-// locatorURI.getPath(),
-// null,
-// null
-// );
client = createClient(si.defSS, locatorURI, connectTimeout);
} else {
client = new HClient(si.defSS, locatorURI, connectTimeout);
} catch (APIException /*| URISyntaxException*/ e) {
throw new LocatorException(e);
}
+ lclient = new HClient(si.defSS, locatorURI, connectTimeout);
if(si.access.willLog(Access.Level.DEBUG)) {
si.access.log(Access.Level.DEBUG, "Root URI:",client.getURI());
}
+
+ String dnsString;
+ if(locatorURI.getPort()<0) {
+ dnsString=locatorURI.getScheme() + "://" + locatorURI.getHost();
+ } else {
+ dnsString=locatorURI.getScheme() + "://" +locatorURI.getHost()+':'+locatorURI.getPort();
+ }
+ if(dnsString.contains("null")) { // for Testing Purposes, mostly.
+ locatorLocator = null;
+ } else {
+ locatorLocator = new DNSLocator(access, dnsString);
+ locatorItem = locatorLocator.best();
+ }
+ }
+
+ private URI locatorFail(URI uri) throws LocatorException, URISyntaxException {
+ locatorLocator.invalidate(locatorItem);
+ locatorItem = locatorLocator.best();
+ URI newURI = locatorLocator.get(locatorItem);
+ return new URI(uri.getScheme(),
+ uri.getUserInfo(),
+ newURI.getHost(),
+ newURI.getPort(),
+ uri.getPath(),
+ uri.getQuery(),
+ uri.getFragment());
}
+ protected final int maxIters() {
+ return locatorLocator.size();
+ }
+
+
@Override
public boolean refresh() {
try {
- client.setMethod("GET");
- client.send();
- Future<Endpoints> fr = client.futureRead(epsDF, TYPE.JSON);
- if (fr.get(client.timeout())) {
+ int max = locatorLocator.size();
+ for(int i=0;i<max;) {
+ ++i;
+ try {
+ lclient.setMethod("GET");
+ lclient.send();
+ break;
+ } catch (APIException connectE) {
+ Throwable ce = connectE.getCause();
+ if(ce!=null && ce instanceof java.net.ConnectException && i< maxIters()) {
+ try {
+ URI old = client.getURI();
+ lclient.setURI(locatorFail(old));
+ access.printf(Level.INFO, "AAF Locator changed from %s to %s",old, lclient.getURI());
+ continue;
+ } catch (LocatorException e) {
+ throw connectE;
+ }
+ }
+ // last one, just throw
+ throw connectE;
+ }
+ }
+ Future<Endpoints> fr = lclient.futureRead(epsDF, TYPE.JSON);
+ if (fr.get(lclient.timeout())) {
List<EP> epl = new LinkedList<>();
for (Endpoint endpoint : fr.value.getEndpoint()) {
epl.add(new EP(endpoint,latitude,longitude));
} catch (UnknownHostException | CadiException e1) {
throw new LocatorException(e1);
}
+ URI aaf_locator_uri;
try {
aaf_locator_host = rph.replacements(getClass().getSimpleName(),"https://"+Config.AAF_LOCATE_URL_TAG,null,null);
if(aaf_locator_host.endsWith("/locate")) {
} else {
aaf_locator_uri = new URI(aaf_locator_host+"/locate");
}
-
access.printf(Level.INFO, "AbsAAFLocator AAF URI is %s",aaf_locator_uri);
} catch (URISyntaxException e) {
throw new LocatorException(e);
this.name = split[0];
this.version = (split.length > 1) ? split[1] : access.getProperty(Config.AAF_API_VERSION,Config.AAF_DEFAULT_API_VERSION);
}
-
}
-
+
/**
* This is the way to setup specialized AAFLocators ahead of time.
* @param preload
}
return null;
}
-
+
protected static class AAFLItem implements Item {
private Iterator<EP> iter;
private URI uri;
package org.onap.aaf.cadi.aaf.v2_0.test;
-import static org.junit.Assert.*;
-import static org.hamcrest.CoreMatchers.*;
-import static org.mockito.Matchers.*;
-import static org.mockito.Mockito.*;
-import org.junit.*;
-import org.mockito.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.onap.aaf.cadi.Access;
import org.onap.aaf.cadi.Locator.Item;
import org.onap.aaf.cadi.LocatorException;
package org.onap.aaf.cadi.oauth.test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-
import org.onap.aaf.cadi.CadiException;
import org.onap.aaf.cadi.Locator;
import org.onap.aaf.cadi.Locator.Item;
import org.onap.aaf.cadi.PropAccess;
import org.onap.aaf.cadi.client.Rcli;
import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.config.SecurityInfoC;
import org.onap.aaf.cadi.oauth.TimedToken;
import org.onap.aaf.cadi.oauth.TzHClient;
import org.onap.aaf.misc.env.APIException;
-import org.onap.aaf.cadi.config.Config;
-import org.onap.aaf.cadi.config.SecurityInfoC;
public class JU_TzHClient {
MockitoAnnotations.initMocks(this);
access = new PropAccess(new PrintStream(new ByteArrayOutputStream()), new String[0]);
access.setProperty(Config.CADI_LATITUDE, "38.62"); // St Louis approx lat
- access.setProperty(Config.CADI_LONGITUDE, "90.19"); // St Louis approx lon }
-
+ access.setProperty(Config.CADI_LONGITUDE, "90.19"); // St Louis approx long
+ //access.setProperty("tag", "http://aaf.something.com");
+
errStream = new ByteArrayOutputStream();
System.setErr(new PrintStream(errStream));
}
private Host[] hosts;
private int startPort, endPort;
private String suffix;
+
+ private int size = 1; // initial, until refreshed.
public DNSLocator(Access access, String protocol, String host, String range) {
this.host = host;
}
}
hosts = temp;
+ size = temp.length * (endPort-startPort+1);
return true;
} catch (Exception e) {
access.log(Level.ERROR, e);
}
public void destroy() {}
+
+ public int size() {
+ return size;
+ }
}
\r
@Test\r
public void testLoggable() {\r
+ Logger l4jLogger = Logger.getLogger("testLogger");\r
+ l4jLogger.setLevel(Level.DEBUG);\r
Log4JLogTarget logObj = null;\r
try {\r
logObj = new Log4JLogTarget( "testLogger", Level.DEBUG);\r