From 220ac182f41049e611f34448b10503dee5126e72 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Sun, 28 Apr 2024 19:27:32 +1000 Subject: [PATCH] feat: sydney haproxy cluster - add au-syd1 halb cluster - add http-response to frontends - manage haproxy after enc_role is correct --- .../au/region/drw1/infra/halb/haproxy.yaml | 5 + .../au/region/syd1/infra/halb/haproxy.yaml | 93 +++++++++++++++++++ .../manifests/haproxy/balancemember.pp | 2 +- site/profiles/manifests/haproxy/fe_http.pp | 10 +- site/profiles/manifests/haproxy/fe_https.pp | 10 +- site/profiles/manifests/haproxy/server.pp | 43 +++++---- site/profiles/manifests/proxmox/init.pp | 1 + site/profiles/manifests/proxmox/params.pp | 3 +- site/profiles/manifests/proxmox/weblb.pp | 21 +++++ 9 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 hieradata/country/au/region/syd1/infra/halb/haproxy.yaml create mode 100644 site/profiles/manifests/proxmox/weblb.pp diff --git a/hieradata/country/au/region/drw1/infra/halb/haproxy.yaml b/hieradata/country/au/region/drw1/infra/halb/haproxy.yaml index a582f9b..017eb4d 100644 --- a/hieradata/country/au/region/drw1/infra/halb/haproxy.yaml +++ b/hieradata/country/au/region/drw1/infra/halb/haproxy.yaml @@ -1,6 +1,11 @@ --- # mappings profiles::haproxy::mappings: + fe_http: + ensure: present + mappings: + - 'puppetboard.main.unkin.net be_puppetboard' + - 'puppetdbapi.main.unkin.net be_puppetdbapi' fe_https: ensure: present mappings: diff --git a/hieradata/country/au/region/syd1/infra/halb/haproxy.yaml b/hieradata/country/au/region/syd1/infra/halb/haproxy.yaml new file mode 100644 index 0000000..5bcf4c8 --- /dev/null +++ b/hieradata/country/au/region/syd1/infra/halb/haproxy.yaml @@ -0,0 +1,93 @@ +--- +# mappings +profiles::haproxy::mappings: + fe_http: + ensure: present + mappings: + - 'au-syd1-pve.main.unkin.net be_ausyd1pve' + fe_https: + ensure: present + mappings: + - 'au-syd1-pve.main.unkin.net be_ausyd1pve' + +# profiles::haproxy::listeners: +# ls_puppetdbapi_direct: +# collect_exported: false # handled in custom function +# ipaddress: "%{facts.networking.ip}" +# ports: +# - 8081 +# mode: tcp +# options: +# option: +# - tcplog +# - ssl-hello-chk +# balance: roundrobin + +profiles::haproxy::backends: + be_ausyd1pve: + description: Backend for au-syd1 pve cluster + collect_exported: false # handled in custom function + options: + balance: roundrobin + option: + - httpchk GET / + - forwardfor + cookie: SRVNAME insert + http-request: + - set-header X-Forwarded-Port %[dst_port] + - add-header X-Forwarded-Proto https if { dst_port 443 } + redirect: 'scheme https if !{ ssl_fc }' + be_letsencrypt: + description: Backend for LetsEncrypt Verifications + collect_exported: true + options: + balance: roundrobin + be_default: + description: Backend for unmatched HTTP traffic + collect_exported: true + options: + balance: roundrobin + option: + - httpchk GET / + - forwardfor + cookie: SRVNAME insert + http-request: + - set-header X-Forwarded-Port %[dst_port] + - add-header X-Forwarded-Proto https if { dst_port 443 } + +# fe_http +profiles::haproxy::fe_http::bind_addr: 0.0.0.0 +profiles::haproxy::fe_http::bind_port: 80 +profiles::haproxy::fe_http::bind_opts: + - transparent +profiles::haproxy::fe_http::acls: + - 'acl-letsencrypt path_beg /.well-known/acme-challenge/' +profiles::haproxy::fe_http::http_request: + - 'set-header X-Forwarded-Proto https' + - 'set-header X-Real-IP %[src]' + +# fe_https +profiles::haproxy::fe_https::bind_addr: 0.0.0.0 +profiles::haproxy::fe_https::bind_port: 443 +profiles::haproxy::fe_https::bind_opts: + - ssl + - crt-list /etc/haproxy/certificate.list + - ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH + - force-tlsv12 +profiles::haproxy::fe_https::acls: + - 'acl-letsencrypt path_beg /.well-known/acme-challenge/' +profiles::haproxy::fe_https::http_request: + - 'set-header X-Forwarded-Proto https' + - 'set-header X-Real-IP %[src]' + +profiles::haproxy::certlist::enabled: true +profiles::haproxy::certlist::certificates: + - /etc/pki/tls/vault/certificate.pem + +# additional altnames +profiles::pki::vault::alt_names: + - au-syd1-pve.main.unkin.net + +# additional cnames +profiles::haproxy::dns::cnames: + - au-syd1-pve.main.unkin.net diff --git a/site/profiles/manifests/haproxy/balancemember.pp b/site/profiles/manifests/haproxy/balancemember.pp index 6acbf84..a477a91 100644 --- a/site/profiles/manifests/haproxy/balancemember.pp +++ b/site/profiles/manifests/haproxy/balancemember.pp @@ -8,7 +8,7 @@ define profiles::haproxy::balancemember ( $location_environment = "${facts['country']}-${facts['region']}-${facts['environment']}" $balancemember_tag = "${service}_${location_environment}" - @@haproxy::balancermember { $balancemember_tag: + @@haproxy::balancermember { $title: listening_service => $service, ports => $ports, server_names => $facts['networking']['hostname'], diff --git a/site/profiles/manifests/haproxy/fe_http.pp b/site/profiles/manifests/haproxy/fe_http.pp index 19909c1..1d91f11 100644 --- a/site/profiles/manifests/haproxy/fe_http.pp +++ b/site/profiles/manifests/haproxy/fe_http.pp @@ -5,16 +5,18 @@ class profiles::haproxy::fe_http ( Array $bind_opts = ['transparent'], Array $acls = [], Array $http_request = [], + Array $http_response = [], ) { haproxy::frontend { 'fe_http': description => 'Default HTTP Frontend', bind => { "${bind_addr}:${bind_port}" => $bind_opts }, mode => 'http', options => { - 'acl' => $acls, - 'http-request' => $http_request, - 'use_backend' => [ - '%[req.hdr(host),lower,map(/etc/haproxy/domains-to-backends.map,be_default)]', + 'acl' => $acls, + 'http-request' => $http_request, + 'http-response' => $http_response, + 'use_backend' => [ + '%[req.hdr(host),lower,map(/etc/haproxy/fe_http.map,be_default)]', ], }, } diff --git a/site/profiles/manifests/haproxy/fe_https.pp b/site/profiles/manifests/haproxy/fe_https.pp index 7e98328..e7c9b0f 100644 --- a/site/profiles/manifests/haproxy/fe_https.pp +++ b/site/profiles/manifests/haproxy/fe_https.pp @@ -5,16 +5,18 @@ class profiles::haproxy::fe_https ( Array $bind_opts = [], Array $acls = [], Array $http_request = [], + Array $http_response = [], ) { haproxy::frontend { 'fe_https': description => 'Default HTTPS Frontend', bind => { "${bind_addr}:${bind_port}" => $bind_opts }, mode => 'http', options => { - 'acl' => $acls, - 'http-request' => $http_request, - 'use_backend' => [ - '%[req.hdr(host),lower,map(/etc/haproxy/domains-to-backends.map,be_default)]', + 'acl' => $acls, + 'http-request' => $http_request, + 'http-response' => $http_response, + 'use_backend' => [ + '%[req.hdr(host),lower,map(/etc/haproxy/fe_https.map,be_default)]', ], }, } diff --git a/site/profiles/manifests/haproxy/server.pp b/site/profiles/manifests/haproxy/server.pp index fde8f2f..0a27fea 100644 --- a/site/profiles/manifests/haproxy/server.pp +++ b/site/profiles/manifests/haproxy/server.pp @@ -35,24 +35,31 @@ class profiles::haproxy::server ( $merged_global_options = merge($global_options, $globals) $merged_default_options = merge($default_options, $defaults) - # manage selinux - include profiles::haproxy::selinux + # wait until enc_role matches haproxy enc_role + if $facts['enc_role'] == 'roles::infra::halb::haproxy' { - # create the haproxy service/instance - class { 'haproxy': - global_options => $merged_global_options, - defaults_options => $merged_default_options, - require => Class['profiles::haproxy::selinux'] + # manage selinux + include profiles::haproxy::selinux + + # create the haproxy service/instance + class { 'haproxy': + global_options => $merged_global_options, + defaults_options => $merged_default_options, + require => Class['profiles::haproxy::selinux'] + } + + include profiles::haproxy::certlist # manage the certificate list file + include profiles::haproxy::mappings # manage the domain to backend mappings + include profiles::haproxy::ls_stats # default status listener + include profiles::haproxy::fe_http # default http frontend + include profiles::haproxy::fe_https # default https frontend + include profiles::haproxy::dns # manage dns for haproxy + include profiles::haproxy::frontends # create frontends + include profiles::haproxy::backends # create backends + include profiles::haproxy::listeners # create listeners + + Class['profiles::haproxy::certlist'] + -> Class['profiles::haproxy::dns'] + -> Class['profiles::haproxy::mappings'] } - - include profiles::haproxy::certlist # manage the certificate list file - include profiles::haproxy::mappings # manage the domain to backend mappings - include profiles::haproxy::ls_stats # default status listener - include profiles::haproxy::fe_http # default http frontend - include profiles::haproxy::fe_https # default https frontend - include profiles::haproxy::dns # manage dns for haproxy - include profiles::haproxy::frontends # create frontends - include profiles::haproxy::backends # create backends - include profiles::haproxy::listeners # create listeners - } diff --git a/site/profiles/manifests/proxmox/init.pp b/site/profiles/manifests/proxmox/init.pp index f7d769f..1d90b3d 100644 --- a/site/profiles/manifests/proxmox/init.pp +++ b/site/profiles/manifests/proxmox/init.pp @@ -7,6 +7,7 @@ class profiles::proxmox::init { include profiles::proxmox::clusterjoin include profiles::proxmox::ceph include profiles::proxmox::config + include profiles::proxmox::weblb Class['profiles::proxmox::repos'] -> Class['profiles::proxmox::install'] diff --git a/site/profiles/manifests/proxmox/params.pp b/site/profiles/manifests/proxmox/params.pp index d520f45..17e69ce 100644 --- a/site/profiles/manifests/proxmox/params.pp +++ b/site/profiles/manifests/proxmox/params.pp @@ -38,6 +38,7 @@ class profiles::proxmox::params ( 'ceph-volume', 'gdisk', 'nvme-cli' - ] + ], + Stdlib::Port $pve_webport = 8006, ){ } diff --git a/site/profiles/manifests/proxmox/weblb.pp b/site/profiles/manifests/proxmox/weblb.pp new file mode 100644 index 0000000..2f6f4e5 --- /dev/null +++ b/site/profiles/manifests/proxmox/weblb.pp @@ -0,0 +1,21 @@ +# profiles::proxmox::weblb +class profiles::proxmox::weblb { + + # include params class + include profiles::proxmox::params + + # export haproxy balancemember + profiles::haproxy::balancemember { "${facts['networking']['fqdn']}_${profiles::proxmox::params::pve_webport}}": + service => "be_${facts['country']}${facts['region']}pve", + ports => [$profiles::proxmox::params::pve_webport], + options => [ + "cookie ${facts['networking']['hostname']}", + 'ssl', + 'verify none', + 'check', + 'inter 2s', + 'rise 3', + 'fall 2', + ] + } +}