Merge pull request #1066 from nghttp2/nghttpx-add-affinity-cookie-secure

nghttpx: Add affinity-cookie-secure parameter to backend option
This commit is contained in:
Tatsuhiro Tsujikawa 2017-11-21 23:24:40 +09:00 committed by GitHub
commit 2a981a3f56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 "affinity-cookie-name=<NAME>" must be used to specify a
name of cookie to use. Optionally, name of cookie to use. Optionally,
"affinity-cookie-path=<PATH>" can be used to specify a "affinity-cookie-path=<PATH>" can be used to specify a
path which cookie is applied. The Secure attribute of a path which cookie is applied. The optional
cookie is determined by a request scheme. If a request "affinity-cookie-secure=<SECURE>" controls the Secure
scheme is "https", then Secure attribute is added. attribute of a cookie. The default value is "auto", and
Otherwise, it is not added. 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 By default, name resolution of backend host name is done
at start up, or reloading configuration. If "dns" 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=")) { } else if (util::istarts_with_l(param, "affinity-cookie-path=")) {
out.affinity.cookie.path = out.affinity.cookie.path =
StringRef{first + str_size("affinity-cookie-path="), end}; 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)) { } else if (util::strieq_l("dns", param)) {
out.dns = true; out.dns = true;
} else if (util::strieq_l("redirect-if-not-tls", param)) { } 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( g.affinity.cookie.path = make_string_ref(
downstreamconf.balloc, params.affinity.cookie.path); downstreamconf.balloc, params.affinity.cookie.path);
} }
g.affinity.cookie.secure = params.affinity.cookie.secure;
} }
} else if (g.affinity.type != params.affinity.type || } else if (g.affinity.type != params.affinity.type ||
g.affinity.cookie.name != params.affinity.cookie.name || 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 " LOG(ERROR) << "backend: affinity: multiple different affinity "
"configurations found in a single group"; "configurations found in a single group";
return -1; return -1;
@ -1046,6 +1062,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
g.affinity.cookie.path = g.affinity.cookie.path =
make_string_ref(downstreamconf.balloc, params.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; g.redirect_if_not_tls = params.redirect_if_not_tls;

View File

@ -360,6 +360,16 @@ enum shrpx_session_affinity {
AFFINITY_COOKIE, 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 { struct AffinityConfig {
// Type of session affinity. // Type of session affinity.
shrpx_session_affinity type; shrpx_session_affinity type;
@ -368,6 +378,8 @@ struct AffinityConfig {
StringRef name; StringRef name;
// Path which a cookie is applied to. // Path which a cookie is applied to.
StringRef path; StringRef path;
// Secure attribute
shrpx_cookie_secure secure;
} cookie; } cookie;
}; };

View File

@ -199,6 +199,18 @@ StringRef create_affinity_cookie(BlockAllocator &balloc, const StringRef &name,
return StringRef{iov.base, p}; 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 http
} // namespace shrpx } // namespace shrpx

View File

@ -31,6 +31,7 @@
#include <nghttp2/nghttp2.h> #include <nghttp2/nghttp2.h>
#include "shrpx_config.h"
#include "util.h" #include "util.h"
#include "allocator.h" #include "allocator.h"
@ -73,6 +74,11 @@ StringRef create_affinity_cookie(BlockAllocator &balloc, const StringRef &name,
uint32_t affinity_cookie, uint32_t affinity_cookie,
const StringRef &path, bool secure); 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 http
} // namespace shrpx } // namespace shrpx

View File

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

View File

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