View Javadoc
1   /**
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.swid.swidval.controller;
28  
29  import gov.nist.secauto.decima.core.assessment.AssessmentException;
30  import gov.nist.secauto.decima.core.assessment.AssessmentExecutor;
31  import gov.nist.secauto.decima.core.assessment.result.AssessmentResultBuilder;
32  import gov.nist.secauto.decima.core.assessment.result.AssessmentResults;
33  import gov.nist.secauto.decima.core.assessment.result.ResultStatus;
34  import gov.nist.secauto.decima.core.document.DocumentException;
35  import gov.nist.secauto.decima.xml.assessment.result.ReportGenerator;
36  import gov.nist.secauto.decima.xml.assessment.result.XMLResultBuilder;
37  import gov.nist.secauto.decima.xml.assessment.schematron.SchematronAssessment;
38  import gov.nist.secauto.decima.xml.document.JDOMDocument;
39  import gov.nist.secauto.decima.xml.document.XMLDocument;
40  import gov.nist.secauto.swid.swidval.SWIDAssessmentResultBuilderFactory;
41  import gov.nist.secauto.swid.swidval.SWIDRequirementsManager;
42  import gov.nist.secauto.swid.swidval.SWIDTagCharacteristics;
43  import gov.nist.secauto.swid.swidval.TagType;
44  
45  import org.apache.logging.log4j.LogManager;
46  import org.apache.logging.log4j.Logger;
47  import org.jdom2.Document;
48  import org.jdom2.transform.JDOMSource;
49  import org.springframework.stereotype.Controller;
50  import org.springframework.web.bind.annotation.ExceptionHandler;
51  import org.springframework.web.bind.annotation.RequestMapping;
52  import org.springframework.web.bind.annotation.RequestMethod;
53  import org.springframework.web.bind.annotation.RequestParam;
54  import org.springframework.web.bind.annotation.RestController;
55  import org.springframework.web.multipart.MultipartFile;
56  import org.springframework.web.servlet.ModelAndView;
57  
58  import java.io.IOException;
59  import java.io.InputStream;
60  import java.net.URI;
61  import java.net.URISyntaxException;
62  import java.util.HashMap;
63  import java.util.Map;
64  
65  import javax.servlet.http.HttpServletRequest;
66  import javax.servlet.http.HttpServletResponse;
67  import javax.xml.transform.TransformerException;
68  import javax.xml.transform.stream.StreamResult;
69  import javax.xml.xpath.XPathExpressionException;
70  import javax.xml.xpath.XPathFactoryConfigurationException;
71  
72  @RestController
73  @Controller
74  public class SWIDValController {
75    private static final Logger log = LogManager.getLogger(SchematronAssessment.class);
76  
77    public static final String MODEL_KEY_ASSESSMENT_RESULT = "assessment";
78    public static final String MODEL_KEY_FILENAME = "filename";
79  
80    private static final TagType TAG_TYPE_DEFAULT = TagType.PRIMARY;
81    private static final boolean TAG_AUTHORITATIVE_DEFAULT = true;
82  
83    private final SWIDAssessmentManagerer/SWIDAssessmentManager.html#SWIDAssessmentManager">SWIDAssessmentManager manager = new SWIDAssessmentManager();
84  
85    // @PostMapping("/validate.html")
86    @RequestMapping(name = "/validate", method = RequestMethod.POST)
87    public void validate(HttpServletRequest requestEntity, HttpServletResponse response)
88        throws AssessmentException, DocumentException, IOException, TransformerException, URISyntaxException {
89  
90      InputStream is = requestEntity.getInputStream();
91      // File tempFile = File.createTempFile("swid", ".swidtag");
92      // tempFile.deleteOnExit();
93      // file.transferTo(tempFile);
94  
95      JDOMDocument swidDocuemnt = new JDOMDocument(is, null);
96  
97      // TagType tagType = TagType.lookup(tagType);
98      SWIDTagCharacteristics swidTagCharacteristics = getSWIDTagCharacteristics(swidDocuemnt);
99  
100     AssessmentResults results = performAssessment(swidDocuemnt, swidTagCharacteristics);
101 
102     String accept = requestEntity.getHeader("Accept");
103     if (accept == null) {
104       accept = "application/xml";
105     }
106     XMLResultBuilder writer = new XMLResultBuilder();
107     if (accept.equals("application/xml")) {
108       writer.write(results, response.getOutputStream());
109     } else if (accept.equals("text/html")) {
110       Document document = writer.newDocument(results);
111       ReportGenerator reportGenerator = new ReportGenerator();
112       reportGenerator.setIgnoreNotTestedResults(true);
113       reportGenerator.setIgnoreOutOfScopeResults(true);
114       reportGenerator.setXslTemplateExtension(new URI("classpath:xsl/swid-result.xsl"));
115       // reportGenerator.setTargetName(model.get(SWIDValController.MODEL_KEY_FILENAME).toString());
116       reportGenerator.generate(new JDOMSource(document), new StreamResult(response.getOutputStream()));
117 
118     }
119   }
120 
121   @RequestMapping("/validate-form")
122   public ModelAndView validateForm(@RequestParam("file") MultipartFile file,
123       @RequestParam("tag-type") String tagTypeParam)
124       throws AssessmentException, UnrecognizedContentException, DocumentException, IOException {
125     if (file.isEmpty()) {
126       throw new UnrecognizedContentException("A valid SWID tag was not provided.");
127     }
128 
129     InputStream is = file.getInputStream();
130     // File tempFile = File.createTempFile("swid", ".swidtag");
131     // tempFile.deleteOnExit();
132     // file.transferTo(tempFile);
133 
134     XMLDocument swidDocuemnt = new JDOMDocument(is, null);
135 
136     SWIDTagCharacteristics swidTagCharacteristics = getSWIDTagCharacteristics(swidDocuemnt);
137     if (tagTypeParam != null) {
138       TagType tagType = TagType.lookup(tagTypeParam);
139       if (tagType != null) {
140         // override with requested type
141         swidTagCharacteristics = new SWIDTagCharacteristics(tagType, swidTagCharacteristics.isAuthoritative());
142       }
143     }
144 
145     AssessmentResults results = performAssessment(swidDocuemnt, swidTagCharacteristics);
146 
147     if (!ResultStatus.PASS.equals(results.getBaseRequirementResult("GEN-1").getStatus())) {
148       throw new UnrecognizedContentException("The provided file was not a schema valid SWID tag.");
149     }
150 
151     Map<String, Object> model = new HashMap<>();
152     model.put(MODEL_KEY_ASSESSMENT_RESULT, results);
153     model.put(MODEL_KEY_FILENAME, file.getOriginalFilename());
154     return new ModelAndView(new DecimaResultView(), model);
155   }
156 
157   @ExceptionHandler(Exception.class)
158   public void handleError(HttpServletRequest request, HttpServletResponse response, Exception ex) throws IOException {
159     log.error("Requested URL '" + request.getRequestURL() + "' raised an exception:", ex);
160 
161     response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
162     // ModelAndView modelAndView = new ModelAndView();
163     // modelAndView.addObject("exception", ex);
164     // modelAndView.addObject("url", request.getRequestURL());
165     //
166     // modelAndView.setViewName("error");
167     // return modelAndView;
168   }
169 
170   private SWIDTagCharacteristics getSWIDTagCharacteristics(XMLDocument swidDocuemnt) {
171     SWIDTagCharacteristics characteristics;
172     try {
173       characteristics = SWIDTagCharacteristics.getSWIDTagCharacteristics(swidDocuemnt);
174       log.debug("Based on the tag contents, the tag appears to be {} {} tag",
175           characteristics.isAuthoritative() ? "an authoritative" : "a non-authoritative",
176           characteristics.getTagType().getName());
177     } catch (XPathExpressionException | XPathFactoryConfigurationException ex) {
178       log.debug("Unable to determine the type and authoritativeness of the tag", ex);
179       characteristics = new SWIDTagCharacteristics(TAG_TYPE_DEFAULT, TAG_AUTHORITATIVE_DEFAULT);
180     }
181     return characteristics;
182   }
183 
184   private AssessmentResults performAssessment(XMLDocument swidDocuemnt, SWIDTagCharacteristics swidTagCharacteristics)
185       throws AssessmentException {
186     // setup the document assessment
187     AssessmentExecutor<XMLDocument> executor
188         = manager.getAssessmentExecutor(swidTagCharacteristics.getTagType(), swidTagCharacteristics.isAuthoritative());
189     AssessmentResultBuilder assessmentResultBuilder = SWIDAssessmentResultBuilderFactory
190         .newAssessmentResultBuilder(swidTagCharacteristics.getTagType(), swidTagCharacteristics.isAuthoritative());
191 
192     // do the assessment
193     executor.execute(swidDocuemnt, assessmentResultBuilder);
194 
195     // generate the results
196     return assessmentResultBuilder.end().build(SWIDRequirementsManager.getInstance());
197   }
198 }