mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-11-29 14:50:59 +01:00
MINOR: proxy/http-ana: Add support of extra attributes for the cookie directive
It is now possible to insert any attribute when a cookie is inserted by
HAProxy. Any value may be set, no check is performed except the syntax validity
(CTRL chars and ';' are forbidden). For instance, it may be used to add the
SameSite attribute:
cookie SRV insert attr "SameSite=Strict"
The attr option may be repeated to add several attributes.
This patch should fix the issue #361.
This commit is contained in:
parent
e9ff8992a1
commit
2f5339079b
@ -3340,7 +3340,7 @@ compression offload
|
|||||||
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
|
cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
|
||||||
[ postonly ] [ preserve ] [ httponly ] [ secure ]
|
[ postonly ] [ preserve ] [ httponly ] [ secure ]
|
||||||
[ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
|
[ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
|
||||||
[ dynamic ]
|
[ dynamic ] [ attr <value> ]*
|
||||||
Enable cookie-based persistence in a backend.
|
Enable cookie-based persistence in a backend.
|
||||||
May be used in sections : defaults | frontend | listen | backend
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
yes | no | yes | yes
|
yes | no | yes | yes
|
||||||
@ -3499,6 +3499,11 @@ cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ]
|
|||||||
The cookie will be regenerated each time the IP address change,
|
The cookie will be regenerated each time the IP address change,
|
||||||
and is only generated for IPv4/IPv6.
|
and is only generated for IPv4/IPv6.
|
||||||
|
|
||||||
|
attr This option tells haproxy to add an extra attribute when a
|
||||||
|
cookie is inserted. The attribute value can contain any
|
||||||
|
characters except control ones or ";". This option may be
|
||||||
|
repeated.
|
||||||
|
|
||||||
There can be only one persistence cookie per HTTP backend, and it can be
|
There can be only one persistence cookie per HTTP backend, and it can be
|
||||||
declared in a defaults section. The value of the cookie will be the value
|
declared in a defaults section. The value of the cookie will be the value
|
||||||
indicated after the "cookie" keyword in a "server" statement. If no cookie
|
indicated after the "cookie" keyword in a "server" statement. If no cookie
|
||||||
|
|||||||
@ -338,6 +338,7 @@ struct proxy {
|
|||||||
int cookie_len; /* strlen(cookie_name), computed only once */
|
int cookie_len; /* strlen(cookie_name), computed only once */
|
||||||
char *cookie_domain; /* domain used to insert the cookie */
|
char *cookie_domain; /* domain used to insert the cookie */
|
||||||
char *cookie_name; /* name of the cookie to look for */
|
char *cookie_name; /* name of the cookie to look for */
|
||||||
|
char *cookie_attrs; /* list of attributes to add to the cookie */
|
||||||
char *dyncookie_key; /* Secret key used to generate dynamic persistent cookies */
|
char *dyncookie_key; /* Secret key used to generate dynamic persistent cookies */
|
||||||
unsigned int cookie_maxidle; /* max idle time for this cookie */
|
unsigned int cookie_maxidle; /* max idle time for this cookie */
|
||||||
unsigned int cookie_maxlife; /* max life time for this cookie */
|
unsigned int cookie_maxlife; /* max life time for this cookie */
|
||||||
|
|||||||
@ -326,6 +326,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
|
curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
|
||||||
curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
|
curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
|
||||||
|
|
||||||
|
if (defproxy.cookie_attrs)
|
||||||
|
curproxy->cookie_attrs = strdup(defproxy.cookie_attrs);
|
||||||
|
|
||||||
if (defproxy.lbprm.arg_str)
|
if (defproxy.lbprm.arg_str)
|
||||||
curproxy->lbprm.arg_str = strdup(defproxy.lbprm.arg_str);
|
curproxy->lbprm.arg_str = strdup(defproxy.lbprm.arg_str);
|
||||||
@ -476,6 +478,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
free(defproxy.rdp_cookie_name);
|
free(defproxy.rdp_cookie_name);
|
||||||
free(defproxy.dyncookie_key);
|
free(defproxy.dyncookie_key);
|
||||||
free(defproxy.cookie_domain);
|
free(defproxy.cookie_domain);
|
||||||
|
free(defproxy.cookie_attrs);
|
||||||
free(defproxy.lbprm.arg_str);
|
free(defproxy.lbprm.arg_str);
|
||||||
free(defproxy.capture_name);
|
free(defproxy.capture_name);
|
||||||
free(defproxy.monitor_uri);
|
free(defproxy.monitor_uri);
|
||||||
@ -988,9 +991,34 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
|||||||
err_code |= ERR_WARN;
|
err_code |= ERR_WARN;
|
||||||
curproxy->ck_opts |= PR_CK_DYNAMIC;
|
curproxy->ck_opts |= PR_CK_DYNAMIC;
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(args[cur_arg], "attr")) {
|
||||||
|
char *val;
|
||||||
|
if (!*args[cur_arg + 1]) {
|
||||||
|
ha_alert("parsing [%s:%d]: '%s' expects <value> as argument.\n",
|
||||||
|
file, linenum, args[cur_arg]);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
val = args[cur_arg + 1];
|
||||||
|
while (*val) {
|
||||||
|
if (iscntrl(*val) || *val == ';') {
|
||||||
|
ha_alert("parsing [%s:%d]: character '%%x%02X' is not permitted in attribute value.\n",
|
||||||
|
file, linenum, *val);
|
||||||
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
val++;
|
||||||
|
}
|
||||||
|
/* don't add ';' for the first attribute */
|
||||||
|
if (!curproxy->cookie_attrs)
|
||||||
|
curproxy->cookie_attrs = strdup(args[cur_arg + 1]);
|
||||||
|
else
|
||||||
|
memprintf(&curproxy->cookie_attrs, "%s; %s", curproxy->cookie_attrs, args[cur_arg + 1]);
|
||||||
|
cur_arg++;
|
||||||
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
ha_alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic' and 'maxlife' options.\n",
|
ha_alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle', 'dynamic', 'maxlife' and 'attr' options.\n",
|
||||||
file, linenum, args[0]);
|
file, linenum, args[0]);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
@ -2339,6 +2339,7 @@ void deinit(void)
|
|||||||
free(p->check_req);
|
free(p->check_req);
|
||||||
free(p->cookie_name);
|
free(p->cookie_name);
|
||||||
free(p->cookie_domain);
|
free(p->cookie_domain);
|
||||||
|
free(p->cookie_attrs);
|
||||||
free(p->lbprm.arg_str);
|
free(p->lbprm.arg_str);
|
||||||
free(p->capture_name);
|
free(p->capture_name);
|
||||||
free(p->monitor_uri);
|
free(p->monitor_uri);
|
||||||
|
|||||||
@ -2068,6 +2068,9 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
|
|||||||
if (s->be->ck_opts & PR_CK_SECURE)
|
if (s->be->ck_opts & PR_CK_SECURE)
|
||||||
chunk_appendf(&trash, "; Secure");
|
chunk_appendf(&trash, "; Secure");
|
||||||
|
|
||||||
|
if (s->be->cookie_attrs)
|
||||||
|
chunk_appendf(&trash, "; %s", s->be->cookie_attrs);
|
||||||
|
|
||||||
if (unlikely(!http_add_header(htx, ist("Set-Cookie"), ist2(trash.area, trash.data))))
|
if (unlikely(!http_add_header(htx, ist("Set-Cookie"), ist2(trash.area, trash.data))))
|
||||||
goto return_int_err;
|
goto return_int_err;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user