diff --git a/openscap-policies/pom-template.xml b/openscap-policies/pom-template.xml
new file mode 100644
index 000000000..b76c72dec
--- /dev/null
+++ b/openscap-policies/pom-template.xml
@@ -0,0 +1,152 @@
+
+ 4.0.0
+ com.normation.plugins
+ openscap-policies
+ jar
+
+ ${plugin-version}
+
+
+ com.normation.plugins
+ plugins-parent
+ ${rudder-branch}-${parent-version}
+
+
+
+ OpenSCAP audits managed by Rudder
+
+
+
+ openscappolicies
+
+
+
+
+
+
+ org.codehaus.mojo
+ properties-maven-plugin
+
+
+ maven-resources-plugin
+
+
+ maven-shade-plugin
+
+
+
+
+
+
+
+ org.owasp.antisamy
+ antisamy
+ 1.5.9
+
+
+
+
+
+
+
+
+ internal-default
+
+
+ !limited
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.0.0
+
+
+ add-source
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+
+
+
+ internal-limited
+
+
+ limited
+
+
+
+ org.codehaus.mojo
+ templating-maven-plugin
+ 1.0.0
+
+
+ filter-src
+
+ filter-sources
+
+
+ ${basedir}/src/main/scala-templates/limited
+ ${project.build.directory}/generated
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ 3.0.0
+
+
+ add-license-checker-source
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+
+
+ com.normation.plugins
+ plugins-common-private
+
+
+
+
+ rudder-release-private
+ http://nexus.normation.com/nexus/content/repositories/private-releases/
+ default
+ false
+
+
+ rudder-snapshot-private
+ http://nexus.normation.com/nexus/content/repositories/private-snapshots/
+ default
+ true
+
+
+
+
+
+
diff --git a/openscap-policies/src/main/resources/antisamy-slashdot.xml b/openscap-policies/src/main/resources/antisamy-slashdot.xml
new file mode 100644
index 000000000..4e32d0286
--- /dev/null
+++ b/openscap-policies/src/main/resources/antisamy-slashdot.xml
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ g
+ grin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openscap-policies/src/main/resources/antisamy.xml b/openscap-policies/src/main/resources/antisamy.xml
new file mode 100644
index 000000000..762813f65
--- /dev/null
+++ b/openscap-policies/src/main/resources/antisamy.xml
@@ -0,0 +1,2789 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ g
+ grin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openscap-policies/src/main/scala-templates/default/com/normation/plugins/openscappolicies/EnablePluginImpl.scala b/openscap-policies/src/main/scala-templates/default/com/normation/plugins/openscappolicies/EnablePluginImpl.scala
new file mode 100644
index 000000000..ab6f05131
--- /dev/null
+++ b/openscap-policies/src/main/scala-templates/default/com/normation/plugins/openscappolicies/EnablePluginImpl.scala
@@ -0,0 +1,48 @@
+/*
+*************************************************************************************
+* Copyright 2020 Normation SAS
+*************************************************************************************
+*
+* This file is part of Rudder.
+*
+* Rudder is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* In accordance with the terms of section 7 (7. Additional Terms.) of
+* the GNU General Public License version 3, the copyright holders add
+* the following Additional permissions:
+* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
+* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
+* Public License version 3, when you create a Related Module, this
+* Related Module is not considered as a part of the work and may be
+* distributed under the license agreement of your choice.
+* A "Related Module" means a set of sources files including their
+* documentation that, without modification of the Source Code, enables
+* supplementary functions or services in addition to those offered by
+* the Software.
+*
+* Rudder is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Rudder. If not, see .
+
+*
+*************************************************************************************
+*/
+
+package com.normation.plugins.openscappolicies
+
+import com.normation.plugins.PluginEnableImpl
+import com.normation.rudder.services.nodes.NodeInfoService
+
+/*
+ * The class will be loaded by ServiceLoader, it needs an empty constructor.
+ */
+
+final class CheckRudderPluginEnableImpl(nodeInfoService: NodeInfoService) extends PluginEnableImpl
+
diff --git a/openscap-policies/src/main/scala-templates/limited/com/normation/plugins/openscappolicies/EnablePluginImpl.scala b/openscap-policies/src/main/scala-templates/limited/com/normation/plugins/openscappolicies/EnablePluginImpl.scala
new file mode 100644
index 000000000..1123bc42f
--- /dev/null
+++ b/openscap-policies/src/main/scala-templates/limited/com/normation/plugins/openscappolicies/EnablePluginImpl.scala
@@ -0,0 +1,59 @@
+/*
+*************************************************************************************
+* Copyright 2020 Normation SAS
+*************************************************************************************
+*
+* This file is part of Rudder.
+*
+* Rudder is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* In accordance with the terms of section 7 (7. Additional Terms.) of
+* the GNU General Public License version 3, the copyright holders add
+* the following Additional permissions:
+* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
+* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
+* Public License version 3, when you create a Related Module, this
+* Related Module is not considered as a part of the work and may be
+* distributed under the license agreement of your choice.
+* A "Related Module" means a set of sources files including their
+* documentation that, without modification of the Source Code, enables
+* supplementary functions or services in addition to those offered by
+* the Software.
+*
+* Rudder is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Rudder. If not, see .
+
+*
+*************************************************************************************
+*/
+
+package com.normation.plugins.openscappolicies
+
+import com.normation.plugins.LicensedPluginCheck
+import com.normation.rudder.services.nodes.NodeInfoService
+
+/*
+ * This template file will processed at build time to choose
+ * the correct immplementation to use for the interface.
+ * The default implementation is to always enable status.
+ *
+ * The class will be loaded by ServiceLoader, it needs an empty constructor.
+ */
+final class CheckRudderPluginEnableImpl(nodeInfoService: NodeInfoService) extends LicensedPluginCheck {
+ // here are processed variables
+ def pluginResourcePublickey = "${plugin-resource-publickey}"
+ def pluginResourceLicense = "${plugin-resource-license}"
+ def pluginDeclaredVersion = "${plugin-declared-version}"
+ def pluginId = "${plugin-fullname}"
+
+ override def getNumberOfNodes: Int = nodeInfoService.getNumberOfManagedNodes
+}
+
diff --git a/openscap-policies/src/main/scala/bootstrap/rudder/plugin/OpenscapPoliciesConf.scala b/openscap-policies/src/main/scala/bootstrap/rudder/plugin/OpenscapPoliciesConf.scala
new file mode 100644
index 000000000..ed8e783d4
--- /dev/null
+++ b/openscap-policies/src/main/scala/bootstrap/rudder/plugin/OpenscapPoliciesConf.scala
@@ -0,0 +1,68 @@
+/*
+*************************************************************************************
+* Copyright 2020 Normation SAS
+*************************************************************************************
+*
+* This file is part of Rudder.
+*
+* Rudder is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* In accordance with the terms of section 7 (7. Additional Terms.) of
+* the GNU General Public License version 3, the copyright holders add
+* the following Additional permissions:
+* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
+* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
+* Public License version 3, when you create a Related Module, this
+* Related Module is not considered as a part of the work and may be
+* distributed under the license agreement of your choice.
+* A "Related Module" means a set of sources files including their
+* documentation that, without modification of the Source Code, enables
+* supplementary functions or services in addition to those offered by
+* the Software.
+*
+* Rudder is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Rudder. If not, see .
+
+*
+*************************************************************************************
+*/
+
+package bootstrap.rudder.plugin
+
+import bootstrap.liftweb.RudderConfig
+import com.normation.plugins.openscappolicies.OpenscapPoliciesPluginDef
+import com.normation.plugins.openscappolicies.CheckRudderPluginEnableImpl
+import net.liftweb.common.Loggable
+import com.normation.plugins.RudderPluginModule
+import com.normation.plugins.openscappolicies.api.OpenScapApiImpl
+import com.normation.plugins.openscappolicies.extension.OpenScapNodeDetailsExtension
+import com.normation.plugins.openscappolicies.services.{OpenScapReportReader, ReportSanitizer}
+
+/*
+ * Actual configuration of the plugin logic
+ */
+object OpenscapPoliciesConf extends RudderPluginModule {
+
+ val POLICY_SANITIZATION_FILE = "/home/nicolas/dev/rudder-plugins/openscap-policies/src/main/resources/antisamy.xml"
+ // by build convention, we have only one of that on the classpath
+ lazy val pluginStatusService = new CheckRudderPluginEnableImpl(RudderConfig.nodeInfoService)
+
+ lazy val pluginDef = new OpenscapPoliciesPluginDef(OpenscapPoliciesConf.pluginStatusService)
+
+ lazy val reportSanitizer = new ReportSanitizer(POLICY_SANITIZATION_FILE)
+ lazy val openScapReportReader = new OpenScapReportReader(RudderConfig.nodeInfoService)
+
+ lazy val openScapApiImpl = new OpenScapApiImpl(RudderConfig.restExtractorService, openScapReportReader, reportSanitizer)
+ // other service instanciation / initialization
+ RudderConfig.snippetExtensionRegister.register(new OpenScapNodeDetailsExtension(pluginStatusService, openScapReportReader, reportSanitizer))
+
+
+}
diff --git a/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/DataTypes.scala b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/DataTypes.scala
new file mode 100644
index 000000000..42a2790ee
--- /dev/null
+++ b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/DataTypes.scala
@@ -0,0 +1,57 @@
+/*
+*************************************************************************************
+* Copyright 2020 Normation SAS
+*************************************************************************************
+*
+* This file is part of Rudder.
+*
+* Rudder is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* In accordance with the terms of section 7 (7. Additional Terms.) of
+* the GNU General Public License version 3, the copyright holders add
+* the following Additional permissions:
+* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
+* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
+* Public License version 3, when you create a Related Module, this
+* Related Module is not considered as a part of the work and may be
+* distributed under the license agreement of your choice.
+* A "Related Module" means a set of sources files including their
+* documentation that, without modification of the Source Code, enables
+* supplementary functions or services in addition to those offered by
+* the Software.
+*
+* Rudder is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Rudder. If not, see .
+
+*
+*************************************************************************************
+*/
+
+package com.normation.plugins.openscappolicies
+
+import java.io.FileNotFoundException
+
+import com.normation.inventory.domain.NodeId
+import net.liftweb.common._
+import org.slf4j.LoggerFactory
+import org.xml.sax.SAXParseException
+
+import scala.xml._
+
+/**
+ * Applicative log of interest for Rudder ops.
+ */
+object OpenscapPoliciesLogger extends Logger {
+ override protected def _logger = LoggerFactory.getLogger("openscap-policies")
+}
+
+// other data types for you plugin
+case class OpenScapReport(nodeId: NodeId, content: String)
\ No newline at end of file
diff --git a/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/OpenscapPoliciesPluginDef.scala b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/OpenscapPoliciesPluginDef.scala
new file mode 100644
index 000000000..99cb939ea
--- /dev/null
+++ b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/OpenscapPoliciesPluginDef.scala
@@ -0,0 +1,83 @@
+/*
+*************************************************************************************
+* Copyright 2020 Normation SAS
+*************************************************************************************
+*
+* This file is part of Rudder.
+*
+* Rudder is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* In accordance with the terms of section 7 (7. Additional Terms.) of
+* the GNU General Public License version 3, the copyright holders add
+* the following Additional permissions:
+* Notwithstanding to the terms of section 5 (5. Conveying Modified Source
+* Versions) and 6 (6. Conveying Non-Source Forms.) of the GNU General
+* Public License version 3, when you create a Related Module, this
+* Related Module is not considered as a part of the work and may be
+* distributed under the license agreement of your choice.
+* A "Related Module" means a set of sources files including their
+* documentation that, without modification of the Source Code, enables
+* supplementary functions or services in addition to those offered by
+* the Software.
+*
+* Rudder is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with Rudder. If not, see .
+
+*
+*************************************************************************************
+*/
+
+package com.normation.plugins.openscappolicies
+
+import bootstrap.liftweb.Boot
+import bootstrap.rudder.plugin.OpenscapPoliciesConf
+import com.normation.plugins._
+import com.normation.rudder.AuthorizationType.Administration
+import com.normation.rudder.rest.EndpointSchema
+import com.normation.rudder.rest.lift.LiftApiModuleProvider
+import net.liftweb.http.ClasspathTemplates
+import net.liftweb.sitemap.Loc.LocGroup
+import net.liftweb.sitemap.Loc.Template
+import net.liftweb.sitemap.Loc.TestAccess
+import net.liftweb.sitemap.LocPath.stringToLocPath
+import net.liftweb.sitemap.Menu
+
+class OpenscapPoliciesPluginDef(override val status: PluginStatus) extends DefaultPluginDef {
+
+ override val basePackage = "com.normation.plugins.openscappolicies"
+
+ def init = {}
+
+ def oneTimeInit : Unit = {}
+
+ override def apis: Option[LiftApiModuleProvider[_ <: EndpointSchema]] = {
+ Some(OpenscapPoliciesConf.openScapApiImpl)
+ }
+
+ val configFiles = Seq()
+
+ override def updateSiteMap(menus:List[Menu]) : List[Menu] = {
+ val OpenscapPoliciesMenu = (
+ Menu("OpenscapPolicies", OpenSCAP Policies) /
+ "secure" / "administration" / "OpenscapPoliciesManagement"
+ >> LocGroup("administrationGroup")
+ >> TestAccess ( () => Boot.userIsAllowed("/secure/administration/policyServerManagement", Administration.Read))
+ >> Template(() => ClasspathTemplates("template" :: "OpenscapPoliciesManagement" :: Nil ) openOr
Template not found
)
+ )
+
+ menus.map {
+ case m@Menu(l, _* ) if(l.name == "AdministrationHome") =>
+ Menu(l , m.kids.toSeq :+ OpenscapPoliciesMenu:_* )
+ case m => m
+ }
+ }
+
+}
diff --git a/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/api/OpenScapApi.scala b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/api/OpenScapApi.scala
new file mode 100644
index 000000000..ddb8486a8
--- /dev/null
+++ b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/api/OpenScapApi.scala
@@ -0,0 +1,130 @@
+package com.normation.plugins.openscappolicies.api
+
+import java.io.InputStream
+
+import com.normation.inventory.domain.NodeId
+import com.normation.plugins.openscappolicies.OpenscapPoliciesLogger
+import com.normation.plugins.openscappolicies.services.{OpenScapReportReader, ReportSanitizer}
+import com.normation.rudder.api.HttpAction.{GET, PUT}
+import com.normation.rudder.rest.EndpointSchema.syntax._
+import com.normation.rudder.rest.{ApiModuleProvider, EndpointSchema, GeneralApi, SortIndex, StartsAtVersion10, ZeroParam}
+import com.normation.rudder.rest.EndpointSchema.syntax._
+import com.normation.rudder.rest._
+import com.normation.rudder.rest.lift.{DefaultParams, LiftApiModule, LiftApiModule0, LiftApiModuleProvider}
+import net.liftweb.http.{InMemoryResponse, LiftResponse, OutputStreamResponse, Req}
+import net.liftweb.json.JsonAST.JNothing
+import net.liftweb.json.{JValue, NoTypeHints}
+import net.liftweb.common.{Box, EmptyBox, Failure, Full}
+import sourcecode.Line
+import com.normation.box._
+
+sealed trait OpenScapApi extends EndpointSchema with GeneralApi with SortIndex
+object OpenScapApi extends ApiModuleProvider[OpenScapApi] {
+
+ final case object GetOpenScapReport extends OpenScapApi with OneParam with StartsAtVersion10 {
+ val z = implicitly[Line].value
+ val description = "Get OpenScap report for a node"
+ val (action, path) = GET / "openscap" / "report" / "{id}"
+ }
+
+ final case object GetSanitizedOpenScapReport extends OpenScapApi with OneParam with StartsAtVersion15 {
+ val z = implicitly[Line].value
+ val description = "Get sanitized OpenScap report for a node"
+ val (action, path) = GET / "openscap" / "sanitized" / "{id}"
+ }
+
+ def endpoints = ca.mrvisser.sealerate.values[OpenScapApi].toList.sortBy( _.z )
+}
+
+
+class OpenScapApiImpl(
+ restExtractorService: RestExtractorService
+ , openScapReportReader: OpenScapReportReader
+ , reportSanitizer : ReportSanitizer
+) extends LiftApiModuleProvider[OpenScapApi] {
+ api =>
+
+ val logger = OpenscapPoliciesLogger
+
+ implicit val formats = net.liftweb.json.Serialization.formats(NoTypeHints)
+
+ def schemas = OpenScapApi
+
+ def getLiftEndpoints(): List[LiftApiModule] = {
+ OpenScapApi.endpoints.map { case e => println(e); e match {
+ case OpenScapApi.GetOpenScapReport => GetOpenScapReport
+ case OpenScapApi.GetSanitizedOpenScapReport => GetSanitizedOpenScapReport
+ }}.toList
+ }
+
+ def response(function: Box[JValue], req: Req, errorMessage: String, id: Option[String], dataName : String)(implicit action: String): LiftResponse = {
+ RestUtils.response(restExtractorService, dataName, id)(function, req, errorMessage)
+ }
+
+ object GetOpenScapReport extends LiftApiModule {
+ val schema = OpenScapApi.GetOpenScapReport
+ val restExtractor = api.restExtractorService
+
+ def process(version: ApiVersion, path: ApiPath, nodeId: String, req: Req, params: DefaultParams, authzToken: AuthzToken): LiftResponse = {
+ implicit val action = "getOpenScapReport"
+println("process")
+ (for {
+ report <- openScapReportReader.getOpenScapReport(NodeId(nodeId))
+
+ } yield {
+ logger.info("found report for the API")
+ report
+ // OutputStreamResponse(InputStream(report.content))
+ }) match {
+ case Full(report) =>
+ logger.info("doing in memory response")
+ InMemoryResponse(
+ report.content.getBytes()
+ , ("Content-Type" -> "text/html") ::
+ ("Content-Disposition","""attachment;filename="rudder-openscap-%s.html"""".format(nodeId)) ::
+ Nil
+ , Nil
+ , 200)
+ case _ =>
+ RestUtils.toJsonError(None, JNothing)(schema.name, params.prettify)
+ }
+
+ }
+ }
+
+ object GetSanitizedOpenScapReport extends LiftApiModule {
+ val schema = OpenScapApi.GetSanitizedOpenScapReport
+ val restExtractor = api.restExtractorService
+
+ def process(version: ApiVersion, path: ApiPath, nodeId: String, req: Req, params: DefaultParams, authzToken: AuthzToken): LiftResponse = {
+ implicit val action = "getSanitizedOpenScapReport"
+ (for {
+ report <- openScapReportReader.getOpenScapReport(NodeId(nodeId)) ?~! s"Cannot get OpenScap Report for node ${nodeId}"
+ sanitizedXml <- reportSanitizer.sanitizeReport(report).toBox ?~! "Error while sanitizing report"
+ } yield {
+ logger.trace(s"Report for node ${nodeId} has been found and sanitized")
+ sanitizedXml
+ }) match {
+ case Full(sanitizedReport) =>
+ logger.info("doing in memory response")
+ InMemoryResponse(
+ sanitizedReport.toString().getBytes()
+ // somehow, the X-FRAME-OPTIONS get rewrote to DENY here
+ , ("Content-Type", "text/html") :: ("Content-Disposition", "inline") :: Nil
+ , Nil
+ , 200)
+ case eb: EmptyBox =>
+ val errorMessage = eb ?~! "Could not get the OpenScap report for node ${nodeId}"
+ logger.error(errorMessage.messageChain)
+ val html =
{errorMessage}
+ InMemoryResponse(
+ html.toString().getBytes()
+ , ("Content-Type", "text/html") :: ("Content-Disposition", "inline") :: Nil
+ , Nil
+ , 403)
+ }
+
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/extension/OpenScapNodeDetailsExtension.scala b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/extension/OpenScapNodeDetailsExtension.scala
new file mode 100644
index 000000000..55d896e87
--- /dev/null
+++ b/openscap-policies/src/main/scala/com/normation/plugins/openscappolicies/extension/OpenScapNodeDetailsExtension.scala
@@ -0,0 +1,88 @@
+package com.normation.plugins.openscappolicies.extension
+
+import com.normation.plugins.openscappolicies.OpenScapReport
+import com.normation.plugins.openscappolicies.services.{OpenScapReportReader, ReportSanitizer}
+import com.normation.plugins.{PluginExtensionPoint, PluginStatus}
+import com.normation.rudder.web.components.ShowNodeDetailsFromNode
+import net.liftweb.common.{EmptyBox, Full, Loggable}
+
+import scala.reflect.ClassTag
+import scala.xml.NodeSeq
+import net.liftweb.util.CssSel
+import net.liftweb.util.Helpers._
+import com.normation.box._
+import com.normation.inventory.domain.NodeId
+
+class OpenScapNodeDetailsExtension(
+ val status: PluginStatus
+ , openScapReader: OpenScapReportReader
+ , reportSanitizer: ReportSanitizer)(implicit val ttag: ClassTag[ShowNodeDetailsFromNode]) extends PluginExtensionPoint[ShowNodeDetailsFromNode] with Loggable {
+
+ def pluginCompose(snippet: ShowNodeDetailsFromNode) : Map[String, NodeSeq => NodeSeq] = Map(
+ "popupDetails" -> addExternalReportTab(snippet) _
+ , "mainDetails" -> addExternalReportTab(snippet) _
+ )
+
+ /**
+ * Add a tab:
+ * - add an li in ul with id=openScapExtensionTab
+ */
+ def addExternalReportTab(snippet: ShowNodeDetailsFromNode)(xml: NodeSeq) = {
+
+ val content = openScapReader.getOpenScapReport(snippet.nodeId) match {
+ case eb: EmptyBox =>
+ val e = eb ?~! "Can not display OpenScap report for that node"
+ (
{e.messageChain}
)
+ case Full(report) =>
+ reportSanitizer.sanitizeReport(report).toBox match {
+ case eb: EmptyBox => val e = eb ?~! "Cannot parse OpenScap report"
+ (
{e.messageChain}
)
+ case Full(x) =>
+ frameContent(snippet.nodeId)(openScapExtensionXml)
+ }
+
+
+ }
+
+
+ //tabContent(Map("key" ->"value"))(openScapExtensionXml)
+ val tabTitle = "OpenScap"
+
+ status.isEnabled() match {
+ case false =>
+
Plugin is disabled
+ case true =>
+ (
+ "#NodeDetailsTabMenu *" #> { (x: NodeSeq) =>
+ x ++ (
+