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 #23799: Make rudderc able to compile techniques using a per method policy mode override #5207

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
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}");

}