backend/common/rhnException.py | 10
backend/server/action/scap.py | 2
backend/server/handlers/xmlrpc/__init__.py | 2
backend/server/handlers/xmlrpc/scap.py | 104
++++++++++
backend/server/rhnLib.py | 13
+
client/rhel/spacewalk-oscap/scap.py | 92
+++++++-
java/code/src/com/redhat/rhn/domain/audit/XccdfTestResult.java | 12
+
java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java | 78
+++++++
java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml | 3
java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapFileManager.java | 68
++++++
java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java | 93
++++++++
java/code/webapp/WEB-INF/decorators.xml | 1
java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp | 12
+
java/code/webapp/WEB-INF/struts-config.xml | 6
14 files changed, 483 insertions(+), 13 deletions(-)
New commits:
commit 39b532a41612985fdbb9db8d93c0e90a53bc7558
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 23 15:59:12 2013 +0200
Open HTML Reports in a new window.
diff --git
a/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
index b9db5a9..56d68fe 100644
--- a/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
+++ b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
@@ -69,7 +69,7 @@ public class ScapDownloadAction extends DownloadAction {
ScapResultFile file = new ScapResultFile(testResult, filename);
log.debug("Serving " + file);
- if (!file.isHTML()) {
+ if (!file.getHTML()) {
response.setHeader("Content-Disposition", "attachment;
filename=" + filename);
}
return file;
diff --git a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
index c385370..d70f925 100644
--- a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
+++ b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
@@ -55,7 +55,7 @@ public class ScapResultFile implements StreamInfo {
* Query if the format of the given file is HTML.
* @return answer
*/
- public Boolean isHTML() {
+ public Boolean getHTML() {
return filename.endsWith(".html");
}
@@ -66,7 +66,7 @@ public class ScapResultFile implements StreamInfo {
if (filename.endsWith(".xml")) {
return "text/xml";
}
- else if (isHTML()) {
+ else if (getHTML()) {
return "text/html";
}
else {
diff --git a/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
b/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
index 78000c4..f22ddb1 100644
--- a/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
+++ b/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
@@ -88,8 +88,8 @@
<th><bean:message
key="system.audit.xccdfdetails.jsp.files"/>:</th>
<td>
<c:forEach items="${testResult.files}" var="file">
- <a
href="/rhn/systems/details/audit/ScapResultDownload.do?sid=${param.sid}&xid=${param.xid}&name=${file.filename}"><c:out
value="${file.filename}"/></a>
-
+ <a
href="/rhn/systems/details/audit/ScapResultDownload.do?sid=${param.sid}&xid=${param.xid}&name=${file.filename}"
+ target="${file.HTML ? '_blank' :
'_self'}"><c:out value="${file.filename}"/></a>
</c:forEach>
</td>
</tr>
commit 54aea31c301413a0254132cfeb3c51a59238c480
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 23 13:59:37 2013 +0200
Only non-HTML files shall be marked as an attachement.
HTML files (OpenSCAP SCAN Report) shall be opened directly
in the firefox. Non HTML files should be served as an attachement
offering users the save-as dialog.
diff --git
a/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
index ef7ef38..b9db5a9 100644
--- a/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
+++ b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
@@ -69,7 +69,9 @@ public class ScapDownloadAction extends DownloadAction {
ScapResultFile file = new ScapResultFile(testResult, filename);
log.debug("Serving " + file);
- response.setHeader("Content-Disposition", "attachment;
filename=" + filename);
+ if (!file.isHTML()) {
+ response.setHeader("Content-Disposition", "attachment;
filename=" + filename);
+ }
return file;
}
diff --git a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
index 61e3239..c385370 100644
--- a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
+++ b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
@@ -52,13 +52,21 @@ public class ScapResultFile implements StreamInfo {
}
/**
+ * Query if the format of the given file is HTML.
+ * @return answer
+ */
+ public Boolean isHTML() {
+ return filename.endsWith(".html");
+ }
+
+ /**
* {@inheritDoc}
*/
public String getContentType() {
if (filename.endsWith(".xml")) {
return "text/xml";
}
- else if (filename.endsWith(".html")) {
+ else if (isHTML()) {
return "text/html";
}
else {
commit 8b2a36ff58edfff5d1b76e6af9beb117daa5c476
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 23 13:37:58 2013 +0200
Exclude HTML file download from sitemesh.
diff --git a/java/code/webapp/WEB-INF/decorators.xml
b/java/code/webapp/WEB-INF/decorators.xml
index c3a34a0..062ba35 100644
--- a/java/code/webapp/WEB-INF/decorators.xml
+++ b/java/code/webapp/WEB-INF/decorators.xml
@@ -3,6 +3,7 @@
<decorators defaultdir="/WEB-INF/decorators">
<excludes>
<pattern>/img/*</pattern>
+ <pattern>/systems/details/audit/ScapResultDownload.do*</pattern>
</excludes>
<decorator name="layout_c" page="layout_c.jsp">
<pattern>/*</pattern>
commit 97e568f3b532d03762f6a43358e3551c9c125ac2
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Tue May 21 17:21:05 2013 +0200
Downloaded files shall be logged in debug mode.
diff --git
a/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
index 243d27d..ef7ef38 100644
--- a/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
+++ b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
@@ -17,6 +17,7 @@ package com.redhat.rhn.frontend.action.systems.audit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.apache.log4j.Logger;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DownloadAction;
@@ -56,6 +57,7 @@ public class ScapDownloadAction extends DownloadAction {
@Override
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
+ Logger log = Logger.getLogger(ScapDownloadAction.class);
RequestContext context = new RequestContext(request);
User user = context.getLoggedInUser();
Long sid = context.getRequiredParam("sid");
@@ -66,6 +68,7 @@ public class ScapDownloadAction extends DownloadAction {
String filename = context.getRequiredParamAsString("name");
ScapResultFile file = new ScapResultFile(testResult, filename);
+ log.debug("Serving " + file);
response.setHeader("Content-Disposition", "attachment;
filename=" + filename);
return file;
}
diff --git a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
index 4597900..61e3239 100644
--- a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
+++ b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
@@ -72,4 +72,14 @@ public class ScapResultFile implements StreamInfo {
public InputStream getInputStream() throws IOException {
return new FileInputStream(getAbsolutePath());
}
+
+ /**
+ * Get human readable representation of this class
+ * @return string
+ */
+ public String toString() {
+ return this.getClass().getName() +
+ "[path=" + getAbsolutePath() +
+ "]";
+ }
}
commit c0dbdf250e430e53c9935d0319a4a3c566cd2464
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Mon May 20 16:36:20 2013 +0200
Download of detailed SCAP result files.
diff --git a/java/code/src/com/redhat/rhn/domain/audit/XccdfTestResult.java
b/java/code/src/com/redhat/rhn/domain/audit/XccdfTestResult.java
index 7c422c8..70e4668 100644
--- a/java/code/src/com/redhat/rhn/domain/audit/XccdfTestResult.java
+++ b/java/code/src/com/redhat/rhn/domain/audit/XccdfTestResult.java
@@ -15,13 +15,15 @@
package com.redhat.rhn.domain.audit;
import java.util.Date;
+import java.util.List;
import com.redhat.rhn.common.hibernate.HibernateFactory;
import com.redhat.rhn.domain.action.scap.ScapActionDetails;
import com.redhat.rhn.domain.server.Server;
import com.redhat.rhn.manager.audit.ScapManager;
import com.redhat.rhn.manager.audit.scap.RuleResultDiffer;
-
+import com.redhat.rhn.manager.audit.scap.file.ScapFileManager;
+import com.redhat.rhn.manager.audit.scap.file.ScapResultFile;
/**
* XccdfTestResult - Class representation of the table rhnXccdfTestResult.
@@ -216,4 +218,12 @@ public class XccdfTestResult {
}
return diffIcon;
}
+
+ /**
+ * Return a list of detailed SCAP files assigned with this scan run.
+ * @return the result
+ */
+ public List<ScapResultFile> getFiles() {
+ return ScapFileManager.lookupFilesForTestResult(this);
+ }
}
diff --git
a/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
new file mode 100644
index 0000000..243d27d
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/frontend/action/systems/audit/ScapDownloadAction.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ *
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package com.redhat.rhn.frontend.action.systems.audit;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts.action.ActionForm;
+import org.apache.struts.action.ActionMapping;
+import org.apache.struts.actions.DownloadAction;
+
+import com.redhat.rhn.domain.audit.ScapFactory;
+import com.redhat.rhn.domain.audit.XccdfTestResult;
+import com.redhat.rhn.domain.server.Server;
+import com.redhat.rhn.domain.user.User;
+import com.redhat.rhn.frontend.struts.RequestContext;
+import com.redhat.rhn.manager.audit.scap.file.ScapResultFile;
+import com.redhat.rhn.manager.system.SystemManager;
+
+/**
+ * ScapDownloadAction
+ */
+public class ScapDownloadAction extends DownloadAction {
+/*
+ public ActionForward execute(ActionMapping mapping, ActionForm formIn,
+ HttpServletRequest request,
+ HttpServletResponse response) {
+
+ response.setHeader("Content-
+
+ try {
+ OutputStream
+
+ request.setAttribute("testResult", testResult);
+ request.setAttribute("system", server);
+
+ request.setAttribute(ListTagHelper.PARENT_URL,
+ request.getRequestURI() + "?sid=" + sid + "&xid="
+ xid);
+ SdcHelper.ssmCheck(request, sid, user);
+
+ return mapping.findForward(RhnHelper.DEFAULT_FORWARD);
+ }
+*/
+ @Override
+ protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form,
+ HttpServletRequest request, HttpServletResponse response) throws Exception {
+ RequestContext context = new RequestContext(request);
+ User user = context.getLoggedInUser();
+ Long sid = context.getRequiredParam("sid");
+ Server server = SystemManager.lookupByIdAndUser(sid, user);
+ Long xid = context.getRequiredParam("xid");
+ XccdfTestResult testResult = ScapFactory.lookupTestResultByIdAndSid(xid,
+ server.getId());
+ String filename = context.getRequiredParamAsString("name");
+ ScapResultFile file = new ScapResultFile(testResult, filename);
+
+ response.setHeader("Content-Disposition", "attachment;
filename=" + filename);
+ return file;
+ }
+
+}
diff --git a/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml
b/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml
index 9fa7e91..7662af1 100644
--- a/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml
+++ b/java/code/src/com/redhat/rhn/frontend/strings/jsp/StringResource_en_US.xml
@@ -11041,6 +11041,9 @@ the <strong>Red Hat Enterprise Linux System
Administration Guide.</stro
<trans-unit id="system.audit.xccdfdetails.jsp.errors">
<source>Scan's Error output</source>
</trans-unit>
+ <trans-unit id="system.audit.xccdfdetails.jsp.files">
+ <source>Detailed Results</source>
+ </trans-unit>
<trans-unit id="system.audit.xccdfdetails.jsp.xccdfrules">
<source>XCCDF Rule Results</source>
</trans-unit>
diff --git a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapFileManager.java
b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapFileManager.java
new file mode 100644
index 0000000..fcd8804
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapFileManager.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ *
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package com.redhat.rhn.manager.audit.scap.file;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.redhat.rhn.common.conf.Config;
+import com.redhat.rhn.common.conf.ConfigDefaults;
+import com.redhat.rhn.domain.audit.XccdfTestResult;
+
+/**
+ * ScapFileManager - Handling of full SCAP results assigned to a rhnXccdfTestResult
+ */
+public class ScapFileManager {
+ private ScapFileManager() {
+ }
+
+ /**
+ * Find SCAP Result files assigned with the given testResult
+ * @param testResult XccdfTestResult
+ * @return the list of files
+ */
+ public static List<ScapResultFile> lookupFilesForTestResult(
+ XccdfTestResult testResult) {
+ List<ScapResultFile> result = new ArrayList<ScapResultFile>();
+ File folder = new File(getStoragePath(testResult));
+ for (File file : folder.listFiles()) {
+ if (file.isFile()) {
+ result.add(new ScapResultFile(testResult, file.getName()));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Get file path to the storage directory assigned with a given testResult
+ * @param tr TestResult
+ * @return the path
+ */
+ public static String getStoragePath(XccdfTestResult tr) {
+ return Config.get().getString(ConfigDefaults.MOUNT_POINT) +
+ "/" + getStorageRelativePath(tr);
+ }
+
+ private static String getStorageRelativePath(XccdfTestResult tr) {
+ return getActionPath(tr.getServer().getOrg().getId(),
+ tr.getServer().getId(),
tr.getScapActionDetails().getParentAction().getId());
+ }
+
+ private static String getActionPath(Long orgId, Long systemId, Long actionId) {
+ // an equivalent of rhnLib.get_action_path()
+ return "systems/" + orgId + "/" + systemId +
"/actions/" + actionId;
+ }
+}
diff --git a/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
new file mode 100644
index 0000000..4597900
--- /dev/null
+++ b/java/code/src/com/redhat/rhn/manager/audit/scap/file/ScapResultFile.java
@@ -0,0 +1,75 @@
+/**
+ * Copyright (c) 2013 Red Hat, Inc.
+ *
+ * This software is licensed to you under the GNU General Public License,
+ * version 2 (GPLv2). There is NO WARRANTY for this software, express or
+ * implied, including the implied warranties of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+ * along with this software; if not, see
+ *
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * Red Hat trademarks are not licensed under GPLv2. No permission is
+ * granted to use or replicate Red Hat trademarks that are incorporated
+ * in this software or its documentation.
+ */
+package com.redhat.rhn.manager.audit.scap.file;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.struts.actions.DownloadAction.StreamInfo;
+
+import com.redhat.rhn.domain.audit.XccdfTestResult;
+
+/**
+ * ScapResultFile
+ */
+public class ScapResultFile implements StreamInfo {
+ private XccdfTestResult testResult;
+ private String filename;
+
+ /**
+ * Constructeur
+ * @param testResultIn The XccdfTestResult which is assigned with the given file
+ * @param filenameIn The file name
+ */
+ public ScapResultFile(XccdfTestResult testResultIn, String filenameIn) {
+ testResult = testResultIn;
+ filename = filenameIn;
+ }
+
+ /**
+ * Return the file name of this file
+ * @return the file name
+ */
+ public String getFilename() {
+ return filename;
+ }
+
+ private String getAbsolutePath() {
+ return ScapFileManager.getStoragePath(testResult) + "/" + filename;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getContentType() {
+ if (filename.endsWith(".xml")) {
+ return "text/xml";
+ }
+ else if (filename.endsWith(".html")) {
+ return "text/html";
+ }
+ else {
+ return "application/octet-stream";
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InputStream getInputStream() throws IOException {
+ return new FileInputStream(getAbsolutePath());
+ }
+}
diff --git a/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
b/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
index 5e52a0b..78000c4 100644
--- a/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
+++ b/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
@@ -83,6 +83,17 @@
<th><bean:message
key="system.audit.xccdfdetails.jsp.errors"/>:</th>
<td><pre><c:out
value="${testResult.errrosContents}"/></pre></th>
</tr>
+ <c:if test="${not empty testResult.files}">
+ <tr>
+ <th><bean:message
key="system.audit.xccdfdetails.jsp.files"/>:</th>
+ <td>
+ <c:forEach items="${testResult.files}" var="file">
+ <a
href="/rhn/systems/details/audit/ScapResultDownload.do?sid=${param.sid}&xid=${param.xid}&name=${file.filename}"><c:out
value="${file.filename}"/></a>
+
+ </c:forEach>
+ </td>
+ </tr>
+ </c:if>
</table>
<h2><bean:message
key="system.audit.xccdfdetails.jsp.xccdfrules"/></h2>
diff --git a/java/code/webapp/WEB-INF/struts-config.xml
b/java/code/webapp/WEB-INF/struts-config.xml
index 272846e..edaad8a 100644
--- a/java/code/webapp/WEB-INF/struts-config.xml
+++ b/java/code/webapp/WEB-INF/struts-config.xml
@@ -2997,6 +2997,12 @@
path="/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp"/>
</action>
+ <action path="/systems/details/audit/ScapResultDownload"
+ scope="request"
+ type="com.redhat.rhn.frontend.action.systems.audit.ScapDownloadAction"
+ className="com.redhat.rhn.frontend.struts.RhnActionMapping">
+ </action>
+
<action path="/systems/details/audit/RuleDetails"
scope="request"
input="/WEB-INF/pages/systems/details/audit/ruledetails.jsp"
commit 9af2e9263d8f6177bfa97c5ad0c897d5b7609a3a
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Mon May 20 10:14:14 2013 +0200
Godforsaken closing <tr> node.
diff --git a/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
b/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
index 0b83133..5e52a0b 100644
--- a/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
+++ b/java/code/webapp/WEB-INF/pages/systems/details/audit/xccdfdetails.jsp
@@ -82,6 +82,7 @@
<tr>
<th><bean:message
key="system.audit.xccdfdetails.jsp.errors"/>:</th>
<td><pre><c:out
value="${testResult.errrosContents}"/></pre></th>
+ </tr>
</table>
<h2><bean:message
key="system.audit.xccdfdetails.jsp.xccdfrules"/></h2>
commit b31837cac3bd3e364bd6bbd8f5cc8aa0b992704a
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Tue May 21 16:49:01 2013 +0200
Submit the OpenSCAP HTML report as well.
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index 2ce4726..4caa7cc 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -84,7 +84,7 @@ def _popen(args):
def _process_params(args, filename, results_dir=None):
params = ['--results', filename]
if results_dir:
- params += ['--oval-results']
+ params += ['--oval-results', '--report',
'xccdf-report.html']
errors = ''
if args:
allowed_args = {
commit fd631cb7ceb8b451fde9fcecf989f8372bfebad9
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Fri May 17 09:08:51 2013 +0200
Rewind, after using SAX to parse XML.
Otherwise, a subsequent read will go short.
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index 38532f7..2ce4726 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -159,7 +159,10 @@ def _cleanup_temp(results_dir):
def _assert_xml(f):
try:
- xml.sax.parse(f, xml.sax.ContentHandler())
- return True
- except:
- return False
+ try:
+ xml.sax.parse(f, xml.sax.ContentHandler())
+ return True
+ except:
+ return False
+ finally:
+ f.seek(0)
commit 85f92dc2942e5c7cc04278cc1c794981a38b186a
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 16 14:22:44 2013 +0200
Upload also full XCCDF results along the OVAL results.
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index c62a8f2..38532f7 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -39,17 +39,18 @@ def xccdf_eval(args, cache_only=None):
return (1, 'oscap tool did not produce valid xml.\n' + oscap_err, {})
ret, resume, xslt_err = _xccdf_resume(results_file.name)
- del(results_file)
if ret != 0 or resume == '':
+ del(results_file)
_cleanup_temp(results_dir)
return (1, 'Problems with extracting resume:\n' + xslt_err, {})
try:
- up_err = _upload_results(results_dir, args)
+ up_err = _upload_results(results_file, results_dir, args)
except:
# An error during the upload must not prevent scan completion
log.log_exception(*sys.exc_info())
up_err = "Upload of detailed results failed. Fatal error in Python code
occurred"
+ del(results_file)
_cleanup_temp(results_dir)
return (0, 'openscap scan completed', {
'resume': encodestring(resume),
@@ -110,7 +111,7 @@ def _process_params(args, filename, results_dir=None):
errors += '\n'
return params, errors
-def _upload_results(results_dir, args):
+def _upload_results(xccdf_result, results_dir, args):
errors = ''
if results_dir:
server = rhnserver.RhnServer()
@@ -119,9 +120,14 @@ def _upload_results(results_dir, args):
systemid = up2dateAuth.getSystemId()
for filename in os.listdir(results_dir):
path = os.path.join(results_dir, filename)
- f = open(path, 'r')
+ if path == xccdf_result.name:
+ f = xccdf_result.file
+ filename = "xccdf-results.xml"
+ else:
+ f = open(path, 'r')
errors += _upload_file(server, systemid, args, path, filename, f)
- f.close()
+ if path != xccdf_result.name:
+ f.close()
return errors
def _upload_file(server, systemid, args, path, filename, f):
commit d564f03081d91920fe1b319f5feac81daccf89f0
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 16 13:40:08 2013 +0200
Refactor: Extract function _upload_file().
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index 6336dbe..c62a8f2 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -120,30 +120,32 @@ def _upload_results(results_dir, args):
for filename in os.listdir(results_dir):
path = os.path.join(results_dir, filename)
f = open(path, 'r')
- if not _assert_xml(f):
- log.log_debug('Excluding "%s" file from upload. Not an
XML.', path)
- errors += '\nFile "%s" not uploaded. Not an XML file
format.', filename
- f.close()
- continue
-
- stat = os.fstat(f.fileno())
- if stat.st_size < args['file_size']:
- try:
- ret = server.scap.upload_result(systemid, args['id'],
+ errors += _upload_file(server, systemid, args, path, filename, f)
+ f.close()
+ return errors
+
+def _upload_file(server, systemid, args, path, filename, f):
+ if not _assert_xml(f):
+ log.log_debug('Excluding "%s" file from upload. Not an XML.',
path)
+ return '\nFile "%s" not uploaded. Not an XML file format.',
filename
+
+ stat = os.fstat(f.fileno())
+ if stat.st_size < args['file_size']:
+ try:
+ ret = server.scap.upload_result(systemid, args['id'],
{'filename': filename,
'filecontent': encodestring(f.read()),
'content-encoding': 'base64',
})
- if ret and ret['result']:
- log.log_debug('The file %s uploaded successfully.' %
filename)
- except up2dateErrors.Error, e:
- log.log_exception(*sys.exc_info())
- errors += '\nFile "%s" not uploaded. %s' %
(filename, e)
- else:
- errors += '\nFile "%s" not uploaded. File size (%d B)
exceeds the limit.' \
- % (filename, stat.st_size)
- f.close()
- return errors
+ if ret and ret['result']:
+ log.log_debug('The file %s uploaded successfully.' % filename)
+ return ''
+ except up2dateErrors.Error, e:
+ log.log_exception(*sys.exc_info())
+ return '\nFile "%s" not uploaded. %s' % (filename, e)
+ else:
+ return '\nFile "%s" not uploaded. File size (%d B) exceeds the
limit.' \
+ % (filename, stat.st_size)
def _cleanup_temp(results_dir):
if results_dir:
commit eba95bdbcb0dfe83007905a9eeeaf8dae606fab2
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 16 11:40:38 2013 +0200
Make sure to only upload XML files
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index de8fec2..6336dbe 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -120,6 +120,12 @@ def _upload_results(results_dir, args):
for filename in os.listdir(results_dir):
path = os.path.join(results_dir, filename)
f = open(path, 'r')
+ if not _assert_xml(f):
+ log.log_debug('Excluding "%s" file from upload. Not an
XML.', path)
+ errors += '\nFile "%s" not uploaded. Not an XML file
format.', filename
+ f.close()
+ continue
+
stat = os.fstat(f.fileno())
if stat.st_size < args['file_size']:
try:
commit 999fa65d57be9048294bdcdc020bbec220cd3691
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 16 11:35:40 2013 +0200
Use opened socket when to assessing file type.
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index e5a1f2a..de8fec2 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -33,7 +33,7 @@ def xccdf_eval(args, cache_only=None):
if results_dir:
os.chdir(pwd)
- if not _assert_xml(results_file.name):
+ if not _assert_xml(results_file.file):
del(results_file)
_cleanup_temp(results_dir)
return (1, 'oscap tool did not produce valid xml.\n' + oscap_err, {})
@@ -143,14 +143,9 @@ def _cleanup_temp(results_dir):
if results_dir:
shutil.rmtree(results_dir)
-def _assert_xml(filename):
- f = open(filename, 'rb')
+def _assert_xml(f):
try:
- try:
- xml.sax.parse(f, xml.sax.ContentHandler())
- return True
- except:
- return False
- finally:
- f.close()
-
+ xml.sax.parse(f, xml.sax.ContentHandler())
+ return True
+ except:
+ return False
commit af1fdd902a64a6c53477a2025c7003eaad6449ff
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Fri May 10 09:02:48 2013 +0200
Client shall upload full results of the scap.xccdf_eval action
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index 05e6af7..e5a1f2a 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -1,11 +1,16 @@
import sys
+import os
import subprocess
import xml.sax
import tempfile
+import shutil
from base64 import encodestring
sys.path.append("/usr/share/rhn/")
from up2date_client import up2dateLog
+from up2date_client import rhnserver
+from up2date_client import up2dateAuth
+from up2date_client import up2dateErrors
__rhnexport__ = [ 'xccdf_eval' ]
@@ -15,21 +20,40 @@ def xccdf_eval(args, cache_only=None):
if cache_only:
return (0, 'no-ops for caching', {})
- results_file = tempfile.NamedTemporaryFile()
- params, oscap_err = _process_params(args['params'], results_file.name)
+ results_dir = None
+ if ('id' in args) and ('file_size' in args) and
args['file_size'] > 0:
+ results_dir = tempfile.mkdtemp()
+ pwd = os.getcwd()
+ os.chdir(results_dir)
+
+ results_file = tempfile.NamedTemporaryFile(dir=results_dir)
+ params, oscap_err = _process_params(args['params'], results_file.name,
results_dir)
+
oscap_err += _run_oscap(['xccdf', 'eval'] + params +
[args['path']])
+ if results_dir:
+ os.chdir(pwd)
if not _assert_xml(results_file.name):
del(results_file)
+ _cleanup_temp(results_dir)
return (1, 'oscap tool did not produce valid xml.\n' + oscap_err, {})
ret, resume, xslt_err = _xccdf_resume(results_file.name)
del(results_file)
if ret != 0 or resume == '':
+ _cleanup_temp(results_dir)
return (1, 'Problems with extracting resume:\n' + xslt_err, {})
+
+ try:
+ up_err = _upload_results(results_dir, args)
+ except:
+ # An error during the upload must not prevent scan completion
+ log.log_exception(*sys.exc_info())
+ up_err = "Upload of detailed results failed. Fatal error in Python code
occurred"
+ _cleanup_temp(results_dir)
return (0, 'openscap scan completed', {
'resume': encodestring(resume),
- 'errors': encodestring(oscap_err + xslt_err)
+ 'errors': encodestring(oscap_err + xslt_err + up_err)
})
def _run_oscap(arguments):
@@ -56,8 +80,10 @@ def _popen(args):
return subprocess.Popen(args, bufsize=-1, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
-def _process_params(args, filename):
+def _process_params(args, filename, results_dir=None):
params = ['--results', filename]
+ if results_dir:
+ params += ['--oval-results']
errors = ''
if args:
allowed_args = {
@@ -84,6 +110,39 @@ def _process_params(args, filename):
errors += '\n'
return params, errors
+def _upload_results(results_dir, args):
+ errors = ''
+ if results_dir:
+ server = rhnserver.RhnServer()
+ # No need to check capabilities. The server supports detailed results
+ # If rhe 'file_size' and 'id' was in supplied in the argument
list.
+ systemid = up2dateAuth.getSystemId()
+ for filename in os.listdir(results_dir):
+ path = os.path.join(results_dir, filename)
+ f = open(path, 'r')
+ stat = os.fstat(f.fileno())
+ if stat.st_size < args['file_size']:
+ try:
+ ret = server.scap.upload_result(systemid, args['id'],
+ {'filename': filename,
+ 'filecontent': encodestring(f.read()),
+ 'content-encoding': 'base64',
+ })
+ if ret and ret['result']:
+ log.log_debug('The file %s uploaded successfully.' %
filename)
+ except up2dateErrors.Error, e:
+ log.log_exception(*sys.exc_info())
+ errors += '\nFile "%s" not uploaded. %s' %
(filename, e)
+ else:
+ errors += '\nFile "%s" not uploaded. File size (%d B)
exceeds the limit.' \
+ % (filename, stat.st_size)
+ f.close()
+ return errors
+
+def _cleanup_temp(results_dir):
+ if results_dir:
+ shutil.rmtree(results_dir)
+
def _assert_xml(filename):
f = open(filename, 'rb')
try:
commit 4aa54f32ab198b70ec0deb6559a1adb391996f8d
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Fri May 10 14:24:44 2013 +0200
Backend handlers for receiving full SCAP results
diff --git a/backend/common/rhnException.py b/backend/common/rhnException.py
index ee82eea..6db1316 100644
--- a/backend/common/rhnException.py
+++ b/backend/common/rhnException.py
@@ -234,14 +234,20 @@ maximum membership exceeded"),
4016: _("Invalid revision number"),
4017: _("Cannot compare files of different file type"),
- # 5000 - 5999: crash reporting errors
+ # 5000 - 5999: client content uploading errors
+ # 5000 - 5099: crash reporting errors
5000: _("Crash information is invalid or incomplete"),
5001: _("Crash file information is invalid or incomplete"),
5002: _("Error composing crash directory path"),
5003: _("Error composing crash file path"),
5004: _("Invalid content encoding"),
5005: _("Invalid crash name"),
- 5006: _("Crash reporting is disabled for this organization")
+ 5006: _("Crash reporting is disabled for this organization"),
+ # 5100 - 5199: scap results reporting error
+ 5101: _("SCAP results file transfer is invalid or incomplete"),
+ 5102: _("Error composing directory path for detailed SCAP results"),
+ 5103: _("Error composing file path for detailed SCAP results"),
+ 5104: _("Invalid content encoding"),
}
diff --git a/backend/server/handlers/xmlrpc/__init__.py
b/backend/server/handlers/xmlrpc/__init__.py
index 708b4cd..ee2a005 100644
--- a/backend/server/handlers/xmlrpc/__init__.py
+++ b/backend/server/handlers/xmlrpc/__init__.py
@@ -25,6 +25,7 @@ import errata
import proxy
import get_handler
import abrt
+import scap
rpcClasses = {
"registration" : registration.Registration,
@@ -34,6 +35,7 @@ rpcClasses = {
"proxy" : proxy.Proxy,
"servers" : up2date.Servers,
"abrt" : abrt.Abrt,
+ "scap" : scap.Scap,
}
getHandler = get_handler.GetHandler
diff --git a/backend/server/handlers/xmlrpc/scap.py
b/backend/server/handlers/xmlrpc/scap.py
new file mode 100644
index 0000000..2a483bf
--- /dev/null
+++ b/backend/server/handlers/xmlrpc/scap.py
@@ -0,0 +1,104 @@
+#
+# Copyright (c) 2013 Red Hat, Inc.
+#
+# This software is licensed to you under the GNU General Public License,
+# version 2 (GPLv2). There is NO WARRANTY for this software, express or
+# implied, including the implied warranties of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
+# along with this software; if not, see
+#
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+#
+# Red Hat trademarks are not licensed under GPLv2. No permission is
+# granted to use or replicate Red Hat trademarks that are incorporated
+# in this software or its documentation.
+#
+
+import os
+import stat
+from base64 import decodestring
+
+from spacewalk.common.rhnException import rhnFault
+from spacewalk.common.rhnConfig import CFG
+from spacewalk.common.rhnLog import log_error, log_debug
+from spacewalk.server import rhnSQL
+from spacewalk.server.rhnHandler import rhnHandler
+from spacewalk.server.rhnLib import get_action_path, get_actionfile_path
+
+class Scap(rhnHandler):
+ def __init__(self):
+ rhnHandler.__init__(self)
+ self.functions.append('upload_result')
+
+ def upload_result(self, system_id, action_id, scap_file):
+ self.auth_system(system_id)
+ self._authorize_request(action_id)
+
+ required_keys = ['filename', 'filecontent',
'content-encoding']
+ for k in required_keys:
+ if not scap_file.has_key(k):
+ log_debug(1, self.server_id, "The scap file data is invalid or
incomplete: %s" % scap_file)
+ raise rhnFault(5101, "Missing or invalid key: %s" % k)
+
+ return self._store_file(action_id, scap_file)
+
+ def _store_file(self, action_id, scap_file):
+ r_dir = get_action_path(self.server.server['org_id'], self.server_id,
action_id)
+ if not r_dir:
+ log_debug(1, self.server_id, "Error composing SCAP action directory
path")
+ raise rhnFault(5102)
+ r_file = get_actionfile_path(self.server.server['org_id'],
self.server_id, action_id, scap_file['filename'])
+ if not r_file:
+ log_debug(1, self.server_id, "Error composing SCAP action file
path")
+ raise rhnFault(5103)
+
+ if not scap_file['content-encoding'] == 'base64':
+ log_debug(1, self.server_id, "Invalid content encoding: %s" %
scap_file['content-encoding'])
+ raise rhnFault(5104)
+
+ # Create the file on filer
+ filecontent = decodestring(scap_file['filecontent'])
+ # TODO assert for the size of the file
+
+ absolute_dir = os.path.join(CFG.MOUNT_POINT, r_dir)
+ absolute_file = os.path.join(absolute_dir, scap_file['filename'])
+
+ if not os.path.exists(absolute_dir):
+ log_debug(1, self.server_id, "Creating action directory: %s" %
absolute_dir)
+ os.makedirs(absolute_dir)
+ mode = stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | stat.S_IXOTH
+ os.chmod(absolute_dir, mode)
+ os.chmod(os.path.dirname(os.path.normpath(absolute_dir)), mode)
+ log_debug(1, self.server_id, "Creating file: %s" % absolute_file)
+ f = open(absolute_file, 'w+')
+ f.write(filecontent)
+ return {'result': True,
+ }
+
+ def _authorize_request(self, action_id):
+ # Make sure that database contains records in
+ # rhnServerAction and rhnActionScap
+ # and not contains records in
+ # rhnXccdfTestResult
+ # for given (system_id, action_id) pair
+ h = rhnSQL.prepare(_query_authorize_request)
+ h.execute(server_id=self.server_id, action_id=action_id)
+ exists = h.fetchone()
+ if len(exists) != 1:
+ raise rhnFault(50, _("Invalid system_id/action_id pair."))
+
+_query_authorize_request = rhnSQL.Statement("""
+select 1
+ from rhnServerAction rsa,
+ rhnActionScap ras
+ where rsa.server_id = :server_id
+ and rsa.action_id = :action_id
+ and rsa.action_id = ras.action_id
+ and rsa.status in (0, 1)
+ and not exists
+ (
+ select rxt.id
+ from rhnXccdfTestresult rxt
+ where rxt.server_id = rsa.server_id
+ and rxt.action_scap_id = ras.id
+ )
+""")
diff --git a/backend/server/rhnLib.py b/backend/server/rhnLib.py
index 50ddb54..75c1a0f 100644
--- a/backend/server/rhnLib.py
+++ b/backend/server/rhnLib.py
@@ -228,3 +228,16 @@ def get_crashfile_path(org_id, system_id, crash, filename):
return path
else:
return None
+
+def get_action_path(org_id, system_id, action_id):
+ """For a given org_id, system_id, and action_id, return relative path
to a store directory."""
+ path = os.path.join('systems', str(org_id), str(system_id),
'actions', str(action_id))
+ if _is_secure_path(path):
+ return path
+
+def get_actionfile_path(org_id, system_id, action_id, filename):
+ """For a given org_id, system_id, action_id, and file, return relative
path to a file."""
+ path = os.path.join(get_action_path(org_id, system_id, action_id), str(filename))
+
+ if _is_secure_path(path):
+ return path
commit f531866c4d7ab0e951ba98d7b572451f45678c0e
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 2 16:11:18 2013 +0200
Delete the temp file even when the content is useless
diff --git a/client/rhel/spacewalk-oscap/scap.py b/client/rhel/spacewalk-oscap/scap.py
index 6cd4f6b..05e6af7 100644
--- a/client/rhel/spacewalk-oscap/scap.py
+++ b/client/rhel/spacewalk-oscap/scap.py
@@ -20,6 +20,7 @@ def xccdf_eval(args, cache_only=None):
oscap_err += _run_oscap(['xccdf', 'eval'] + params +
[args['path']])
if not _assert_xml(results_file.name):
+ del(results_file)
return (1, 'oscap tool did not produce valid xml.\n' + oscap_err, {})
ret, resume, xslt_err = _xccdf_resume(results_file.name)
commit 04db8531747fd6c256504fcb2657add19d456374
Author: Simon Lukasik <slukasik(a)redhat.com>
Date: Thu May 2 14:56:59 2013 +0200
Challenge clients to upload result files from the audit
diff --git a/backend/server/action/scap.py b/backend/server/action/scap.py
index d587a79..c28274b 100644
--- a/backend/server/action/scap.py
+++ b/backend/server/action/scap.py
@@ -33,5 +33,7 @@ def xccdf_eval(server_id, action_id, dry_run=0):
"%s for server %s" % (action_id, server_id))
return ({
'path': dict['path'],
+ 'id': action_id,
+ 'file_size': 2097152,
'params': rhnSQL.read_lob(dict['parameters']) or ''
},)