--- /dev/null
+# 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" |>
+ }
+}
--- /dev/null
+# 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
+ }
+}
--- /dev/null
+# 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
+######################################
+