unique postgres::cluster::hba_entry names for hosts with more than one cluster
[mirror/dsa-puppet.git] / modules / postgres / manifests / cluster / hba_entry.pp
1 # An entry in pg_hba and the corresponding firewall rule if necessary
2 #
3 # This currently only supports a limited number of entry types.  Only
4 # what we need at the moment.
5 #
6 # See the upstream documentation at https://www.postgresql.org/docs/11/auth-pg-hba-conf.html
7 # for details.
8 #
9 # @param pg_port          port of the postgres cluster
10 # @param pg_cluster       cluster name
11 # @param pg_version       pg version of the cluster
12 # @param connection_type  connection type
13 # @param database         database (or all, sameuser, replication, etc.)
14 # @param user             user (or all, etc.)
15 # @param address          hosts that match
16 # @param method           auth method
17 # @param order            ordering of this entry in pg_hba.conf
18 define postgres::cluster::hba_entry (
19   Integer $pg_port,
20   String $pg_cluster,
21   String $pg_version,
22   Enum['local', 'hostssl'] $connection_type = 'hostssl',
23   Variant[String,Array[String]] $database = 'sameuser',
24   Variant[String,Array[String]] $user = 'all',
25   Optional[Variant[Stdlib::IP::Address, Array[Stdlib::IP::Address]]] $address = undef,
26   Enum['md5', 'trust'] $method = 'md5',
27   String $order = '50',
28 ) {
29   $address_methods = ['md5']
30   if $method in $address_methods {
31     if !$address {
32       fail("Authentication method ${method} needs an address")
33     }
34   } else {
35     if !($method in $address_methods) {
36       fail("Authentication method ${method} needs no address")
37     }
38   }
39
40   if ($address) {
41     ferm::rule::simple { "postgres::cluster::hba_entry::${name}":
42       description => "allow access to pg${pg_version}/${pg_cluster}: ${name}",
43       saddr       => $address,
44       chain       => "pg-${pg_port}",
45     }
46   }
47
48   $real_database = Array($database, true).sort().join(',')
49   $real_user     = Array($user, true).sort().join(',')
50   $real_address  = $address ? {
51     undef   => [''],
52     default => Array($address, true).map |$a| {
53       if    $a =~ Stdlib::IP::Address::V4::CIDR     { $a }
54       elsif $a =~ Stdlib::IP::Address::V4::Nosubnet { "${a}/32" }
55       elsif $a =~ Stdlib::IP::Address::V6::CIDR     { $a }
56       elsif $a =~ Stdlib::IP::Address::V6::Nosubnet { "${a}/128" }
57       else { fail("Do not know address type for ${a}") }
58     }
59   }
60
61   @concat::fragment { "postgres::cluster::pg_hba::${name}":
62     tag     => "postgres::cluster::${pg_version}::${pg_cluster}::hba",
63     target  => "postgres::cluster::${pg_version}::${pg_cluster}::hba",
64     order   => $order,
65     content => inline_template( @(EOF) ),
66                   #
67                   # rule <%= @name %>
68                   <% @real_address.each do |addr| -%>
69                   <%= [@connection_type, @real_database, @real_user, addr, @method].join(' ') %>
70                   <% end -%>
71                   #
72                   | EOF
73   }
74 }