Add Basic Authentication support for HAProxy

In order to get a proper support for authenticated endpoints, this patch
creates a new definition (tripleo::haproxy::userlist) and exploit it in
the dynamic endpoint (tripleo::haproxy::service_endpoints) as well as
standard tripleo::haproxy::endpoint.

It also detected a small issue with the "underscorization" of the
service name, the missing 'G' flag for regsubst, that preventend all
dashes to be replaced by underscores.

Change-Id: Ie7471155d1ef3f6adc177a468b81ac410bbfb9c0
Closes-Bug: 1736132
This commit is contained in:
Cédric Jeanneret 2017-12-05 08:57:50 +01:00
parent 75b4f9bda6
commit 9d438cd142
8 changed files with 206 additions and 3 deletions

View File

@ -91,6 +91,11 @@
# (false means disabled, and true means enabled)
# Defaults to hiera('tripleo::firewall::manage_firewall', true)
#
# [*authorized_userlist*]
# (optional) Userlist that may access the endpoint. Activate Basic Authentication.
# You'll need to create a tripleo::haproxy::userlist in order to use that option.
# Defaults to undef
#
define tripleo::haproxy::endpoint (
$internal_ip,
$service_port,
@ -109,6 +114,7 @@ define tripleo::haproxy::endpoint (
$internal_certificates_specs = {},
$service_network = undef,
$manage_firewall = hiera('tripleo::firewall::manage_firewall', true),
$authorized_userlist = undef,
) {
if $public_virtual_ip {
# service exposed to the public network
@ -163,13 +169,27 @@ define tripleo::haproxy::endpoint (
$internal_bind_opts = list_to_hash(suffix(any2array($internal_ip), ":${service_port}"), $haproxy_listen_bind_param)
}
}
if $authorized_userlist {
$access_rules = {
'acl' => "acl Auth${name} http_auth(${authorized_userlist})",
'http-request' => "auth realm ${name} if !Auth${name}",
}
Haproxy::Listen[$name] {
require => Tripleo::Haproxy::Userlist[$authorized_userlist],
}
} else {
$access_rules = {}
}
$_real_options = merge($listen_options_real, $access_rules)
$bind_opts = merge($internal_bind_opts, $public_bind_opts)
haproxy::listen { "${name}":
bind => $bind_opts,
collect_exported => false,
mode => $mode,
options => $listen_options_real,
options => $_real_options,
}
haproxy::balancermember { "${name}":
listening_service => $name,

View File

@ -24,19 +24,25 @@
#
define tripleo::haproxy::service_endpoints ($service_name = $title) {
$underscore_name = regsubst($service_name, '-', '_')
$underscore_name = regsubst($service_name, '-', '_', 'G')
# This allows each composable service to load its own custom rules by
# creating its own flat hiera key named:
# tripleo.<service name with underscores>.haproxy_endpoints
# tripleo.<service name with underscores>.haproxy_userlists
$dots_endpoints = hiera("tripleo.${underscore_name}.haproxy_endpoints", {})
$dots_userlists = hiera("tripleo.${underscore_name}.haproxy_userlists", {})
# Supports standard "::" notation
# tripleo::<service name with underscores>::haproxy_endpoints
# tripleo::<service name with underscores>::haproxy_userlists
$colons_endpoints = hiera("tripleo::${underscore_name}::haproxy_endpoints", {})
$colons_userlists = hiera("tripleo::${underscore_name}::haproxy_userlists", {})
# Merge hashes
$service_endpoints = merge($colons_endpoints, $dots_endpoints)
$service_userlists = merge($colons_userlists, $dots_userlists)
create_resources('tripleo::haproxy::userlist', $service_userlists)
create_resources('tripleo::haproxy::endpoint', $service_endpoints)
}

View File

@ -0,0 +1,54 @@
# Copyright 2017 Camptocamp SA.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# == Definition: tripleo::haproxy::userlist
#
# Configure an HAProxy userlist. It wrapps haproxy::userlist definition.
#
# [*groups*]
# List of groups
#
# [*users*]
# List of users
#
# == Example
# ::tripleo::haproxy::userlist {'starwars':
# groups => [
# 'aldebaran users leia,luke',
# 'deathstar users anakin,sith',
# ],
# users => [
# 'leia insecure-password sister',
# 'luke insecure-password jedi',
# 'anakin insecure-password darthvador',
# 'sith password $5$h9LsKUOeCr$UlD62CNEpuZQkGYdBoiFJLsM6TlXluRLBlhEnpjDdaC', # mkpasswd -m sha-256 darkSideOfTheForce
# ]
# }
#
# Please refer to the following HAProxy documentation for more options:
# http://cbonte.github.io/haproxy-dconv/configuration-1.4.html#3.4-user
# http://cbonte.github.io/haproxy-dconv/configuration-1.4.html#3.4-group
#
#
define tripleo::haproxy::userlist(
Optional[Array] $groups = [],
Optional[Array] $users = [],
) {
::haproxy::userlist {$name:
users => $users,
groups => $groups,
}
}

View File

@ -0,0 +1,8 @@
---
features:
- |
Adds Basic Authentication support for HAProxy endpoints.
fixes:
- Fixes `bug 1736132
<https://launchpad.net/bugs/1736132>`__ by implementing
Basic Authentication in HAProxy endpoint.

View File

@ -28,7 +28,8 @@ describe 'tripleo::haproxy::endpoint' do
:bind => [
['10.0.0.1:9696', ['transparent']],
['192.168.0.1:9696', ['transparent']]
]
],
:options => {'option' => []},
)
end
end
@ -50,6 +51,29 @@ describe 'tripleo::haproxy::endpoint' do
)
end
end
context 'with userlist' do
before :each do
params.merge!({
:authorized_userlist => 'starwars',
})
end
let :pre_condition do
'include ::haproxy
::tripleo::haproxy::userlist {"starwars": users => ["leia password sister"]}
'
end
it 'should configure an ACL' do
is_expected.to compile.with_all_deps
is_expected.to contain_haproxy__listen('neutron').with(
:options => {
'option' => [],
'acl' => 'acl Authneutron http_auth(starwars)',
'http-request' => 'auth realm neutron if !Authneutron',
}
)
end
end
end
context 'on Debian platforms' do

View File

@ -23,6 +23,18 @@ describe 'tripleo::haproxy::service_endpoints' do
is_expected.to compile.with_all_deps
end
end
context 'with userlist' do
let(:title) {'haproxy-basic-auth'}
it 'should compile' do
is_expected.to compile.with_all_deps
end
it 'should create haproxy endpoint' do
is_expected.to contain_tripleo__haproxy__endpoint('starwars')
end
it 'should create userlist' do
is_expected.to contain_tripleo__haproxy__userlist('starwars')
end
end
end
context 'on Debian platforms' do

View File

@ -0,0 +1,56 @@
require 'spec_helper'
describe 'tripleo::haproxy::userlist' do
let(:title) { 'starwars' }
let :pre_condition do
'include ::haproxy'
end
let :params do {
:groups => [
'aldebaran users leia,luke',
'deathstar users anakin,sith',
],
:users => [
'leia insecure-password sister',
'luke insecure-password jedi',
'anakin insecure-password darthvador',
'sith password $5$h9LsKUOeCr$UlD62CNEpuZQkGYdBoiFJLsM6TlXluRLBlhEnpjDdaC', # mkpasswd -m sha-256 darkSideOfTheForce
],
}
end
shared_examples_for 'tripleo haproxy userlist' do
context 'with basic parameters to configure neutron binding' do
it 'should compile' do
is_expected.to compile.with_all_deps
end
it 'should configure haproxy' do
is_expected.to contain_haproxy__userlist('starwars').with(
:users => [
'leia insecure-password sister',
'luke insecure-password jedi',
'anakin insecure-password darthvador',
'sith password $5$h9LsKUOeCr$UlD62CNEpuZQkGYdBoiFJLsM6TlXluRLBlhEnpjDdaC',
],
:groups => [
'aldebaran users leia,luke',
'deathstar users anakin,sith',
]
)
end
end
end
on_supported_os.each do |os, facts|
context "on #{os}" do
let(:facts) do
facts.merge({})
end
it_behaves_like 'tripleo haproxy userlist'
end
end
end

View File

@ -77,3 +77,26 @@ tripleo::dynamic_stuff::haproxy_endpoints:
public_ssl_port: 19696
member_options: [ 'check', 'inter 2000', 'rise 2', 'fall 5' ]
haproxy_listen_bind_param: ['transparent']
tripleo::haproxy_basic_auth::haproxy_endpoints:
starwars:
public_virtual_ip: '192.168.0.1'
internal_ip: '10.0.0.1'
service_port: 9696
ip_addresses: ['10.0.0.2', '10.0.0.3', '10.0.0.4']
server_names: ['controller1', 'controller2', 'controller3']
public_ssl_port: 19696
member_options: [ 'check', 'inter 2000', 'rise 2', 'fall 5' ]
haproxy_listen_bind_param: ['transparent']
authorized_userlist: 'starwars'
# HAProxy userlists
tripleo::haproxy_basic_auth::haproxy_userlists:
starwars:
groups:
- 'aldebaran users leia,luke'
- 'deathstar users anakin,sith'
users:
- 'leia insecure-password sister'
- 'luke insecure-password jedi'
- 'anakin insecure-password darthvador'
- 'sith password $5$h9LsKUOeCr$UlD62CNEpuZQkGYdBoiFJLsM6TlXluRLBlhEnpjDdaC'