--- /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.authz.service.validation;\r
+\r
+import java.util.regex.Pattern;\r
+\r
+import org.onap.aaf.authz.cadi.DirectAAFLur.PermPermission;\r
+import org.onap.aaf.authz.env.AuthzTrans;\r
+import org.onap.aaf.authz.layer.Result;\r
+import org.onap.aaf.authz.org.Organization;\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.Namespace;\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.UserRoleDAO;\r
+\r
+/**\r
+ * Validator\r
+ * Consistently apply content rules for content (incoming)\r
+ * \r
+ * Note: We restrict content for usability in URLs (because RESTful service), and avoid \r
+ * issues with Regular Expressions, and other enabling technologies. \r
+ *\r
+ */\r
+public class Validator {\r
+ // % () ,-. 0-9 =A-Z _a-z\r
+ private static final String ESSENTIAL="\\x25\\x28\\x29\\x2C-\\x2E\\x30-\\x39\\x3D\\x40-\\x5A\\x5F\\x61-\\x7A";\r
+ private static final Pattern ESSENTIAL_CHARS=Pattern.compile("["+ESSENTIAL+"]+");\r
+ \r
+ // Must be 1 or more of Alphanumeric or the following :._-\r
+ // '*' only allowed when it is the only character, or the only element in a key separator\r
+ // :* :hello:* :hello:*:there etc\r
+ public static final Pattern ACTION_CHARS=Pattern.compile(\r
+ "["+ESSENTIAL+"]+" + // All AlphaNumeric+\r
+ "|\\*" // Just Star\r
+ );\r
+\r
+ public static final Pattern INST_CHARS=Pattern.compile(\r
+ "["+ESSENTIAL+"]+[\\*]*" + // All AlphaNumeric+ possibly ending with *\r
+ "|\\*" + // Just Star\r
+ "|(([:/]\\*)|([:/][!]{0,1}["+ESSENTIAL+"]+[\\*]*[:/]*))+" // Key :asdf:*:sdf*:sdk\r
+ );\r
+ \r
+ // Must be 1 or more of Alphanumeric or the following ._-, and be in the form id@domain\r
+ public static final Pattern ID_CHARS=Pattern.compile("[\\w.-]+@[\\w.-]+");\r
+ // Must be 1 or more of Alphanumeric or the following ._-\r
+ public static final Pattern NAME_CHARS=Pattern.compile("[\\w.-]+");\r
+ \r
+ private final Pattern actionChars;\r
+ private final Pattern instChars;\r
+ private StringBuilder msgs;\r
+\r
+ /**\r
+ * Default Validator does not check for non-standard Action/Inst chars\r
+ * \r
+ * \r
+ * IMPORTANT: Use ONLY when the Validator is doing something simple... NullOrBlank\r
+ */\r
+ public Validator() {\r
+ actionChars = ACTION_CHARS;\r
+ instChars = INST_CHARS;\r
+ }\r
+ \r
+ /**\r
+ * When Trans is passed in, check for non-standard Action/Inst chars\r
+ * \r
+ * This is an opportunity to change characters, if required.\r
+ * \r
+ * Use for any Object method passed (i.e. role(RoleDAO.Data d) ), to ensure fewer bugs.\r
+ * \r
+ * @param trans\r
+ */\r
+ public Validator(AuthzTrans trans) {\r
+ actionChars = ACTION_CHARS;\r
+ instChars = INST_CHARS;\r
+ }\r
+\r
+\r
+ public Validator perm(Result<PermDAO.Data> rpd) {\r
+ if(rpd.notOK()) {\r
+ msg(rpd.details);\r
+ } else {\r
+ perm(rpd.value);\r
+ }\r
+ return this;\r
+ }\r
+\r
+\r
+ public Validator perm(PermDAO.Data pd) {\r
+ if(pd==null) {\r
+ msg("Perm Data is null.");\r
+ } else {\r
+ ns(pd.ns);\r
+ permType(pd.type,pd.ns);\r
+ permInstance(pd.instance);\r
+ permAction(pd.action);\r
+ if(pd.roles!=null) { \r
+ for(String role : pd.roles) {\r
+ role(role);\r
+ }\r
+ }\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator role(Result<RoleDAO.Data> rrd) {\r
+ if(rrd.notOK()) {\r
+ msg(rrd.details);\r
+ } else {\r
+ role(rrd.value);\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator role(RoleDAO.Data pd) {\r
+ if(pd==null) {\r
+ msg("Role Data is null.");\r
+ } else {\r
+ ns(pd.ns);\r
+ role(pd.name);\r
+ if(pd.perms!=null) {\r
+ for(String perm : pd.perms) {\r
+ String[] ps = perm.split("\\|");\r
+ if(ps.length!=3) {\r
+ msg("Perm [" + perm + "] in Role [" + pd.fullName() + "] is not correctly separated with '|'");\r
+ } else {\r
+ permType(ps[0],null);\r
+ permInstance(ps[1]);\r
+ permAction(ps[2]);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator delegate(Organization org, Result<DelegateDAO.Data> rdd) {\r
+ if(rdd.notOK()) {\r
+ msg(rdd.details);\r
+ } else {\r
+ delegate(org, rdd.value);\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator delegate(Organization org, DelegateDAO.Data dd) {\r
+ if(dd==null) {\r
+ msg("Delegate Data is null.");\r
+ } else {\r
+ user(org,dd.user);\r
+ user(org,dd.delegate);\r
+ }\r
+ return this;\r
+ }\r
+\r
+\r
+ public Validator cred(Organization org, Result<CredDAO.Data> rcd, boolean isNew) {\r
+ if(rcd.notOK()) {\r
+ msg(rcd.details);\r
+ } else {\r
+ cred(org,rcd.value,isNew);\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator cred(Organization org, CredDAO.Data cd, boolean isNew) {\r
+ if(cd==null) {\r
+ msg("Cred Data is null.");\r
+ } else {\r
+ if(nob(cd.id,ID_CHARS)) {\r
+ msg("ID [" + cd.id + "] is invalid");\r
+ }\r
+ if(!org.isValidCred(cd.id)) {\r
+ msg("ID [" + cd.id + "] is invalid for a cred");\r
+ }\r
+ String str = cd.id;\r
+ int idx = str.indexOf('@');\r
+ if(idx>0) {\r
+ str = str.substring(0,idx);\r
+ }\r
+ \r
+ if(cd.id.endsWith(org.getRealm())) {\r
+ if(isNew && (str=org.isValidID(str)).length()>0) {\r
+ msg(cd.id,str);\r
+ }\r
+ }\r
+ \r
+ if(cd.type==null) {\r
+ msg("Credential Type must be set");\r
+ } else {\r
+ switch(cd.type) {\r
+ case CredDAO.BASIC_AUTH_SHA256:\r
+ // ok\r
+ break;\r
+ default:\r
+ msg("Credential Type [",Integer.toString(cd.type),"] is invalid");\r
+ }\r
+ }\r
+ }\r
+ return this;\r
+ }\r
+\r
+\r
+ public Validator user(Organization org, String user) {\r
+ if(nob(user,ID_CHARS)) {\r
+ msg("User [",user,"] is invalid.");\r
+ }\r
+ //TODO Change when Multi-Org solution is created\r
+// if(org instanceof ATT) {\r
+// if(!user.endsWith("@csp.att.com") &&\r
+// !org.isValidCred(user)) \r
+// msg("User [",user,"] is not valid ID for Credential in ",org.getRealm());\r
+// }\r
+ return this;\r
+ }\r
+\r
+ public Validator ns(Result<Namespace> nsd) {\r
+ notOK(nsd);\r
+ ns(nsd.value.name);\r
+ for(String s : nsd.value.admin) {\r
+ if(nob(s,ID_CHARS)) {\r
+ msg("Admin [" + s + "] is invalid."); \r
+ }\r
+ \r
+ }\r
+ for(String s : nsd.value.owner) {\r
+ if(nob(s,ID_CHARS)) {\r
+ msg("Responsible [" + s + "] is invalid."); \r
+ }\r
+ \r
+ }\r
+ return this;\r
+ }\r
+\r
+\r
+ public Validator ns(String ns) {\r
+ if(nob(ns,NAME_CHARS)){\r
+ msg("NS [" + ns + "] is invalid.");\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public String errs() {\r
+ return msgs.toString();\r
+ }\r
+\r
+\r
+ public Validator permType(String type, String ns) {\r
+ // TODO check for correct Splits? Type|Instance|Action ?\r
+ if(nob(type,NAME_CHARS)) {\r
+ msg("Perm Type [" + (ns==null?"":ns+(type.length()==0?"":'.'))+type + "] is invalid.");\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator permInstance(String instance) {\r
+ // TODO check for correct Splits? Type|Instance|Action ?\r
+ if(nob(instance,instChars)) {\r
+ msg("Perm Instance [" + instance + "] is invalid.");\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator permAction(String action) {\r
+ // TODO check for correct Splits? Type|Instance|Action ?\r
+ if(nob(action, actionChars)) {\r
+ msg("Perm Action [" + action + "] is invalid.");\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator role(String role) {\r
+ if(nob(role, NAME_CHARS)) {\r
+ msg("Role [" + role + "] is invalid.");\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator user_role(UserRoleDAO.Data urdd) {\r
+ if(urdd==null) {\r
+ msg("UserRole is null");\r
+ } else {\r
+ role(urdd.role);\r
+ nullOrBlank("UserRole.ns",urdd.ns);\r
+ nullOrBlank("UserRole.rname",urdd.rname);\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator nullOrBlank(String name, String str) {\r
+ if(str==null) {\r
+ msg(name + " is null.");\r
+ } else if(str.length()==0) {\r
+ msg(name + " is blank.");\r
+ }\r
+ return this;\r
+ }\r
+ \r
+ public Validator nullOrBlank(PermDAO.Data pd) {\r
+ if(pd==null) {\r
+ msg("Permission is null");\r
+ } else {\r
+ nullOrBlank("NS",pd.ns).\r
+ nullOrBlank("Type",pd.type).\r
+ nullOrBlank("Instance",pd.instance).\r
+ nullOrBlank("Action",pd.action);\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator nullOrBlank(RoleDAO.Data rd) {\r
+ if(rd==null) {\r
+ msg("Role is null");\r
+ } else {\r
+ nullOrBlank("NS",rd.ns).\r
+ nullOrBlank("Name",rd.name);\r
+ }\r
+ return this;\r
+ }\r
+\r
+ // nob = Null Or Not match Pattern\r
+ private boolean nob(String str, Pattern p) {\r
+ return str==null || !p.matcher(str).matches(); \r
+ }\r
+\r
+ private void msg(String ... strs) {\r
+ if(msgs==null) {\r
+ msgs=new StringBuilder();\r
+ }\r
+ for(String str : strs) {\r
+ msgs.append(str);\r
+ }\r
+ msgs.append('\n');\r
+ }\r
+ \r
+ public boolean err() {\r
+ return msgs!=null;\r
+ }\r
+\r
+\r
+ public Validator notOK(Result<?> res) {\r
+ if(res==null) {\r
+ msgs.append("Result object is blank");\r
+ } else if(res.notOK()) {\r
+ msgs.append(res.getClass().getSimpleName() + " is not OK");\r
+ }\r
+ return this;\r
+ }\r
+\r
+ public Validator key(String key) {\r
+ if(nob(key,NAME_CHARS)) {\r
+ msg("NS Prop Key [" + key + "] is invalid");\r
+ }\r
+ return this;\r
+ }\r
+ \r
+ public Validator value(String value) {\r
+ if(nob(value,ESSENTIAL_CHARS)) {\r
+ msg("NS Prop value [" + value + "] is invalid");\r
+ }\r
+ return this;\r
+ }\r
+\r
+\r
+}\r