From c53ac3f84852a42aa8b7341ee7fe0a629d2e3579 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Wed, 27 Jun 2018 20:45:15 +0200 Subject: [PATCH] Refactor postgresql configuration --- .../profile/files/postgresql/pam_postgresql | 3 + modules/profile/manifests/pam_ldap.pp | 13 ++ .../profile/manifests/postgresql/pam_ldap.pp | 28 +++++ .../manifests/postgresql/replication.pp | 60 +++++++++ modules/profile/manifests/postgresql/ssl.pp | 73 +++++++++++ .../profile/manifests/postgresql_master.pp | 119 ++---------------- .../postgresql/pam_ldap_postgresql.conf.erb | 6 + modules/role/manifests/backup/postgresql.pp | 2 - 8 files changed, 191 insertions(+), 113 deletions(-) create mode 100644 modules/profile/files/postgresql/pam_postgresql create mode 100644 modules/profile/manifests/pam_ldap.pp create mode 100644 modules/profile/manifests/postgresql/pam_ldap.pp create mode 100644 modules/profile/manifests/postgresql/replication.pp create mode 100644 modules/profile/manifests/postgresql/ssl.pp create mode 100644 modules/profile/templates/postgresql/pam_ldap_postgresql.conf.erb diff --git a/modules/profile/files/postgresql/pam_postgresql b/modules/profile/files/postgresql/pam_postgresql new file mode 100644 index 0000000..70a90ae --- /dev/null +++ b/modules/profile/files/postgresql/pam_postgresql @@ -0,0 +1,3 @@ +auth required pam_ldap.so config=/etc/pam_ldap.d/postgresql.conf +account required pam_ldap.so config=/etc/pam_ldap.d/postgresql.conf + diff --git a/modules/profile/manifests/pam_ldap.pp b/modules/profile/manifests/pam_ldap.pp new file mode 100644 index 0000000..956a7cd --- /dev/null +++ b/modules/profile/manifests/pam_ldap.pp @@ -0,0 +1,13 @@ +class profile::pam_ldap ( +) { + ensure_packages(["pam_ldap"]) + + file { "/etc/pam_ldap.d": + ensure => directory, + mode => "0755", + owner => "root", + group => "root", + require => Package["pam_ldap"], + } +} + diff --git a/modules/profile/manifests/postgresql/pam_ldap.pp b/modules/profile/manifests/postgresql/pam_ldap.pp new file mode 100644 index 0000000..f068245 --- /dev/null +++ b/modules/profile/manifests/postgresql/pam_ldap.pp @@ -0,0 +1,28 @@ +class profile::postgresql::pam_ldap ( + String $pg_user = "postgres" +) { + include "profile::pam_ldap" + + $password_seed = lookup("base_installation::puppet_pass_seed") + $ldap_server = lookup("base_installation::ldap_server") + $ldap_base = lookup("base_installation::ldap_base") + $ldap_dn = lookup("base_installation::ldap_dn") + $ldap_password = generate_password(24, $password_seed, "ldap") + $ldap_attribute = "cn" + + file { "/etc/pam_ldap.d/postgresql.conf": + ensure => "present", + mode => "0400", + owner => $pg_user, + group => "root", + content => template("profile/postgresql/pam_ldap_postgresql.conf.erb"), + require => File["/etc/pam_ldap.d"], + } -> + file { "/etc/pam.d/postgresql": + ensure => "present", + mode => "0644", + owner => "root", + group => "root", + source => "puppet:///modules/profile/postgresql/pam_postgresql" + } +} diff --git a/modules/profile/manifests/postgresql/replication.pp b/modules/profile/manifests/postgresql/replication.pp new file mode 100644 index 0000000..33b147f --- /dev/null +++ b/modules/profile/manifests/postgresql/replication.pp @@ -0,0 +1,60 @@ +define profile::postgresql::replication ( + Boolean $handle_role = false, + Boolean $add_self_role = false, + Boolean $handle_slot = false, +) { + include "profile::postgresql::pam_ldap" + + $host_cn = $title + $host_infos = find_host($facts["ldapvar"]["other"], $host_cn) + + if empty($host_infos) { + fail("Unable to find host for replication") + } + + ensure_resource("postgresql::server::config_entry", "wal_level", { + value => "logical", + }) + + $host_infos["ipHostNumber"].each |$ip| { + $infos = split($ip, "/") + $ipaddress = $infos[0] + if (length($infos) == 1 and $ipaddress =~ /:/) { + $mask = "128" + } elsif (length($infos) == 1) { + $mask = "32" + } else { + $mask = $infos[1] + } + + postgresql::server::pg_hba_rule { "allow TCP access for replication to user $host_cn from $ipaddress/$mask": + type => 'hostssl', + database => 'replication', + user => $host_cn, + address => "$ipaddress/$mask", + auth_method => 'pam', + order => "06-01", + } + } + + if $handle_role { + postgresql::server::role { $host_cn: + replication => true, + } + + if $add_self_role { + $ldap_cn = lookup("base_installation::ldap_cn") + + # Needed to be replicated to the backup and be able to recover later + ensure_resource("postgresql::server::role", $ldap_cn, { + replication => true, + }) + } + } + + if $handle_slot { + postgresql_replication_slot { regsubst($host_cn, '-', "_", "G"): + ensure => present + } + } +} diff --git a/modules/profile/manifests/postgresql/ssl.pp b/modules/profile/manifests/postgresql/ssl.pp new file mode 100644 index 0000000..e4da8af --- /dev/null +++ b/modules/profile/manifests/postgresql/ssl.pp @@ -0,0 +1,73 @@ +define profile::postgresql::ssl ( + Optional[String] $cert = undef, + Optional[String] $key = undef, + Optional[String] $certname = undef, + Optional[Boolean] $copy_keys = true, + Optional[String] $pg_user = $profile::postgresql::pg_user, + Optional[String] $pg_group = $profile::postgresql::pg_user +) { + $pg_dir = $title + $datadir = "$pg_dir/data" + + file { "$datadir/certs": + ensure => directory, + mode => "0700", + owner => $pg_user, + group => $pg_group, + require => File[$pg_dir], + } + + if empty($cert) or empty($key) { + if empty($certname) { + fail("A certificate name is necessary to generate ssl certificate") + } + + ssl::self_signed_certificate { $certname: + common_name => $certname, + country => "FR", + days => "3650", + organization => "Immae", + owner => $pg_user, + group => $pg_group, + directory => "$datadir/certs", + } + + $ssl_key = "$datadir/certs/$backup_host_cn.key" + $ssl_cert = "$datadir/certs/$backup_host_cn.crt" + } elsif $copy_keys { + $ssl_key = "$datadir/certs/privkey.pem" + $ssl_cert = "$datadir/certs/cert.pem" + + file { $ssl_cert: + source => "file://$cert", + mode => "0600", + links => "follow", + owner => $pg_user, + group => $pg_group, + require => File["$datadir/certs"], + } + file { $ssl_key: + source => "file://$key", + mode => "0600", + links => "follow", + owner => $pg_user, + group => $pg_group, + require => File["$datadir/certs"], + } + } else { + $ssl_key = $key + $ssl_cert = $cert + } + + postgresql::server::config_entry { "ssl": + value => "on", + } + + postgresql::server::config_entry { "ssl_cert_file": + value => $ssl_cert, + } + + postgresql::server::config_entry { "ssl_key_file": + value => $ssl_key, + } +} diff --git a/modules/profile/manifests/postgresql_master.pp b/modules/profile/manifests/postgresql_master.pp index 067345a..e28c1b0 100644 --- a/modules/profile/manifests/postgresql_master.pp +++ b/modules/profile/manifests/postgresql_master.pp @@ -2,120 +2,17 @@ define profile::postgresql_master ( $letsencrypt_host = undef, $backup_hosts = [], ) { - $password_seed = lookup("base_installation::puppet_pass_seed") - - ensure_resource("file", "/var/lib/postgres/data/certs", { - ensure => directory, - mode => "0700", - owner => $::profile::postgresql::pg_user, - group => $::profile::postgresql::pg_user, - require => File["/var/lib/postgres"], - }) - - ensure_resource("file", "/var/lib/postgres/data/certs/cert.pem", { - source => "file:///etc/letsencrypt/live/$letsencrypt_host/cert.pem", - mode => "0600", - links => "follow", - owner => $::profile::postgresql::pg_user, - group => $::profile::postgresql::pg_user, - require => [Letsencrypt::Certonly[$letsencrypt_host], File["/var/lib/postgres/data/certs"]] - }) - - ensure_resource("file", "/var/lib/postgres/data/certs/privkey.pem", { - source => "file:///etc/letsencrypt/live/$letsencrypt_host/privkey.pem", - mode => "0600", - links => "follow", - owner => $::profile::postgresql::pg_user, - group => $::profile::postgresql::pg_user, - require => [Letsencrypt::Certonly[$letsencrypt_host], File["/var/lib/postgres/data/certs"]] - }) - - ensure_resource("postgresql::server::config_entry", "wal_level", { - value => "logical", - }) - - ensure_resource("postgresql::server::config_entry", "ssl", { - value => "on", + profile::postgresql::ssl { "/var/lib/postgres": + cert => "/etc/letsencrypt/live/$letsencrypt_host/cert.pem", + key => "/etc/letsencrypt/live/$letsencrypt_host/privkey.pem", require => Letsencrypt::Certonly[$letsencrypt_host], - }) - - ensure_resource("postgresql::server::config_entry", "ssl_cert_file", { - value => "/var/lib/postgres/data/certs/cert.pem", - require => Letsencrypt::Certonly[$letsencrypt_host], - }) - - ensure_resource("postgresql::server::config_entry", "ssl_key_file", { - value => "/var/lib/postgres/data/certs/privkey.pem", - require => Letsencrypt::Certonly[$letsencrypt_host], - }) + } $backup_hosts.each |$backup_host| { - ensure_packages(["pam_ldap"]) - - $host = find_host($facts["ldapvar"]["other"], $backup_host) - unless empty($host) { - $host["ipHostNumber"].each |$ip| { - $infos = split($ip, "/") - $ipaddress = $infos[0] - if (length($infos) == 1 and $ipaddress =~ /:/) { - $mask = "128" - } elsif (length($infos) == 1) { - $mask = "32" - } else { - $mask = $infos[1] - } - - postgresql::server::pg_hba_rule { "allow TCP access to replication user from backup for replication from $ipaddress/$mask": - type => 'hostssl', - database => 'replication', - user => $backup_host, - address => "$ipaddress/$mask", - auth_method => 'pam', - order => "06-01", - } - } - - postgresql::server::role { $backup_host: - replication => true, - } - - postgresql_replication_slot { regsubst($backup_host, '-', "_", "G"): - ensure => present - } + profile::postgresql::replication { $backup_host: + handle_role => true, + handle_slot => true, + add_self_role => true, } } - - $ldap_server = lookup("base_installation::ldap_server") - $ldap_base = lookup("base_installation::ldap_base") - $ldap_dn = lookup("base_installation::ldap_dn") - $ldap_cn = lookup("base_installation::ldap_cn") - $ldap_password = generate_password(24, $password_seed, "ldap") - $ldap_attribute = "cn" - - # This is to be replicated to the backup - postgresql::server::role { $ldap_cn: - replication => true, - } - - file { "/etc/pam_ldap.d": - ensure => directory, - mode => "0755", - owner => "root", - group => "root", - } -> - file { "/etc/pam_ldap.d/postgresql.conf": - ensure => "present", - mode => "0600", - owner => $::profile::postgresql::pg_user, - group => "root", - content => template("profile/postgresql_master/pam_ldap_postgresql.conf.erb"), - } -> - file { "/etc/pam.d/postgresql": - ensure => "present", - mode => "0644", - owner => "root", - group => "root", - source => "puppet:///modules/profile/postgresql_master/pam_postgresql" - } - } diff --git a/modules/profile/templates/postgresql/pam_ldap_postgresql.conf.erb b/modules/profile/templates/postgresql/pam_ldap_postgresql.conf.erb new file mode 100644 index 0000000..f3d9674 --- /dev/null +++ b/modules/profile/templates/postgresql/pam_ldap_postgresql.conf.erb @@ -0,0 +1,6 @@ +host <%= @ldap_server %> + +base <%= @ldap_base %> +binddn <%= @ldap_dn %> +bindpw <%= @ldap_password %> +pam_login_attribute <%= @ldap_attribute %> diff --git a/modules/role/manifests/backup/postgresql.pp b/modules/role/manifests/backup/postgresql.pp index ee62a00..8c7542b 100644 --- a/modules/role/manifests/backup/postgresql.pp +++ b/modules/role/manifests/backup/postgresql.pp @@ -1,6 +1,4 @@ class role::backup::postgresql inherits role::backup { - # This manifest is supposed to be part of the backup server - $password_seed = lookup("base_installation::puppet_pass_seed") $user = lookup("role::backup::user") -- 2.41.0