diff --git a/manifests/server/config.pp b/manifests/server/config.pp index f5b3bbed6b..700c3d752b 100644 --- a/manifests/server/config.pp +++ b/manifests/server/config.pp @@ -1,267 +1,32 @@ # @api private class postgresql::server::config { - $ip_mask_deny_postgres_user = $postgresql::server::ip_mask_deny_postgres_user - $ip_mask_allow_all_users = $postgresql::server::ip_mask_allow_all_users - $listen_addresses = $postgresql::server::listen_addresses - $port = $postgresql::server::port - $ipv4acls = $postgresql::server::ipv4acls - $ipv6acls = $postgresql::server::ipv6acls - $pg_hba_conf_path = $postgresql::server::pg_hba_conf_path - $pg_ident_conf_path = $postgresql::server::pg_ident_conf_path - $postgresql_conf_path = $postgresql::server::postgresql_conf_path - $postgresql_conf_mode = $postgresql::server::postgresql_conf_mode - $recovery_conf_path = $postgresql::server::recovery_conf_path - $pg_hba_conf_defaults = $postgresql::server::pg_hba_conf_defaults - $user = $postgresql::server::user - $group = $postgresql::server::group - $version = $postgresql::server::_version - $manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf - $manage_pg_ident_conf = $postgresql::server::manage_pg_ident_conf - $manage_recovery_conf = $postgresql::server::manage_recovery_conf - $manage_postgresql_conf_perms = $postgresql::server::manage_postgresql_conf_perms - $datadir = $postgresql::server::datadir - $logdir = $postgresql::server::logdir - $service_name = $postgresql::server::service_name - $service_enable = $postgresql::server::service_enable - $log_line_prefix = $postgresql::server::log_line_prefix - $timezone = $postgresql::server::timezone - $password_encryption = $postgresql::server::password_encryption - $extra_systemd_config = $postgresql::server::extra_systemd_config - - if ($manage_pg_hba_conf == true) { - # Prepare the main pg_hba file - concat { $pg_hba_conf_path: - owner => $user, - group => $group, - mode => '0640', - warn => true, - notify => Class['postgresql::server::reload'], - } - - if $pg_hba_conf_defaults { - Postgresql::Server::Pg_hba_rule { - database => 'all', - user => 'all', - } - - # Lets setup the base rules - $local_auth_option = $version ? { - '8.1' => 'sameuser', - default => undef, - } - - postgresql::server::pg_hba_rule { - 'local access as postgres user': - type => 'local', - user => $user, - auth_method => 'ident', - auth_option => $local_auth_option, - order => 1; - - 'local access to database with same name': - type => 'local', - auth_method => 'ident', - auth_option => $local_auth_option, - order => 2; - - 'allow localhost TCP access to postgresql user': - type => 'host', - user => $user, - address => '127.0.0.1/32', - auth_method => 'md5', - order => 3; - - 'deny access to postgresql user': - type => 'host', - user => $user, - address => $ip_mask_deny_postgres_user, - auth_method => 'reject', - order => 4; - - 'allow access to all users': - type => 'host', - address => $ip_mask_allow_all_users, - auth_method => 'md5', - order => 100; - - 'allow access to ipv6 localhost': - type => 'host', - address => '::1/128', - auth_method => 'md5', - order => 101; - } - } - - # $ipv4acls and $ipv6acls are arrays of rule strings - # They are converted into hashes we can iterate over to create postgresql::server::pg_hba_rule resources. - ( - postgresql::postgresql_acls_to_resources_hash($ipv4acls, 'ipv4acls', 10) + - postgresql::postgresql_acls_to_resources_hash($ipv6acls, 'ipv6acls', 102) - ).each | String $key, Hash $attrs| { - postgresql::server::pg_hba_rule { $key: - * => $attrs, - } - } - } - - if $manage_postgresql_conf_perms { - file { $postgresql_conf_path: - ensure => file, - owner => $user, - group => $group, - mode => $postgresql_conf_mode, - } - } - - if $listen_addresses { - postgresql::server::config_entry { 'listen_addresses': - value => $listen_addresses, - } - } - - # ensure that SELinux has a proper label for the port defined - if $postgresql::server::manage_selinux == true and $facts['os']['selinux']['enabled'] == true { - case $facts['os']['family'] { - 'RedHat', 'Linux': { - if $facts['os']['name'] == 'Amazon' { - $package_name = 'policycoreutils' - } - else { - $package_name = $facts['os']['release']['major'] ? { - '5' => 'policycoreutils', - '6' => 'policycoreutils-python', - '7' => 'policycoreutils-python', - default => 'policycoreutils-python-utils', - } - } - } - default: { - $package_name = 'policycoreutils' - } - } - - ensure_packages([$package_name]) - - $exec_command = ['/usr/sbin/semanage', 'port', '-a', '-t', 'postgresql_port_t', '-p', 'tcp', $port] - $exec_unless = "/usr/sbin/semanage port -l | grep -qw ${port}" - exec { "/usr/sbin/semanage port -a -t postgresql_port_t -p tcp ${port}": - command => $exec_command, - unless => $exec_unless, - before => Postgresql::Server::Config_entry['port'], - require => Package[$package_name], - } - } - - postgresql::server::config_entry { 'port': - value => $port, - } - - if ($password_encryption) and (versioncmp($version, '10') >= 0) { - postgresql::server::config_entry { 'password_encryption': - value => $password_encryption, - } - } - - postgresql::server::config_entry { 'data_directory': - value => $datadir, - } - if $timezone { - postgresql::server::config_entry { 'timezone': - value => $timezone, - } - } - if $logdir { - postgresql::server::config_entry { 'log_directory': - value => $logdir, - } - } - # Allow timestamps in log by default - if $log_line_prefix { - postgresql::server::config_entry { 'log_line_prefix': - value => $log_line_prefix, - } - } - - # RedHat-based systems hardcode some PG* variables in the init script, and need to be overriden - # in /etc/sysconfig/pgsql/postgresql. Create a blank file so we can manage it with augeas later. - if $facts['os']['family'] == 'RedHat' and versioncmp($facts['os']['release']['major'], '7') < 0 { - file { '/etc/sysconfig/pgsql/postgresql': - ensure => file, - replace => false, - } - - # The init script from the packages of the postgresql.org repository - # sources an alternate sysconfig file. - # I. e. /etc/sysconfig/pgsql/postgresql-9.3 for PostgreSQL 9.3 - # Link to the sysconfig file set by this puppet module - file { "/etc/sysconfig/pgsql/postgresql-${version}": - ensure => link, - target => '/etc/sysconfig/pgsql/postgresql', - require => File['/etc/sysconfig/pgsql/postgresql'], - } - } - - if ($manage_pg_ident_conf == true) { - concat { $pg_ident_conf_path: - owner => $user, - group => $group, - mode => '0640', - warn => true, - notify => Class['postgresql::server::reload'], - } - } - - # RHEL 7 and 8 both support drop-in files for systemd units. The old include directive is deprecated and may be removed in future systemd releases. - # Gentoo also supports drop-in files. - if $facts['os']['family'] in ['RedHat', 'Gentoo'] and $facts['service_provider'] == 'systemd' { - # While Puppet 6.1 and newer can do a daemon-reload if needed, systemd - # doesn't appear to report that correctly in all cases. - # One such case seems to be when an overriding unit file is removed from /etc - # and the original one from /lib *should* be used again. - # - # This can be removed when Puppet < 6.1 support is dropped *and* the file - # old-systemd-override is removed. - $systemd_command = ['systemctl', 'daemon-reload'] - exec { 'restart-systemd': - command => $systemd_command, - refreshonly => true, - path => '/bin:/usr/bin:/usr/local/bin', - before => Class['postgresql::server::service'], - } - - file { - default: - ensure => file, - owner => root, - group => root, - notify => [Exec['restart-systemd'], Class['postgresql::server::service']], - before => Class['postgresql::server::reload']; - - 'systemd-conf-dir': - ensure => directory, - path => "/etc/systemd/system/${service_name}.service.d"; - - # Template uses: - # - $facts['os']['name'] - # - $facts['os']['release']['major'] - # - $service_name - # - $port - # - $datadir - # - $extra_systemd_config - 'systemd-override': - path => "/etc/systemd/system/${service_name}.service.d/${service_name}.conf", - content => template('postgresql/systemd-override.erb'), - require => File['systemd-conf-dir']; - } - - if $service_enable != 'mask' { - # Remove old unit file to avoid conflicts - file { 'old-systemd-override': - ensure => absent, - path => "/etc/systemd/system/${service_name}.service", - notify => [Exec['restart-systemd'], Class['postgresql::server::service']], - before => Class['postgresql::server::reload'], - } - } + postgresql::server::instance_config { 'main': + ip_mask_deny_postgres_user => $postgresql::server::ip_mask_deny_postgres_user, + ip_mask_allow_all_users => $postgresql::server::ip_mask_allow_all_users, + listen_addresses => $postgresql::server::listen_addresses, + port => $postgresql::server::port, + ipv4acls => $postgresql::server::ipv4acls, + ipv6acls => $postgresql::server::ipv6acls, + pg_hba_conf_path => $postgresql::server::pg_hba_conf_path, + pg_ident_conf_path => $postgresql::server::pg_ident_conf_path, + postgresql_conf_path => $postgresql::server::postgresql_conf_path, + postgresql_conf_mode => $postgresql::server::postgresql_conf_mode, + recovery_conf_path => $postgresql::server::recovery_conf_path, + pg_hba_conf_defaults => $postgresql::server::pg_hba_conf_defaults, + user => $postgresql::server::user, + group => $postgresql::server::group, + version => $postgresql::server::_version, + manage_pg_hba_conf => $postgresql::server::manage_pg_hba_conf, + manage_pg_ident_conf => $postgresql::server::manage_pg_ident_conf, + manage_recovery_conf => $postgresql::server::manage_recovery_conf, + manage_postgresql_conf_perms => $postgresql::server::manage_postgresql_conf_perms, + datadir => $postgresql::server::datadir, + logdir => $postgresql::server::logdir, + service_name => $postgresql::server::service_name, + service_enable => $postgresql::server::service_enable, + log_line_prefix => $postgresql::server::log_line_prefix, + timezone => $postgresql::server::timezone, + password_encryption => $postgresql::server::password_encryption, + extra_systemd_config => $postgresql::server::extra_systemd_config, } } diff --git a/manifests/server/instance_config.pp b/manifests/server/instance_config.pp new file mode 100644 index 0000000000..8fb5794dfc --- /dev/null +++ b/manifests/server/instance_config.pp @@ -0,0 +1,302 @@ +# lint:ignore:140chars +# @param ip_mask_deny_postgres_user Specifies the IP mask from which remote connections should be denied for the postgres superuser. +# Default value: '0.0.0.0/0', which denies any remote connection. +# @param ip_mask_allow_all_users Overrides PostgreSQL defaults for remote connections. By default, PostgreSQL does not allow database user accounts to connect via TCP from remote machines. If you'd like to allow this, you can override this setting. +# Set to '0.0.0.0/0' to allow database users to connect from any remote machine, or '192.168.0.0/1' to allow connections from any machine on your local '192.168' subnet. +# Default value: '127.0.0.1/32'. +# @param listen_addresses Address list on which the PostgreSQL service will listen +# @param port Specifies the port for the PostgreSQL server to listen on. Note: The same port number is used for all IP addresses the server listens on. Also, for Red Hat systems and early Debian systems, changing the port causes the server to come to a full stop before being able to make the change. +# Default value: 5432. Meaning the Postgres server listens on TCP port 5432. +# @param ipv4acls Lists strings for access control for connection method, users, databases, IPv4 addresses. +# @param ipv6acls Lists strings for access control for connection method, users, databases, IPv6 addresses. +# @param pg_hba_conf_path Specifies the path to your pg_hba.conf file. +# @param pg_ident_conf_path Specifies the path to your pg_ident.conf file. +# @param postgresql_conf_path Specifies the path to your postgresql.conf file. +# @param postgresql_conf_mode Sets the mode of your postgresql.conf file. Only relevant if manage_postgresql_conf_perms is true. +# @param recovery_conf_path Specifies the path to your recovery.conf file. +# @param pg_hba_conf_defaults If false, disables the defaults supplied with the module for pg_hba.conf. This is useful if you disagree with the defaults and wish to override them yourself. Be sure that your changes of course align with the rest of the module, as some access is required to perform basic psql operations for example. +# @param user Overrides the default PostgreSQL super user and owner of PostgreSQL related files in the file system. +# @param group Overrides the default postgres user group to be used for related files in the file system. +# @param version, Sets PostgreSQL version +# @param manage_pg_hba_conf Boolean. Whether to manage the pg_hba.conf. +# @param manage_pg_ident_conf Boolean. Overwrites the pg_ident.conf file. +# @param manage_recovery_conf Boolean. Specifies whether or not manage the recovery.conf. +# @param manage_postgresql_conf_perms +# Whether to manage the postgresql conf file permissions. This means owner, +# group and mode. Contents are not managed but should be managed through +# postgresql::server::config_entry. +# @param datadir PostgreSQL data directory +# @param logdir PostgreSQL log directory +# @param service_name Overrides the default PostgreSQL service name. +# @param service_enable Enable the PostgreSQL service +# @param log_line_prefix PostgreSQL log line prefix +# @param timezone Set timezone for the PostgreSQL instance +# @param extra_systemd_config Adds extra config to systemd config file, can for instance be used to add extra openfiles. This can be a multi line string +# lint:endignore:140chars +define postgresql::server::instance_config ( + $ip_mask_deny_postgres_user = $postgresql::server::ip_mask_deny_postgres_user, + $ip_mask_allow_all_users = $postgresql::server::ip_mask_allow_all_users, + $listen_addresses = $postgresql::server::listen_addresses, + $port = $postgresql::server::port, + Array[String[1]] $ipv4acls = $postgresql::server::ipv4acls, + Array[String[1]] $ipv6acls = $postgresql::server::ipv6acls, + $pg_hba_conf_path = $postgresql::server::pg_hba_conf_path, + $pg_ident_conf_path = $postgresql::server::pg_ident_conf_path, + $postgresql_conf_path = $postgresql::server::postgresql_conf_path, + Optional[Stdlib::Filemode] $postgresql_conf_mode = $postgresql::server::postgresql_conf_mode, + $recovery_conf_path = $postgresql::server::recovery_conf_path, + $pg_hba_conf_defaults = $postgresql::server::pg_hba_conf_defaults, + $user = $postgresql::server::user, + $group = $postgresql::server::group, + $version = $postgresql::server::_version, + Boolean $manage_pg_hba_conf = $postgresql::server::manage_pg_hba_conf, + Boolean $manage_pg_ident_conf = $postgresql::server::manage_pg_ident_conf, + Boolean $manage_recovery_conf = $postgresql::server::manage_recovery_conf, + Boolean $manage_postgresql_conf_perms = $postgresql::server::manage_postgresql_conf_perms, + $datadir = $postgresql::server::datadir, + $logdir = $postgresql::server::logdir, + $service_name = $postgresql::server::service_name, + $service_enable = $postgresql::server::service_enable, + $log_line_prefix = $postgresql::server::log_line_prefix, + $timezone = $postgresql::server::timezone, + $password_encryption = $postgresql::server::password_encryption, + $extra_systemd_config = $postgresql::server::extra_systemd_config, +) { + if ($manage_pg_hba_conf == true) { + # Prepare the main pg_hba file + concat { $pg_hba_conf_path: + owner => $user, + group => $group, + mode => '0640', + warn => true, + notify => Class['postgresql::server::reload'], + } + + if $pg_hba_conf_defaults { + Postgresql::Server::Pg_hba_rule { + database => 'all', + user => 'all', + } + + # Lets setup the base rules + $local_auth_option = $version ? { + '8.1' => 'sameuser', + default => undef, + } + + postgresql::server::pg_hba_rule { + 'local access as postgres user': + type => 'local', + user => $user, + auth_method => 'ident', + auth_option => $local_auth_option, + order => 1; + + 'local access to database with same name': + type => 'local', + auth_method => 'ident', + auth_option => $local_auth_option, + order => 2; + + 'allow localhost TCP access to postgresql user': + type => 'host', + user => $user, + address => '127.0.0.1/32', + auth_method => 'md5', + order => 3; + + 'deny access to postgresql user': + type => 'host', + user => $user, + address => $ip_mask_deny_postgres_user, + auth_method => 'reject', + order => 4; + + 'allow access to all users': + type => 'host', + address => $ip_mask_allow_all_users, + auth_method => 'md5', + order => 100; + + 'allow access to ipv6 localhost': + type => 'host', + address => '::1/128', + auth_method => 'md5', + order => 101; + } + } + + # $ipv4acls and $ipv6acls are arrays of rule strings + # They are converted into hashes we can iterate over to create postgresql::server::pg_hba_rule resources. + ( + postgresql::postgresql_acls_to_resources_hash($ipv4acls, 'ipv4acls', 10) + + postgresql::postgresql_acls_to_resources_hash($ipv6acls, 'ipv6acls', 102) + ).each | String $key, Hash $attrs| { + postgresql::server::pg_hba_rule { $key: + * => $attrs, + } + } + } + + if $manage_postgresql_conf_perms { + file { $postgresql_conf_path: + ensure => file, + owner => $user, + group => $group, + mode => $postgresql_conf_mode, + } + } + + if $listen_addresses { + postgresql::server::config_entry { 'listen_addresses': + value => $listen_addresses, + } + } + + # ensure that SELinux has a proper label for the port defined + if $postgresql::server::manage_selinux == true and $facts['os']['selinux']['enabled'] == true { + case $facts['os']['family'] { + 'RedHat', 'Linux': { + if $facts['os']['name'] == 'Amazon' { + $package_name = 'policycoreutils' + } + else { + $package_name = $facts['os']['release']['major'] ? { + '5' => 'policycoreutils', + '6' => 'policycoreutils-python', + '7' => 'policycoreutils-python', + default => 'policycoreutils-python-utils', + } + } + } + default: { + $package_name = 'policycoreutils' + } + } + + ensure_packages([$package_name]) + + $exec_command = ['/usr/sbin/semanage', 'port', '-a', '-t', 'postgresql_port_t', '-p', 'tcp', $port] + $exec_unless = "/usr/sbin/semanage port -l | grep -qw ${port}" + exec { "/usr/sbin/semanage port -a -t postgresql_port_t -p tcp ${port}": + command => $exec_command, + unless => $exec_unless, + before => Postgresql::Server::Config_entry['port'], + require => Package[$package_name], + } + } + + postgresql::server::config_entry { 'port': + value => $port, + } + + if ($password_encryption) and (versioncmp($version, '10') >= 0) { + postgresql::server::config_entry { 'password_encryption': + value => $password_encryption, + } + } + + postgresql::server::config_entry { 'data_directory': + value => $datadir, + } + if $timezone { + postgresql::server::config_entry { 'timezone': + value => $timezone, + } + } + if $logdir { + postgresql::server::config_entry { 'log_directory': + value => $logdir, + } + } + # Allow timestamps in log by default + if $log_line_prefix { + postgresql::server::config_entry { 'log_line_prefix': + value => $log_line_prefix, + } + } + + # RedHat-based systems hardcode some PG* variables in the init script, and need to be overriden + # in /etc/sysconfig/pgsql/postgresql. Create a blank file so we can manage it with augeas later. + if $facts['os']['family'] == 'RedHat' and versioncmp($facts['os']['release']['major'], '7') < 0 { + file { '/etc/sysconfig/pgsql/postgresql': + ensure => file, + replace => false, + } + + # The init script from the packages of the postgresql.org repository + # sources an alternate sysconfig file. + # I. e. /etc/sysconfig/pgsql/postgresql-9.3 for PostgreSQL 9.3 + # Link to the sysconfig file set by this puppet module + file { "/etc/sysconfig/pgsql/postgresql-${version}": + ensure => link, + target => '/etc/sysconfig/pgsql/postgresql', + require => File['/etc/sysconfig/pgsql/postgresql'], + } + } + + if ($manage_pg_ident_conf == true) { + concat { $pg_ident_conf_path: + owner => $user, + group => $group, + mode => '0640', + warn => true, + notify => Class['postgresql::server::reload'], + } + } + # lint:ignore:140chars + # RHEL 7 and 8 both support drop-in files for systemd units. The old include directive is deprecated and may be removed in future systemd releases. + # Gentoo also supports drop-in files. + # lint:endignore:140chars + if $facts['os']['family'] in ['RedHat', 'Gentoo'] and $facts['service_provider'] == 'systemd' { + # While Puppet 6.1 and newer can do a daemon-reload if needed, systemd + # doesn't appear to report that correctly in all cases. + # One such case seems to be when an overriding unit file is removed from /etc + # and the original one from /lib *should* be used again. + # + # This can be removed when Puppet < 6.1 support is dropped *and* the file + # old-systemd-override is removed. + $systemd_command = ['systemctl', 'daemon-reload'] + exec { 'restart-systemd': + command => $systemd_command, + refreshonly => true, + path => '/bin:/usr/bin:/usr/local/bin', + before => Class['postgresql::server::service'], + } + + file { + default: + ensure => file, + owner => root, + group => root, + notify => [Exec['restart-systemd'], Class['postgresql::server::service']], + before => Class['postgresql::server::reload']; + + 'systemd-conf-dir': + ensure => directory, + path => "/etc/systemd/system/${service_name}.service.d"; + + # Template uses: + # - $facts['os']['name'] + # - $facts['os']['release']['major'] + # - $service_name + # - $port + # - $datadir + # - $extra_systemd_config + 'systemd-override': + path => "/etc/systemd/system/${service_name}.service.d/${service_name}.conf", + content => template('postgresql/systemd-override.erb'), + require => File['systemd-conf-dir']; + } + + if $service_enable != 'mask' { + # Remove old unit file to avoid conflicts + file { 'old-systemd-override': + ensure => absent, + path => "/etc/systemd/system/${service_name}.service", + notify => [Exec['restart-systemd'], Class['postgresql::server::service']], + before => Class['postgresql::server::reload'], + } + } + } +} diff --git a/manifests/server/recovery.pp b/manifests/server/recovery.pp index aaf4a0586e..47f25f1ef5 100644 --- a/manifests/server/recovery.pp +++ b/manifests/server/recovery.pp @@ -52,8 +52,8 @@ } concat { $target: - owner => $postgresql::server::config::user, - group => $postgresql::server::config::group, + owner => $postgresql::server::user, + group => $postgresql::server::group, force => true, # do not crash if there is no recovery conf file mode => '0640', warn => true, diff --git a/spec/defines/server/instance_config.rb b/spec/defines/server/instance_config.rb new file mode 100644 index 0000000000..8fa49eac71 --- /dev/null +++ b/spec/defines/server/instance_config.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'postgresql::server::instance_config' do + let(:title) { 'main' } + + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let :facts do + os_facts + end + + let :pre_condition do + "class {'postgresql::server':}" + end + + context 'with defaults from config_class' do + it { is_expected.to compile.with_all_deps } + end + end + end +end