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