Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #7207: Select and display agent mode (verify/enforce) #1236

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -44,6 +44,7 @@ import com.normation.rudder.reports.AgentRunInterval
import com.normation.rudder.reports.HeartbeatConfiguration
import net.liftweb.common._
import com.normation.inventory.domain.NodeId
import com.normation.rudder.domain.policies.PolicyMode

/**
* Node Repository
Expand Down
Expand Up @@ -50,6 +50,7 @@ import com.normation.rudder.reports.AgentRunInterval
import com.normation.rudder.reports.HeartbeatConfiguration
import net.liftweb.common._
import com.normation.rudder.repository.EventLogRepository
import com.normation.rudder.domain.policies.PolicyMode

class WoLDAPNodeRepository(
nodeDit : NodeDit
Expand Down
8 changes: 5 additions & 3 deletions rudder-web/src/main/scala/bootstrap/liftweb/AppConfig.scala
Expand Up @@ -387,7 +387,7 @@ object RudderConfig extends Loggable {
val reportsRepository : ReportsRepository = reportsRepositoryImpl
val eventLogDeploymentService: EventLogDeploymentService = eventLogDeploymentServiceImpl
val allBootstrapChecks : BootstrapChecks = allChecks
lazy val srvGrid = new SrvGrid(roAgentRunsRepository, asyncComplianceService)
lazy val srvGrid = new SrvGrid(roAgentRunsRepository, asyncComplianceService, configService)
val findExpectedReportRepository : FindExpectedReportRepository = findExpectedRepo
val historizationRepository : HistorizationRepository = historizationJdbcRepository
val roApiAccountRepository : RoApiAccountRepository = roLDAPApiAccountRepository
Expand Down Expand Up @@ -1117,7 +1117,7 @@ object RudderConfig extends Loggable {
, diffRepos
, PendingInventory
)
private[this] lazy val nodeGridImpl = new NodeGrid(ldapFullInventoryRepository, nodeInfoServiceImpl)
private[this] lazy val nodeGridImpl = new NodeGrid(ldapFullInventoryRepository, nodeInfoServiceImpl, configService)

private[this] lazy val modificationService = new ModificationService(logRepository,gitModificationRepository,itemArchiveManagerImpl,uuidGen)
private[this] lazy val eventListDisplayerImpl = new EventListDisplayer(
Expand Down Expand Up @@ -1748,7 +1748,9 @@ object RudderConfig extends Loggable {
roLdapRuleRepository
, roLdapDirectiveRepository
, reportingServiceImpl
, techniqueRepositoryImpl)
, techniqueRepositoryImpl
, configService
)
private[this] lazy val propertyRepository = new RudderPropertiesSquerylRepository(
squerylDatasourceProvider
, reportsRepository )
Expand Down
@@ -0,0 +1,33 @@
package com.normation.rudder.web.components

import net.liftweb.http.DispatchSnippet
import net.liftweb.common._
import net.liftweb.http.{SHtml,S}
import scala.xml._
import net.liftweb.http.js._
import JsCmds._
import JE._
import net.liftweb.util.Helpers
import net.liftweb.util.Helpers._
import net.liftweb.http.Templates

class AgentPolicyModeEditForm extends DispatchSnippet with Loggable {

// Html template
def templatePath = List("templates-hidden", "components", "ComponentAgentPolicyMode")
def template() = Templates(templatePath) match {
case Empty | Failure(_,_,_) =>
sys.error("Template for Agent Policy Mode configuration not found. I was looking for %s.html"
.format(templatePath.mkString("/")))
case Full(n) => n
}
def agentPolicyModeTemplate = chooseTemplate("agentpolicymode", "form", template)

def dispatch = {
case "cfagentPolicyModeConfiguration" => (xml) => cfagentPolicyModeConfiguration
}

def cfagentPolicyModeConfiguration = {
agentPolicyModeTemplate ++ Script(OnLoad(JsRaw("angular.bootstrap('#auditMode', ['auditmode']);")))
}
}
Expand Up @@ -212,9 +212,9 @@ class ComplianceModeEditForm [T <: ComplianceMode] (
s"""
angular.bootstrap("#complianceMode", ['complianceMode']);
var scope = angular.element($$("#complianceModeController")).scope();
scope.$$apply(function(){
scope.init(${toJs(complianceMode)}, ${toJs(globalMode)}, ${isNodePage} ,${callback.toJsCmd}, "${S.contextPath}", ${allModes});
} );
scope.$$apply(function(){
scope.init(${toJs(complianceMode)}, ${toJs(globalMode)}, ${isNodePage} ,${callback.toJsCmd}, "${S.contextPath}", ${allModes});
});
"""
}) match {
case eb:EmptyBox =>
Expand Down
Expand Up @@ -68,6 +68,10 @@ import com.normation.cfclerk.domain.TechniqueName
import com.normation.rudder.web.components.popup.ModificationValidationPopup
import com.normation.cfclerk.domain.TechniqueId
import com.normation.cfclerk.domain.TechniqueVersion
import com.normation.rudder.web.rest.node.SettingsAPI8
import com.normation.rudder.web.rest.node.SettingsApi
import com.normation.rudder.domain.policies.PolicyMode.Verify
import com.normation.rudder.domain.policies.PolicyMode.Enforce

object DirectiveEditForm {

Expand Down Expand Up @@ -100,17 +104,18 @@ object DirectiveEditForm {
* Parameters can not be null.
*/
class DirectiveEditForm(
htmlId_policyConf : String
, technique : Technique
, activeTechnique : ActiveTechnique
, fullActiveTechnique : FullActiveTechnique
, val directive : Directive
, oldDirective : Option[Directive]
, workflowEnabled : Boolean
, onSuccessCallback : (Either[Directive,ChangeRequestId]) => JsCmd = { (Directive) => Noop }
, onMigrationCallback : (Directive, Option[Directive]) => JsCmd
, onFailureCallback : () => JsCmd = { () => Noop }
, isADirectiveCreation : Boolean = false
htmlId_policyConf : String
, technique : Technique
, activeTechnique : ActiveTechnique
, fullActiveTechnique : FullActiveTechnique
, val directive : Directive
, oldDirective : Option[Directive]
, workflowEnabled : Boolean
, globalMode : GlobalPolicyMode
, onSuccessCallback : (Either[Directive,ChangeRequestId]) => JsCmd = { (Directive) => Noop }
, onMigrationCallback : (Directive, Option[Directive]) => JsCmd
, onFailureCallback : () => JsCmd = { () => Noop }
, isADirectiveCreation : Boolean = false
, onRemoveSuccessCallBack : () => JsCmd = { () => Noop }
) extends DispatchSnippet with Loggable {

Expand All @@ -122,21 +127,22 @@ class DirectiveEditForm(
private[this] val woChangeRequestRepo = RudderConfig.woChangeRequestRepository
private[this] val roChangeRequestRepo = RudderConfig.roChangeRequestRepository
private[this] val techniqueRepo = RudderConfig.techniqueRepository
private[this] val roRuleRepo = RudderConfig.roRuleRepository
private[this] val roRuleCategoryRepo = RudderConfig.roRuleCategoryRepository
private[this] val roRuleRepo = RudderConfig.roRuleRepository
private[this] val roRuleCategoryRepo = RudderConfig.roRuleCategoryRepository
private[this] val configService = RudderConfig.configService

private[this] val htmlId_save = htmlId_policyConf + "Save"
private[this] val parameterEditor = {
directiveEditorService.get(technique.id, directive.id, directive.parameters) match {
case Full(pe) => pe
case Empty => {
val errMsg = "Can not initialize the parameter editor for Directive %s " +
"(template %s). No error returned"
"(template %s). No error returned"
throw new IllegalArgumentException(errMsg.format(directive.id, technique.id))
}
case Failure(m, _, _) => {
val errMsg = "Can not initialize the parameter editor for Directive %s " +
"(template %s). Error message: %s"
"(template %s). Error message: %s"
throw new IllegalArgumentException(errMsg.format(directive.id, technique.id, m))
}
}
Expand Down Expand Up @@ -207,7 +213,7 @@ class DirectiveEditForm(
val agentCompEmpty : NodeSeq =
<span>
Can be used on any agent.
</span>
</span>
technique.compatible match {
case None =>
(osCompEmpty,agentCompEmpty)
Expand All @@ -226,7 +232,7 @@ class DirectiveEditForm(
case agent =>
<span>
{agent.mkString(", ")}
</span>
</span>
}
(osComp,agentComp)
}
Expand Down Expand Up @@ -272,6 +278,7 @@ class DirectiveEditForm(
"#shortDescriptionField" #> piShortDescription.toForm_! &
"#longDescriptionField" #> piLongDescription.toForm_! &
"#priority" #> piPriority.toForm_! &
"#policyModes" #> policyModes.toForm_! &
"#version" #> versionSelect.toForm_! &
"#migrate" #> migrateButton(directiveVersion.is,"Migrate") &
"#parameters" #> parameterEditor.toFormNodeSeq &
Expand Down Expand Up @@ -396,28 +403,25 @@ class DirectiveEditForm(

private[this] val piPriority =
new WBSelectObjField(
"Priority:"
"Priority"
, (0 to 10).map(i => (i, i.toString))
, defaultValue = directive.priority
) {
override val displayHtml =
<div>
<b>Priority:</b>
<span class="tw-bs">
<span tooltipid="priorityId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<div class="tooltipContent" id="priorityId">
<h4> Priority </h4>
Priority determines which <b> unique </b> Directive will be applied.
<br/>
Unique Directives can be applied only once (ie. Time Settings), so only the highest priority will be appllied.
<br/>
Highest Priority is 0
</div>
</span>
</div>
<b>Priority</b>
<span class="tw-bs">
<span tooltipid="priorityId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<div class="tooltipContent" id="priorityId">
<h4> Priority </h4>
<p>Priority determines which <b> unique </b> Directive will be applied.</p>
<p>Unique Directives can be applied only once (ie. Time Settings), so only the highest priority will be appllied.</p>
<p>Highest Priority is 0.</p>
</div>
</span>
</div>
override def className = "twoCol"
override def labelClassName = "threeCol directiveInfo"

}

def showDeprecatedVersion (version : TechniqueVersion) = {
Expand All @@ -427,6 +431,55 @@ class DirectiveEditForm(
}
s"${version} ${deprecationInfo}"
}
private[this] val globalOverrideText = configService.rudder_policy_overridable().getOrElse("") match {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: globalPolicyMode should be passed as parameter of DirectiveEditForm

case true =>
<div>
You may override the agent policy mode on this directive.
If set to <b>Audit</b> this directive will never be enforced.
If set to <b>Enforce</b> this directive will appply necessary changes except on Nodes with a <b>Verify</b> override setting.
</div>
case false =>
<p>
Currrent global settings do not allow this mode to be overriden on a per-directive bases. You may change this in <b>Settings</b>,
or contact your Rudder administrator about this.
</p>
}
private[this] val policyModes = {
val globalPolicyModeName = configService.rudder_policy_mode_name().getOrElse("error").toString
val policyName = directive.policyMode match {
case None => globalPolicyModeName
case _ => directive.policyMode.getOrElse("error").toString
}
val l = Seq(None -> s"Use global default mode (currently ${globalPolicyModeName})", Some(Enforce) -> "Override to Enforce", Some(Verify) -> "Override to Audit")
new WBSelectObjField(
"Policy mode"
, l
, defaultValue = directive.policyMode
) {
override val displayHtml =
<div>
<b>Policy mode</b>
<span class="tw-bs">
<span tooltipid="policyModeId" class="ruddericon tooltipable glyphicon glyphicon-question-sign" title=""></span>
<div class="tooltipContent" id="policyModeId">
<h4>Policy mode</h4>
<p>Configuration rules in Rudder can operate in one of two modes:</p>
<ol>
<li><b>Audit</b>: the agent will examine configurations and report any differences, but will not make any changes</li>
<li><b>Enforce</b>: the agent will make changes to fix any configurations that differ from your directives</li>
</ol>
<p>
By default all nodes and all directives operate in the global default mode defined in
<b> Settings</b>, which is currently <b>{globalPolicyModeName}</b>.
</p>
{globalOverrideText}
</div>
</span>
</div>
override def className = "twoCol"
override def labelClassName = "threeCol directiveInfo"
}
}

val versions = fullActiveTechnique.techniques.keys.map(v => (v,showDeprecatedVersion(v))).toSeq.sortBy(_._1)

Expand Down Expand Up @@ -487,12 +540,13 @@ class DirectiveEditForm(
}

val newDirective = directive.copy(
parameters = parameterEditor.mapValueSeq
, name = piName.is
parameters = parameterEditor.mapValueSeq
, name = piName.is
, shortDescription = piShortDescription.is
, priority = piPriority.is
, longDescription = piLongDescription.is
, _isEnabled = directive.isEnabled
, priority = piPriority.is
, longDescription = piLongDescription.is
, _isEnabled = directive.isEnabled
, policyMode = policyModes.is
)

displayConfirmationPopup(
Expand All @@ -506,11 +560,13 @@ class DirectiveEditForm(
val isMigration = oldDirective.map( _.techniqueVersion != directive.techniqueVersion).getOrElse(false)

val updatedDirective = directive.copy(
parameters = parameterEditor.mapValueSeq,
name = piName.is,
shortDescription = piShortDescription.is,
priority = piPriority.is,
longDescription = piLongDescription.is)
parameters = parameterEditor.mapValueSeq
, name = piName.is
, shortDescription = piShortDescription.is
, priority = piPriority.is
, longDescription = piLongDescription.is
, policyMode = policyModes.is
)

if ((!isMigration && directive == updatedDirective && updatedRules.isEmpty)) {
onNothingToDo()
Expand Down
Expand Up @@ -89,6 +89,7 @@ class RuleCompliance (
private[this] val reportingService = RudderConfig.reportingService
private[this] val recentChangesService = RudderConfig.recentChangesService
private[this] val categoryService = RudderConfig.ruleCategoryService
private[this] val configService = RudderConfig.configService

//fresh value when refresh
private[this] val roRuleRepository = RudderConfig.roRuleRepository
Expand Down Expand Up @@ -154,7 +155,7 @@ class RuleCompliance (
function refresh() {${refresh().toJsCmd}};
createDirectiveTable(true, false, "${S.contextPath}")("reportsGrid",[],refresh);
createNodeComplianceTable("nodeReportsGrid",[],"${S.contextPath}", refresh);
createChangesTable("changesGrid",[],"${S.contextPath}");
createChangesTable("changesGrid",[],"${S.contextPath}", refresh);
correctButtons();
refresh();
""")))
Expand Down Expand Up @@ -293,10 +294,11 @@ class RuleCompliance (
updatedRule <- roRuleRepository.get(rule.id)
directiveLib <- getFullDirectiveLib()
allNodeInfos <- getAllNodeInfos()
globalMode <- configService.rudder_global_policy_mode()
} yield {

val directiveData = ComplianceData.getRuleByDirectivesComplianceDetails(reports, updatedRule, allNodeInfos, directiveLib).json.toJsCmd
val nodeData = ComplianceData.getRuleByNodeComplianceDetails(directiveLib, reports, allNodeInfos).json.toJsCmd
val directiveData = ComplianceData.getRuleByDirectivesComplianceDetails(reports, updatedRule, allNodeInfos, directiveLib, globalMode).json.toJsCmd
val nodeData = ComplianceData.getRuleByNodeComplianceDetails(directiveLib, reports, allNodeInfos, globalMode).json.toJsCmd
JsRaw(s"""
refreshTable("reportsGrid", ${directiveData});
refreshTable("nodeReportsGrid", ${nodeData});
Expand Down