diff --git a/libpromises/attributes.c b/libpromises/attributes.c index 43fba90eb4..298e42d403 100644 --- a/libpromises/attributes.c +++ b/libpromises/attributes.c @@ -673,13 +673,22 @@ static TransactionContext GetTransactionConstraints(const EvalContext *ctx, cons value = PromiseGetConstraintAsRval(pp, "action_policy", RVAL_TYPE_SCALAR); - if (value && ((strcmp(value, "warn") == 0) || (strcmp(value, "nop") == 0))) + if ((value == NULL) || StringEqual(value, "fix")) + { + t.action = cfa_fix; // default + } + else if (StringEqual(value, "warn") || StringEqual(value, "nop")) { t.action = cfa_warn; } else { - t.action = cfa_fix; // default + /* The parser only checks the option list for literal values, so an + * expanded one gets here unchecked. Falling back to 'fix' would make + * changes on a host where the policy asked only to warn, so refuse to + * run instead. A literal typo is already fatal at policy check time. */ + PromiseRef(LOG_LEVEL_ERR, pp); + FatalError(ctx, "Unrecognized 'action_policy' value '%s'", value); } t.background = PromiseGetConstraintAsBoolean(ctx, "background", pp); diff --git a/tests/acceptance/00_basics/03_bodies/invalid_action_policy_errors.cf b/tests/acceptance/00_basics/03_bodies/invalid_action_policy_errors.cf new file mode 100644 index 0000000000..ac054edb20 --- /dev/null +++ b/tests/acceptance/00_basics/03_bodies/invalid_action_policy_errors.cf @@ -0,0 +1,27 @@ +body common control +{ + inputs => { "../../default.sub.cf" }; + bundlesequence => { default("$(this.promise_filename)") }; +} + +####################################################### +bundle agent test +{ + meta: + "description" -> { "CFE-1982" } + string => "Test that an unrecognized action_policy is a fatal error instead of being silently treated as fix"; +} + +####################################################### +bundle agent check +{ + methods: + "" + usebundle => dcs_passif_output( + ".*Fatal CFEngine error: Unrecognized 'action_policy' value 'waarn'.*", + # The agent should refuse to run, so the promise must not be actuated + ".*R: Report with a misspelled action_policy.*", + "$(sys.cf_agent) -Kf $(this.promise_filename).sub", + $(this.promise_filename) + ); +} diff --git a/tests/acceptance/00_basics/03_bodies/invalid_action_policy_errors.cf.sub b/tests/acceptance/00_basics/03_bodies/invalid_action_policy_errors.cf.sub new file mode 100644 index 0000000000..807ca291b2 --- /dev/null +++ b/tests/acceptance/00_basics/03_bodies/invalid_action_policy_errors.cf.sub @@ -0,0 +1,19 @@ +body common control +{ + bundlesequence => { "main" }; +} + +# The value has to arrive through a variable. A literal invalid option is +# already rejected by the parser, which is why this defect is only reachable +# via an expanded value. +body action parameterized_action_policy(policy) +{ + action_policy => "$(policy)"; +} + +bundle agent main +{ + reports: + "Report with a misspelled action_policy" + action => parameterized_action_policy("waarn"); +}