Update Fixes from testing
[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
102     public FacadeImpl(AAF_CM certman,
103                       CMService service, 
104                       Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper, 
105                       Data.TYPE dataType) throws APIException {
106         this.service = service;
107         this.mapper = mapper;
108         AuthzEnv env = certman.env;
109         //TODO: Gabe [JUnit] Static issue, talk to Jonathan
110         (errDF                 = env.newDataFactory(mapper.getClass(API.ERROR))).in(dataType).out(dataType);
111         (certRequestDF         = env.newDataFactory(mapper.getClass(API.CERT_REQ))).in(dataType).out(dataType);
112         (certRenewDF         = env.newDataFactory(mapper.getClass(API.CERT_RENEW))).in(dataType).out(dataType);
113         (certDropDF         = env.newDataFactory(mapper.getClass(API.CERT_DROP))).in(dataType).out(dataType);
114         (certDF             = env.newDataFactory(mapper.getClass(API.CERT))).in(dataType).out(dataType);
115         (artiDF             = env.newDataFactory(mapper.getClass(API.ARTIFACTS))).in(dataType).out(dataType);
116 //        sCertAuth = env.slot(API_Cert.CERT_AUTH);
117         if (artiDF.getOutType().name().contains("xml")) {
118             voidResp = "application/Void+xml;charset=utf-8;version=1.0,application/xml;version=1.0,*/*";
119         } else {
120             voidResp = "application/Void+json;charset=utf-8;version=1.0,application/json;version=1.0,*/*";
121         }
122     }
123     
124     public Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper() {
125         return mapper;
126     }
127     
128     /* (non-Javadoc)
129      * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, int)
130      * 
131      * Note: Conforms to AT&T TSS RESTful Error Structure
132      */
133     @Override
134     public void error(AuthzTrans trans, HttpServletResponse response, Result<?> result) {
135         error(trans, response, result.status,
136                 result.details==null?"":result.details.trim(),
137                 result.variables==null?Result.EMPTY_VARS:result.variables);
138     }
139         
140     @Override
141     public void error(AuthzTrans trans, HttpServletResponse response, int status, final String _msg, final Object ... _detail) {
142         String msgId;
143         String prefix;
144         boolean hidemsg=false;
145         switch(status) {
146             case 202:
147             case ERR_ActionNotCompleted:
148                 msgId = "SVC1202";
149                 prefix = "Accepted, Action not complete";
150                 response.setStatus(/*httpstatus=*/202);
151                 break;
152
153             case 403:
154             case ERR_Policy:
155             case ERR_Security:
156             case ERR_Denied:
157                 msgId = "SVC1403";
158                 prefix = "Forbidden";
159                 response.setStatus(/*httpstatus=*/403);
160                 break;
161                 
162             case 404:
163             case ERR_NotFound:
164                 msgId = "SVC1404";
165                 prefix = "Not Found";
166                 response.setStatus(/*httpstatus=*/404);
167                 break;
168
169             case 406:
170             case ERR_BadData:
171                 msgId="SVC1406";
172                 prefix = "Not Acceptable";
173                 response.setStatus(/*httpstatus=*/406);
174                 break;
175                 
176             case 409:
177             case ERR_ConflictAlreadyExists:
178                 msgId = "SVC1409";
179                 prefix = "Conflict Already Exists";
180                 response.setStatus(/*httpstatus=*/409);
181                 break;
182             
183             case 501:
184             case ERR_NotImplemented:
185                 msgId = "SVC1501";
186                 prefix = "Not Implemented"; 
187                 response.setStatus(/*httpstatus=*/501);
188                 break;
189                 
190
191             default:
192                 msgId = "SVC1500";
193                 prefix = "General Service Error";
194                 response.setStatus(/*httpstatus=*/500);
195                 hidemsg=true;
196                 break;
197         }
198
199         try {
200             StringBuilder holder = new StringBuilder();
201             ERROR em = mapper().errorFromMessage(holder, msgId,prefix + ": " + _msg,_detail);
202             trans.checkpoint(
203                     "ErrResp [" + 
204                     msgId +
205                     "] " +
206                     holder.toString(),
207                     Env.ALWAYS);
208             if (hidemsg) {
209                 holder.setLength(0);
210                 em = mapper().errorFromMessage(holder, msgId, "Server had an issue processing this request");
211             }
212             errDF.newData(trans).load(em).to(response.getOutputStream());
213             
214         } catch (Exception e) {
215             trans.error().log(e,"unable to send response for",_msg);
216         }
217     }
218
219     @Override
220     public Result<Void> check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException {
221         String[] p = Split.split('|',perm);
222         AAFPermission ap;
223         switch(p.length) {
224             case 3:
225                  ap = new AAFPermission(null, p[0],p[1],p[2]);
226                  break;
227             case 4:
228                 ap = new AAFPermission(p[0],p[1],p[2],p[3]);
229                 break;
230             default:
231                 return Result.err(Result.ERR_BadData,"Invalid Perm String");
232         }
233         if (AAF_CM.aafLurPerm.fish(trans.getUserPrincipal(), ap)) {
234             resp.setContentType(voidResp);
235             resp.getOutputStream().write(0);
236             return Result.ok();
237         } else {
238             return Result.err(Result.ERR_Denied,"%s does not have %s",trans.user(),ap.getKey());
239         }
240     }
241
242     /* (non-Javadoc)
243      * @see com.att.auth.certman.facade.Facade#requestCert(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
244      */
245     @Override
246     public Result<Void> requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
247         TimeTaken tt = trans.start(REQUEST_CERT, Env.SUB|Env.ALWAYS);
248         String wt;
249         boolean withTrust=(wt=req.getParameter("withTrust"))!=null || TRUE.equalsIgnoreCase(wt);
250         try {
251             REQ request;
252             try {
253                 Data<REQ> rd = certRequestDF.newData().load(req.getInputStream());
254                 request = rd.asObject();
255             } catch (APIException e) {
256                 trans.error().log("Invalid Input",IN,REQUEST_CERT);
257                 return Result.err(Result.ERR_BadData,"Invalid Input");
258             }
259             
260             Result<CertResp> rcr = service.requestCert(trans,mapper.toReq(trans,request), ca);
261             if (rcr.notOK()) {
262                 return Result.err(rcr);
263             }
264             
265             Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
266             if (rc.status == OK) {
267                 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
268                 data.to(resp.getOutputStream());
269
270                 setContentType(resp, certDF.getOutType());
271                 return Result.ok();
272             }
273             return Result.err(rc);
274
275         } catch (Exception e) {
276             trans.error().log(e,IN,REQUEST_CERT);
277             return Result.err(e);
278         } finally {
279             tt.done();
280         }
281     }
282     
283     /* (non-Javadoc)
284      * @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)
285      */
286     @Override
287     public Result<Void> requestPersonalCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
288         return Result.err(Result.ERR_NotImplemented, "not implemented yet");
289     }
290
291     @Override
292     public Result<Void> renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) {
293         TimeTaken tt = trans.start(RENEW_CERT, Env.SUB|Env.ALWAYS);
294         try {
295             REQ request;
296             try {
297                 Data<REQ> rd = certRenewDF.newData().load(req.getInputStream());
298                 request = rd.asObject();
299             } catch (APIException e) {
300                 trans.error().log("Invalid Input",IN,RENEW_CERT);
301                 return Result.err(Result.ERR_BadData,"Invalid Input");
302             }
303             
304             Result<CertResp> rcr = service.renewCert(trans,mapper.toRenew(trans,request));
305             Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
306
307             if (rc.status == OK) {
308                 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
309                 data.to(resp.getOutputStream());
310
311                 setContentType(resp, certDF.getOutType());
312                 return Result.ok();
313             }
314             return Result.err(rc);
315         } catch (Exception e) {
316             trans.error().log(e,IN,RENEW_CERT);
317             return Result.err(e);
318         } finally {
319             tt.done();
320         }
321
322     }
323
324     @Override
325     public Result<Void> dropCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
326         TimeTaken tt = trans.start(DROP_CERT, Env.SUB|Env.ALWAYS);
327         try {
328             REQ request;
329             try {
330                 Data<REQ> rd = certDropDF.newData().load(req.getInputStream());
331                 request = rd.asObject();
332             } catch (APIException e) {
333                 trans.error().log("Invalid Input",IN,DROP_CERT);
334                 return Result.err(Result.ERR_BadData,"Invalid Input");
335             }
336             
337             Result<Void> rv = service.dropCert(trans,mapper.toDrop(trans, request));
338             if (rv.status == OK) {
339                 setContentType(resp, certRequestDF.getOutType());
340                 return Result.ok();
341             }
342             return Result.err(rv);
343         } catch (Exception e) {
344             trans.error().log(e,IN,DROP_CERT);
345             return Result.err(e);
346         } finally {
347             tt.done();
348         }
349     }
350
351     /* (non-Javadoc)
352      * @see org.onap.aaf.auth.cm.facade.Facade#readCertsByMechID(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String)
353      */
354     @Override
355     public Result<Void> readCertsByMechID(AuthzTrans trans, HttpServletResponse resp, String mechID) {
356         TimeTaken tt = trans.start(READ_CERTS_MECHID, Env.SUB|Env.ALWAYS);
357         try {
358             Result<CERT> rc = mapper.toCert(trans, service.readCertsByMechID(trans,mechID));
359             if (rc.status == OK) {
360                 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
361                 data.to(resp.getOutputStream());
362
363                 setContentType(resp, certDF.getOutType());
364                 return Result.ok();
365             }
366             return Result.err(rc);
367         } catch (Exception e) {
368             trans.error().log(e,IN,READ_CERTS_MECHID);
369             return Result.err(e);
370         } finally {
371             tt.done();
372         }
373     }
374
375     ////////////////////////////
376     // Artifacts
377     ////////////////////////////
378     @Override
379     public Result<Void> createArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
380         TimeTaken tt = trans.start(CREATE_ARTIFACTS, Env.SUB);
381         try {
382             ARTIFACTS arti;
383             try {
384                 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
385                 arti = rd.asObject();
386             } catch (APIException e) {
387                 trans.error().log("Invalid Input",IN,CREATE_ARTIFACTS);
388                 return Result.err(Result.ERR_BadData,"Invalid Input");
389             }
390             
391             return service.createArtifact(trans,mapper.toArtifact(trans,arti));
392         } catch (Exception e) {
393
394             trans.error().log(e,IN,CREATE_ARTIFACTS);
395             return Result.err(e);
396         } finally {
397             tt.done();
398         }
399     }
400
401     @Override
402     public Result<Void> readArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
403         TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
404         try {
405             String mechid = req.getParameter("mechid");
406             String machine = req.getParameter("machine");
407             String ns = req.getParameter("ns");
408             
409             Result<ARTIFACTS> ra;
410             if ( machine !=null && mechid == null) {
411                 ra = mapper.fromArtifacts(service.readArtifactsByMachine(trans, machine));
412             } else if (mechid!=null && machine==null) {
413                 ra = mapper.fromArtifacts(service.readArtifactsByMechID(trans, mechid));
414             } else if (mechid!=null && machine!=null) {
415                 ArtiDAO.Data add = new ArtiDAO.Data();
416                 add.mechid = mechid;
417                 add.machine = machine;
418                 add.ns = ns;
419                 ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
420             } else if (ns!=null) {
421                 ra = mapper.fromArtifacts(service.readArtifactsByNs(trans, ns));
422             } else {
423                 ra = Result.err(Status.ERR_BadData,"Invalid request inputs");
424             }
425             
426             if (ra.isOK()) {
427                 RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
428                 data.to(resp.getOutputStream());
429                 setContentType(resp,artiDF.getOutType());
430                 return Result.ok();
431             } else {
432                 return Result.err(ra);
433             }
434
435         } catch (Exception e) {
436             trans.error().log(e,IN,READ_ARTIFACTS);
437             return Result.err(e);
438         } finally {
439             tt.done();
440         }
441     }
442
443     @Override
444     public Result<Void> readArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
445         TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
446         try {
447             ArtiDAO.Data add = new ArtiDAO.Data();
448             add.mechid = mechid;
449             add.machine = machine;
450             Result<ARTIFACTS> ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
451             if (ra.isOK()) {
452                 RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
453                 data.to(resp.getOutputStream());
454                 setContentType(resp,artiDF.getOutType());
455                 return Result.ok();
456             } else {
457                 return Result.err(ra);
458             }
459         } catch (Exception e) {
460             trans.error().log(e,IN,READ_ARTIFACTS);
461             return Result.err(e);
462         } finally {
463             tt.done();
464         }
465     }
466
467
468     @Override
469     public Result<Void> updateArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
470         TimeTaken tt = trans.start(UPDATE_ARTIFACTS, Env.SUB);
471         try {
472             ARTIFACTS arti;
473             try {
474                 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
475                 arti = rd.asObject();
476             } catch (APIException e) {
477                 trans.error().log("Invalid Input",IN,UPDATE_ARTIFACTS);
478                 return Result.err(Result.ERR_BadData,"Invalid Input");
479             }
480             
481             return service.updateArtifact(trans,mapper.toArtifact(trans,arti));
482         } catch (Exception e) {
483             trans.error().log(e,IN,UPDATE_ARTIFACTS);
484             return Result.err(e);
485         } finally {
486             tt.done();
487         }
488     }
489
490     @Override
491     public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
492         TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
493         try {
494             ARTIFACTS arti;
495             try {
496                 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
497                 arti = rd.asObject();
498             } catch (APIException e) {
499                 trans.error().log("Invalid Input",IN,DELETE_ARTIFACTS);
500                 return Result.err(Result.ERR_BadData,"Invalid Input");
501             }
502             
503             Result<Void> rv = service.deleteArtifact(trans,mapper.toArtifact(trans,arti));
504             if (rv.status == OK) {
505                 setContentType(resp, artiDF.getOutType());
506             }
507             return rv;
508         } catch (Exception e) {
509             trans.error().log(e,IN,DELETE_ARTIFACTS);
510             return Result.err(e);
511         } finally {
512             tt.done();
513         }
514     }
515
516     @Override
517     public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
518         TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
519         try {
520             Result<Void> rv = service.deleteArtifact(trans, mechid, machine);
521             if (rv.status == OK) {
522                 setContentType(resp, artiDF.getOutType());
523             }
524             return rv;
525         } catch (Exception e) {
526             trans.error().log(e,IN,DELETE_ARTIFACTS);
527             return Result.err(e);
528         } finally {
529             tt.done();
530         }
531     }
532
533
534 }