Create separate resource for HAProxy horizon endpoint
authorJuan Antonio Osorio Robles <jaosorior@redhat.com>
Mon, 7 Aug 2017 11:09:15 +0000 (14:09 +0300)
committerJuan Antonio Osorio Robles <jaosorior@redhat.com>
Thu, 17 Aug 2017 13:29:03 +0000 (13:29 +0000)
This removes clutter from the main haproxy manifest and allows TLS in
the internal network as well. Trying to keep the previous behavior.

bp tls-via-certmonger-containers
Change-Id: I1a68771cc7be7fb2b32abbad81db7890bd2c5502

manifests/haproxy.pp
manifests/haproxy/horizon_endpoint.pp [new file with mode: 0644]

index a3d088a..83ca930 100644 (file)
 #  (optional) Specify the network heat_cloudwatch is running on.
 #  Defaults to hiera('heat_api_cloudwatch_network', undef)
 #
+# [*horizon_network*]
+#  (optional) Specify the network horizon is running on.
+#  Defaults to hiera('horizon_network', undef)
+#
 # [*ironic_inspector_network*]
 #  (optional) Specify the network ironic_inspector is running on.
 #  Defaults to hiera('ironic_inspector_network', undef)
@@ -644,6 +648,7 @@ class tripleo::haproxy (
   $heat_api_network            = hiera('heat_api_network', undef),
   $heat_cfn_network            = hiera('heat_api_cfn_network', undef),
   $heat_cloudwatch_network     = hiera('heat_api_cloudwatch_network', undef),
+  $horizon_network             = hiera('horizon_network', undef),
   $ironic_inspector_network    = hiera('ironic_inspector_network', undef),
   $ironic_network              = hiera('ironic_api_network', undef),
   $keystone_admin_network      = hiera('keystone_admin_api_network', undef),
@@ -772,43 +777,6 @@ class tripleo::haproxy (
     $controller_hosts_names_real = downcase(any2array(split($controller_hosts_names, ',')))
   }
 
-  $horizon_vip = hiera('horizon_vip', $controller_virtual_ip)
-  if $service_certificate {
-    # NOTE(jaosorior): If the horizon_vip and the public_virtual_ip are the
-    # same, the first option takes precedence. Which is the case when network
-    # isolation is not enabled. This is not a problem as both options are
-    # identical. If network isolation is enabled, this works correctly and
-    # will add a TLS binding to both the horizon_vip and the
-    # public_virtual_ip.
-    # Even though for the public_virtual_ip the port 80 is listening, we
-    # redirect to https in the horizon_options below.
-    $horizon_bind_opts = {
-      "${horizon_vip}:80"        => $haproxy_listen_bind_param,
-      "${horizon_vip}:443"       => union($haproxy_listen_bind_param, ['ssl', 'crt', $service_certificate]),
-      "${public_virtual_ip}:80"  => $haproxy_listen_bind_param,
-      "${public_virtual_ip}:443" => union($haproxy_listen_bind_param, ['ssl', 'crt', $service_certificate]),
-    }
-    $horizon_options = {
-      'cookie'       => 'SERVERID insert indirect nocache',
-      'rsprep'       => '^Location:\ http://(.*) Location:\ https://\1',
-      # NOTE(jaosorior): We always redirect to https for the public_virtual_ip.
-      'redirect'     => 'scheme https code 301 if !{ ssl_fc }',
-      'option'       => [ 'forwardfor', 'httpchk' ],
-      'http-request' => [
-          'set-header X-Forwarded-Proto https if { ssl_fc }',
-          'set-header X-Forwarded-Proto http if !{ ssl_fc }'],
-    }
-  } else {
-    $horizon_bind_opts = {
-      "${horizon_vip}:80" => $haproxy_listen_bind_param,
-      "${public_virtual_ip}:80" => $haproxy_listen_bind_param,
-    }
-    $horizon_options = {
-      'cookie' => 'SERVERID insert indirect nocache',
-      'option' => [ 'forwardfor', 'httpchk' ],
-    }
-  }
-
   $mysql_vip = hiera('mysql_vip', $controller_virtual_ip)
   $mysql_bind_opts = {
     "${mysql_vip}:3306" => $haproxy_listen_bind_param,
@@ -1274,18 +1242,17 @@ class tripleo::haproxy (
   }
 
   if $horizon {
-    haproxy::listen { 'horizon':
-      bind             => $horizon_bind_opts,
-      options          => $horizon_options,
-      mode             => 'http',
-      collect_exported => false,
-    }
-    haproxy::balancermember { 'horizon':
-      listening_service => 'horizon',
-      ports             => '80',
-      ipaddresses       => hiera('horizon_node_ips', $controller_hosts_real),
-      server_names      => hiera('horizon_node_names', $controller_hosts_names_real),
-      options           => union($haproxy_member_options, ["cookie ${::hostname}"]),
+    class { '::tripleo::haproxy::horizon_endpoint':
+      public_virtual_ip           => $public_virtual_ip,
+      internal_ip                 => hiera('horizon_vip', $controller_virtual_ip),
+      haproxy_listen_bind_param   => $haproxy_listen_bind_param,
+      ip_addresses                => hiera('horizon_node_ips', $controller_hosts_real),
+      server_names                => hiera('horizon_node_names', $controller_hosts_names_real),
+      member_options              => union($haproxy_member_options, $internal_tls_member_options),
+      public_certificate          => $service_certificate,
+      use_internal_certificates   => $use_internal_certificates,
+      internal_certificates_specs => $internal_certificates_specs,
+      service_network             => $horizon_network,
     }
   }
 
diff --git a/manifests/haproxy/horizon_endpoint.pp b/manifests/haproxy/horizon_endpoint.pp
new file mode 100644 (file)
index 0000000..c7dfd88
--- /dev/null
@@ -0,0 +1,154 @@
+# 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::endpoint
+#
+# Configure a HAProxy listen endpoint
+#
+# [*internal_ip*]
+#  The IP in which the proxy endpoint will be listening in the internal
+#  network.
+#
+# [*ip_addresses*]
+#  The ordered list of IPs to be used to contact the balancer member.
+#
+# [*server_names*]
+#  The names of the balancer members, which usually should be the hostname.
+#
+# [*member_options*]
+#  Options for the balancer member, specified after the server declaration.
+#  These should go in the member's configuration block.
+#
+# [*public_virtual_ip*]
+#  Address in which the proxy endpoint will be listening in the public network.
+#  If this service is internal only this should be ommitted.
+#  Defaults to undef.
+#
+# [*haproxy_listen_bind_param*]
+#  A list of params to be added to the HAProxy listener bind directive.
+#  Defaults to undef.
+#
+# [*public_certificate*]
+#  Certificate path used to enable TLS for the public proxy endpoint.
+#  Defaults to undef.
+#
+# [*use_internal_certificates*]
+#  Flag that indicates if we'll use an internal certificate for this specific
+#  service. When set, enables SSL on the internal API endpoints using the file
+#  that certmonger is tracking; this is derived from the network the service is
+#  listening on.
+#  Defaults to false
+#
+# [*internal_certificates_specs*]
+#  A hash that should contain the specs that were used to create the
+#  certificates. As the name indicates, only the internal certificates will be
+#  fetched from here. And the keys should follow the following pattern
+#  "haproxy-<network name>". The network name should be as it was defined in
+#  tripleo-heat-templates.
+#  Note that this is only taken into account if the $use_internal_certificates
+#  flag is set.
+#  Defaults to {}
+#
+# [*service_network*]
+#  (optional) Indicates the network that the service is running on. Used for
+#  fetching the certificate for that specific network.
+#  Defaults to undef
+#
+class tripleo::haproxy::horizon_endpoint (
+  $internal_ip,
+  $ip_addresses,
+  $server_names,
+  $member_options,
+  $public_virtual_ip,
+  $haproxy_listen_bind_param   = undef,
+  $public_certificate          = undef,
+  $use_internal_certificates   = false,
+  $internal_certificates_specs = {},
+  $service_network             = undef,
+) {
+  # service exposed to the public network
+  if $public_certificate {
+    if $use_internal_certificates {
+      if !$service_network {
+        fail("The service_network for this service is undefined. Can't configure TLS for the internal network.")
+      }
+      # NOTE(jaosorior): The key of the internal_certificates_specs hash must
+      # must match the convention haproxy-<network name> or else this
+      # will fail. Futherly, it must contain the path that we'll use under
+      # 'service_pem'.
+      $internal_cert_path = $internal_certificates_specs["haproxy-${service_network}"]['service_pem']
+      $internal_bind_opts = union($haproxy_listen_bind_param, ['ssl', 'crt', $internal_cert_path])
+    } else {
+      # If no internal cert is given, we still configure TLS for the internal
+      # network, however, we expect that the public certificate has appropriate
+      # subjectaltnames set.
+      $internal_bind_opts = union($haproxy_listen_bind_param, ['ssl', 'crt', $public_certificate])
+    }
+    # NOTE(jaosorior): If the internal_ip and the public_virtual_ip are the
+    # same, the first option takes precedence. Which is the case when network
+    # isolation is not enabled. This is not a problem as both options are
+    # identical. If network isolation is enabled, this works correctly and
+    # will add a TLS binding to both the internal_ip and the
+    # public_virtual_ip.
+    # Even though for the public_virtual_ip the port 80 is listening, we
+    # redirect to https in the horizon_options below.
+    $horizon_bind_opts = {
+      "${internal_ip}:80"        => $haproxy_listen_bind_param,
+      "${internal_ip}:443"       => $internal_bind_opts,
+      "${public_virtual_ip}:80"  => $haproxy_listen_bind_param,
+      "${public_virtual_ip}:443" => union($haproxy_listen_bind_param, ['ssl', 'crt', $public_certificate]),
+    }
+    $horizon_options = {
+      'cookie'       => 'SERVERID insert indirect nocache',
+      'rsprep'       => '^Location:\ http://(.*) Location:\ https://\1',
+      # NOTE(jaosorior): We always redirect to https for the public_virtual_ip.
+      'redirect'     => 'scheme https code 301 if !{ ssl_fc }',
+      'option'       => [ 'forwardfor', 'httpchk' ],
+      'http-request' => [
+          'set-header X-Forwarded-Proto https if { ssl_fc }',
+          'set-header X-Forwarded-Proto http if !{ ssl_fc }'],
+    }
+  } else {
+    $horizon_bind_opts = {
+      "${internal_ip}:80" => $haproxy_listen_bind_param,
+      "${public_virtual_ip}:80" => $haproxy_listen_bind_param,
+    }
+    $horizon_options = {
+      'cookie' => 'SERVERID insert indirect nocache',
+      'option' => [ 'forwardfor', 'httpchk' ],
+    }
+  }
+
+  if $use_internal_certificates {
+    # Use SSL port if TLS in the internal network is enabled.
+    $backend_port = '443'
+  } else {
+    $backend_port = '80'
+  }
+
+  haproxy::listen { 'horizon':
+    bind             => $horizon_bind_opts,
+    options          => $horizon_options,
+    mode             => 'http',
+    collect_exported => false,
+  }
+  haproxy::balancermember { 'horizon':
+    listening_service => 'horizon',
+    ports             => $backend_port,
+    ipaddresses       => $ip_addresses,
+    server_names      => $server_names,
+    options           => union($member_options, ["cookie ${::hostname}"]),
+  }
+}