nghttpx: Add affinity-cookie-secure parameter to backend option

This commit is contained in:
Tatsuhiro Tsujikawa 2017-11-21 22:24:38 +09:00
parent ee8bfddfc9
commit 0028275d7b
8 changed files with 67 additions and 12 deletions

View File

@ -1790,10 +1790,14 @@ Connections:
"affinity-cookie-name=<NAME>" must be used to specify a
name of cookie to use. Optionally,
"affinity-cookie-path=<PATH>" can be used to specify a
path which cookie is applied. The Secure attribute of a
cookie is determined by a request scheme. If a request
scheme is "https", then Secure attribute is added.
Otherwise, it is not added.
path which cookie is applied. The optional
"affinity-cookie-secure=<SECURE>" controls the Secure
attribute of a cookie. The default value is "auto", and
the Secure attribute is determined by a request scheme.
If a request scheme is "https", then Secure attribute is
set. Otherwise, it is not set. If <SECURE> is "yes",
the Secure attribute is always set. If <SECURE> is
"no", the Secure attribute is always omitted.
By default, name resolution of backend host name is done
at start up, or reloading configuration. If "dns"

View File

@ -901,6 +901,19 @@ int parse_downstream_params(DownstreamParams &out,
} else if (util::istarts_with_l(param, "affinity-cookie-path=")) {
out.affinity.cookie.path =
StringRef{first + str_size("affinity-cookie-path="), end};
} else if (util::istarts_with_l(param, "affinity-cookie-secure=")) {
auto valstr = StringRef{first + str_size("affinity-cookie-secure="), end};
if (util::strieq_l("auto", valstr)) {
out.affinity.cookie.secure = COOKIE_SECURE_AUTO;
} else if (util::strieq_l("yes", valstr)) {
out.affinity.cookie.secure = COOKIE_SECURE_YES;
} else if (util::strieq_l("no", valstr)) {
out.affinity.cookie.secure = COOKIE_SECURE_NO;
} else {
LOG(ERROR) << "backend: affinity-cookie-secure: value must be one of "
"auto, yes, and no";
return -1;
}
} else if (util::strieq_l("dns", param)) {
out.dns = true;
} else if (util::strieq_l("redirect-if-not-tls", param)) {
@ -1011,10 +1024,13 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
g.affinity.cookie.path = make_string_ref(
downstreamconf.balloc, params.affinity.cookie.path);
}
g.affinity.cookie.secure = params.affinity.cookie.secure;
}
} else if (g.affinity.type != params.affinity.type ||
g.affinity.cookie.name != params.affinity.cookie.name ||
g.affinity.cookie.path != params.affinity.cookie.path) {
g.affinity.cookie.path != params.affinity.cookie.path ||
g.affinity.cookie.secure !=
params.affinity.cookie.secure) {
LOG(ERROR) << "backend: affinity: multiple different affinity "
"configurations found in a single group";
return -1;
@ -1046,6 +1062,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
g.affinity.cookie.path =
make_string_ref(downstreamconf.balloc, params.affinity.cookie.path);
}
g.affinity.cookie.secure = params.affinity.cookie.secure;
}
g.redirect_if_not_tls = params.redirect_if_not_tls;

View File

@ -360,6 +360,16 @@ enum shrpx_session_affinity {
AFFINITY_COOKIE,
};
enum shrpx_cookie_secure {
// Secure attribute of session affinity cookie is determined by the
// request scheme.
COOKIE_SECURE_AUTO,
// Secure attribute of session affinity cookie is always set.
COOKIE_SECURE_YES,
// Secure attribute of session affinity cookie is always unset.
COOKIE_SECURE_NO,
};
struct AffinityConfig {
// Type of session affinity.
shrpx_session_affinity type;
@ -368,6 +378,8 @@ struct AffinityConfig {
StringRef name;
// Path which a cookie is applied to.
StringRef path;
// Secure attribute
shrpx_cookie_secure secure;
} cookie;
};

View File

@ -199,6 +199,18 @@ StringRef create_affinity_cookie(BlockAllocator &balloc, const StringRef &name,
return StringRef{iov.base, p};
}
bool require_cookie_secure_attribute(shrpx_cookie_secure secure,
const StringRef &scheme) {
switch (secure) {
case COOKIE_SECURE_AUTO:
return scheme == "https";
case COOKIE_SECURE_YES:
return true;
default:
return false;
}
}
} // namespace http
} // namespace shrpx

View File

@ -31,6 +31,7 @@
#include <nghttp2/nghttp2.h>
#include "shrpx_config.h"
#include "util.h"
#include "allocator.h"
@ -73,6 +74,11 @@ StringRef create_affinity_cookie(BlockAllocator &balloc, const StringRef &name,
uint32_t affinity_cookie,
const StringRef &path, bool secure);
// Returns true if |secure| indicates that Secure attribute should be
// set.
bool require_cookie_secure_attribute(shrpx_cookie_secure secure,
const StringRef &scheme);
} // namespace http
} // namespace shrpx

View File

@ -1708,9 +1708,10 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
auto &group = dconn->get_downstream_addr_group();
auto &shared_addr = group->shared_addr;
auto &cookieconf = shared_addr->affinity.cookie;
auto cookie_str =
http::create_affinity_cookie(balloc, cookieconf.name, affinity_cookie,
cookieconf.path, req.scheme == "https");
auto secure =
http::require_cookie_secure_attribute(cookieconf.secure, req.scheme);
auto cookie_str = http::create_affinity_cookie(
balloc, cookieconf.name, affinity_cookie, cookieconf.path, secure);
nva.push_back(http2::make_nv_ls_nocopy("set-cookie", cookie_str));
}
}

View File

@ -1155,9 +1155,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
auto &group = dconn->get_downstream_addr_group();
auto &shared_addr = group->shared_addr;
auto &cookieconf = shared_addr->affinity.cookie;
auto cookie_str =
http::create_affinity_cookie(balloc, cookieconf.name, affinity_cookie,
cookieconf.path, req.scheme == "https");
auto secure =
http::require_cookie_secure_attribute(cookieconf.secure, req.scheme);
auto cookie_str = http::create_affinity_cookie(
balloc, cookieconf.name, affinity_cookie, cookieconf.path, secure);
buf->append("Set-Cookie: ");
buf->append(cookie_str);
buf->append("\r\n");

View File

@ -83,7 +83,8 @@ bool match_shared_downstream_addr(
if (lhs->affinity.type == AFFINITY_COOKIE &&
(lhs->affinity.cookie.name != rhs->affinity.cookie.name ||
lhs->affinity.cookie.path != rhs->affinity.cookie.path)) {
lhs->affinity.cookie.path != rhs->affinity.cookie.path ||
lhs->affinity.cookie.secure != rhs->affinity.cookie.secure)) {
return false;
}
@ -200,6 +201,7 @@ void Worker::replace_downstream_config(
shared_addr->affinity.cookie.path =
make_string_ref(shared_addr->balloc, src.affinity.cookie.path);
}
shared_addr->affinity.cookie.secure = src.affinity.cookie.secure;
}
shared_addr->affinity_hash = src.affinity_hash;
shared_addr->redirect_if_not_tls = src.redirect_if_not_tls;