[AAF-21] Initial code import
[aaf/authz.git] / authz-service / src / main / java / com / att / authz / service / validation / Validator.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aai\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * Copyright © 2017 Amdocs\r
7  * * ===========================================================================\r
8  * * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * * you may not use this file except in compliance with the License.\r
10  * * You may obtain a copy of the License at\r
11  * * \r
12  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
13  * * \r
14  *  * Unless required by applicable law or agreed to in writing, software\r
15  * * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * * See the License for the specific language governing permissions and\r
18  * * limitations under the License.\r
19  * * ============LICENSE_END====================================================\r
20  * *\r
21  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
22  * *\r
23  ******************************************************************************/\r
24 package com.att.authz.service.validation;\r
25 \r
26 import java.util.regex.Pattern;\r
27 \r
28 import com.att.authz.cadi.DirectAAFLur.PermPermission;\r
29 import com.att.authz.env.AuthzTrans;\r
30 import com.att.authz.layer.Result;\r
31 import com.att.authz.org.Organization;\r
32 import com.att.dao.aaf.cass.CredDAO;\r
33 import com.att.dao.aaf.cass.DelegateDAO;\r
34 import com.att.dao.aaf.cass.Namespace;\r
35 import com.att.dao.aaf.cass.PermDAO;\r
36 import com.att.dao.aaf.cass.RoleDAO;\r
37 import com.att.dao.aaf.cass.UserRoleDAO;\r
38 \r
39 /**\r
40  * Validator\r
41  * Consistently apply content rules for content (incoming)\r
42  * \r
43  * Note: We restrict content for usability in URLs (because RESTful service), and avoid \r
44  * issues with Regular Expressions, and other enabling technologies. \r
45  *\r
46  */\r
47 public class Validator {\r
48         // % () ,-. 0-9 =A-Z _a-z\r
49         private static final String ESSENTIAL="\\x25\\x28\\x29\\x2C-\\x2E\\x30-\\x39\\x3D\\x40-\\x5A\\x5F\\x61-\\x7A";\r
50         private static final Pattern ESSENTIAL_CHARS=Pattern.compile("["+ESSENTIAL+"]+");\r
51         \r
52         // Must be 1 or more of Alphanumeric or the following  :._-\r
53         // '*' only allowed when it is the only character, or the only element in a key separator\r
54         //  :* :hello:* :hello:*:there  etc\r
55         public static final Pattern ACTION_CHARS=Pattern.compile(\r
56                         "["+ESSENTIAL+"]+" +    // All AlphaNumeric+\r
57                         "|\\*"                                          // Just Star\r
58                         );\r
59 \r
60         public static final Pattern INST_CHARS=Pattern.compile(\r
61                         "["+ESSENTIAL+"]+[\\*]*" +                              // All AlphaNumeric+ possibly ending with *\r
62                         "|\\*" +                                                                // Just Star\r
63                         "|(([:/]\\*)|([:/][!]{0,1}["+ESSENTIAL+"]+[\\*]*[:/]*))+"       // Key :asdf:*:sdf*:sdk\r
64                         );\r
65         \r
66         // Must be 1 or more of Alphanumeric or the following  ._-, and be in the form id@domain\r
67         public static final Pattern ID_CHARS=Pattern.compile("[\\w.-]+@[\\w.-]+");\r
68         // Must be 1 or more of Alphanumeric or the following  ._-\r
69         public static final Pattern NAME_CHARS=Pattern.compile("[\\w.-]+");\r
70         \r
71         private final Pattern actionChars;\r
72         private final Pattern instChars;\r
73         private StringBuilder msgs;\r
74 \r
75         /**\r
76          * Default Validator does not check for non-standard Action/Inst chars\r
77          * \r
78          * \r
79          * IMPORTANT: Use ONLY when the Validator is doing something simple... NullOrBlank\r
80          */\r
81         public Validator() {\r
82                 actionChars = ACTION_CHARS;\r
83                 instChars = INST_CHARS;\r
84         }\r
85         \r
86         /**\r
87          * When Trans is passed in, check for non-standard Action/Inst chars\r
88          * \r
89          * This is an opportunity to change characters, if required.\r
90          * \r
91          * Use for any Object method passed (i.e. role(RoleDAO.Data d) ), to ensure fewer bugs.\r
92          * \r
93          * @param trans\r
94          */\r
95         public Validator(AuthzTrans trans) {\r
96                 actionChars = ACTION_CHARS;\r
97                 instChars = INST_CHARS;\r
98         }\r
99 \r
100 \r
101         public Validator perm(Result<PermDAO.Data> rpd) {\r
102                 if(rpd.notOK()) {\r
103                         msg(rpd.details);\r
104                 } else {\r
105                         perm(rpd.value);\r
106                 }\r
107                 return this;\r
108         }\r
109 \r
110 \r
111         public Validator perm(PermDAO.Data pd) {\r
112                 if(pd==null) {\r
113                         msg("Perm Data is null.");\r
114                 } else {\r
115                         ns(pd.ns);\r
116                         permType(pd.type,pd.ns);\r
117                         permInstance(pd.instance);\r
118                         permAction(pd.action);\r
119                         if(pd.roles!=null) { \r
120                                 for(String role : pd.roles) {\r
121                                         role(role);\r
122                                 }\r
123                         }\r
124                 }\r
125                 return this;\r
126         }\r
127 \r
128         public Validator role(Result<RoleDAO.Data> rrd) {\r
129                 if(rrd.notOK()) {\r
130                         msg(rrd.details);\r
131                 } else {\r
132                         role(rrd.value);\r
133                 }\r
134                 return this;\r
135         }\r
136 \r
137         public Validator role(RoleDAO.Data pd) {\r
138                 if(pd==null) {\r
139                         msg("Role Data is null.");\r
140                 } else {\r
141                         ns(pd.ns);\r
142                         role(pd.name);\r
143                         if(pd.perms!=null) {\r
144                                 for(String perm : pd.perms) {\r
145                                         String[] ps = perm.split("\\|");\r
146                                         if(ps.length!=3) {\r
147                                                 msg("Perm [" + perm + "] in Role [" + pd.fullName() + "] is not correctly separated with '|'");\r
148                                         } else {\r
149                                                 permType(ps[0],null);\r
150                                                 permInstance(ps[1]);\r
151                                                 permAction(ps[2]);\r
152                                         }\r
153                                 }\r
154                         }\r
155                 }\r
156                 return this;\r
157         }\r
158 \r
159         public Validator delegate(Organization org, Result<DelegateDAO.Data> rdd) {\r
160                 if(rdd.notOK()) {\r
161                         msg(rdd.details);\r
162                 } else {\r
163                         delegate(org, rdd.value);\r
164                 }\r
165                 return this;\r
166         }\r
167 \r
168         public Validator delegate(Organization org, DelegateDAO.Data dd) {\r
169                 if(dd==null) {\r
170                         msg("Delegate Data is null.");\r
171                 } else {\r
172                         user(org,dd.user);\r
173                         user(org,dd.delegate);\r
174                 }\r
175                 return this;\r
176         }\r
177 \r
178 \r
179         public Validator cred(Organization org, Result<CredDAO.Data> rcd, boolean isNew) {\r
180                 if(rcd.notOK()) {\r
181                         msg(rcd.details);\r
182                 } else {\r
183                         cred(org,rcd.value,isNew);\r
184                 }\r
185                 return this;\r
186         }\r
187 \r
188         public Validator cred(Organization org, CredDAO.Data cd, boolean isNew) {\r
189                 if(cd==null) {\r
190                         msg("Cred Data is null.");\r
191                 } else {\r
192                         if(nob(cd.id,ID_CHARS)) {\r
193                                 msg("ID [" + cd.id + "] is invalid");\r
194                         }\r
195                         if(!org.isValidCred(cd.id)) {\r
196                                 msg("ID [" + cd.id + "] is invalid for a cred");\r
197                         }\r
198                         String str = cd.id;\r
199                         int idx = str.indexOf('@');\r
200                         if(idx>0) {\r
201                                 str = str.substring(0,idx);\r
202                         }\r
203                         \r
204                         if(cd.id.endsWith(org.getRealm())) {\r
205                                 if(isNew && (str=org.isValidID(str)).length()>0) {\r
206                                         msg(cd.id,str);\r
207                                 }\r
208                         }\r
209         \r
210                         if(cd.type==null) {\r
211                                 msg("Credential Type must be set");\r
212                         } else {\r
213                                 switch(cd.type) {\r
214                                         case CredDAO.BASIC_AUTH_SHA256:\r
215                                                 // ok\r
216                                                 break;\r
217                                         default:\r
218                                                 msg("Credential Type [",Integer.toString(cd.type),"] is invalid");\r
219                                 }\r
220                         }\r
221                 }\r
222                 return this;\r
223         }\r
224 \r
225 \r
226         public Validator user(Organization org, String user) {\r
227                 if(nob(user,ID_CHARS)) {\r
228                         msg("User [",user,"] is invalid.");\r
229                 }\r
230                 //TODO Change when Multi-Org solution is created\r
231 //              if(org instanceof ATT) {\r
232 //                      if(!user.endsWith("@csp.att.com") &&\r
233 //                         !org.isValidCred(user)) \r
234 //                                      msg("User [",user,"] is not valid ID for Credential in ",org.getRealm());\r
235 //              }\r
236                 return this;\r
237         }\r
238 \r
239         public Validator ns(Result<Namespace> nsd) {\r
240                 notOK(nsd);\r
241                 ns(nsd.value.name);\r
242                 for(String s : nsd.value.admin) {\r
243                         if(nob(s,ID_CHARS)) {\r
244                                 msg("Admin [" + s + "] is invalid.");           \r
245                         }\r
246                         \r
247                 }\r
248                 for(String s : nsd.value.owner) {\r
249                         if(nob(s,ID_CHARS)) {\r
250                                 msg("Responsible [" + s + "] is invalid.");             \r
251                         }\r
252                         \r
253                 }\r
254                 return this;\r
255         }\r
256 \r
257 \r
258         public Validator ns(String ns) {\r
259                 if(nob(ns,NAME_CHARS)){\r
260                         msg("NS [" + ns + "] is invalid.");\r
261                 }\r
262                 return this;\r
263         }\r
264 \r
265         public String errs() {\r
266                 return msgs.toString();\r
267         }\r
268 \r
269 \r
270         public Validator permType(String type, String ns) {\r
271                 // TODO check for correct Splits?  Type|Instance|Action ?\r
272                 if(nob(type,NAME_CHARS)) {\r
273                         msg("Perm Type [" + (ns==null?"":ns+(type.length()==0?"":'.'))+type + "] is invalid.");\r
274                 }\r
275                 return this;\r
276         }\r
277 \r
278         public Validator permInstance(String instance) {\r
279                 // TODO check for correct Splits?  Type|Instance|Action ?\r
280                 if(nob(instance,instChars)) {\r
281                         msg("Perm Instance [" + instance + "] is invalid.");\r
282                 }\r
283                 return this;\r
284         }\r
285 \r
286         public Validator permAction(String action) {\r
287                 // TODO check for correct Splits?  Type|Instance|Action ?\r
288                 if(nob(action, actionChars)) {\r
289                         msg("Perm Action [" + action + "] is invalid.");\r
290                 }\r
291                 return this;\r
292         }\r
293 \r
294         public Validator role(String role) {\r
295                 if(nob(role, NAME_CHARS)) {\r
296                         msg("Role [" + role + "] is invalid.");\r
297                 }\r
298                 return this;\r
299         }\r
300 \r
301         public Validator user_role(UserRoleDAO.Data urdd) {\r
302                 if(urdd==null) {\r
303                         msg("UserRole is null");\r
304                 } else {\r
305                         role(urdd.role);\r
306                         nullOrBlank("UserRole.ns",urdd.ns);\r
307                         nullOrBlank("UserRole.rname",urdd.rname);\r
308                 }\r
309                 return this;\r
310         }\r
311 \r
312         public Validator nullOrBlank(String name, String str) {\r
313                 if(str==null) {\r
314                         msg(name + " is null.");\r
315                 } else if(str.length()==0) {\r
316                         msg(name + " is blank.");\r
317                 }\r
318                 return this;\r
319         }\r
320         \r
321         public Validator nullOrBlank(PermDAO.Data pd) {\r
322                 if(pd==null) {\r
323                         msg("Permission is null");\r
324                 } else {\r
325                         nullOrBlank("NS",pd.ns).\r
326                         nullOrBlank("Type",pd.type).\r
327                         nullOrBlank("Instance",pd.instance).\r
328                         nullOrBlank("Action",pd.action);\r
329                 }\r
330                 return this;\r
331         }\r
332 \r
333         public Validator nullOrBlank(RoleDAO.Data rd) {\r
334                 if(rd==null) {\r
335                         msg("Role is null");\r
336                 } else {\r
337                         nullOrBlank("NS",rd.ns).\r
338                         nullOrBlank("Name",rd.name);\r
339                 }\r
340                 return this;\r
341         }\r
342 \r
343         // nob = Null Or Not match Pattern\r
344         private boolean nob(String str, Pattern p) {\r
345                 return str==null || !p.matcher(str).matches(); \r
346         }\r
347 \r
348         private void msg(String ... strs) {\r
349                 if(msgs==null) {\r
350                         msgs=new StringBuilder();\r
351                 }\r
352                 for(String str : strs) {\r
353                         msgs.append(str);\r
354                 }\r
355                 msgs.append('\n');\r
356         }\r
357         \r
358         public boolean err() {\r
359                 return msgs!=null;\r
360         }\r
361 \r
362 \r
363         public Validator notOK(Result<?> res) {\r
364                 if(res==null) {\r
365                         msgs.append("Result object is blank");\r
366                 } else if(res.notOK()) {\r
367                         msgs.append(res.getClass().getSimpleName() + " is not OK");\r
368                 }\r
369                 return this;\r
370         }\r
371 \r
372         public Validator key(String key) {\r
373                 if(nob(key,NAME_CHARS)) {\r
374                         msg("NS Prop Key [" + key + "] is invalid");\r
375                 }\r
376                 return this;\r
377         }\r
378         \r
379         public Validator value(String value) {\r
380                 if(nob(value,ESSENTIAL_CHARS)) {\r
381                         msg("NS Prop value [" + value + "] is invalid");\r
382                 }\r
383                 return this;\r
384         }\r
385 \r
386 \r
387 }\r