MINOR: http-rules: Add a rule to enable or disable the strict rewriting mode

It is now possible to explicitly instruct rewriting rules to be strict or not
towards errors. It means that in this mode, an internal error is trigger if a
rewrite rule fails. The HTTP action "strict-mode" can be used to enable or
disable the strict rewriting mode. It can be used in an http-request and an
http-response ruleset.

For now, by default the strict rewriting mode is disabled. Because it is the
current behavior. But it will be changed in another patch.
This commit is contained in:
Christopher Faulet 2019-12-20 10:07:22 +01:00
parent e00d06c99f
commit 46f95543c5
3 changed files with 90 additions and 0 deletions

View File

@ -4828,6 +4828,21 @@ http-request silent-drop [ { if | unless } <condition> ]
router, though it's still delivered to local networks. Do not use it unless
you fully understand how it works.
http-request strict-mode { on | off }
This enables or disables the strict rewriting mode for following rules. It
does not affect rules declared before it and it is only applicable on rules
performing a rewrite on the requests. When the strict mode is enabled, any
rewrite failure triggers an internal error. Otherwise, such errors are
silently ignored. The purpose of the strict rewriting mode is to make some
rewrites optionnal while others must be performed to continue the request
processing.
By default, the strict rewriting mode is disabled. Its value is also reset
when a ruleset evaluation ends. So, for instance, if you change the mode on
the frontend, the default mode is restored when HAProxy starts the backend
rules evaluation.
http-request tarpit [deny_status <status>] [ { if | unless } <condition> ]
This stops the evaluation of the rules and immediately blocks the request
@ -5216,6 +5231,21 @@ http-response silent-drop [ { if | unless } <condition> ]
router, though it's still delivered to local networks. Do not use it unless
you fully understand how it works.
http-response strict-mode { on | off }
This enables or disables the strict rewriting mode for following rules. It
does not affect rules declared before it and it is only applicable on rules
performing a rewrite on the responses. When the strict mode is enabled, any
rewrite failure triggers an internal error. Otherwise, such errors are
silently ignored. The purpose of the strict rewriting mode is to make some
rewrites optionnal while others must be performed to continue the response
processing.
By default, the strict rewriting mode is disabled. Its value is also reset
when a ruleset evaluation ends. So, for instance, if you change the mode on
the bacnkend, the default mode is restored when HAProxy starts the frontend
rules evaluation.
http-response track-sc0 <key> [table <table>] [ { if | unless } <condition> ]
http-response track-sc1 <key> [table <table>] [ { if | unless } <condition> ]
http-response track-sc2 <key> [table <table>] [ { if | unless } <condition> ]

View File

@ -1211,6 +1211,50 @@ static enum act_parse_ret parse_http_track_sc(const char **args, int *orig_arg,
return ACT_RET_PRS_OK;
}
/* This function executes a strict-mode actions. On success, it always returns
* ACT_RET_CONT
*/
static enum act_return http_action_strict_mode(struct act_rule *rule, struct proxy *px,
struct session *sess, struct stream *s, int flags)
{
struct http_msg *msg = ((rule->from == ACT_F_HTTP_REQ) ? &s->txn->req : &s->txn->rsp);
if (rule->action == 0) // strict-mode on
msg->flags &= ~HTTP_MSGF_SOFT_RW;
else // strict-mode off
msg->flags |= HTTP_MSGF_SOFT_RW;
return ACT_RET_CONT;
}
/* Parse a "strict-mode" action. It returns ACT_RET_PRS_OK on success,
* ACT_RET_PRS_ERR on error.
*/
static enum act_parse_ret parse_http_strict_mode(const char **args, int *orig_arg, struct proxy *px,
struct act_rule *rule, char **err)
{
int cur_arg;
cur_arg = *orig_arg;
if (!*args[cur_arg]) {
memprintf(err, "expects exactly 1 arguments");
return ACT_RET_PRS_ERR;
}
if (strcasecmp(args[cur_arg], "on") == 0)
rule->action = 0; // strict-mode on
else if (strcasecmp(args[cur_arg], "off") == 0)
rule->action = 1; // strict-mode off
else {
memprintf(err, "Unexpected value '%s'. Only 'on' and 'off' are supported", args[cur_arg]);
return ACT_RET_PRS_ERR;
}
rule->action_ptr = http_action_strict_mode;
*orig_arg = cur_arg + 1;
return ACT_RET_PRS_OK;
}
/************************************************************************/
/* All supported http-request action keywords must be declared here. */
/************************************************************************/
@ -1244,6 +1288,7 @@ static struct action_kw_list http_req_actions = {
{ "set-query", parse_set_req_line, 0 },
{ "set-tos", parse_http_set_tos, 0 },
{ "set-uri", parse_set_req_line, 0 },
{ "strict-mode", parse_http_strict_mode, 0 },
{ "tarpit", parse_http_req_deny, 0 },
{ "track-sc", parse_http_track_sc, 1 },
{ NULL, NULL }
@ -1272,6 +1317,7 @@ static struct action_kw_list http_res_actions = {
{ "set-nice", parse_http_set_nice, 0 },
{ "set-status", parse_http_set_status, 0 },
{ "set-tos", parse_http_set_tos, 0 },
{ "strict-mode", parse_http_strict_mode, 0 },
{ "track-sc", parse_http_track_sc, 1 },
{ NULL, NULL }
}

View File

@ -2943,6 +2943,9 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
}
s->current_rule_list = rules;
/* start the ruleset evaluation in soft mode */
txn->req.flags |= HTTP_MSGF_SOFT_RW;
list_for_each_entry(rule, rules, list) {
/* check optional condition */
if (rule->cond) {
@ -3309,6 +3312,10 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
rule_ret = HTTP_RULE_RES_ERROR;
}
/* if the ruleset evaluation is finished reset the soft mode */
if (rule_ret != HTTP_RULE_RES_YIELD)
txn->req.flags |= HTTP_MSGF_SOFT_RW;
/* we reached the end of the rules, nothing to report */
return rule_ret;
}
@ -3349,6 +3356,9 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
}
s->current_rule_list = rules;
/* start the ruleset evaluation in soft mode */
txn->rsp.flags |= HTTP_MSGF_SOFT_RW;
list_for_each_entry(rule, rules, list) {
/* check optional condition */
if (rule->cond) {
@ -3671,6 +3681,10 @@ resume_execution:
}
end:
/* if the ruleset evaluation is finished reset the soft mode */
if (rule_ret != HTTP_RULE_RES_YIELD)
txn->rsp.flags |= HTTP_MSGF_SOFT_RW;
/* we reached the end of the rules, nothing to report */
return rule_ret;
}