2 * ============LICENSE_START====================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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====================================================
23 package org.onap.aaf.auth.cm.facade;
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;
35 import java.io.IOException;
37 import javax.servlet.http.HttpServletRequest;
38 import javax.servlet.http.HttpServletResponse;
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;
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.
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
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
80 public abstract class FacadeImpl<REQ,CERT,ARTIFACTS,ERROR> extends org.onap.aaf.auth.layer.FacadeImpl implements Facade<REQ,CERT,ARTIFACTS,ERROR>
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";
92 private CMService service;
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 AAF_CM certman;
101 private final String voidResp;
103 public FacadeImpl(AAF_CM certman,
105 Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper,
106 Data.TYPE dataType) throws APIException {
107 this.service = service;
108 this.mapper = mapper;
109 this.certman = certman;
110 AuthzEnv env = certman.env;
111 //TODO: Gabe [JUnit] Static issue, talk to Jonathan
112 (errDF = env.newDataFactory(mapper.getClass(API.ERROR))).in(dataType).out(dataType);
113 (certRequestDF = env.newDataFactory(mapper.getClass(API.CERT_REQ))).in(dataType).out(dataType);
114 (certRenewDF = env.newDataFactory(mapper.getClass(API.CERT_RENEW))).in(dataType).out(dataType);
115 (certDropDF = env.newDataFactory(mapper.getClass(API.CERT_DROP))).in(dataType).out(dataType);
116 (certDF = env.newDataFactory(mapper.getClass(API.CERT))).in(dataType).out(dataType);
117 (artiDF = env.newDataFactory(mapper.getClass(API.ARTIFACTS))).in(dataType).out(dataType);
118 // sCertAuth = env.slot(API_Cert.CERT_AUTH);
119 if (artiDF.getOutType().name().contains("xml")) {
120 voidResp = "application/Void+xml;charset=utf-8;version=1.0,application/xml;version=1.0,*/*";
122 voidResp = "application/Void+json;charset=utf-8;version=1.0,application/json;version=1.0,*/*";
126 public Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper() {
131 * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, int)
133 * Note: Conforms to AT&T TSS RESTful Error Structure
136 public void error(AuthzTrans trans, HttpServletResponse response, Result<?> result) {
137 error(trans, response, result.status,
138 result.details==null?"":result.details.trim(),
139 result.variables==null?Result.EMPTY_VARS:result.variables);
143 public void error(AuthzTrans trans, HttpServletResponse response, int status, final String _msg, final Object ... _detail) {
146 boolean hidemsg=false;
149 case ERR_ActionNotCompleted:
151 prefix = "Accepted, Action not complete";
152 response.setStatus(/*httpstatus=*/202);
160 prefix = "Forbidden";
161 response.setStatus(/*httpstatus=*/403);
167 prefix = "Not Found";
168 response.setStatus(/*httpstatus=*/404);
174 prefix = "Not Acceptable";
175 response.setStatus(/*httpstatus=*/406);
179 case ERR_ConflictAlreadyExists:
181 prefix = "Conflict Already Exists";
182 response.setStatus(/*httpstatus=*/409);
186 case ERR_NotImplemented:
188 prefix = "Not Implemented";
189 response.setStatus(/*httpstatus=*/501);
195 prefix = "General Service Error";
196 response.setStatus(/*httpstatus=*/500);
202 StringBuilder holder = new StringBuilder();
203 ERROR em = mapper().errorFromMessage(holder, msgId,prefix + ": " + _msg,_detail);
212 em = mapper().errorFromMessage(holder, msgId, "Server had an issue processing this request");
214 errDF.newData(trans).load(em).to(response.getOutputStream());
216 } catch (Exception e) {
217 trans.error().log(e,"unable to send response for",_msg);
222 public Result<Void> check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException {
223 String[] p = Split.split('|',perm);
227 ap = new AAFPermission(null, p[0],p[1],p[2]);
230 ap = new AAFPermission(p[0],p[1],p[2],p[3]);
233 return Result.err(Result.ERR_BadData,"Invalid Perm String");
235 if (AAF_CM.aafLurPerm.fish(trans.getUserPrincipal(), ap)) {
236 resp.setContentType(voidResp);
237 resp.getOutputStream().write(0);
240 return Result.err(Result.ERR_Denied,"%s does not have %s",trans.user(),ap.getKey());
245 * @see com.att.auth.certman.facade.Facade#requestCert(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
248 public Result<Void> requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
249 TimeTaken tt = trans.start(REQUEST_CERT, Env.SUB|Env.ALWAYS);
251 boolean withTrust=(wt=req.getParameter("withTrust"))!=null || TRUE.equalsIgnoreCase(wt);
255 Data<REQ> rd = certRequestDF.newData().load(req.getInputStream());
256 request = rd.asObject();
257 } catch (APIException e) {
258 trans.error().log("Invalid Input",IN,REQUEST_CERT);
259 return Result.err(Result.ERR_BadData,"Invalid Input");
262 Result<CertResp> rcr = service.requestCert(trans,mapper.toReq(trans,request), ca);
264 return Result.err(rcr);
267 Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
268 if (rc.status == OK) {
269 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
270 data.to(resp.getOutputStream());
272 setContentType(resp, certDF.getOutType());
275 return Result.err(rc);
277 } catch (Exception e) {
278 trans.error().log(e,IN,REQUEST_CERT);
279 return Result.err(e);
286 * @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)
289 public Result<Void> requestPersonalCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
290 return Result.err(Result.ERR_NotImplemented, "not implemented yet");
294 public Result<Void> renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) {
295 TimeTaken tt = trans.start(RENEW_CERT, Env.SUB|Env.ALWAYS);
299 Data<REQ> rd = certRenewDF.newData().load(req.getInputStream());
300 request = rd.asObject();
301 } catch (APIException e) {
302 trans.error().log("Invalid Input",IN,RENEW_CERT);
303 return Result.err(Result.ERR_BadData,"Invalid Input");
306 Result<CertResp> rcr = service.renewCert(trans,mapper.toRenew(trans,request));
307 Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
309 if (rc.status == OK) {
310 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
311 data.to(resp.getOutputStream());
313 setContentType(resp, certDF.getOutType());
316 return Result.err(rc);
317 } catch (Exception e) {
318 trans.error().log(e,IN,RENEW_CERT);
319 return Result.err(e);
327 public Result<Void> dropCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
328 TimeTaken tt = trans.start(DROP_CERT, Env.SUB|Env.ALWAYS);
332 Data<REQ> rd = certDropDF.newData().load(req.getInputStream());
333 request = rd.asObject();
334 } catch (APIException e) {
335 trans.error().log("Invalid Input",IN,DROP_CERT);
336 return Result.err(Result.ERR_BadData,"Invalid Input");
339 Result<Void> rv = service.dropCert(trans,mapper.toDrop(trans, request));
340 if (rv.status == OK) {
341 setContentType(resp, certRequestDF.getOutType());
344 return Result.err(rv);
345 } catch (Exception e) {
346 trans.error().log(e,IN,DROP_CERT);
347 return Result.err(e);
354 * @see org.onap.aaf.auth.cm.facade.Facade#readCertsByMechID(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String)
357 public Result<Void> readCertsByMechID(AuthzTrans trans, HttpServletResponse resp, String mechID) {
358 TimeTaken tt = trans.start(READ_CERTS_MECHID, Env.SUB|Env.ALWAYS);
360 Result<CERT> rc = mapper.toCert(trans, service.readCertsByMechID(trans,mechID));
361 if (rc.status == OK) {
362 RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
363 data.to(resp.getOutputStream());
365 setContentType(resp, certDF.getOutType());
368 return Result.err(rc);
369 } catch (Exception e) {
370 trans.error().log(e,IN,READ_CERTS_MECHID);
371 return Result.err(e);
377 ////////////////////////////
379 ////////////////////////////
381 public Result<Void> createArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
382 TimeTaken tt = trans.start(CREATE_ARTIFACTS, Env.SUB);
386 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
387 arti = rd.asObject();
388 } catch (APIException e) {
389 trans.error().log("Invalid Input",IN,CREATE_ARTIFACTS);
390 return Result.err(Result.ERR_BadData,"Invalid Input");
393 return service.createArtifact(trans,mapper.toArtifact(trans,arti));
394 } catch (Exception e) {
396 trans.error().log(e,IN,CREATE_ARTIFACTS);
397 return Result.err(e);
404 public Result<Void> readArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
405 TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
407 String mechid = req.getParameter("mechid");
408 String machine = req.getParameter("machine");
409 String ns = req.getParameter("ns");
411 Result<ARTIFACTS> ra;
412 if ( machine !=null && mechid == null) {
413 ra = mapper.fromArtifacts(service.readArtifactsByMachine(trans, machine));
414 } else if (mechid!=null && machine==null) {
415 ra = mapper.fromArtifacts(service.readArtifactsByMechID(trans, mechid));
416 } else if (mechid!=null && machine!=null) {
417 ArtiDAO.Data add = new ArtiDAO.Data();
419 add.machine = machine;
421 ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
422 } else if (ns!=null) {
423 ra = mapper.fromArtifacts(service.readArtifactsByNs(trans, ns));
425 ra = Result.err(Status.ERR_BadData,"Invalid request inputs");
429 RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
430 data.to(resp.getOutputStream());
431 setContentType(resp,artiDF.getOutType());
434 return Result.err(ra);
437 } catch (Exception e) {
438 trans.error().log(e,IN,READ_ARTIFACTS);
439 return Result.err(e);
446 public Result<Void> readArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
447 TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
449 ArtiDAO.Data add = new ArtiDAO.Data();
451 add.machine = machine;
452 Result<ARTIFACTS> ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
454 RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
455 data.to(resp.getOutputStream());
456 setContentType(resp,artiDF.getOutType());
459 return Result.err(ra);
461 } catch (Exception e) {
462 trans.error().log(e,IN,READ_ARTIFACTS);
463 return Result.err(e);
471 public Result<Void> updateArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
472 TimeTaken tt = trans.start(UPDATE_ARTIFACTS, Env.SUB);
476 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
477 arti = rd.asObject();
478 } catch (APIException e) {
479 trans.error().log("Invalid Input",IN,UPDATE_ARTIFACTS);
480 return Result.err(Result.ERR_BadData,"Invalid Input");
483 return service.updateArtifact(trans,mapper.toArtifact(trans,arti));
484 } catch (Exception e) {
485 trans.error().log(e,IN,UPDATE_ARTIFACTS);
486 return Result.err(e);
493 public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
494 TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
498 Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
499 arti = rd.asObject();
500 } catch (APIException e) {
501 trans.error().log("Invalid Input",IN,DELETE_ARTIFACTS);
502 return Result.err(Result.ERR_BadData,"Invalid Input");
505 Result<Void> rv = service.deleteArtifact(trans,mapper.toArtifact(trans,arti));
506 if (rv.status == OK) {
507 setContentType(resp, artiDF.getOutType());
510 } catch (Exception e) {
511 trans.error().log(e,IN,DELETE_ARTIFACTS);
512 return Result.err(e);
519 public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
520 TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
522 Result<Void> rv = service.deleteArtifact(trans, mechid, machine);
523 if (rv.status == OK) {
524 setContentType(resp, artiDF.getOutType());
527 } catch (Exception e) {
528 trans.error().log(e,IN,DELETE_ARTIFACTS);
529 return Result.err(e);