Skip to content

Commit ba80247

Browse files
committed
Improve configuration for initial postgres install
This commit adds some configuration management for postgres, to allow users to get a more complete setup from their initial install. Prior to this commit, we were basically only ensuring that the package was installed and the service was running. Now, we support limited configuration for the pg_hba.conf file to enable md5 authentication for remote hosts, and for the postgresql.conf file to specify the listener addresses where TCP connections should be accepted. Without these two changes the initial postgres configuration doesn't allow *any* connections from outside of the local host. This commit also adds an option for opening up the postgres port in the firewall on redhat-based systems, and an option to allow setting the password for the 'postgres' database user. As of this commit, this module now has dependencies on puppetlabs-stdlib (version > 2.3.4, which includes the new 'match' parameter for the 'file_line' resource type), and on puppetlabs-firewall.
1 parent 6034e12 commit ba80247

File tree

7 files changed

+325
-12
lines changed

7 files changed

+325
-12
lines changed

manifests/config.pp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Class: postgresql::config
2+
#
3+
# Parameters:
4+
#
5+
# [*postgres_password*] - postgres db user password.
6+
# [*ip_mask_postgres_user*] - ip mask for allowing remote access for postgres user; defaults to '127.0.0.1/32'
7+
# [*ip_mask_all_users*] - ip mask for allowing remote access for other users (besides postgres);
8+
# defaults to '127.0.0.1/32'
9+
# [*listen_addresses*] - what IP address(es) to listen on; comma-separated list of addresses; defaults to
10+
# 'localhost', '*' = all
11+
# [*pg_hba_conf_path*] - path to pg_hba.conf file
12+
# [*postgresql_conf_path*] - path to postgresql.conf file
13+
# [*manage_redhat_firewall*] - boolean indicating whether or not the module should open a port in the firewall on
14+
# redhat-based systems; this parameter is likely to change in future versions. Possible
15+
# changes include support for non-RedHat systems and finer-grained control over the
16+
# firewall rule (currently, it simply opens up the postgres port to all TCP connections).
17+
#
18+
#
19+
# Actions:
20+
#
21+
# Requires:
22+
#
23+
# Usage:
24+
#
25+
# class { 'postgresql::config':
26+
# postgres_password => 'postgres',
27+
# ip_mask_other_user => '127.0.0.1/32',
28+
# }
29+
#
30+
class postgresql::config(
31+
$postgres_password = undef,
32+
$ip_mask_postgres_user = $postgresql::params::ip_mask_postgres_user,
33+
$ip_mask_all_users = $postgresql::params::ip_mask_all_users,
34+
$listen_addresses = $postgresql::params::listen_addresses,
35+
$pg_hba_conf_path = $postgresql::params::pg_hba_conf_path,
36+
$postgresql_conf_path = $postgresql::params::postgresql_conf_path,
37+
$manage_redhat_firewall = $postgresql::params::manage_redhat_firewall,
38+
) inherits postgresql::params {
39+
40+
# Basically, all this class needs to handle is passing parameters on
41+
# to the "beforeservice" and "afterservice" classes, and ensure
42+
# the proper ordering.
43+
44+
class { "postgresql::config::beforeservice":
45+
ip_mask_postgres_user => $ip_mask_postgres_user,
46+
ip_mask_all_users => $ip_mask_all_users,
47+
listen_addresses => $listen_addresses,
48+
pg_hba_conf_path => $pg_hba_conf_path,
49+
postgresql_conf_path => $postgresql_conf_path,
50+
manage_redhat_firewall => $manage_redhat_firewall,
51+
}
52+
53+
class { "postgresql::config::afterservice":
54+
postgres_password => $postgres_password,
55+
}
56+
57+
Class['postgresql::config'] ->
58+
Class['postgresql::config::beforeservice'] ->
59+
Service['postgresqld'] ->
60+
Class['postgresql::config::afterservice']
61+
62+
63+
}

manifests/config/afterservice.pp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Class: postgresql::config::afterservice
2+
#
3+
# Parameters:
4+
#
5+
# [*postgres_password*] - postgres db user password.
6+
#
7+
# Actions:
8+
#
9+
# Requires:
10+
#
11+
# Usage:
12+
# This class is not intended to be used directly; it is
13+
# managed by postgresl::config. It contains resources
14+
# that should be handled *after* the postgres service
15+
# has been started up.
16+
#
17+
# class { 'postgresql::config::afterservice':
18+
# postgres_password => 'postgres'
19+
# }
20+
#
21+
class postgresql::config::afterservice(
22+
$postgres_password = undef
23+
) inherits postgresql::params {
24+
if ($postgres_password != undef) {
25+
# NOTE: this password-setting logic relies on the pg_hba.conf being configured
26+
# to allow the postgres system user to connect via psql without specifying
27+
# a password ('ident', 'peer', or 'trust' security). This is the default
28+
# for pg_hba.conf.
29+
exec { 'set_postgres_postgrespw':
30+
# This command works w/no password because we run it as postgres system user
31+
command => "psql -c \"ALTER ROLE postgres PASSWORD '$postgres_password'\"",
32+
user => $postgresql::params::user,
33+
group => $postgresql::params::group,
34+
logoutput => true,
35+
cwd => '/tmp',
36+
# With this command we're passing -h to force TCP authentication, which does require
37+
# a password. We specify the password via the PGPASSWORD environment variable. If
38+
# the password is correct (current), this command will exit with an exit code of 0,
39+
# which will prevent the main command from running.
40+
unless => "env PGPASSWORD=\"$postgres_password\" psql -h localhost -c 'select 1' > /dev/null",
41+
path => '/usr/bin:/usr/local/bin',
42+
}
43+
}
44+
}

manifests/config/beforeservice.pp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Class: postgresql::config::beforeservice
2+
#
3+
# Parameters:
4+
#
5+
# [*ip_mask_postgres_user*] - ip mask for allowing remote access for postgres user; defaults to '127.0.0.1/32'
6+
# [*ip_mask_all_users*] - ip mask for allowing remote access for other users (besides postgres);
7+
# defaults to '127.0.0.1/32'
8+
# [*listen_addresses*] - what IP address(es) to listen on; comma-separated list of addresses; defaults to
9+
# 'localhost', '*' = all
10+
# [*pg_hba_conf_path*] - path to pg_hba.conf file
11+
# [*postgresql_conf_path*] - path to postgresql.conf file
12+
# [*manage_redhat_firewall*] - boolean indicating whether or not the module should open a port in the firewall on
13+
# redhat-based systems; this parameter is likely to change in future versions. Possible
14+
# changes include support for non-RedHat systems and finer-grained control over the
15+
# firewall rule (currently, it simply opens up the postgres port to all TCP connections).
16+
#
17+
# Actions:
18+
#
19+
# Requires:
20+
#
21+
# Usage:
22+
# This class is not intended to be used directly; it is
23+
# managed by postgresl::config. It contains resources
24+
# that should be handled *before* the postgres service
25+
# has been started up.
26+
#
27+
# class { 'postgresql::config::before_service':
28+
# ip_mask_other_user => '127.0.0.1/32',
29+
# }
30+
#
31+
class postgresql::config::beforeservice(
32+
$ip_mask_postgres_user = $postgresql::params::ip_mask_postgres_user,
33+
$ip_mask_all_users = $postgresql::params::ip_mask_all_users,
34+
$listen_addresses = $postgresql::params::listen_addresses,
35+
$pg_hba_conf_path = $postgresql::params::pg_hba_conf_path,
36+
$postgresql_conf_path = $postgresql::params::postgresql_conf_path,
37+
$manage_redhat_firewall = $postgresql::params::manage_redhat_firewall,
38+
) inherits postgresql::params {
39+
40+
File {
41+
owner => $postgresql::params::user,
42+
group => $postgresql::params::group,
43+
}
44+
45+
# We use a templated version of pg_hba.conf. Our main needs are to
46+
# make sure that md5 authentication can be made available for
47+
# remote hosts.
48+
file { 'pg_hba.conf':
49+
ensure => file,
50+
path => $pg_hba_conf_path,
51+
content => template("postgresql/pg_hba.conf.erb"),
52+
notify => Service['postgresqld'],
53+
}
54+
55+
# We must set a "listen_addresses" line in the postgresql.conf if we
56+
# want to allow any connections from remote hosts.
57+
file_line { 'postgresql.conf':
58+
path => $postgresql_conf_path,
59+
match => '^listen_addresses\s*=.*$',
60+
line => "listen_addresses = '${listen_addresses}'",
61+
notify => Service['postgresqld'],
62+
}
63+
64+
# TODO: is this a reasonable place for this firewall stuff?
65+
# TODO: figure out a way to make this not platform-specific; debian and ubuntu have
66+
# an out-of-the-box firewall configuration that seems trickier to manage
67+
# TODO: get rid of hard-coded port
68+
if ($manage_redhat_firewall and $firewall_supported) {
69+
exec { "persist-firewall":
70+
command => $persist_firewall_command,
71+
refreshonly => true,
72+
}
73+
74+
Firewall {
75+
notify => Exec["persist-firewall"]
76+
}
77+
78+
firewall { '5432 accept - postgres':
79+
port => '5432',
80+
proto => 'tcp',
81+
action => 'accept',
82+
}
83+
}
84+
}

manifests/params.pp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
#
1313
class postgresql::params {
1414

15+
16+
$user = 'postgres'
17+
$group = 'postgres'
18+
$ip_mask_postgres_user = '127.0.0.1/32'
19+
$ip_mask_all_users = '127.0.0.1/32'
20+
$listen_addresses = 'localhost'
21+
# TODO: figure out a way to make this not platform-specific
22+
$manage_redhat_firewall = false
23+
1524
case $::operatingsystem {
1625
"Ubuntu": {
1726
$service_provider = upstart
@@ -23,21 +32,31 @@
2332

2433
case $::osfamily {
2534
'RedHat': {
26-
$service_name = 'postgresql'
27-
$client_package_name = 'postgresql'
28-
$server_package_name = 'postgresql-server'
29-
$needs_initdb = true
30-
$initdb_path = '/usr/bin/initdb'
31-
$datadir = '/var/lib/pgsql/data/'
35+
$service_name = 'postgresql'
36+
$client_package_name = 'postgresql'
37+
$server_package_name = 'postgresql-server'
38+
$needs_initdb = true
39+
$initdb_path = '/usr/bin/initdb'
40+
$datadir = '/var/lib/pgsql/data/'
41+
$pg_hba_conf_path = '/var/lib/pgsql/data/pg_hba.conf'
42+
$postgresql_conf_path = '/var/lib/pgsql/data/postgresql.conf'
43+
$firewall_supported = true
44+
$persist_firewall_command = '/sbin/iptables-save > /etc/sysconfig/iptables'
3245
}
3346

3447
'Debian': {
35-
$service_name = "postgresql-${::postgres_default_version}"
36-
$client_package_name = 'postgresql-client'
37-
$server_package_name = 'postgresql'
38-
$needs_initdb = false
39-
$initdb_path = "/usr/lib/postgresql/${::postgres_default_version}/bin/initdb"
40-
$datadir = "/var/lib/postgresql/${::postgres_default_version}/main"
48+
$service_name = "postgresql-${::postgres_default_version}"
49+
$client_package_name = 'postgresql-client'
50+
$server_package_name = 'postgresql'
51+
$needs_initdb = false
52+
$initdb_path = "/usr/lib/postgresql/${::postgres_default_version}/bin/initdb"
53+
$datadir = "/var/lib/postgresql/${::postgres_default_version}/main"
54+
$pg_hba_conf_path = "/etc/postgresql/${::postgres_default_version}/main/pg_hba.conf"
55+
$postgresql_conf_path = "/etc/postgresql/${::postgres_default_version}/main/postgresql.conf"
56+
$firewall_supported = false
57+
# TODO: not exactly sure yet what the right thing to do for Debian/Ubuntu is.
58+
#$persist_firewall_command = '/sbin/iptables-save > /etc/iptables/rules.v4'
59+
4160
}
4261

4362

manifests/server.pp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,17 @@
2525
ensure => $package_ensure,
2626
}
2727

28+
$config_class = {}
29+
$config_class['postgresql::config'] = $config_hash
30+
31+
create_resources( 'class', $config_class )
32+
33+
Package['postgresql-server'] -> Class['postgresql::config']
34+
2835
if ($needs_initdb) {
2936
include postgresql::initdb
3037

38+
Class['postgresql::initdb'] -> Class['postgresql::config']
3139
Class['postgresql::initdb'] -> Service['postgresqld']
3240
}
3341

templates/pg_hba.conf.erb

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# PostgreSQL Client Authentication Configuration File
2+
# ===================================================
3+
#
4+
# Refer to the "Client Authentication" section in the
5+
# PostgreSQL documentation for a complete description
6+
# of this file. A short synopsis follows.
7+
#
8+
# This file controls: which hosts are allowed to connect, how clients
9+
# are authenticated, which PostgreSQL user names they can use, which
10+
# databases they can access. Records take one of these forms:
11+
#
12+
# local DATABASE USER METHOD [OPTIONS]
13+
# host DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]
14+
# hostssl DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]
15+
# hostnossl DATABASE USER CIDR-ADDRESS METHOD [OPTIONS]
16+
#
17+
# (The uppercase items must be replaced by actual values.)
18+
#
19+
# The first field is the connection type: "local" is a Unix-domain socket,
20+
# "host" is either a plain or SSL-encrypted TCP/IP socket, "hostssl" is an
21+
# SSL-encrypted TCP/IP socket, and "hostnossl" is a plain TCP/IP socket.
22+
#
23+
# DATABASE can be "all", "sameuser", "samerole", a database name, or
24+
# a comma-separated list thereof.
25+
#
26+
# USER can be "all", a user name, a group name prefixed with "+", or
27+
# a comma-separated list thereof. In both the DATABASE and USER fields
28+
# you can also write a file name prefixed with "@" to include names from
29+
# a separate file.
30+
#
31+
# CIDR-ADDRESS specifies the set of hosts the record matches.
32+
# It is made up of an IP address and a CIDR mask that is an integer
33+
# (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that specifies
34+
# the number of significant bits in the mask. Alternatively, you can write
35+
# an IP address and netmask in separate columns to specify the set of hosts.
36+
#
37+
# METHOD can be "trust", "reject", "md5", "password", "gss", "sspi", "krb5",
38+
# "ident", "pam", "ldap" or "cert". Note that "password" sends passwords
39+
# in clear text; "md5" is preferred since it sends encrypted passwords.
40+
#
41+
# OPTIONS are a set of options for the authentication in the format
42+
# NAME=VALUE. The available options depend on the different authentication
43+
# methods - refer to the "Client Authentication" section in the documentation
44+
# for a list of which options are available for which authentication methods.
45+
#
46+
# Database and user names containing spaces, commas, quotes and other special
47+
# characters must be quoted. Quoting one of the keywords "all", "sameuser" or
48+
# "samerole" makes the name lose its special character, and just match a
49+
# database or username with that name.
50+
#
51+
# This file is read on server startup and when the postmaster receives
52+
# a SIGHUP signal. If you edit the file on a running system, you have
53+
# to SIGHUP the postmaster for the changes to take effect. You can use
54+
# "pg_ctl reload" to do that.
55+
56+
# Put your actual configuration here
57+
# ----------------------------------
58+
#
59+
# If you want to allow non-local connections, you need to add more
60+
# "host" records. In that case you will also need to make PostgreSQL listen
61+
# on a non-local interface via the listen_addresses configuration parameter,
62+
# or via the -i or -h command line switches.
63+
#
64+
65+
66+
67+
68+
# DO NOT DISABLE!
69+
# If you change this first entry you will need to make sure that the
70+
# database
71+
# super user can access the database using some other method.
72+
# Noninteractive
73+
# access to all databases is required during automatic maintenance
74+
# (custom daily cronjobs, replication, and similar tasks).
75+
#
76+
# Database administrative login by UNIX sockets
77+
local all postgres ident
78+
79+
# TYPE DATABASE USER CIDR-ADDRESS METHOD
80+
81+
# "local" is for Unix domain socket connections only
82+
local all all ident
83+
# IPv4 local connections:
84+
host all postgres <%= @ip_mask_postgres_user + "\t" %> md5
85+
host all all <%= @ip_mask_all_users + "\t" %> md5
86+
# IPv6 local connections:
87+
host all all ::1/128 md5
88+

tests/server.pp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
class { 'postgresql::server':
2+
config_hash => {
3+
'ip_mask_postgres_user' => '0.0.0.0/0',
4+
'ip_mask_all_users' => '0.0.0.0/0',
5+
'listen_addresses' => '*',
6+
'manage_redhat_firewall' => true,
7+
'postgres_password' => 'postgres',
8+
},
29
}

0 commit comments

Comments
 (0)