Skip to content

Commit

Permalink
Fixes #23799: Make rudderc able to compile techniques using a per met…
Browse files Browse the repository at this point in the history
…hod policy mode override (#5207)
  • Loading branch information
Fdall authored Nov 30, 2023
1 parent 01ccce6 commit d709e31
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 19 deletions.
6 changes: 6 additions & 0 deletions policies/_typos.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
[default]
extend-ignore-re = [
"[0-9a-fA-F]{8}[-_][0-9a-fA-F]{4}[-_][0-9a-fA-F]{4}[-_][0-9a-fA-F]{4}[-_][0-9a-fA-F]{12}"
]

[default.extend-words]
# from fusion
SOFTWARES = "SOFTWARES"
# crate name
flate = "flate"

18 changes: 18 additions & 0 deletions policies/rudder-commons/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,24 @@ pub enum PolicyMode {
Audit,
}

impl PolicyMode {
pub fn from_string<'de, D>(deserializer: D) -> Result<Option<PolicyMode>, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::Error;
String::deserialize(deserializer).and_then(|string| match string.as_ref() {
"enforce" => Ok(Some(PolicyMode::Enforce)),
"audit" => Ok(Some(PolicyMode::Audit)),
"default" => Ok(None),
_ => Err(Error::custom(format!(
"Could not parse policy mode '{}'",
string
))),
})
}
}

impl fmt::Display for PolicyMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
Expand Down
55 changes: 42 additions & 13 deletions policies/rudderc/src/backends/unix/ncf/method_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//! signature, type, and constraints).
use anyhow::{bail, Result};
use rudder_commons::{canonify, methods::method::Agent};
use rudder_commons::{canonify, methods::method::Agent, PolicyMode};

use crate::{
backends::unix::cfengine::{
Expand Down Expand Up @@ -102,19 +102,43 @@ pub fn method_call(
info.bundle_name
);

let push_policy_mode = m.policy_mode.map(|p| {
Promise::usebundle(
"push_dry_run_mode",
Some(&report_component),
Some(unique),
vec![match p {
PolicyMode::Enforce => quoted("false").to_string(),
PolicyMode::Audit => quoted("true").to_string(),
}],
)
});
let pop_policy_mode = if m.policy_mode.is_some() {
Some(Promise::usebundle(
"pop_dry_run_mode",
Some(&report_component),
Some(unique),
vec![],
))
} else {
None
};

let mut promises = match (&condition, is_supported) {
(Condition::Expression(_), true) => vec![
reporting_context,
method.if_condition(condition.clone()),
Promise::usebundle("_classes_noop", Some(&report_component), Some(unique), vec![na_condition.clone()]).unless_condition(&condition),
Promise::usebundle("log_rudder", Some(&report_component), Some(unique), vec![
quoted(&format!("Skipping method '{}' with key parameter '{}' since condition '{}' is not reached", &method_name, &report_parameter, condition)),
quoted(&report_parameter),
na_condition.clone(),
na_condition,
"@{args}".to_string()
]).unless_condition(&condition)
],
Some(reporting_context),
push_policy_mode,
Some(method.if_condition(condition.clone())),
pop_policy_mode,
Some(Promise::usebundle("_classes_noop", Some(&report_component), Some(unique), vec![na_condition.clone()]).unless_condition(&condition)),
Some(Promise::usebundle("log_rudder", Some(&report_component), Some(unique), vec![
quoted(&format!("Skipping method '{}' with key parameter '{}' since condition '{}' is not reached", &method_name, &report_parameter, condition)),
quoted(&report_parameter),
na_condition.clone(),
na_condition,
"@{args}".to_string()
]).unless_condition(&condition))
].into_iter().flatten().collect(),
(Condition::NotDefined, true) => vec![
reporting_context,
Promise::usebundle("_classes_noop", Some(&report_component), Some(unique), vec![na_condition.clone()]),
Expand All @@ -126,7 +150,12 @@ pub fn method_call(
"@{args}".to_string()
])
],
(Condition::Defined, true) => vec![reporting_context, method],
(Condition::Defined, true) => vec![
Some(reporting_context),
push_policy_mode,
Some(method),
pop_policy_mode,
].into_iter().flatten().collect(),
(_, false) => vec![
reporting_context,
Promise::usebundle(
Expand Down
16 changes: 14 additions & 2 deletions policies/rudderc/src/backends/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::path::Path;

use anyhow::{bail, Result};
use askama::Template;
use rudder_commons::{methods::method::Agent, Escaping};
use rudder_commons::{methods::method::Agent, Escaping, PolicyMode};

use super::Backend;
use crate::ir::{
Expand Down Expand Up @@ -62,7 +62,7 @@ pub mod filters {
use std::fmt::Display;

use anyhow::Error;
use rudder_commons::{regex_comp, Escaping, Target};
use rudder_commons::{regex_comp, Escaping, PolicyMode, Target};

use crate::ir::value::Expression;

Expand Down Expand Up @@ -135,6 +135,16 @@ pub mod filters {
Escaping::Raw => value,
})
}

pub fn policy_mode_fmt(op: &Option<PolicyMode>) -> askama::Result<String> {
match op {
None => Ok("$policyMode".to_string()),
Some(p) => match p {
PolicyMode::Audit => Ok("([Rudder.PolicyMode]::Audit)".to_string()),
PolicyMode::Enforce => Ok("([Rudder.PolicyMode]::Enforce)".to_string()),
},
}
}
}

struct WindowsMethod {
Expand All @@ -147,6 +157,7 @@ struct WindowsMethod {
args: Vec<(String, String, Escaping)>,
name: String,
is_supported: bool,
policy_mode: Option<PolicyMode>,
}

fn method_call(m: Method, condition: Condition) -> Result<WindowsMethod> {
Expand Down Expand Up @@ -196,6 +207,7 @@ fn method_call(m: Method, condition: Condition) -> Result<WindowsMethod> {
args,
name: filters::dsc_case(&m.info.as_ref().unwrap().bundle_name).unwrap(),
is_supported,
policy_mode: m.policy_mode,
})
}

Expand Down
8 changes: 7 additions & 1 deletion policies/rudderc/src/ir/technique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{
};

use anyhow::{bail, Error, Result};
use rudder_commons::{methods::method::MethodInfo, RegexConstraint, Select};
use rudder_commons::{methods::method::MethodInfo, PolicyMode, RegexConstraint, Select};
use serde::{de, Deserialize, Deserializer, Serialize};
use serde_yaml::Value;
use uuid::Uuid;
Expand Down Expand Up @@ -351,6 +351,9 @@ pub struct Block {
pub id: Id,
#[serde(default)]
pub reporting: BlockReporting,
#[serde(deserialize_with = "PolicyMode::from_string")]
#[serde(default)]
pub policy_mode: Option<PolicyMode>,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
Expand Down Expand Up @@ -388,6 +391,9 @@ pub struct Method {
pub reporting: LeafReporting,
#[serde(skip)]
pub info: Option<&'static MethodInfo>,
#[serde(deserialize_with = "PolicyMode::from_string")]
#[serde(default)]
pub policy_mode: Option<PolicyMode>,
}

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
Expand Down
11 changes: 11 additions & 0 deletions policies/rudderc/src/technique.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@
"tags": {
"type": "object"
},
"policyMode": {
"type": "string",
"enum": [
"audit",
"enforce",
"default"
]
},
"reportingMode": {
"oneOf": [
{
Expand Down Expand Up @@ -234,6 +242,9 @@
"tags": {
"$ref": "#/$defs/tags"
},
"policy_mode": {
"$ref": "#/$defs/policyMode"
},
"condition": {
"type": ["string", "boolean"]
},
Expand Down
6 changes: 3 additions & 3 deletions policies/rudderc/templates/technique.ps1.askama
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function {{ id|dsc_case }} {
ClassPrefix = ([Rudder.Condition]::canonify(("{{ m.class_prefix }}_" + $componentKey)))
ComponentKey = $componentKey
ComponentName = "{{ m.component_name|escape_double_quotes }}"
PolicyMode = $policyMode
PolicyMode = {{ m.policy_mode|policy_mode_fmt }}
ReportId = $reportId
DisableReporting = ${{ m.disable_reporting }}
TechniqueName = $techniqueName
Expand All @@ -47,7 +47,7 @@ function {{ id|dsc_case }} {
{{- arg.0 }} = {{ arg|parameter_fmt }}
{% endfor %}
}
$call = {{ m.name|dsc_case }} @methodParams -PolicyMode $policyMode
$call = {{ m.name|dsc_case }} @methodParams -PolicyMode {{ m.policy_mode|policy_mode_fmt }}
$methodContext = Compute-Method-Call @reportParams -MethodCall $call
$localContext.merge($methodContext)
} else {
Expand All @@ -59,7 +59,7 @@ function {{ id|dsc_case }} {
{{- arg.0 }} = {{ arg|parameter_fmt }}
{% endfor %}
}
$call = {{ m.name|dsc_case }} @methodParams -PolicyMode $policyMode
$call = {{ m.name|dsc_case }} @methodParams -PolicyMode {{ m.policy_mode|policy_mode_fmt }}
$methodContext = Compute-Method-Call @reportParams -MethodCall $call
$localContext.merge($methodContext)
{% endmatch %}
Expand Down
56 changes: 56 additions & 0 deletions policies/rudderc/tests/cases/general/policy_mode/metadata.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<TECHNIQUE name="test audit">
<DESCRIPTION>test audit</DESCRIPTION>
<USEMETHODREPORTING>true</USEMETHODREPORTING>
<MULTIINSTANCE>false</MULTIINSTANCE>
<POLICYGENERATION>separated</POLICYGENERATION>
<AGENT type="cfengine-community">
<BUNDLES>
<NAME>test_audit</NAME>
</BUNDLES>
<FILES>
<FILE name="technique.cf">
<INCLUDED>true</INCLUDED>
</FILE>
</FILES>
</AGENT>
<AGENT type="dsc">
<BUNDLES>
<NAME>Test-Audit</NAME>
</BUNDLES>
<FILES>
<FILE name="technique.ps1">
<INCLUDED>true</INCLUDED>
</FILE>
</FILES>
</AGENT>
<SECTIONS>
<SECTION name="In audit mode" id="46b8025a-0b06-485c-9127-50e4258ee7e6" component="true" multivalued="true">
<REPORTKEYS>
<VALUE id="46b8025a-0b06-485c-9127-50e4258ee7e6">
/tmp/1
</VALUE>
</REPORTKEYS>
</SECTION>
<SECTION name="In omit mode" id="1eedce7b-3441-4251-bdd6-706fda3ec7a8" component="true" multivalued="true">
<REPORTKEYS>
<VALUE id="1eedce7b-3441-4251-bdd6-706fda3ec7a8">
/tmp/1
</VALUE>
</REPORTKEYS>
</SECTION>
<SECTION name="In enforce mode" id="dbd5ba50-8dfc-11ee-a57e-84a938c470d4" component="true" multivalued="true">
<REPORTKEYS>
<VALUE id="dbd5ba50-8dfc-11ee-a57e-84a938c470d4">
/tmp/1
</VALUE>
</REPORTKEYS>
</SECTION>
<SECTION name="In default mode" id="1d809592-808e-4177-8351-8b7b7769af69" component="true" multivalued="true">
<REPORTKEYS>
<VALUE id="1d809592-808e-4177-8351-8b7b7769af69">
/tmp/1
</VALUE>
</REPORTKEYS>
</SECTION>
</SECTIONS>
</TECHNIQUE>
53 changes: 53 additions & 0 deletions policies/rudderc/tests/cases/general/policy_mode/technique.cf
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# @name test audit
# @version 1.0

bundle agent test_audit {

vars:
"args" slist => {};
"report_param" string => join("_", args);
"full_class_prefix" string => canonify("test_audit_${report_param}");
"class_prefix" string => string_head("${full_class_prefix}", "1000");

methods:
"46b8025a-0b06-485c-9127-50e4258ee7e6_${report_data.directive_id}" usebundle => call_test_audit_46b8025a_0b06_485c_9127_50e4258ee7e6("In audit mode", "/tmp/1", "46b8025a-0b06-485c-9127-50e4258ee7e6", @{args}, "${class_prefix}", "/tmp/1", "foobar", "true");

"1eedce7b-3441-4251-bdd6-706fda3ec7a8_${report_data.directive_id}" usebundle => call_test_audit_1eedce7b_3441_4251_bdd6_706fda3ec7a8("In omit mode", "/tmp/1", "1eedce7b-3441-4251-bdd6-706fda3ec7a8", @{args}, "${class_prefix}", "/tmp/1", "foobar", "true");

"dbd5ba50-8dfc-11ee-a57e-84a938c470d4_${report_data.directive_id}" usebundle => call_test_audit_dbd5ba50_8dfc_11ee_a57e_84a938c470d4("In enforce mode", "/tmp/1", "dbd5ba50-8dfc-11ee-a57e-84a938c470d4", @{args}, "${class_prefix}", "/tmp/1", "foobar", "true");

"1d809592-808e-4177-8351-8b7b7769af69_${report_data.directive_id}" usebundle => call_test_audit_1d809592_808e_4177_8351_8b7b7769af69("In default mode", "/tmp/1", "1d809592-808e-4177-8351-8b7b7769af69", @{args}, "${class_prefix}", "/tmp/1", "foobar", "true");

}
bundle agent call_test_audit_46b8025a_0b06_485c_9127_50e4258ee7e6(c_name, c_key, report_id, args, class_prefix, path, lines, enforce) {

methods:
"46b8025a-0b06-485c-9127-50e4258ee7e6_${report_data.directive_id}" usebundle => _method_reporting_context_v4("${c_name}", "${c_key}", "${report_id}");
"46b8025a-0b06-485c-9127-50e4258ee7e6_${report_data.directive_id}" usebundle => push_dry_run_mode("true");
"46b8025a-0b06-485c-9127-50e4258ee7e6_${report_data.directive_id}" usebundle => file_content("${path}", "${lines}", "${enforce}");
"46b8025a-0b06-485c-9127-50e4258ee7e6_${report_data.directive_id}" usebundle => pop_dry_run_mode();

}
bundle agent call_test_audit_1eedce7b_3441_4251_bdd6_706fda3ec7a8(c_name, c_key, report_id, args, class_prefix, path, lines, enforce) {

methods:
"1eedce7b-3441-4251-bdd6-706fda3ec7a8_${report_data.directive_id}" usebundle => _method_reporting_context_v4("${c_name}", "${c_key}", "${report_id}");
"1eedce7b-3441-4251-bdd6-706fda3ec7a8_${report_data.directive_id}" usebundle => file_content("${path}", "${lines}", "${enforce}");

}
bundle agent call_test_audit_dbd5ba50_8dfc_11ee_a57e_84a938c470d4(c_name, c_key, report_id, args, class_prefix, path, lines, enforce) {

methods:
"dbd5ba50-8dfc-11ee-a57e-84a938c470d4_${report_data.directive_id}" usebundle => _method_reporting_context_v4("${c_name}", "${c_key}", "${report_id}");
"dbd5ba50-8dfc-11ee-a57e-84a938c470d4_${report_data.directive_id}" usebundle => push_dry_run_mode("false");
"dbd5ba50-8dfc-11ee-a57e-84a938c470d4_${report_data.directive_id}" usebundle => file_content("${path}", "${lines}", "${enforce}");
"dbd5ba50-8dfc-11ee-a57e-84a938c470d4_${report_data.directive_id}" usebundle => pop_dry_run_mode();

}
bundle agent call_test_audit_1d809592_808e_4177_8351_8b7b7769af69(c_name, c_key, report_id, args, class_prefix, path, lines, enforce) {

methods:
"1d809592-808e-4177-8351-8b7b7769af69_${report_data.directive_id}" usebundle => _method_reporting_context_v4("${c_name}", "${c_key}", "${report_id}");
"1d809592-808e-4177-8351-8b7b7769af69_${report_data.directive_id}" usebundle => file_content("${path}", "${lines}", "${enforce}");

}
Loading

0 comments on commit d709e31

Please sign in to comment.