Add mechanism for cookie-based sessions in endpoints.

In order to allow SAML integration, we need to persist sessions for
the Keystone public API. Rather than use a one-off resource, this
patch introduces a generic mechanism for adding cookie-based sessions
to any endpoint that uses the endpoint resource and uses that mechanism
to provide a session persistence option for the Keystone public API.

Closes-Bug: #1779744
Change-Id: I7e1c9a4ddc8b849b487b863635b8c45fc935a751
(cherry picked from commit 37bc58d9b1)
This commit is contained in:
Andrew Austin 2018-06-21 22:08:51 +00:00
parent 668480d665
commit 47ec9ce49b
2 changed files with 56 additions and 11 deletions

View File

@ -418,6 +418,15 @@
# (optional) Specify the network keystone_public is running on.
# Defaults to hiera('keystone_network', undef)
#
# [*keystone_sticky_sessions*]
# (optional) Use cookie-based session persistence for the Keystone
# public API.
# Defaults to hiera('keystone_sticky_sessions', false)
#
# [*keystone_session_cookie*]
# (optional) Use a specified name for the Keystone sticky session cookie.
# Defaults to hiera('keystone_session_cookie', 'KEYSTONESESSION')
#
# [*manila_network*]
# (optional) Specify the network manila is running on.
# Defaults to hiera('manila_api_network', undef)
@ -654,6 +663,8 @@ class tripleo::haproxy (
$kubernetes_master_network = hiera('kubernetes_master_network', undef),
$keystone_admin_network = hiera('keystone_admin_api_network', undef),
$keystone_public_network = hiera('keystone_public_api_network', undef),
$keystone_sticky_sessions = hiera('keystone_sticky_sessions', false),
$keystone_session_cookie = hiera('keystone_session_cookie,', 'KEYSTONESESSION'),
$manila_network = hiera('manila_api_network', undef),
$mistral_network = hiera('mistral_api_network', undef),
$neutron_network = hiera('neutron_api_network', undef),
@ -894,6 +905,8 @@ class tripleo::haproxy (
listen_options => merge($default_listen_options, $keystone_listen_opts),
public_ssl_port => $ports[keystone_public_api_ssl_port],
service_network => $keystone_public_network,
sticky_sessions => $keystone_sticky_sessions,
session_cookie => $keystone_session_cookie,
member_options => union($haproxy_member_options, $internal_tls_member_options),
}
}

View File

@ -98,6 +98,13 @@
# You'll need to create a tripleo::haproxy::userlist in order to use that option.
# Defaults to undef
#
# [*sticky_sessions*]
# (optional) Enable sticky sessions for this frontend using a cookie
#
# [*session_cookie*]
# (optional) Cookie name to use for sticky sessions. This should be different
# for each service using sticky sessions.
#
define tripleo::haproxy::endpoint (
$internal_ip,
$service_port,
@ -117,6 +124,8 @@ define tripleo::haproxy::endpoint (
$service_network = undef,
$manage_firewall = hiera('tripleo::firewall::manage_firewall', true),
$authorized_userlist = undef,
$sticky_sessions = false,
$session_cookie = 'STICKYSESSION',
) {
# Let users override the options on a per-service basis
$custom_options = hiera("tripleo::haproxy::${name}::options", undef)
@ -130,22 +139,29 @@ define tripleo::haproxy::endpoint (
'redirect' => "scheme https code 301 if { hdr(host) -i ${public_virtual_ip} } !{ ssl_fc }",
'option' => 'forwardfor',
}
$listen_options_real = merge($tls_listen_options, $listen_options, $custom_options)
$listen_options_precookie = merge($tls_listen_options, $listen_options, $custom_options)
} else {
$listen_options_real = merge($listen_options, $custom_options)
$listen_options_precookie = merge($listen_options, $custom_options)
}
$public_bind_opts = list_to_hash(suffix(any2array($public_virtual_ip), ":${public_ssl_port}"),
union($haproxy_listen_bind_param, ['ssl', 'crt', $public_certificate]))
} else {
$listen_options_real = merge($listen_options, $custom_options)
$listen_options_precookie = merge($listen_options, $custom_options)
$public_bind_opts = list_to_hash(suffix(any2array($public_virtual_ip), ":${service_port}"), $haproxy_listen_bind_param)
}
} else {
# internal service only
$public_bind_opts = {}
$listen_options_real = merge($listen_options, $custom_options)
$listen_options_precookie = merge($listen_options, $custom_options)
}
if $sticky_sessions {
$cookie_options = {
'cookie' => "${session_cookie} insert indirect nocache",
}
$listen_options_real = merge($listen_options_precookie, $cookie_options)
} else {
$listen_options_real = $listen_options_precookie
}
if $use_internal_certificates {
if !$service_network {
fail("The service_network for this service is undefined. Can't configure TLS for the internal network.")
@ -195,13 +211,29 @@ define tripleo::haproxy::endpoint (
mode => $mode,
options => $_real_options,
}
haproxy::balancermember { "${name}":
listening_service => $name,
ports => $service_port,
ipaddresses => $ip_addresses,
server_names => $server_names,
options => $member_options,
if $sticky_sessions {
hash(zip($ip_addresses, $server_names)).each | $ip, $server | {
# We need to be sure the IP (IPv6) don't have colons
# which is a reserved character to reference manifests
$non_colon_ip = regsubst($ip, ':', '-', 'G')
haproxy::balancermember { "${name}_${non_colon_ip}_${server}":
listening_service => $name,
ports => $service_port,
ipaddresses => $ip,
server_names => $server,
options => union($member_options, ["cookie ${server}"]),
}
}
} else {
haproxy::balancermember { "${name}":
listening_service => $name,
ports => $service_port,
ipaddresses => $ip_addresses,
server_names => $server_names,
options => $member_options,
}
}
if $manage_firewall {
include ::tripleo::firewall
# This block will construct firewall rules only when we specify