Enable TLS for the HAProxy stats interface

This creates a new class for the stats interface and furtherly
configures it to also use the certificates that are provided by
certmonger (via the internal_certificates_specs variable).

Note that the already existing haproxy_stats_certificate still works and
will take precedence if it's set.

bp tls-via-certmonger

Change-Id: Iea65d91648ab13dbe6ec20241a1a7c95ce856e3e
This commit is contained in:
Juan Antonio Osorio Robles 2017-06-29 15:03:11 +03:00
parent 01ae503525
commit e51e796920
4 changed files with 198 additions and 27 deletions

View File

@ -766,12 +766,6 @@ class tripleo::haproxy (
$controller_hosts_names_real = downcase(any2array(split($controller_hosts_names, ',')))
}
# TODO(bnemec): When we have support for SSL on private and admin endpoints,
# have the haproxy stats endpoint use that certificate by default.
if $haproxy_stats_certificate {
$haproxy_stats_bind_certificate = $haproxy_stats_certificate
}
$horizon_vip = hiera('horizon_vip', $controller_virtual_ip)
if $service_certificate {
# NOTE(jaosorior): If the horizon_vip and the public_virtual_ip are the
@ -809,16 +803,6 @@ class tripleo::haproxy (
}
}
if $haproxy_stats_bind_certificate {
$haproxy_stats_bind_opts = {
"${controller_virtual_ip}:1993" => union($haproxy_listen_bind_param, ['ssl', 'crt', $haproxy_stats_bind_certificate]),
}
} else {
$haproxy_stats_bind_opts = {
"${controller_virtual_ip}:1993" => $haproxy_listen_bind_param,
}
}
$mysql_vip = hiera('mysql_vip', $controller_virtual_ip)
$mysql_bind_opts = {
"${mysql_vip}:3306" => $haproxy_listen_bind_param,
@ -884,19 +868,20 @@ class tripleo::haproxy (
}
if $haproxy_stats {
$stats_base = ['enable', 'uri /']
if $haproxy_stats_password {
$stats_config = union($stats_base, ["auth ${haproxy_stats_user}:${haproxy_stats_password}"])
if $haproxy_stats_certificate {
$haproxy_stats_certificate_real = $haproxy_stats_certificate
} elsif $use_internal_certificates {
# NOTE(jaosorior): Right now it's hardcoded to use the ctlplane network
$haproxy_stats_certificate_real = $internal_certificates_specs["haproxy-ctlplane"]['service_pem']
} else {
$stats_config = $stats_base
$haproxy_stats_certificate_real = undef
}
haproxy::listen { 'haproxy.stats':
bind => $haproxy_stats_bind_opts,
mode => 'http',
options => {
'stats' => $stats_config,
},
collect_exported => false,
class { '::tripleo::haproxy::stats':
haproxy_listen_bind_param => $haproxy_listen_bind_param,
ip => $controller_virtual_ip,
password => $haproxy_stats_password,
certificate => $haproxy_stats_certificate_real,
user => $haproxy_stats_user,
}
}

View File

@ -0,0 +1,74 @@
# Copyright 2014 Red Hat, Inc.
# 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.
# == Class: tripleo::haproxy::stats
#
# Configure the HAProxy stats interface
#
# [*haproxy_listen_bind_param*]
# A list of params to be added to the HAProxy listener bind directive.
#
# [*ip*]
# IP Address on which the stats interface is listening on. This right now
# assumes that it's in the ctlplane network.
#
# [*password*]
# Password for haproxy stats authentication. When set, authentication is
# enabled on the haproxy stats endpoint.
# A string.
# Defaults to undef
#
# [*certificate*]
# Filename of an HAProxy-compatible certificate and key file
# When set, enables SSL on the haproxy stats endpoint using the specified file.
# Defaults to undef
#
# [*user*]
# Username for haproxy stats authentication.
# A string.
# Defaults to 'admin'
#
class tripleo::haproxy::stats (
$haproxy_listen_bind_param,
$ip,
$password = undef,
$certificate = undef,
$user = 'admin'
) {
if $certificate {
$haproxy_stats_bind_opts = {
"${ip}:1993" => union($haproxy_listen_bind_param, ['ssl', 'crt', $certificate]),
}
} else {
$haproxy_stats_bind_opts = {
"${ip}:1993" => $haproxy_listen_bind_param,
}
}
$stats_base = ['enable', 'uri /']
if $password {
$stats_config = union($stats_base, ["auth ${user}:${password}"])
} else {
$stats_config = $stats_base
}
haproxy::listen { 'haproxy.stats':
bind => $haproxy_stats_bind_opts,
mode => 'http',
options => {
'stats' => $stats_config,
},
collect_exported => false,
}
}

View File

@ -0,0 +1,8 @@
---
features:
- When TLS everywhere is enabled, the HAProxy stats interface will also use
TLS. This requires the user to access the interface through the ctlplane
FQDN (which is configured by the CloudNameCtlplane parameter in
tripleo-heat-templates). Note that one can still use the
haproxy_stats_certificate parameter from the haproxy class, and that one
will take precedence if set.

View File

@ -0,0 +1,104 @@
#
# Copyright (C) 2016 Red Hat, Inc.
#
# 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.
#
require 'spec_helper'
describe 'tripleo::haproxy::stats' do
shared_examples_for 'tripleo::haproxy::stats' do
let :pre_condition do
"Haproxy::Listen {
config_file => '/etc/haproxy.cfg'
}"
end
context 'with only required parameters' do
let(:params) do
{
:ip => '127.0.0.1',
:haproxy_listen_bind_param => ['transparent'],
}
end
it 'should configure basic stats frontend' do
is_expected.to contain_haproxy__listen('haproxy.stats').with(
:bind => {
"127.0.0.1:1993" => ['transparent']
},
:mode => 'http',
:options => {
'stats' => ['enable', 'uri /']
},
:collect_exported => false
)
end
end
context 'with auth parameters' do
let(:params) do
{
:ip => '127.0.0.1',
:haproxy_listen_bind_param => ['transparent'],
:user => 'myuser',
:password => 'superdupersecret',
}
end
it 'should configure stats frontend with auth enabled' do
is_expected.to contain_haproxy__listen('haproxy.stats').with(
:bind => {
"127.0.0.1:1993" => ['transparent']
},
:mode => 'http',
:options => {
'stats' => ['enable', 'uri /', 'auth myuser:superdupersecret']
},
:collect_exported => false
)
end
end
context 'with certificate parameter' do
let(:params) do
{
:ip => '127.0.0.1',
:haproxy_listen_bind_param => ['transparent'],
:certificate => '/path/to/cert',
}
end
it 'should configure stats frontend with TLS enabled' do
is_expected.to contain_haproxy__listen('haproxy.stats').with(
:bind => {
"127.0.0.1:1993" => ['transparent', 'ssl', 'crt', '/path/to/cert']
},
:mode => 'http',
:options => {
'stats' => ['enable', 'uri /']
},
:collect_exported => false
)
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::stats'
end
end
end