+++ /dev/null
-/*******************************************************************************\r
- * ============LICENSE_START====================================================\r
- * * org.onap.aaf\r
- * * ===========================================================================\r
- * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
- * * ===========================================================================\r
- * * Licensed under the Apache License, Version 2.0 (the "License");\r
- * * you may not use this file except in compliance with the License.\r
- * * You may obtain a copy of the License at\r
- * * \r
- * * http://www.apache.org/licenses/LICENSE-2.0\r
- * * \r
- * * Unless required by applicable law or agreed to in writing, software\r
- * * distributed under the License is distributed on an "AS IS" BASIS,\r
- * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * * See the License for the specific language governing permissions and\r
- * * limitations under the License.\r
- * * ============LICENSE_END====================================================\r
- * *\r
- * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
- * *\r
- ******************************************************************************/\r
-package org.onap.aaf.dao.aaf.hl;\r
-\r
-import java.io.IOException;\r
-import java.nio.ByteBuffer;\r
-import java.security.NoSuchAlgorithmException;\r
-import java.security.SecureRandom;\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.Date;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.TreeSet;\r
-\r
-import org.onap.aaf.authz.common.Define;\r
-import org.onap.aaf.authz.env.AuthzTrans;\r
-import org.onap.aaf.authz.env.AuthzTransFilter;\r
-import org.onap.aaf.authz.layer.Result;\r
-import org.onap.aaf.authz.org.Organization;\r
-import org.onap.aaf.authz.org.Organization.Identity;\r
-import org.onap.aaf.dao.AbsCassDAO;\r
-import org.onap.aaf.dao.CachedDAO;\r
-import org.onap.aaf.dao.DAOException;\r
-import org.onap.aaf.dao.aaf.cached.CachedCertDAO;\r
-import org.onap.aaf.dao.aaf.cached.CachedCredDAO;\r
-import org.onap.aaf.dao.aaf.cached.CachedNSDAO;\r
-import org.onap.aaf.dao.aaf.cached.CachedPermDAO;\r
-import org.onap.aaf.dao.aaf.cached.CachedRoleDAO;\r
-import org.onap.aaf.dao.aaf.cached.CachedUserRoleDAO;\r
-import org.onap.aaf.dao.aaf.cass.ApprovalDAO;\r
-import org.onap.aaf.dao.aaf.cass.CacheInfoDAO;\r
-import org.onap.aaf.dao.aaf.cass.CertDAO;\r
-import org.onap.aaf.dao.aaf.cass.CredDAO;\r
-import org.onap.aaf.dao.aaf.cass.DelegateDAO;\r
-import org.onap.aaf.dao.aaf.cass.FutureDAO;\r
-import org.onap.aaf.dao.aaf.cass.HistoryDAO;\r
-import org.onap.aaf.dao.aaf.cass.NsDAO;\r
-import org.onap.aaf.dao.aaf.cass.NsSplit;\r
-import org.onap.aaf.dao.aaf.cass.NsType;\r
-import org.onap.aaf.dao.aaf.cass.PermDAO;\r
-import org.onap.aaf.dao.aaf.cass.RoleDAO;\r
-import org.onap.aaf.dao.aaf.cass.Status;\r
-import org.onap.aaf.dao.aaf.cass.UserRoleDAO;\r
-import org.onap.aaf.dao.aaf.cass.NsDAO.Data;\r
-\r
-import org.onap.aaf.cadi.Hash;\r
-import org.onap.aaf.cadi.aaf.PermEval;\r
-import org.onap.aaf.inno.env.APIException;\r
-import org.onap.aaf.inno.env.Env;\r
-import org.onap.aaf.inno.env.Slot;\r
-import org.onap.aaf.inno.env.TimeTaken;\r
-import org.onap.aaf.inno.env.util.Chrono;\r
-import com.datastax.driver.core.Cluster;\r
-\r
-/**\r
- * Question HL DAO\r
- * \r
- * A Data Access Combination Object which asks Security and other Questions\r
- * \r
- *\r
- */\r
-public class Question {\r
- // DON'T CHANGE FROM lower Case!!!\r
- public static enum Type {\r
- ns, role, perm, cred\r
- };\r
-\r
- public static final String OWNER="owner";\r
- public static final String ADMIN="admin";\r
- public static final String DOT_OWNER=".owner";\r
- public static final String DOT_ADMIN=".admin";\r
- static final String ASTERIX = "*";\r
-\r
- public static enum Access {\r
- read, write, create\r
- };\r
-\r
- public static final String READ = Access.read.name();\r
- public static final String WRITE = Access.write.name();\r
- public static final String CREATE = Access.create.name();\r
-\r
- public static final String ROLE = Type.role.name();\r
- public static final String PERM = Type.perm.name();\r
- public static final String NS = Type.ns.name();\r
- public static final String CRED = Type.cred.name();\r
- private static final String DELG = "delg";\r
- public static final String ATTRIB = "attrib";\r
-\r
-\r
- public static final int MAX_SCOPE = 10;\r
- public static final int APP_SCOPE = 3;\r
- public static final int COMPANY_SCOPE = 2;\r
- static Slot PERMS;\r
-\r
- private static Set<String> specialLog = null;\r
- public static final SecureRandom random = new SecureRandom();\r
- private static long traceID = random.nextLong();\r
- private static final String SPECIAL_LOG_SLOT = "SPECIAL_LOG_SLOT";\r
- private static Slot specialLogSlot = null;\r
- private static Slot transIDSlot = null;\r
-\r
-\r
- public final HistoryDAO historyDAO;\r
- public final CachedNSDAO nsDAO;\r
- public final CachedRoleDAO roleDAO;\r
- public final CachedPermDAO permDAO;\r
- public final CachedUserRoleDAO userRoleDAO;\r
- public final CachedCredDAO credDAO;\r
- public final CachedCertDAO certDAO;\r
- public final DelegateDAO delegateDAO;\r
- public final FutureDAO futureDAO;\r
- public final ApprovalDAO approvalDAO;\r
- private final CacheInfoDAO cacheInfoDAO;\r
-\r
- // final ContactDAO contDAO;\r
- // private static final String DOMAIN = "@aaf.att.com";\r
- // private static final int DOMAIN_LENGTH = 0;\r
-\r
- public Question(AuthzTrans trans, Cluster cluster, String keyspace, boolean startClean) throws APIException, IOException {\r
- PERMS = trans.slot("USER_PERMS");\r
- trans.init().log("Instantiating DAOs");\r
- historyDAO = new HistoryDAO(trans, cluster, keyspace);\r
-\r
- // Deal with Cached Entries\r
- cacheInfoDAO = new CacheInfoDAO(trans, historyDAO);\r
-\r
- nsDAO = new CachedNSDAO(new NsDAO(trans, historyDAO, cacheInfoDAO),\r
- cacheInfoDAO);\r
- permDAO = new CachedPermDAO(\r
- new PermDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO);\r
- roleDAO = new CachedRoleDAO(\r
- new RoleDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO);\r
- userRoleDAO = new CachedUserRoleDAO(new UserRoleDAO(trans, historyDAO,\r
- cacheInfoDAO), cacheInfoDAO);\r
- credDAO = new CachedCredDAO(\r
- new CredDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO);\r
- certDAO = new CachedCertDAO(\r
- new CertDAO(trans, historyDAO, cacheInfoDAO), cacheInfoDAO);\r
-\r
- futureDAO = new FutureDAO(trans, historyDAO);\r
- delegateDAO = new DelegateDAO(trans, historyDAO);\r
- approvalDAO = new ApprovalDAO(trans, historyDAO);\r
-\r
- // Only want to aggressively cleanse User related Caches... The others,\r
- // just normal refresh\r
- if(startClean) {\r
- CachedDAO.startCleansing(trans.env(), credDAO, userRoleDAO);\r
- CachedDAO.startRefresh(trans.env(), cacheInfoDAO);\r
- }\r
- // Set a Timer to Check Caches to send messages for Caching changes\r
- \r
- if(specialLogSlot==null) {\r
- specialLogSlot = trans.slot(SPECIAL_LOG_SLOT);\r
- transIDSlot = trans.slot(AuthzTransFilter.TRANS_ID_SLOT);\r
- }\r
- \r
- AbsCassDAO.primePSIs(trans);\r
- }\r
-\r
-\r
- public void close(AuthzTrans trans) {\r
- historyDAO.close(trans);\r
- cacheInfoDAO.close(trans);\r
- nsDAO.close(trans);\r
- permDAO.close(trans);\r
- roleDAO.close(trans);\r
- userRoleDAO.close(trans);\r
- credDAO.close(trans);\r
- certDAO.close(trans);\r
- delegateDAO.close(trans);\r
- futureDAO.close(trans);\r
- approvalDAO.close(trans);\r
- }\r
-\r
- public Result<PermDAO.Data> permFrom(AuthzTrans trans, String type,\r
- String instance, String action) {\r
- Result<NsDAO.Data> rnd = deriveNs(trans, type);\r
- if (rnd.isOK()) {\r
- return Result.ok(new PermDAO.Data(new NsSplit(rnd.value, type),\r
- instance, action));\r
- } else {\r
- return Result.err(rnd);\r
- }\r
- }\r
-\r
- /**\r
- * getPermsByUser\r
- * \r
- * Because this call is frequently called internally, AND because we already\r
- * look for it in the initial Call, we cache within the Transaction\r
- * \r
- * @param trans\r
- * @param user\r
- * @return\r
- */\r
- public Result<List<PermDAO.Data>> getPermsByUser(AuthzTrans trans, String user, boolean lookup) {\r
- return PermLookup.get(trans, this, user).getPerms(lookup);\r
- }\r
- \r
- public Result<List<PermDAO.Data>> getPermsByUserFromRolesFilter(AuthzTrans trans, String user, String forUser) {\r
- PermLookup plUser = PermLookup.get(trans, this, user);\r
- Result<Set<String>> plPermNames = plUser.getPermNames();\r
- if(plPermNames.notOK()) {\r
- return Result.err(plPermNames);\r
- }\r
- \r
- Set<String> nss;\r
- if(forUser.equals(user)) {\r
- nss = null;\r
- } else {\r
- // Setup a TreeSet to check on Namespaces to \r
- nss = new TreeSet<String>();\r
- PermLookup fUser = PermLookup.get(trans, this, forUser);\r
- Result<Set<String>> forUpn = fUser.getPermNames();\r
- if(forUpn.notOK()) {\r
- return Result.err(forUpn);\r
- }\r
- \r
- for(String pn : forUpn.value) {\r
- Result<String[]> decoded = PermDAO.Data.decodeToArray(trans, this, pn);\r
- if(decoded.isOKhasData()) {\r
- nss.add(decoded.value[0]);\r
- } else {\r
- trans.error().log(pn,", derived from a Role, is invalid:",decoded.errorString());\r
- }\r
- }\r
- }\r
-\r
- List<PermDAO.Data> rlpUser = new ArrayList<PermDAO.Data>();\r
- Result<PermDAO.Data> rpdd;\r
- PermDAO.Data pdd;\r
- for(String pn : plPermNames.value) {\r
- rpdd = PermDAO.Data.decode(trans, this, pn);\r
- if(rpdd.isOKhasData()) {\r
- pdd=rpdd.value;\r
- if(nss==null || nss.contains(pdd.ns)) {\r
- rlpUser.add(pdd);\r
- }\r
- } else {\r
- trans.error().log(pn,", derived from a Role, is invalid. Run Data Cleanup:",rpdd.errorString());\r
- }\r
- }\r
- return Result.ok(rlpUser); \r
- }\r
-\r
- public Result<List<PermDAO.Data>> getPermsByType(AuthzTrans trans, String perm) {\r
- Result<NsSplit> nss = deriveNsSplit(trans, perm);\r
- if (nss.notOK()) {\r
- return Result.err(nss);\r
- }\r
- return permDAO.readByType(trans, nss.value.ns, nss.value.name);\r
- }\r
-\r
- public Result<List<PermDAO.Data>> getPermsByName(AuthzTrans trans,\r
- String type, String instance, String action) {\r
- Result<NsSplit> nss = deriveNsSplit(trans, type);\r
- if (nss.notOK()) {\r
- return Result.err(nss);\r
- }\r
- return permDAO.read(trans, nss.value.ns, nss.value.name, instance,action);\r
- }\r
-\r
- public Result<List<PermDAO.Data>> getPermsByRole(AuthzTrans trans, String role, boolean lookup) {\r
- Result<NsSplit> nss = deriveNsSplit(trans, role);\r
- if (nss.notOK()) {\r
- return Result.err(nss);\r
- }\r
-\r
- Result<List<RoleDAO.Data>> rlrd = roleDAO.read(trans, nss.value.ns,\r
- nss.value.name);\r
- if (rlrd.notOKorIsEmpty()) {\r
- return Result.err(rlrd);\r
- }\r
- // Using Set to avoid duplicates\r
- Set<String> permNames = new HashSet<String>();\r
- if (rlrd.isOKhasData()) {\r
- for (RoleDAO.Data drr : rlrd.value) {\r
- permNames.addAll(drr.perms(false));\r
- }\r
- }\r
-\r
- // Note: It should be ok for a Valid user to have no permissions -\r
- // 8/12/2013\r
- List<PermDAO.Data> perms = new ArrayList<PermDAO.Data>();\r
- for (String perm : permNames) {\r
- Result<PermDAO.Data> pr = PermDAO.Data.decode(trans, this, perm);\r
- if (pr.notOK()) {\r
- return Result.err(pr);\r
- }\r
-\r
- if(lookup) {\r
- Result<List<PermDAO.Data>> rlpd = permDAO.read(trans, pr.value);\r
- if (rlpd.isOKhasData()) {\r
- for (PermDAO.Data pData : rlpd.value) {\r
- perms.add(pData);\r
- }\r
- }\r
- } else {\r
- perms.add(pr.value);\r
- }\r
- }\r
-\r
- return Result.ok(perms);\r
- }\r
-\r
- public Result<List<RoleDAO.Data>> getRolesByName(AuthzTrans trans,\r
- String role) {\r
- Result<NsSplit> nss = deriveNsSplit(trans, role);\r
- if (nss.notOK()) {\r
- return Result.err(nss);\r
- }\r
- String r = nss.value.name;\r
- if (r.endsWith(".*")) { // do children Search\r
- return roleDAO.readChildren(trans, nss.value.ns,\r
- r.substring(0, r.length() - 2));\r
- } else if (ASTERIX.equals(r)) {\r
- return roleDAO.readChildren(trans, nss.value.ns, ASTERIX);\r
- } else {\r
- return roleDAO.read(trans, nss.value.ns, r);\r
- }\r
- }\r
-\r
- /**\r
- * Derive NS\r
- * \r
- * Given a Child Namespace, figure out what the best Namespace parent is.\r
- * \r
- * For instance, if in the NS table, the parent "com.att" exists, but not\r
- * "com.att.child" or "com.att.a.b.c", then passing in either\r
- * "com.att.child" or "com.att.a.b.c" will return "com.att"\r
- * \r
- * Uses recursive search on Cached DAO data\r
- * \r
- * @param trans\r
- * @param child\r
- * @return\r
- */\r
- public Result<NsDAO.Data> deriveNs(AuthzTrans trans, String child) {\r
- Result<List<NsDAO.Data>> r = nsDAO.read(trans, child);\r
- \r
- if (r.isOKhasData()) {\r
- return Result.ok(r.value.get(0));\r
- } else {\r
- int dot = child == null ? -1 : child.lastIndexOf('.');\r
- if (dot < 0) {\r
- return Result.err(Status.ERR_NsNotFound,\r
- "No Namespace for [%s]", child);\r
- } else {\r
- return deriveNs(trans, child.substring(0, dot));\r
- }\r
- }\r
- }\r
-\r
- public Result<NsDAO.Data> deriveFirstNsForType(AuthzTrans trans, String str, NsType type) {\r
- NsDAO.Data nsd;\r
-\r
- System.out.println("value of str before for loop ---------0---++++++++++++++++++" +str);\r
- for(int idx = str.indexOf('.');idx>=0;idx=str.indexOf('.',idx+1)) {\r
- // System.out.println("printing value of str-----------------1------------++++++++++++++++++++++" +str);\r
- Result<List<Data>> rld = nsDAO.read(trans, str.substring(0,idx));\r
- System.out.println("value of idx is -----------------++++++++++++++++++++++++++" +idx);\r
- System.out.println("printing value of str.substring-----------------1------------++++++++++++++++++++++" + (str.substring(0,idx)));\r
- System.out.println("value of ResultListData ------------------2------------+++++++++++++++++++++++++++" +rld);\r
- if(rld.isOKhasData()) {\r
- System.out.println("In if loop -----------------3-------------- ++++++++++++++++");\r
- System.out.println("value of nsd=rld.value.get(0).type -----------4------++++++++++++++++++++++++++++++++++++" +(nsd=rld.value.get(0)).type);\r
- System.out.println("value of rld.value.get(0).name.toString()+++++++++++++++++++++++++++++++ " +rld.value.get(0).name);\r
- if(type.type == (nsd=rld.value.get(0)).type) {\r
- return Result.ok(nsd);\r
- }\r
- } else {\r
- System.out.println("In else loop ----------------4------------+++++++++++++++++++++++");\r
- return Result.err(Status.ERR_NsNotFound,"There is no valid Company Namespace for %s",str.substring(0,idx));\r
- }\r
- }\r
- return Result.err(Status.ERR_NotFound, str + " does not contain type " + type.name());\r
- }\r
-\r
- public Result<NsSplit> deriveNsSplit(AuthzTrans trans, String child) {\r
- Result<NsDAO.Data> ndd = deriveNs(trans, child);\r
- if (ndd.isOK()) {\r
- NsSplit nss = new NsSplit(ndd.value, child);\r
- if (nss.isOK()) {\r
- return Result.ok(nss);\r
- } else {\r
- return Result.err(Status.ERR_NsNotFound,\r
- "Cannot split [%s] into valid namespace elements",\r
- child);\r
- }\r
- }\r
- return Result.err(ndd);\r
- }\r
-\r
- /**\r
- * Translate an ID into it's domain\r
- * \r
- * i.e. myid1234@myapp.att.com results in domain of com.att.myapp\r
- * \r
- * @param id\r
- * @return\r
- */\r
- public static String domain2ns(String id) {\r
- int at = id.indexOf('@');\r
- if (at >= 0) {\r
- String[] domain = id.substring(at + 1).split("\\.");\r
- StringBuilder ns = new StringBuilder(id.length());\r
- boolean first = true;\r
- for (int i = domain.length - 1; i >= 0; --i) {\r
- if (first) {\r
- first = false;\r
- } else {\r
- ns.append('.');\r
- }\r
- ns.append(domain[i]);\r
- }\r
- return ns.toString();\r
- } else {\r
- return "";\r
- }\r
-\r
- }\r
-\r
- /**\r
- * Validate Namespace of ID@Domain\r
- * \r
- * Namespace is reverse order of Domain.\r
- * \r
- * i.e. myid1234@myapp.att.com results in domain of com.att.myapp\r
- * \r
- * @param trans\r
- * @param id\r
- * @return\r
- */\r
- public Result<NsDAO.Data> validNSOfDomain(AuthzTrans trans, String id) {\r
- // Take domain, reverse order, and check on NS\r
- String ns;\r
- if(id.indexOf('@')<0) { // it's already an ns, not an ID\r
- ns = id;\r
- } else {\r
- ns = domain2ns(id);\r
- }\r
- if (ns.length() > 0) {\r
- if(!trans.org().getDomain().equals(ns)) { \r
- Result<List<NsDAO.Data>> rlnsd = nsDAO.read(trans, ns);\r
- if (rlnsd.isOKhasData()) {\r
- return Result.ok(rlnsd.value.get(0));\r
- }\r
- }\r
- }\r
- return Result.err(Status.ERR_NsNotFound,\r
- "A Namespace is not available for %s", id);\r
- }\r
-\r
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, Access access) {\r
- // <ns>.access|:role:<role name>|<read|write>\r
- String ns = ndd.name;\r
- int last;\r
- do {\r
- if (isGranted(trans, user, ns, "access", ":ns", access.name())) {\r
- return Result.ok(ndd);\r
- }\r
- if ((last = ns.lastIndexOf('.')) >= 0) {\r
- ns = ns.substring(0, last);\r
- }\r
- } while (last >= 0);\r
- // <root ns>.ns|:<client ns>:ns|<access>\r
- // AAF-724 - Make consistent response for May User", and not take the\r
- // last check... too confusing.\r
- Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + ndd.name + ":ns", access.name());\r
- if (rv.isOK()) {\r
- return rv;\r
- } else if(rv.status==Result.ERR_Backend) {\r
- return Result.err(rv);\r
- } else {\r
- return Result.err(Status.ERR_Denied, "[%s] may not %s in NS [%s]",\r
- user, access.name(), ndd.name);\r
- }\r
- }\r
-\r
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, RoleDAO.Data rdd, Access access) {\r
- Result<NsDAO.Data> rnsd = deriveNs(trans, rdd.ns);\r
- if (rnsd.isOK()) {\r
- return mayUser(trans, user, rnsd.value, rdd, access);\r
- }\r
- return rnsd;\r
- }\r
-\r
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user, NsDAO.Data ndd, RoleDAO.Data rdd, Access access) {\r
- // 1) Is User in the Role?\r
- Result<List<UserRoleDAO.Data>> rurd = userRoleDAO.readUserInRole(trans, user, rdd.fullName());\r
- if (rurd.isOKhasData()) {\r
- return Result.ok(ndd);\r
- }\r
-\r
- String roleInst = ":role:" + rdd.name;\r
- // <ns>.access|:role:<role name>|<read|write>\r
- String ns = rdd.ns;\r
- int last;\r
- do {\r
- if (isGranted(trans, user, ns,"access", roleInst, access.name())) {\r
- return Result.ok(ndd);\r
- }\r
- if ((last = ns.lastIndexOf('.')) >= 0) {\r
- ns = ns.substring(0, last);\r
- }\r
- } while (last >= 0);\r
-\r
- // Check if Access by Global Role perm\r
- // <root ns>.ns|:<client ns>:role:name|<access>\r
- Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":"\r
- + rdd.ns + roleInst, access.name());\r
- if (rnsd.isOK()) {\r
- return rnsd;\r
- } else if(rnsd.status==Result.ERR_Backend) {\r
- return Result.err(rnsd);\r
- }\r
-\r
- // Check if Access to Whole NS\r
- // AAF-724 - Make consistent response for May User", and not take the\r
- // last check... too confusing.\r
- Result<org.onap.aaf.dao.aaf.cass.NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, \r
- ":" + rdd.ns + ":ns", access.name());\r
- if (rv.isOK()) {\r
- return rv;\r
- } else if(rnsd.status==Result.ERR_Backend) {\r
- return Result.err(rnsd);\r
- } else {\r
- return Result.err(Status.ERR_Denied, "[%s] may not %s Role [%s]",\r
- user, access.name(), rdd.fullName());\r
- }\r
-\r
- }\r
-\r
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,PermDAO.Data pdd, Access access) {\r
- Result<NsDAO.Data> rnsd = deriveNs(trans, pdd.ns);\r
- if (rnsd.isOK()) {\r
- return mayUser(trans, user, rnsd.value, pdd, access);\r
- }\r
- return rnsd;\r
- }\r
-\r
- public Result<NsDAO.Data> mayUser(AuthzTrans trans, String user,NsDAO.Data ndd, PermDAO.Data pdd, Access access) {\r
- if (isGranted(trans, user, pdd.ns, pdd.type, pdd.instance, pdd.action)) {\r
- return Result.ok(ndd);\r
- }\r
- String permInst = ":perm:" + pdd.type + ':' + pdd.instance + ':' + pdd.action;\r
- // <ns>.access|:role:<role name>|<read|write>\r
- String ns = ndd.name;\r
- int last;\r
- do {\r
- if (isGranted(trans, user, ns, "access", permInst, access.name())) {\r
- return Result.ok(ndd);\r
- }\r
- if ((last = ns.lastIndexOf('.')) >= 0) {\r
- ns = ns.substring(0, last);\r
- }\r
- } while (last >= 0);\r
-\r
- // Check if Access by NS perm\r
- // <root ns>.ns|:<client ns>:role:name|<access>\r
- Result<NsDAO.Data> rnsd = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + permInst, access.name());\r
- if (rnsd.isOK()) {\r
- return rnsd;\r
- } else if(rnsd.status==Result.ERR_Backend) {\r
- return Result.err(rnsd);\r
- }\r
-\r
- // Check if Access to Whole NS\r
- // AAF-724 - Make consistent response for May User", and not take the\r
- // last check... too confusing.\r
- Result<NsDAO.Data> rv = mayUserVirtueOfNS(trans, user, ndd, ":" + pdd.ns + ":ns", access.name());\r
- if (rv.isOK()) {\r
- return rv;\r
- } else {\r
- return Result.err(Status.ERR_Denied,\r
- "[%s] may not %s Perm [%s|%s|%s]", user, access.name(),\r
- pdd.fullType(), pdd.instance, pdd.action);\r
- }\r
-\r
- }\r
-\r
- public Result<Void> mayUser(AuthzTrans trans, DelegateDAO.Data dd, Access access) {\r
- try {\r
- boolean isUser = trans.user().equals(dd.user);\r
- boolean isDelegate = dd.delegate != null\r
- && (dd.user.equals(dd.delegate) || trans.user().equals(\r
- dd.delegate));\r
- Organization org = trans.org();\r
- switch (access) {\r
- case create:\r
- if (org.getIdentity(trans, dd.user) == null) {\r
- return Result.err(Status.ERR_UserNotFound,\r
- "[%s] is not a user in the company database.",\r
- dd.user);\r
- }\r
- if (!dd.user.equals(dd.delegate) && org.getIdentity(trans, dd.delegate) == null) {\r
- return Result.err(Status.ERR_UserNotFound,\r
- "[%s] is not a user in the company database.",\r
- dd.delegate);\r
- }\r
- if (!trans.forceRequested() && dd.user != null && dd.user.equals(dd.delegate)) {\r
- return Result.err(Status.ERR_BadData,\r
- "[%s] cannot be a delegate for self", dd.user);\r
- }\r
- if (!isUser && !isGranted(trans, trans.user(), Define.ROOT_NS,DELG,\r
- org.getDomain(), Question.CREATE)) {\r
- return Result.err(Status.ERR_Denied,\r
- "[%s] may not create a delegate for [%s]",\r
- trans.user(), dd.user);\r
- }\r
- break;\r
- case read:\r
- case write:\r
- if (!isUser && !isDelegate && \r
- !isGranted(trans, trans.user(), Define.ROOT_NS,DELG,org.getDomain(), access.name())) {\r
- return Result.err(Status.ERR_Denied,\r
- "[%s] may not %s delegates for [%s]", trans.user(),\r
- access.name(), dd.user);\r
- }\r
- break;\r
- default:\r
- return Result.err(Status.ERR_BadData,"Unknown Access type [%s]", access.name());\r
- }\r
- } catch (Exception e) {\r
- return Result.err(e);\r
- }\r
- return Result.ok();\r
- }\r
-\r
- /*\r
- * Check (recursively, if necessary), if able to do something based on NS\r
- */\r
- private Result<NsDAO.Data> mayUserVirtueOfNS(AuthzTrans trans, String user, NsDAO.Data nsd, String ns_and_type, String access) {\r
- String ns = nsd.name;\r
-\r
- // If an ADMIN of the Namespace, then allow\r
- \r
- Result<List<UserRoleDAO.Data>> rurd;\r
- if ((rurd = userRoleDAO.readUserInRole(trans, user, nsd.name+ADMIN)).isOKhasData()) {\r
- return Result.ok(nsd);\r
- } else if(rurd.status==Result.ERR_Backend) {\r
- return Result.err(rurd);\r
- }\r
- \r
- // If Specially granted Global Permission\r
- if (isGranted(trans, user, Define.ROOT_NS,NS, ns_and_type, access)) {\r
- return Result.ok(nsd);\r
- }\r
-\r
- // Check recur\r
-\r
- int dot = ns.length();\r
- if ((dot = ns.lastIndexOf('.', dot - 1)) >= 0) {\r
- Result<NsDAO.Data> rnsd = deriveNs(trans, ns.substring(0, dot));\r
- if (rnsd.isOK()) {\r
- rnsd = mayUserVirtueOfNS(trans, user, rnsd.value, ns_and_type,access);\r
- } else if(rnsd.status==Result.ERR_Backend) {\r
- return Result.err(rnsd);\r
- }\r
- if (rnsd.isOK()) {\r
- return Result.ok(nsd);\r
- } else if(rnsd.status==Result.ERR_Backend) {\r
- return Result.err(rnsd);\r
- }\r
- }\r
- return Result.err(Status.ERR_Denied, "%s may not %s %s", user, access,\r
- ns_and_type);\r
- }\r
-\r
- \r
- /**\r
- * isGranted\r
- * \r
- * Important function - Check internal Permission Schemes for Permission to\r
- * do things\r
- * \r
- * @param trans\r
- * @param type\r
- * @param instance\r
- * @param action\r
- * @return\r
- */\r
- public boolean isGranted(AuthzTrans trans, String user, String ns, String type,String instance, String action) {\r
- Result<List<PermDAO.Data>> perms = getPermsByUser(trans, user, false);\r
- if (perms.isOK()) {\r
- for (PermDAO.Data pd : perms.value) {\r
- if (ns.equals(pd.ns)) {\r
- if (type.equals(pd.type)) {\r
- if (PermEval.evalInstance(pd.instance, instance)) {\r
- if(PermEval.evalAction(pd.action, action)) { // don't return action here, might miss other action \r
- return true;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- public Result<Date> doesUserCredMatch(AuthzTrans trans, String user, byte[] cred) throws DAOException {\r
- Result<List<CredDAO.Data>> result;\r
- TimeTaken tt = trans.start("Read DB Cred", Env.REMOTE);\r
- try {\r
- result = credDAO.readID(trans, user);\r
- } finally {\r
- tt.done();\r
- }\r
-\r
- Result<Date> rv = null;\r
- if(result.isOK()) {\r
- if (result.isEmpty()) {\r
- rv = Result.err(Status.ERR_UserNotFound, user);\r
- if (willSpecialLog(trans,user)) {\r
- trans.audit().log("Special DEBUG:", user, " does not exist in DB");\r
- }\r
- } else {\r
- Date now = new Date();//long now = System.currentTimeMillis();\r
- ByteBuffer md5=null;\r
- \r
- // Bug noticed 6/22. Sorting on the result can cause Concurrency Issues. \r
- List<CredDAO.Data> cddl;\r
- if(result.value.size() > 1) {\r
- cddl = new ArrayList<CredDAO.Data>(result.value.size());\r
- for(CredDAO.Data old : result.value) {\r
- if(old.type==CredDAO.BASIC_AUTH || old.type==CredDAO.BASIC_AUTH_SHA256) {\r
- cddl.add(old);\r
- }\r
- }\r
- if(cddl.size()>1) {\r
- Collections.sort(cddl,new Comparator<CredDAO.Data>() {\r
- @Override\r
- public int compare(org.onap.aaf.dao.aaf.cass.CredDAO.Data a,\r
- org.onap.aaf.dao.aaf.cass.CredDAO.Data b) {\r
- return b.expires.compareTo(a.expires);\r
- }\r
- });\r
- }\r
- } else {\r
- cddl = result.value;\r
- }\r
- \r
- for (CredDAO.Data cdd : cddl) {\r
- if (cdd.expires.after(now)) {\r
- try {\r
- switch(cdd.type) {\r
- case CredDAO.BASIC_AUTH:\r
- if(md5==null) {\r
- md5=ByteBuffer.wrap(Hash.encryptMD5(cred));\r
- }\r
- if(md5.compareTo(cdd.cred)==0) {\r
- return Result.ok(cdd.expires);\r
- } else if (willSpecialLog(trans,user)) {\r
- trans.audit().log("Special DEBUG:", user, "Client sent: ", trans.encryptor().encrypt(new String(cred)) ,cdd.expires);\r
- }\r
- break;\r
- case CredDAO.BASIC_AUTH_SHA256:\r
- ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + cred.length);\r
- bb.putInt(cdd.other);\r
- bb.put(cred);\r
- byte[] hash = Hash.hashSHA256(bb.array());\r
- \r
- ByteBuffer sha256 = ByteBuffer.wrap(hash);\r
- if(sha256.compareTo(cdd.cred)==0) {\r
- return Result.ok(cdd.expires);\r
- } else if (willSpecialLog(trans,user)) {\r
- trans.audit().log("Special DEBUG:", user, "Client sent: ", trans.encryptor().encrypt(new String(cred)) ,cdd.expires);\r
- }\r
- break;\r
- default:\r
- trans.error().log("Unknown Credential Type %s for %s, %s",Integer.toString(cdd.type),cdd.id, Chrono.dateTime(cdd.expires));\r
- }\r
- } catch (NoSuchAlgorithmException e) {\r
- trans.error().log(e);\r
- }\r
- } else {\r
- rv = Result.err(Status.ERR_Security,\r
- "Credentials expired " + cdd.expires.toString());\r
- }\r
- } // end for each\r
- }\r
- } else {\r
- return Result.err(result);\r
- }\r
- return rv == null ? Result.create((Date) null, Status.ERR_Security,\r
- "Wrong credential") : rv;\r
- }\r
-\r
-\r
- public Result<CredDAO.Data> userCredSetup(AuthzTrans trans, CredDAO.Data cred) {\r
- if(cred.type==CredDAO.RAW) {\r
- TimeTaken tt = trans.start("Hash Cred", Env.SUB);\r
- try {\r
- cred.type = CredDAO.BASIC_AUTH_SHA256;\r
- cred.other = random.nextInt();\r
- ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + cred.cred.capacity());\r
- bb.putInt(cred.other);\r
- bb.put(cred.cred);\r
- byte[] hash = Hash.hashSHA256(bb.array());\r
- cred.cred = ByteBuffer.wrap(hash);\r
- return Result.ok(cred);\r
- } catch (NoSuchAlgorithmException e) {\r
- return Result.err(Status.ERR_General,e.getLocalizedMessage());\r
- } finally {\r
- tt.done();\r
- }\r
- \r
- }\r
- return Result.err(Status.ERR_Security,"invalid/unreadable credential");\r
- }\r
-\r
-\r
- public static final String APPROVED = "APPROVE";\r
- public static final String REJECT = "REJECT";\r
- public static final String PENDING = "PENDING";\r
-\r
- public Result<Void> canAddUser(AuthzTrans trans, UserRoleDAO.Data data,\r
- List<ApprovalDAO.Data> approvals) {\r
- // get the approval policy for the organization\r
-\r
- // get the list of approvals with an accept status\r
-\r
- // validate the approvals against the policy\r
-\r
- // for now check if all approvals are received and return\r
- // SUCCESS/FAILURE/SKIP\r
- boolean bReject = false;\r
- boolean bPending = false;\r
-\r
- for (ApprovalDAO.Data approval : approvals) {\r
- if (approval.status.equals(REJECT)) {\r
- bReject = true;\r
- } else if (approval.status.equals(PENDING)) {\r
- bPending = true;\r
- }\r
- }\r
- if (bReject) {\r
- return Result.err(Status.ERR_Policy,\r
- "Approval Polocy not conformed");\r
- }\r
- if (bPending) {\r
- return Result.err(Status.ERR_ActionNotCompleted,\r
- "Required Approvals not received");\r
- }\r
-\r
- return Result.ok();\r
- }\r
-\r
- private static final String NO_CACHE_NAME = "No Cache Data named %s";\r
-\r
- public Result<Void> clearCache(AuthzTrans trans, String cname) {\r
- boolean all = "all".equals(cname);\r
- Result<Void> rv = null;\r
-\r
- if (all || NsDAO.TABLE.equals(cname)) {\r
- int seg[] = series(NsDAO.CACHE_SEG);\r
- for(int i: seg) {cacheClear(trans, NsDAO.TABLE,i);}\r
- rv = cacheInfoDAO.touch(trans, NsDAO.TABLE, seg);\r
- }\r
- if (all || PermDAO.TABLE.equals(cname)) {\r
- int seg[] = series(NsDAO.CACHE_SEG);\r
- for(int i: seg) {cacheClear(trans, PermDAO.TABLE,i);}\r
- rv = cacheInfoDAO.touch(trans, PermDAO.TABLE,seg);\r
- }\r
- if (all || RoleDAO.TABLE.equals(cname)) {\r
- int seg[] = series(NsDAO.CACHE_SEG);\r
- for(int i: seg) {cacheClear(trans, RoleDAO.TABLE,i);}\r
- rv = cacheInfoDAO.touch(trans, RoleDAO.TABLE,seg);\r
- }\r
- if (all || UserRoleDAO.TABLE.equals(cname)) {\r
- int seg[] = series(NsDAO.CACHE_SEG);\r
- for(int i: seg) {cacheClear(trans, UserRoleDAO.TABLE,i);}\r
- rv = cacheInfoDAO.touch(trans, UserRoleDAO.TABLE,seg);\r
- }\r
- if (all || CredDAO.TABLE.equals(cname)) {\r
- int seg[] = series(NsDAO.CACHE_SEG);\r
- for(int i: seg) {cacheClear(trans, CredDAO.TABLE,i);}\r
- rv = cacheInfoDAO.touch(trans, CredDAO.TABLE,seg);\r
- }\r
- if (all || CertDAO.TABLE.equals(cname)) {\r
- int seg[] = series(NsDAO.CACHE_SEG);\r
- for(int i: seg) {cacheClear(trans, CertDAO.TABLE,i);}\r
- rv = cacheInfoDAO.touch(trans, CertDAO.TABLE,seg);\r
- }\r
-\r
- if (rv == null) {\r
- rv = Result.err(Status.ERR_BadData, NO_CACHE_NAME, cname);\r
- }\r
- return rv;\r
- }\r
-\r
- public Result<Void> cacheClear(AuthzTrans trans, String cname,Integer segment) {\r
- Result<Void> rv;\r
- if (NsDAO.TABLE.equals(cname)) {\r
- rv = nsDAO.invalidate(segment);\r
- } else if (PermDAO.TABLE.equals(cname)) {\r
- rv = permDAO.invalidate(segment);\r
- } else if (RoleDAO.TABLE.equals(cname)) {\r
- rv = roleDAO.invalidate(segment);\r
- } else if (UserRoleDAO.TABLE.equals(cname)) {\r
- rv = userRoleDAO.invalidate(segment);\r
- } else if (CredDAO.TABLE.equals(cname)) {\r
- rv = credDAO.invalidate(segment);\r
- } else if (CertDAO.TABLE.equals(cname)) {\r
- rv = certDAO.invalidate(segment);\r
- } else {\r
- rv = Result.err(Status.ERR_BadData, NO_CACHE_NAME, cname);\r
- }\r
- return rv;\r
- }\r
-\r
- private int[] series(int max) {\r
- int[] series = new int[max];\r
- for (int i = 0; i < max; ++i)\r
- series[i] = i;\r
- return series;\r
- }\r
-\r
- public boolean isDelegated(AuthzTrans trans, String user, String approver) {\r
- Result<List<DelegateDAO.Data>> userDelegatedFor = delegateDAO\r
- .readByDelegate(trans, user);\r
- for (DelegateDAO.Data curr : userDelegatedFor.value) {\r
- if (curr.user.equals(approver) && curr.delegate.equals(user)\r
- && curr.expires.after(new Date())) {\r
- return true;\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- public static boolean willSpecialLog(AuthzTrans trans, String user) {\r
- Boolean b = trans.get(specialLogSlot, null);\r
- if(b==null) {\r
- if(specialLog==null) {\r
- return false;\r
- } else {\r
- b = specialLog.contains(user);\r
- trans.put(specialLogSlot, b);\r
- }\r
- }\r
- return b;\r
- }\r
- \r
- public static void logEncryptTrace(AuthzTrans trans, String data) {\r
- long ti;\r
- trans.put(transIDSlot, ti=nextTraceID());\r
- trans.trace().log("id="+Long.toHexString(ti)+",data=\""+trans.env().encryptor().encrypt(data)+'"');\r
- }\r
-\r
- private synchronized static long nextTraceID() {\r
- return ++traceID;\r
- }\r
-\r
- public static synchronized boolean specialLogOn(AuthzTrans trans, String id) {\r
- if (specialLog == null) {\r
- specialLog = new HashSet<String>();\r
- }\r
- boolean rc = specialLog.add(id);\r
- if(rc) {\r
- trans.trace().log("Trace on for",id); \r
- }\r
- return rc;\r
- }\r
-\r
- public static synchronized boolean specialLogOff(AuthzTrans trans, String id) {\r
- if(specialLog==null) {\r
- return false;\r
- }\r
- boolean rv = specialLog.remove(id);\r
- if (specialLog.isEmpty()) {\r
- specialLog = null;\r
- }\r
- if(rv) {\r
- trans.trace().log("Trace off for",id);\r
- }\r
- return rv;\r
- }\r
-\r
- /** \r
- * canMove\r
- * Which Types can be moved\r
- * @param nsType\r
- * @return\r
- */\r
- public boolean canMove(NsType nsType) {\r
- boolean rv;\r
- switch(nsType) {\r
- case DOT:\r
- case ROOT:\r
- case COMPANY:\r
- case UNKNOWN:\r
- rv = false;\r
- break;\r
- default:\r
- rv = true;\r
- }\r
- return rv;\r
- }\r
-\r
- public Result<String> isOwnerSponsor(AuthzTrans trans, String user, String ns, Identity mechID) {\r
- \r
- Identity caller;\r
- Organization org = trans.org();\r
- try {\r
- caller = org.getIdentity(trans, user);\r
- if(caller==null || !caller.isFound()) {\r
- return Result.err(Status.ERR_NotFound,"%s is not a registered %s entity",user,org.getName());\r
- }\r
- } catch (Exception e) {\r
- return Result.err(e);\r
- }\r
- String sponsor = mechID.responsibleTo();\r
- Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_OWNER);\r
- boolean isOwner = false;\r
- if(rur.isOKhasData()) {for(UserRoleDAO.Data urdd : rur.value){\r
- if(urdd.expires.after(new Date())) {\r
- isOwner = true;\r
- }\r
- }};\r
- if(!isOwner) {\r
- return Result.err(Status.ERR_Policy,"%s is not a current owner of %s",user,ns);\r
- }\r
- \r
- if(!caller.id().equals(sponsor)) {\r
- return Result.err(Status.ERR_Denied,"%s is not the sponsor of %s",user,mechID.id());\r
- }\r
- return Result.ok(sponsor);\r
- }\r
- \r
- public boolean isAdmin(AuthzTrans trans, String user, String ns) {\r
- Date now = new Date();\r
- Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+ADMIN);\r
- if(rur.isOKhasData()) {for(UserRoleDAO.Data urdd : rur.value){\r
- if(urdd.expires.after(now)) {\r
- return true;\r
- }\r
- }};\r
- return false;\r
- }\r
- \r
- public boolean isOwner(AuthzTrans trans, String user, String ns) {\r
- Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_OWNER);\r
- Date now = new Date();\r
- if(rur.isOKhasData()) {for(UserRoleDAO.Data urdd : rur.value){\r
- if(urdd.expires.after(now)) {\r
- return true;\r
- }\r
- }};\r
- return false;\r
- }\r
-\r
- public int countOwner(AuthzTrans trans, String user, String ns) {\r
- Result<List<UserRoleDAO.Data>> rur = userRoleDAO.read(trans, user,ns+DOT_OWNER);\r
- Date now = new Date();\r
- int count = 0;\r
- if(rur.isOKhasData()) {for(UserRoleDAO.Data urdd : rur.value){\r
- if(urdd.expires.after(now)) {\r
- ++count;\r
- }\r
- }};\r
- return count;\r
- }\r
-\r
-}\r