From 7bd299a339017d6d41978cdbfd141ff134bc5eb8 Mon Sep 17 00:00:00 2001
From: Phillip Smith <fukawi2@gmail.com>
Date: Fri, 17 Aug 2018 10:22:07 +1000
Subject: [PATCH] break postgres client ips into separate variables

we have to use rich rules in firewalld to restict a specific port to a list of
specific ip addresses. when using rich rules, you have to specify the address
family (ipv4 or ipv6) which we can't do in an automated fashion with the ipv4
and ipv6 addresses of the clients dynamically generated into a single variable.
so this commit creates 2 variables; one for ipv4 clients and one for ipv6
clients which can be referred to as required when creating the rich rules.
---
 playbooks/apollo.yml                    | 10 +++++++---
 roles/postgres/defaults/main.yml        |  3 ++-
 roles/postgres/tasks/main.yml           | 17 ++++++++++++++---
 roles/postgres/templates/pg_hba.conf.j2 |  9 ++++++++-
 4 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/playbooks/apollo.yml b/playbooks/apollo.yml
index 21d34e41a..c7e34c428 100644
--- a/playbooks/apollo.yml
+++ b/playbooks/apollo.yml
@@ -7,12 +7,16 @@
 - name: "prepare postgres ssl hosts list"
   hosts: apollo.archlinux.org
   tasks:
-      - set_fact: postgres_ssl_hosts="{{ [orion4] + [orion6] + detected_ips}}"
+      - set_fact: postgres_ssl_hosts4="{{ [orion4] + detected_ips}}"
         vars:
-            orion4: "{{ hostvars['orion.archlinux.org']['ipv4_address'] }}{{ hostvars['orion.archlinux.org']['ipv4_netmask'] }}"
-            orion6: "{{ hostvars['orion.archlinux.org']['ipv6_address'] }}{{ hostvars['orion.archlinux.org']['ipv6_netmask'] }}"
+            orion4: "{{ hostvars['orion.archlinux.org']['ipv4_address'] }}"
             detected_ips: "{{ groups['mirrors'] | map('extract', hostvars, ['ansible_default_ipv4', 'address']) | map('regex_replace', '^(.*)$', '\\1/32') | list}}"
         tags: ["postgres"]
+      - set_fact: postgres_ssl_hosts6="{{ [orion6] + detected_ips}}"
+        vars:
+            orion6: "{{ hostvars['orion.archlinux.org']['ipv6_address'] }}"
+            detected_ips: "{{ groups['mirrors'] | map('extract', hostvars, ['ansible_default_ipv6', 'address']) | map('regex_replace', '^(.*)$', '\\1/32') | list}}"
+        tags: ["postgres"]
 
 - name: setup apollo
   hosts: apollo.archlinux.org
diff --git a/roles/postgres/defaults/main.yml b/roles/postgres/defaults/main.yml
index bb3e2d00d..d3a0060fa 100644
--- a/roles/postgres/defaults/main.yml
+++ b/roles/postgres/defaults/main.yml
@@ -10,4 +10,5 @@ postgres_ssl_ca_file: '/var/lib/postgres/data/chain.pem'
 
 postgres_shared_buffers: '128MB'
 
-postgres_ssl_hosts: []
+postgres_ssl_hosts4: []
+postgres_ssl_hosts6: []
diff --git a/roles/postgres/tasks/main.yml b/roles/postgres/tasks/main.yml
index 5254a2958..9e171e470 100644
--- a/roles/postgres/tasks/main.yml
+++ b/roles/postgres/tasks/main.yml
@@ -50,7 +50,18 @@
         remote_src=true owner=postgres group=postgres mode=0400
   when: postgres_ssl == 'on'
 
-- name: open firewall holes to known postgresql clients
-  firewalld: service=postgresql permanent=true state=enabled source={{item}} immediate=yes
-  with_items: "{{ postgres_ssl_hosts }}"
+- name: open firewall holes to known postgresql ipv4 clients
+  firewalld: permanent=true state=enabled immediate=yes
+    rich_rule="rule family=ipv4 source address={{item}} port protocol=tcp port=5432 accept"
+  with_items: "{{ postgres_ssl_hosts4 }}"
   when: configure_firewall
+  tags:
+    - firewall
+
+- name: open firewall holes to known postgresql ipv6 clients
+  firewalld: permanent=true state=enabled immediate=yes
+    rich_rule="rule family=ipv4 source address={{item}} port protocol=tcp port=5432 accept"
+  with_items: "{{ postgres_ssl_hosts6 }}"
+  when: configure_firewall
+  tags:
+    - firewall
diff --git a/roles/postgres/templates/pg_hba.conf.j2 b/roles/postgres/templates/pg_hba.conf.j2
index 1d7602cb0..712f15be4 100644
--- a/roles/postgres/templates/pg_hba.conf.j2
+++ b/roles/postgres/templates/pg_hba.conf.j2
@@ -90,6 +90,13 @@ host    sameuser        all             ::1/128                 md5
 #local   replication     all                                     peer
 #host    replication     all             127.0.0.1/32            md5
 #host    replication     all             ::1/128                 md5
-{% for host in postgres_ssl_hosts %}
+
+# IPv4 Remote Clients
+{% for host in postgres_ssl_hosts4 %}
+hostssl all             all             {{ host }}              md5
+{% endfor %}
+
+# IPv6 Remote Clients
+{% for host in postgres_ssl_hosts6 %}
 hostssl all             all             {{ host }}              md5
 {% endfor %}
-- 
GitLab