a93b7cb458f2be0ea6622a8e6ecf64fc41dd1edb
[aaf/authz.git] / auth / auth-certman / src / main / java / org / onap / aaf / auth / cm / facade / FacadeImpl.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 IBM.
7  * ===========================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END====================================================
20  *
21  */
22
23 package org.onap.aaf.auth.cm.facade;
24
25 import static org.onap.aaf.auth.layer.Result.ERR_ActionNotCompleted;
26 import static org.onap.aaf.auth.layer.Result.ERR_BadData;
27 import static org.onap.aaf.auth.layer.Result.ERR_ConflictAlreadyExists;
28 import static org.onap.aaf.auth.layer.Result.ERR_Denied;
29 import static org.onap.aaf.auth.layer.Result.ERR_NotFound;
30 import static org.onap.aaf.auth.layer.Result.ERR_NotImplemented;
31 import static org.onap.aaf.auth.layer.Result.ERR_Policy;
32 import static org.onap.aaf.auth.layer.Result.ERR_Security;
33 import static org.onap.aaf.auth.layer.Result.OK;
34
35 import java.io.IOException;
36
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
39
40 import org.onap.aaf.auth.cm.AAF_CM;
41 import org.onap.aaf.auth.cm.ca.CA;
42 import org.onap.aaf.auth.cm.data.CertResp;
43 import org.onap.aaf.auth.cm.mapper.Mapper;
44 import org.onap.aaf.auth.cm.mapper.Mapper.API;
45 import org.onap.aaf.auth.cm.service.CMService;
46 import org.onap.aaf.auth.dao.cass.ArtiDAO;
47 import org.onap.aaf.auth.dao.cass.Status;
48 import org.onap.aaf.auth.env.AuthzEnv;
49 import org.onap.aaf.auth.env.AuthzTrans;
50 import org.onap.aaf.auth.layer.Result;
51 import org.onap.aaf.cadi.aaf.AAFPermission;
52 import org.onap.aaf.misc.env.APIException;
53 import org.onap.aaf.misc.env.Data;
54 import org.onap.aaf.misc.env.Env;
55 import org.onap.aaf.misc.env.TimeTaken;
56 import org.onap.aaf.misc.env.util.Split;
57 import org.onap.aaf.misc.rosetta.env.RosettaDF;
58 import org.onap.aaf.misc.rosetta.env.RosettaData;
59
60 /**
61  * AuthzFacade
62  * 
63  * This Service Facade encapsulates the essence of the API Service can do, and provides
64  * a single created object for elements such as RosettaDF.
65  *
66  * The Responsibilities of this class are to:
67  * 1) Interact with the Service Implementation (which might be supported by various kinds of Backend Storage)
68  * 2) Validate incoming data (if applicable)
69  * 3) Convert the Service response into the right Format, and mark the Content Type
70  *         a) In the future, we may support multiple Response Formats, aka JSON or XML, based on User Request.
71  * 4) Log Service info, warnings and exceptions as necessary
72  * 5) When asked by the API layer, this will create and write Error content to the OutputStream
73  * 
74  * Note: This Class does NOT set the HTTP Status Code.  That is up to the API layer, so that it can be 
75  * clearly coordinated with the API Documentation
76  * 
77  * @author Jonathan
78  *
79  */
80 public abstract class FacadeImpl<REQ,CERT,ARTIFACTS,ERROR> extends org.onap.aaf.auth.layer.FacadeImpl implements Facade<REQ,CERT,ARTIFACTS,ERROR> 
81     {
82     private static final String TRUE = "TRUE";
83     private static final String REQUEST_CERT = "Request New Certificate";
84     private static final String RENEW_CERT = "Renew Certificate";
85     private static final String DROP_CERT = "Drop Certificate";
86     private static final String READ_CERTS_MECHID = "Read Certificates by MechID";
87     private static final String CREATE_ARTIFACTS = "Create Deployment Artifact";
88     private static final String READ_ARTIFACTS = "Read Deployment Artifact";
89     private static final String UPDATE_ARTIFACTS = "Update Deployment Artifact";
90     private static final String DELETE_ARTIFACTS = "Delete Deployment Artifact";
91
92     private CMService service;
93
94     private final RosettaDF<ERROR>         errDF;
95     private final RosettaDF<REQ>         certRequestDF, certRenewDF, certDropDF;
96     private final RosettaDF<CERT>        certDF;
97     private final RosettaDF<ARTIFACTS>    artiDF;
98     private Mapper<REQ, CERT, ARTIFACTS, ERROR>     mapper;
99 //    private Slot sCertAuth;
100     private final String voidResp;
101     public FacadeImpl(AAF_CM certman,
102                       CMService service, 
103                       Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper, 
104                       Data.TYPE dataType) throws APIException {
105         this.service = service;
106         this.mapper = mapper;
107         AuthzEnv env = certman.env;
108         //TODO: Gabe [JUnit] Static issue, talk to Jonathan
109         (errDF                 = env.newDataFactory(mapper.getClass(API.ERROR))).in(dataType).out(dataType);
110         (certRequestDF         = env.newDataFactory(mapper.getClass(API.CERT_REQ))).in(dataType).out(dataType);
111         (certRenewDF         = env.newDataFactory(mapper.getClass(API.CERT_RENEW))).in(dataType).out(dataType);
112         (certDropDF         = env.newDataFactory(mapper.getClass(API.CERT_DROP))).in(dataType).out(dataType);
113         (certDF             = env.newDataFactory(mapper.getClass(API.CERT))).in(dataType).out(dataType);
114         (artiDF             = env.newDataFactory(mapper.getClass(API.ARTIFACTS))).in(dataType).out(dataType);
115 //        sCertAuth = env.slot(API_Cert.CERT_AUTH);
116         if (artiDF.getOutType().name().contains("xml")) {
117             voidResp = "application/Void+xml;charset=utf-8;version=1.0,application/xml;version=1.0,*/*";
118         } else {
119             voidResp = "application/Void+json;charset=utf-8;version=1.0,application/json;version=1.0,*/*";
120         }
121     }
122     
123     public Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper() {
124         return mapper;
125     }
126     
127     /* (non-Javadoc)
128      * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, int)
129      * 
130      * Note: Conforms to AT&T TSS RESTful Error Structure
131      */
132     @Override
133     public void error(AuthzTrans trans, HttpServletResponse response, Result<?> result) {
134         error(trans, response, result.status,
135                 result.details==null?"":result.details.trim(),
136                 result.variables==null?Result.EMPTY_VARS:result.variables);
137     }
138         
139     @Override
140     public void error(AuthzTrans trans, HttpServletResponse response, int status, final String _msg, final Object ... _detail) {
141         String msgId;
142         String prefix;
143         boolean hidemsg=false;
144         switch(status) {
145             case 202:
146             case ERR_ActionNotCompleted:
147                 msgId = "SVC1202";
148                 prefix = "Accepted, Action not complete";
149                 response.setStatus(/*httpstatus=*/202);
150                 break;
151
152             case 403:
153             case ERR_Policy:
154             case ERR_Security:
155             case ERR_Denied:
156                 msgId = "SVC1403";
157                 prefix = "Forbidden";
158                 response.setStatus(/*httpstatus=*/403);
159                 break;
160                 
161             case 404:
162             case ERR_NotFound:
163                 msgId = "SVC1404";
164                 prefix = "Not Found";
165                 response.setStatus(/*httpstatus=*/404);
166                 break;
167
168             case 406:
169             case ERR_BadData:
170                 msgId="SVC1406";
171                 prefix = "Not Acceptable";
172                 response.setStatus(/*httpstatus=*/406);
173                 break;
174                 
175             case 409:
176             case ERR_ConflictAlreadyExists:
177                 msgId = "SVC1409";
178                 prefix = "Conflict Already Exists";
179                 response.setStatus(/*httpstatus=*/409);
180                 break;
181             
182             case 501:
183             case ERR_NotImplemented:
184                 msgId = "SVC1501";
185                 prefix = "Not Implemented"; 
186                 response.setStatus(/*httpstatus=*/501);
187                 break;
188                 
189
190             default:
191                 msgId = "SVC1500";
192                 prefix = "General Service Error";
193                 response.setStatus(/*httpstatus=*/500);
194                 hidemsg=true;
195                 break;
196         }
197
198         try {
199             StringBuilder holder = new StringBuilder();
200             ERROR em = mapper().errorFromMessage(holder, msgId,prefix + ": " + _msg,_detail);
201             trans.checkpoint(
202                     "ErrResp [" + 
203                     msgId +
204                     "] " +
205                     holder.toString(),
206                     Env.ALWAYS);
207             if (hidemsg) {
208                 holder.setLength(0);
209                 em = mapper().errorFromMessage(holder, msgId, "Server had an issue processing this request");
210             }
211             errDF.newData(trans).load(em).to(response.getOutputStream());
212             
213         } catch (Exception e) {
214             trans.error().log(e,"unable to send response for",_msg);
215         }
216     }
217
218     @Override
219     public Result<Void> check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException {
220         String[] p = Split.split('|',perm);
221         AAFPermission ap;
222         switch(p.length) {
223             case 3:
224                  ap = new AAFPermission(null, p[0],p[1],p[2]);
225                  break;
226             case 4:
227                 ap = new AAFPermission(p[0],p[1],p[2],p[3]);
228                 break;
229             default:
230                 return Result.err(Result.ERR_BadData,"Invalid Perm String");
231         }
232         if (AAF_CM.aafLurPerm.fish(trans.getUserPrincipal(), ap)) {
233             resp.setContentType(voidResp);
234             resp.getOutputStream().write(0);
235             return Result.ok();
236         } else {
237             return Result.err(Result.ERR_Denied,"%s does not have %s",trans.user(),ap.getKey());
238         }
239     }
240
241     /* (non-Javadoc)
242      * @see com.att.auth.certman.facade.Facade#requestCert(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
243      */
244     @Override
245     public Result<Void> requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
246         TimeTaken tt = trans.start(REQUEST_CERT, Env.SUB|Env.ALWAYS);
247         String wt;
248         boolean withTrust=(wt=req.getParameter("withTrust"))!=null || TRUE.equalsIgnoreCase(wt);
249         try {
250             REQ request;
251             try {
252                 Data<REQ> rd = certRequestDF.newData().load(req.getInputStream());
253                 request = rd.asObject();
254             } catch (APIException e) {
255                 trans.error().log("Invalid Input",IN,REQUEST_CERT);
256                 return Result.err(Result.ERR_BadData,"Invalid Input");
257             }
258             
259             Result<CertResp> rcr = service.requestCert(trans,mapper.toReq(trans,request), ca);
260             if (rcr.notOK()) {
261                 return Result.err(rcr);
262             }
263             
264             Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
265             if (rc.status == OK) {
266                 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
267                 data.to(resp.getOutputStream());
268
269                 setContentType(resp, certDF.getOutType());
270                 return Result.ok();
271             }
272             return Result.err(rc);
273
274         } catch (Exception e) {
275             trans.error().log(e,IN,REQUEST_CERT);
276             return Result.err(e);
277         } finally {
278             tt.done();
279         }
280     }
281     
282     /* (non-Javadoc)
283      * @see org.onap.aaf.auth.cm.facade.Facade#requestPersonalCert(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, boolean)
284      */
285     @Override
286     public Result<Void> requestPersonalCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
287         return Result.err(Result.ERR_NotImplemented, "not implemented yet");
288     }
289
290     @Override
291     public Result<Void> renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) {
292         TimeTaken tt = trans.start(RENEW_CERT, Env.SUB|Env.ALWAYS);
293         try {
294             REQ request;
295             try {
296                 Data<REQ> rd = certRenewDF.newData().load(req.getInputStream());
297                 request = rd.asObject();
298             } catch (APIException e) {
299                 trans.error().log("Invalid Input",IN,RENEW_CERT);
300                 return Result.err(Result.ERR_BadData,"Invalid Input");
301             }
302             
303             Result<CertResp> rcr = service.renewCert(trans,mapper.toRenew(trans,request));
304             Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
305
306             if (rc.status == OK) {
307                 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
308                 data.to(resp.getOutputStream());
309
310                 setContentType(resp, certDF.getOutType());
311                 return Result.ok();
312             }
313             return Result.err(rc);
314         } catch (Exception e) {
315             trans.error().log(e,IN,RENEW_CERT);
316             return Result.err(e);
317         } finally {
318             tt.done();
319         }
320
321     }
322
323     @Override
324     public Result<Void> dropCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
325         TimeTaken tt = trans.start(DROP_CERT, Env.SUB|Env.ALWAYS);
326         try {
327             REQ request;
328             try {
329                 Data<REQ> rd = certDropDF.newData().load(req.getInputStream());
330                 request = rd.asObject();
331             } catch (APIException e) {
332                 trans.error().log("Invalid Input",IN,DROP_CERT);
333                 return Result.err(Result.ERR_BadData,"Invalid Input");
334             }
335             
336             Result<Void> rv = service.dropCert(trans,mapper.toDrop(trans, request));
337             if (rv.status == OK) {
338                 setContentType(resp, certRequestDF.getOutType());
339                 return Result.ok();
340             }
341             return Result.err(rv);
342         } catch (Exception e) {
343             trans.error().log(e,IN,DROP_CERT);
344             return Result.err(e);
345         } finally {
346             tt.done();
347         }
348     }
349
350     /* (non-Javadoc)
351      * @see org.onap.aaf.auth.cm.facade.Facade#readCertsByMechID(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String)
352      */
353     @Override
354     public Result<Void> readCertsByMechID(AuthzTrans trans, HttpServletResponse resp, String mechID) {
355         TimeTaken tt = trans.start(READ_CERTS_MECHID, Env.SUB|Env.ALWAYS);
356         try {
357             Result<CERT> rc = mapper.toCert(trans, service.readCertsByMechID(trans,mechID));
358             if (rc.status == OK) {
359                 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
360                 data.to(resp.getOutputStream());
361
362                 setContentType(resp, certDF.getOutType());
363                 return Result.ok();
364             }
365             return Result.err(rc);
366         } catch (Exception e) {
367             trans.error().log(e,IN,READ_CERTS_MECHID);
368             return Result.err(e);
369         } finally {
370             tt.done();
371         }
372     }
373
374     ////////////////////////////
375     // Artifacts
376     ////////////////////////////
377     @Override
378     public Result<Void> createArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
379         TimeTaken tt = trans.start(CREATE_ARTIFACTS, Env.SUB);
380         try {
381             ARTIFACTS arti;
382             try {
383                 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
384                 arti = rd.asObject();
385             } catch (APIException e) {
386                 trans.error().log("Invalid Input",IN,CREATE_ARTIFACTS);
387                 return Result.err(Result.ERR_BadData,"Invalid Input");
388             }
389             
390             return service.createArtifact(trans,mapper.toArtifact(trans,arti));
391         } catch (Exception e) {
392
393             trans.error().log(e,IN,CREATE_ARTIFACTS);
394             return Result.err(e);
395         } finally {
396             tt.done();
397         }
398     }
399
400     @Override
401     public Result<Void> readArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
402         TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
403         try {
404             String mechid = req.getParameter("mechid");
405             String machine = req.getParameter("machine");
406             String ns = req.getParameter("ns");
407             
408             Result<ARTIFACTS> ra;
409             if ( machine !=null && mechid == null) {
410                 ra = mapper.fromArtifacts(service.readArtifactsByMachine(trans, machine));
411             } else if (mechid!=null && machine==null) {
412                 ra = mapper.fromArtifacts(service.readArtifactsByMechID(trans, mechid));
413             } else if (mechid!=null && machine!=null) {
414                 ArtiDAO.Data add = new ArtiDAO.Data();
415                 add.mechid = mechid;
416                 add.machine = machine;
417                 add.ns = ns;
418                 ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
419             } else if (ns!=null) {
420                 ra = mapper.fromArtifacts(service.readArtifactsByNs(trans, ns));
421             } else {
422                 ra = Result.err(Status.ERR_BadData,"Invalid request inputs");
423             }
424             
425             if (ra.isOK()) {
426                 RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
427                 data.to(resp.getOutputStream());
428                 setContentType(resp,artiDF.getOutType());
429                 return Result.ok();
430             } else {
431                 return Result.err(ra);
432             }
433
434         } catch (Exception e) {
435             trans.error().log(e,IN,READ_ARTIFACTS);
436             return Result.err(e);
437         } finally {
438             tt.done();
439         }
440     }
441
442     @Override
443     public Result<Void> readArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
444         TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
445         try {
446             ArtiDAO.Data add = new ArtiDAO.Data();
447             add.mechid = mechid;
448             add.machine = machine;
449             Result<ARTIFACTS> ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
450             if (ra.isOK()) {
451                 RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
452                 data.to(resp.getOutputStream());
453                 setContentType(resp,artiDF.getOutType());
454                 return Result.ok();
455             } else {
456                 return Result.err(ra);
457             }
458         } catch (Exception e) {
459             trans.error().log(e,IN,READ_ARTIFACTS);
460             return Result.err(e);
461         } finally {
462             tt.done();
463         }
464     }
465
466
467     @Override
468     public Result<Void> updateArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
469         TimeTaken tt = trans.start(UPDATE_ARTIFACTS, Env.SUB);
470         try {
471             ARTIFACTS arti;
472             try {
473                 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
474                 arti = rd.asObject();
475             } catch (APIException e) {
476                 trans.error().log("Invalid Input",IN,UPDATE_ARTIFACTS);
477                 return Result.err(Result.ERR_BadData,"Invalid Input");
478             }
479             
480             return service.updateArtifact(trans,mapper.toArtifact(trans,arti));
481         } catch (Exception e) {
482             trans.error().log(e,IN,UPDATE_ARTIFACTS);
483             return Result.err(e);
484         } finally {
485             tt.done();
486         }
487     }
488
489     @Override
490     public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
491         TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
492         try {
493             ARTIFACTS arti;
494             try {
495                 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
496                 arti = rd.asObject();
497             } catch (APIException e) {
498                 trans.error().log("Invalid Input",IN,DELETE_ARTIFACTS);
499                 return Result.err(Result.ERR_BadData,"Invalid Input");
500             }
501             
502             Result<Void> rv = service.deleteArtifact(trans,mapper.toArtifact(trans,arti));
503             if (rv.status == OK) {
504                 setContentType(resp, artiDF.getOutType());
505             }
506             return rv;
507         } catch (Exception e) {
508             trans.error().log(e,IN,DELETE_ARTIFACTS);
509             return Result.err(e);
510         } finally {
511             tt.done();
512         }
513     }
514
515     @Override
516     public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
517         TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
518         try {
519             Result<Void> rv = service.deleteArtifact(trans, mechid, machine);
520             if (rv.status == OK) {
521                 setContentType(resp, artiDF.getOutType());
522             }
523             return rv;
524         } catch (Exception e) {
525             trans.error().log(e,IN,DELETE_ARTIFACTS);
526             return Result.err(e);
527         } finally {
528             tt.done();
529         }
530     }
531
532
533 }