Start with pg cluster configuration
authorPeter Palfrader <peter@palfrader.org>
Sun, 29 Sep 2019 08:57:49 +0000 (10:57 +0200)
committerPeter Palfrader <peter@palfrader.org>
Sun, 29 Sep 2019 08:58:19 +0000 (10:58 +0200)
modules/postgres/manifests/cluster.pp [new file with mode: 0644]
modules/postgres/manifests/cluster/hba_entry.pp [new file with mode: 0644]
modules/postgres/templates/cluster/pg_hba.conf-head.erb [new file with mode: 0644]

diff --git a/modules/postgres/manifests/cluster.pp b/modules/postgres/manifests/cluster.pp
new file mode 100644 (file)
index 0000000..a57f543
--- /dev/null
@@ -0,0 +1,42 @@
+# postgresql cluster configuration
+#
+# @param pg_version      pg version of the cluster
+# @param pg_cluster      cluster name
+# @param pg_port         port of the postgres cluster
+# @param manage_hba      manage pg_hba
+# @param confdir         directory where the configuration resides
+define postgres::cluster(
+  String $pg_version,
+  String $pg_cluster = 'main',
+  Integer $pg_port = 5432,
+  Boolean $manage_hba = false,
+  String $confdir = "/etc/postgresql/${pg_version}/${pg_cluster}",
+) {
+  $reload = "postgresql ${pg_version}/${pg_cluster} reload"
+  exec { $reload:
+    command     => "systemctl reload postgresql@${pg_version}-${pg_cluster}.service",
+    refreshonly => true,
+  }
+
+  ferm::rule::simple { "postgres::cluster::hba_entry::${pg_version}::${pg_cluster}":
+    description => "check access to pg${pg_version}/${pg_cluster}",
+    port        => $pg_port,
+    target      => "pg-${pg_port}",
+  }
+
+  if $manage_hba {
+    concat { "postgres::cluster::${pg_version}::${pg_cluster}::hba":
+      path           => "${confdir}/pg_hba.conf",
+      mode           => '0440',
+      group          => 'postgres',
+      ensure_newline => true,
+      notify         => Exec[$reload],
+    }
+    concat::fragment{ "postgres::cluster::pg_hba-head::${pg_version}::${pg_cluster}":
+      target  => "postgres::cluster::${pg_version}::${pg_cluster}::hba",
+      order   => '00',
+      content => template('postgres/cluster/pg_hba.conf-head.erb'),
+    }
+    Concat::Fragment <| tag == "postgres::cluster::${pg_version}::${pg_cluster}::hba" |>
+  }
+}
diff --git a/modules/postgres/manifests/cluster/hba_entry.pp b/modules/postgres/manifests/cluster/hba_entry.pp
new file mode 100644 (file)
index 0000000..e909a3c
--- /dev/null
@@ -0,0 +1,74 @@
+# An entry in pg_hba and the corresponding firewall rule if necessary
+#
+# This currently only supports a limited number of entry types.  Only
+# what we need at the moment.
+#
+# See the upstream documentation at https://www.postgresql.org/docs/11/auth-pg-hba-conf.html
+# for details.
+#
+# @param pg_port          port of the postgres cluster
+# @param pg_cluster       cluster name
+# @param pg_version       pg version of the cluster
+# @param connection_type  connection type
+# @param database         database (or all, sameuser, replication, etc.)
+# @param user             user (or all, etc.)
+# @param address          hosts that match
+# @param method           auth method
+# @param order            ordering of this entry in pg_hba.conf
+define postgres::cluster::hba_entry (
+  Integer $pg_port,
+  String $pg_cluster,
+  String $pg_version,
+  Enum['local', 'hostssl'] $connection_type = 'hostssl',
+  Variant[String,Array[String]] $database = 'sameuser',
+  Variant[String,Array[String]] $user = 'all',
+  Optional[Variant[Stdlib::IP::Address, Array[Stdlib::IP::Address]]] $address = undef,
+  Enum['md5', 'trust'] $method = 'md5',
+  String $order = '50',
+) {
+  $address_methods = ['md5']
+  if $method in $address_methods {
+    if !$address {
+      fail("Authentication method ${method} needs an address")
+    }
+  } else {
+    if !($method in $address_methods) {
+      fail("Authentication method ${method} needs no address")
+    }
+  }
+
+  if ($address) {
+    ferm::rule::simple { "postgres::cluster::hba_entry::${pg_version}::${pg_cluster}::${name}":
+      description => "allow access to pg${pg_version}/${pg_cluster}: ${name}",
+      saddr       => $address,
+      chain       => "pg-${pg_port}",
+    }
+  }
+
+  $real_database = Array($database, true).sort().join(',')
+  $real_user     = Array($user, true).sort().join(',')
+  $real_address  = $address ? {
+    undef   => [''],
+    default => Array($address, true).map |$a| {
+      if    $a =~ Stdlib::IP::Address::V4::CIDR     { $a }
+      elsif $a =~ Stdlib::IP::Address::V4::Nosubnet { "${a}/32" }
+      elsif $a =~ Stdlib::IP::Address::V6::CIDR     { $a }
+      elsif $a =~ Stdlib::IP::Address::V6::Nosubnet { "${a}/128" }
+      else { fail("Do not know address type for ${a}") }
+    }
+  }
+
+  @concat::fragment { "postgres::cluster::pg_hba::${pg_version}::${pg_cluster}::${name}":
+    tag     => "postgres::cluster::${pg_version}::${pg_cluster}::hba",
+    target  => "postgres::cluster::${pg_version}::${pg_cluster}::hba",
+    order   => $order,
+    content => inline_template( @(EOF) ),
+                  #
+                  # rule <%= @name %>
+                  <% @real_address.each do |addr| -%>
+                  <%= [@connection_type, @real_database, @real_user, addr, @method].join(' ') %>
+                  <% end -%>
+                  #
+                  | EOF
+  }
+}
diff --git a/modules/postgres/templates/cluster/pg_hba.conf-head.erb b/modules/postgres/templates/cluster/pg_hba.conf-head.erb
new file mode 100644 (file)
index 0000000..f899cf1
--- /dev/null
@@ -0,0 +1,22 @@
+# PostgreSQL Client Authentication Configuration File
+# ===================================================
+# maintained via puppet
+
+# default entries allows local access:
+######################################
+# Database administrative login by Unix domain socket
+local   all             postgres                                peer
+
+# "local" is for Unix domain socket connections only
+local   all             all                                     peer
+# IPv4 local connections:
+host    all             all             127.0.0.1/32            md5
+# IPv6 local connections:
+host    all             all             ::1/128                 md5
+# Allow replication connections from localhost, by a user with the
+# replication privilege.
+local   replication     all                                     peer
+host    replication     all             127.0.0.1/32            md5
+host    replication     all             ::1/128                 md5
+######################################
+