diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-06-28 12:17:40 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-06-28 12:17:40 +0200 |
commit | 0a145a25c0a8cbcd50d515d2a828bd6665836ddb (patch) | |
tree | c6e3832098d19917b0ba0bcbe119103c632c7d29 | |
parent | f1d583bfdaf881116e5f9ca9e050307e7acdc28e (diff) | |
parent | 3925777d9715d271c0643faef9f520e7816dba89 (diff) | |
download | Puppet-0a145a25c0a8cbcd50d515d2a828bd6665836ddb.tar.gz Puppet-0a145a25c0a8cbcd50d515d2a828bd6665836ddb.tar.zst Puppet-0a145a25c0a8cbcd50d515d2a828bd6665836ddb.zip |
Merge branch 'refactoring' into dev
22 files changed, 640 insertions, 733 deletions
diff --git a/modules/role/files/backup/pam_pgbouncer b/modules/profile/files/postgresql/pam_pgbouncer index 13f0d3d..13f0d3d 100644 --- a/modules/role/files/backup/pam_pgbouncer +++ b/modules/profile/files/postgresql/pam_pgbouncer | |||
diff --git a/modules/profile/files/postgresql_master/pam_postgresql b/modules/profile/files/postgresql/pam_postgresql index 70a90ae..70a90ae 100644 --- a/modules/profile/files/postgresql_master/pam_postgresql +++ b/modules/profile/files/postgresql/pam_postgresql | |||
diff --git a/modules/role/templates/backup/pgbouncer.ini.erb b/modules/profile/files/postgresql/pgbouncer_head.ini index 3ba8728..3ba8728 100644 --- a/modules/role/templates/backup/pgbouncer.ini.erb +++ b/modules/profile/files/postgresql/pgbouncer_head.ini | |||
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 @@ | |||
1 | class profile::pam_ldap ( | ||
2 | ) { | ||
3 | ensure_packages(["pam_ldap"]) | ||
4 | |||
5 | file { "/etc/pam_ldap.d": | ||
6 | ensure => directory, | ||
7 | mode => "0755", | ||
8 | owner => "root", | ||
9 | group => "root", | ||
10 | require => Package["pam_ldap"], | ||
11 | } | ||
12 | } | ||
13 | |||
diff --git a/modules/profile/manifests/postgresql.pp b/modules/profile/manifests/postgresql.pp index 2cd1bcc..97ce572 100644 --- a/modules/profile/manifests/postgresql.pp +++ b/modules/profile/manifests/postgresql.pp | |||
@@ -1,4 +1,7 @@ | |||
1 | class profile::postgresql { | 1 | class profile::postgresql ( |
2 | Optional[String] $pg_user = "postgres", | ||
3 | Optional[String] $pg_group = "postgres", | ||
4 | ) { | ||
2 | $password_seed = lookup("base_installation::puppet_pass_seed") | 5 | $password_seed = lookup("base_installation::puppet_pass_seed") |
3 | 6 | ||
4 | class { '::postgresql::globals': | 7 | class { '::postgresql::globals': |
@@ -7,16 +10,13 @@ class profile::postgresql { | |||
7 | pg_hba_conf_defaults => false, | 10 | pg_hba_conf_defaults => false, |
8 | } | 11 | } |
9 | 12 | ||
10 | # FIXME: get it from the postgresql module? | ||
11 | $pg_user = "postgres" | ||
12 | |||
13 | class { '::postgresql::client': } | 13 | class { '::postgresql::client': } |
14 | 14 | ||
15 | # FIXME: postgresql module is buggy and doesn't create dir? | 15 | # FIXME: postgresql module is buggy and doesn't create dir? |
16 | file { "/var/lib/postgres": | 16 | file { "/var/lib/postgres": |
17 | ensure => directory, | 17 | ensure => directory, |
18 | owner => $pg_user, | 18 | owner => $pg_user, |
19 | group => $pg_user, | 19 | group => $pg_group, |
20 | before => File["/var/lib/postgres/data"], | 20 | before => File["/var/lib/postgres/data"], |
21 | require => Package["postgresql-server"], | 21 | require => Package["postgresql-server"], |
22 | } | 22 | } |
@@ -26,59 +26,7 @@ class profile::postgresql { | |||
26 | listen_addresses => "*", | 26 | listen_addresses => "*", |
27 | } | 27 | } |
28 | 28 | ||
29 | postgresql::server::pg_hba_rule { 'local access as postgres user': | 29 | profile::postgresql::base_pg_hba_rules { "default": } |
30 | description => 'Allow local access to postgres user', | ||
31 | type => 'local', | ||
32 | database => 'all', | ||
33 | user => $pg_user, | ||
34 | auth_method => 'ident', | ||
35 | order => "00-01", | ||
36 | } | ||
37 | postgresql::server::pg_hba_rule { 'localhost access as postgres user': | ||
38 | description => 'Allow localhost access to postgres user', | ||
39 | type => 'host', | ||
40 | database => 'all', | ||
41 | user => $pg_user, | ||
42 | address => "127.0.0.1/32", | ||
43 | auth_method => 'md5', | ||
44 | order => "00-02", | ||
45 | } | ||
46 | postgresql::server::pg_hba_rule { 'localhost ip6 access as postgres user': | ||
47 | description => 'Allow localhost access to postgres user', | ||
48 | type => 'host', | ||
49 | database => 'all', | ||
50 | user => $pg_user, | ||
51 | address => "::1/128", | ||
52 | auth_method => 'md5', | ||
53 | order => "00-03", | ||
54 | } | ||
55 | postgresql::server::pg_hba_rule { 'deny access to postgresql user': | ||
56 | description => 'Deny remote access to postgres user', | ||
57 | type => 'host', | ||
58 | database => 'all', | ||
59 | user => $pg_user, | ||
60 | address => "0.0.0.0/0", | ||
61 | auth_method => 'reject', | ||
62 | order => "00-04", | ||
63 | } | ||
64 | |||
65 | postgresql::server::pg_hba_rule { 'local access': | ||
66 | description => 'Allow local access with password', | ||
67 | type => 'local', | ||
68 | database => 'all', | ||
69 | user => 'all', | ||
70 | auth_method => 'md5', | ||
71 | order => "10-01", | ||
72 | } | ||
73 | |||
74 | postgresql::server::pg_hba_rule { 'local access with same name': | ||
75 | description => 'Allow local access with same name', | ||
76 | type => 'local', | ||
77 | database => 'all', | ||
78 | user => 'all', | ||
79 | auth_method => 'ident', | ||
80 | order => "10-02", | ||
81 | } | ||
82 | 30 | ||
83 | } | 31 | } |
84 | 32 | ||
diff --git a/modules/profile/manifests/postgresql/backup_dump.pp b/modules/profile/manifests/postgresql/backup_dump.pp new file mode 100644 index 0000000..10e349a --- /dev/null +++ b/modules/profile/manifests/postgresql/backup_dump.pp | |||
@@ -0,0 +1,53 @@ | |||
1 | define profile::postgresql::backup_dump ( | ||
2 | String $pg_user = "postgres", | ||
3 | String $pg_group = "postgres", | ||
4 | ) { | ||
5 | $base_path = $title | ||
6 | $pg_path = "$base_path/postgresql" | ||
7 | $pg_backup_path = "$base_path/postgresql_backup" | ||
8 | $pg_host = split($base_path, "/")[-1] | ||
9 | |||
10 | ensure_packages(["python", "python-pip"]) | ||
11 | ensure_resource("package", "pylog2rotate", { | ||
12 | source => "git+https://github.com/avian2/pylog2rotate", | ||
13 | ensure => present, | ||
14 | provider => "pip3", | ||
15 | require => Package["python-pip"], | ||
16 | }) | ||
17 | |||
18 | file { $pg_backup_path: | ||
19 | ensure => directory, | ||
20 | owner => $pg_user, | ||
21 | group => $pg_group, | ||
22 | mode => "0700", | ||
23 | require => File[$base_path], | ||
24 | } | ||
25 | |||
26 | cron::job::multiple { "backup_psql_$pg_host": | ||
27 | ensure => "present", | ||
28 | require => [File[$pg_backup_path], File[$pg_path]], | ||
29 | jobs => [ | ||
30 | { | ||
31 | command => "/usr/bin/pg_dumpall -h $pg_path -f $pg_backup_path/\$(date -Iseconds).sql", | ||
32 | user => $pg_user, | ||
33 | hour => "22,4,10,16", | ||
34 | minute => 0, | ||
35 | description => "Backup the database", | ||
36 | }, | ||
37 | { | ||
38 | command => "/usr/bin/rm -f $(ls -1 $pg_backup_path/*.sql | grep -v 'T22:' | sort -r | sed -e '1,12d')", | ||
39 | user => $pg_user, | ||
40 | hour => 3, | ||
41 | minute => 0, | ||
42 | description => "Cleanup the database backups", | ||
43 | }, | ||
44 | { | ||
45 | command => "cd $pg_backup_path ; /usr/bin/rm -f $(ls -1 *T22*.sql | log2rotate --skip 7 --fuzz 7 --delete --format='%Y-%m-%dT%H:%M:%S+02:00.sql')", | ||
46 | user => $pg_user, | ||
47 | hour => 3, | ||
48 | minute => 1, | ||
49 | description => "Cleanup the database backups exponentially", | ||
50 | }, | ||
51 | ] | ||
52 | } | ||
53 | } | ||
diff --git a/modules/profile/manifests/postgresql/backup_pgbouncer.pp b/modules/profile/manifests/postgresql/backup_pgbouncer.pp new file mode 100644 index 0000000..45b8ed5 --- /dev/null +++ b/modules/profile/manifests/postgresql/backup_pgbouncer.pp | |||
@@ -0,0 +1,92 @@ | |||
1 | define profile::postgresql::backup_pgbouncer ( | ||
2 | String $base_path, | ||
3 | Hash $pg_infos, | ||
4 | String $pg_user = "postgres", | ||
5 | String $pg_group = "postgres", | ||
6 | ) { | ||
7 | include "profile::postgresql::pam_ldap_pgbouncer" | ||
8 | ensure_packages(["pgbouncer"]) | ||
9 | |||
10 | $host_cn = $title | ||
11 | |||
12 | $host = find_host($facts["ldapvar"]["other"], $host_cn) | ||
13 | if empty($host) { | ||
14 | fail("No host found for pgbouncer") | ||
15 | } elsif has_key($host["vars"], "host") { | ||
16 | $pg_backup_host = $host["vars"]["host"][0] | ||
17 | } else { | ||
18 | $pg_backup_host = $host["vars"]["real_hostname"][0] | ||
19 | } | ||
20 | |||
21 | $pg_path = "$base_path/$pg_backup_host/postgresql" | ||
22 | |||
23 | if has_key($host["vars"], "postgresql_backup_port") { | ||
24 | $pg_port = " port=${host[vars][postgresql_backup_port][0]}" | ||
25 | } else { | ||
26 | $pg_port = "" | ||
27 | } | ||
28 | |||
29 | # Config | ||
30 | ensure_resource("concat", "/etc/pgbouncer/pgbouncer.ini", { | ||
31 | mode => "0644", | ||
32 | owner => "root", | ||
33 | group => "root", | ||
34 | ensure_newline => true, | ||
35 | notify => Service["pgbouncer"], | ||
36 | before => Service["pgbouncer"], | ||
37 | }) | ||
38 | |||
39 | ensure_resource("concat::fragment", "pgbouncer_head", { | ||
40 | target => "/etc/pgbouncer/pgbouncer.ini", | ||
41 | order => 01, | ||
42 | source => "puppet:///modules/profile/postgresql/pgbouncer_head.ini", | ||
43 | }) | ||
44 | |||
45 | concat::fragment { "pgbouncer_$pg_backup_host": | ||
46 | target => "/etc/pgbouncer/pgbouncer.ini", | ||
47 | order => 02, | ||
48 | content => "${pg_infos[pgbouncer_dbname]} = host=$pg_path$pg_port user=${pg_infos[dbuser]} dbname=${pg_infos[dbname]}", | ||
49 | } | ||
50 | |||
51 | # pg_hba for accessed cluster | ||
52 | postgresql::server::pg_hba_rule { "$pg_backup_host - local access as ${pg_infos[dbuser]} user": | ||
53 | description => "Allow local access to ${pg_infos[dbuser]} user", | ||
54 | type => 'local', | ||
55 | database => $pg_infos["dbname"], | ||
56 | user => $pg_infos["dbuser"], | ||
57 | auth_method => 'trust', | ||
58 | order => "01-00", | ||
59 | target => "$pg_path/pg_hba.conf", | ||
60 | postgresql_version => "10", | ||
61 | } | ||
62 | |||
63 | # service | ||
64 | ensure_resource("file", "/etc/systemd/system/pgbouncer.service.d", { | ||
65 | ensure => "directory", | ||
66 | mode => "0644", | ||
67 | owner => "root", | ||
68 | group => "root", | ||
69 | }) | ||
70 | |||
71 | ensure_resource("file", "/etc/systemd/system/pgbouncer.service.d/override.conf", { | ||
72 | ensure => "present", | ||
73 | mode => "0644", | ||
74 | owner => "root", | ||
75 | group => "root", | ||
76 | content => "[Service]\nUser=\nUser=$pg_user\n", | ||
77 | notify => Service["pgbouncer"], | ||
78 | before => Service["pgbouncer"], | ||
79 | }) | ||
80 | |||
81 | ensure_resource("service", "pgbouncer", { | ||
82 | ensure => "running", | ||
83 | enable => true, | ||
84 | require => [ | ||
85 | Package["pgbouncer"], | ||
86 | File["/etc/systemd/system/pgbouncer.service.d/override.conf"], | ||
87 | Concat["/etc/pgbouncer/pgbouncer.ini"] | ||
88 | ], | ||
89 | }) | ||
90 | |||
91 | |||
92 | } | ||
diff --git a/modules/profile/manifests/postgresql/backup_replication.pp b/modules/profile/manifests/postgresql/backup_replication.pp new file mode 100644 index 0000000..a4edb8f --- /dev/null +++ b/modules/profile/manifests/postgresql/backup_replication.pp | |||
@@ -0,0 +1,135 @@ | |||
1 | define profile::postgresql::backup_replication ( | ||
2 | String $base_path, | ||
3 | Hash $pg_infos, | ||
4 | String $pg_user = "postgres", | ||
5 | String $pg_group = "postgres", | ||
6 | ) { | ||
7 | $host_cn = $title | ||
8 | |||
9 | $host = find_host($facts["ldapvar"]["other"], $host_cn) | ||
10 | if empty($host) { | ||
11 | $pg_backup_host = $host_cn | ||
12 | } elsif has_key($host["vars"], "host") { | ||
13 | $pg_backup_host = $host["vars"]["host"][0] | ||
14 | } else { | ||
15 | $pg_backup_host = $host["vars"]["real_hostname"][0] | ||
16 | } | ||
17 | |||
18 | $pg_path = "$base_path/$pg_backup_host/postgresql" | ||
19 | |||
20 | # Replication folder | ||
21 | ensure_resource("file", "$base_path/$pg_backup_host", { | ||
22 | ensure => directory, | ||
23 | }) | ||
24 | |||
25 | file { $pg_path: | ||
26 | ensure => directory, | ||
27 | owner => $pg_user, | ||
28 | group => $pg_group, | ||
29 | mode => "0700", | ||
30 | require => File["$base_path/$pg_backup_host"], | ||
31 | } | ||
32 | |||
33 | # pg_hba.conf | ||
34 | profile::postgresql::base_pg_hba_rules { $pg_backup_host: | ||
35 | pg_path => $pg_path | ||
36 | } | ||
37 | |||
38 | # postgresql.conf file and ssl | ||
39 | concat { "$pg_path/postgresql.conf": | ||
40 | owner => $pg_user, | ||
41 | group => $pg_group, | ||
42 | mode => '0640', | ||
43 | warn => true, | ||
44 | } | ||
45 | |||
46 | if !empty($host) and has_key($host["vars"], "postgresql_backup_port") { | ||
47 | $pg_listen_port = $host["vars"]["postgresql_backup_port"][0] | ||
48 | |||
49 | profile::postgresql::ssl { $pg_path: | ||
50 | certname => $host_cn, | ||
51 | handle_concat_config => true, | ||
52 | before => Service["postgresql_backup@$pg_backup_host"] | ||
53 | } | ||
54 | |||
55 | concat::fragment { "$pg_path/postgresql.conf listen": | ||
56 | target => "$pg_path/postgresql.conf", | ||
57 | content => "listen_addresses = '*'\nport = $pg_listen_port\n", | ||
58 | } | ||
59 | |||
60 | profile::postgresql::replication { $host_cn: | ||
61 | target => "$pg_path/pg_hba.conf", | ||
62 | } | ||
63 | } else { | ||
64 | concat::fragment { "$pg_path/postgresql.conf listen": | ||
65 | target => "$pg_path/postgresql.conf", | ||
66 | content => "listen_addresses = ''\n", | ||
67 | } | ||
68 | } | ||
69 | |||
70 | concat::fragment { "$pg_path/postgresql.conf paths": | ||
71 | target => "$pg_path/postgresql.conf", | ||
72 | content => "unix_socket_directories = '$pg_path'\ndata_directory = '$pg_path'\nwal_level = logical\n", | ||
73 | } | ||
74 | |||
75 | $password_seed = lookup("base_installation::puppet_pass_seed") | ||
76 | $pg_host = $pg_backup_host | ||
77 | $pg_port = $pg_infos["dbport"] | ||
78 | $ldap_cn = lookup("base_installation::ldap_cn") | ||
79 | $ldap_password = generate_password(24, $password_seed, "ldap") | ||
80 | $pg_slot = regsubst($ldap_cn, '-', "_", "G") | ||
81 | |||
82 | # recovery.conf file | ||
83 | $primary_conninfo = "host=$pg_host port=$pg_port user=$ldap_cn password=$ldap_password sslmode=require" | ||
84 | $primary_slot_name = $pg_slot | ||
85 | $standby_mode = "on" | ||
86 | |||
87 | file { "$pg_path/recovery.conf": | ||
88 | owner => $pg_user, | ||
89 | group => $pg_group, | ||
90 | mode => '0640', | ||
91 | content => template('postgresql/recovery.conf.erb'), | ||
92 | } | ||
93 | |||
94 | # Initial replication | ||
95 | exec { "pg_basebackup $pg_path": | ||
96 | cwd => $pg_path, | ||
97 | user => $pg_user, | ||
98 | creates => "$pg_path/PG_VERSION", | ||
99 | environment => ["PGPASSWORD=$ldap_password"], | ||
100 | command => "/usr/bin/pg_basebackup -w -h $pg_host -p $pg_port -U $ldap_cn -D $pg_path -S $pg_slot", | ||
101 | before => [ | ||
102 | Concat["$pg_path/pg_hba.conf"], | ||
103 | File["$pg_path/recovery.conf"], | ||
104 | Concat["$pg_path/postgresql.conf"], | ||
105 | ] | ||
106 | } | ||
107 | |||
108 | # Service | ||
109 | ensure_resource("file", "/etc/systemd/system/postgresql_backup@.service", { | ||
110 | mode => "0644", | ||
111 | owner => "root", | ||
112 | group => "root", | ||
113 | content => template("profile/postgresql/postgresql_backup@.service.erb"), | ||
114 | }) | ||
115 | |||
116 | service { "postgresql_backup@$pg_backup_host": | ||
117 | enable => true, | ||
118 | ensure => "running", | ||
119 | require => [ | ||
120 | File["/etc/systemd/system/postgresql_backup@.service"], | ||
121 | Concat["$pg_path/pg_hba.conf"], | ||
122 | File["$pg_path/recovery.conf"], | ||
123 | Concat["$pg_path/postgresql.conf"], | ||
124 | ], | ||
125 | subscribe => [ | ||
126 | Concat["$pg_path/pg_hba.conf"], | ||
127 | File["$pg_path/recovery.conf"], | ||
128 | Concat["$pg_path/postgresql.conf"], | ||
129 | ] | ||
130 | } | ||
131 | |||
132 | # Dumps | ||
133 | profile::postgresql::backup_dump { "$base_path/$pg_backup_host": } | ||
134 | |||
135 | } | ||
diff --git a/modules/profile/manifests/postgresql/base_pg_hba_rules.pp b/modules/profile/manifests/postgresql/base_pg_hba_rules.pp new file mode 100644 index 0000000..07c4bb6 --- /dev/null +++ b/modules/profile/manifests/postgresql/base_pg_hba_rules.pp | |||
@@ -0,0 +1,74 @@ | |||
1 | define profile::postgresql::base_pg_hba_rules ( | ||
2 | Optional[String] $pg_path = undef, | ||
3 | String $pg_user = "postgres", | ||
4 | String $pg_group = "postgres", | ||
5 | ) { | ||
6 | unless empty($pg_path) { | ||
7 | concat { "$pg_path/pg_hba.conf": | ||
8 | owner => $pg_user, | ||
9 | group => $pg_group, | ||
10 | mode => '0640', | ||
11 | warn => true, | ||
12 | require => File[$pg_path], | ||
13 | } | ||
14 | |||
15 | Postgresql::Server::Pg_hba_rule { | ||
16 | target => "$pg_path/pg_hba.conf", | ||
17 | postgresql_version => "10", | ||
18 | } | ||
19 | } | ||
20 | |||
21 | postgresql::server::pg_hba_rule { "$title - local access as postgres user": | ||
22 | description => 'Allow local access to postgres user', | ||
23 | type => 'local', | ||
24 | database => 'all', | ||
25 | user => $pg_user, | ||
26 | auth_method => 'ident', | ||
27 | order => "00-01", | ||
28 | } | ||
29 | postgresql::server::pg_hba_rule { "$title - localhost access as postgres user": | ||
30 | description => 'Allow localhost access to postgres user', | ||
31 | type => 'host', | ||
32 | database => 'all', | ||
33 | user => $pg_user, | ||
34 | address => "127.0.0.1/32", | ||
35 | auth_method => 'md5', | ||
36 | order => "00-02", | ||
37 | } | ||
38 | postgresql::server::pg_hba_rule { "$title - localhost ip6 access as postgres user": | ||
39 | description => 'Allow localhost access to postgres user', | ||
40 | type => 'host', | ||
41 | database => 'all', | ||
42 | user => $pg_user, | ||
43 | address => "::1/128", | ||
44 | auth_method => 'md5', | ||
45 | order => "00-03", | ||
46 | } | ||
47 | postgresql::server::pg_hba_rule { "$title - deny access to postgresql user": | ||
48 | description => 'Deny remote access to postgres user', | ||
49 | type => 'host', | ||
50 | database => 'all', | ||
51 | user => $pg_user, | ||
52 | address => "0.0.0.0/0", | ||
53 | auth_method => 'reject', | ||
54 | order => "00-04", | ||
55 | } | ||
56 | postgresql::server::pg_hba_rule { "$title - local access": | ||
57 | description => 'Allow local access with password', | ||
58 | type => 'local', | ||
59 | database => 'all', | ||
60 | user => 'all', | ||
61 | auth_method => 'md5', | ||
62 | order => "10-01", | ||
63 | } | ||
64 | |||
65 | postgresql::server::pg_hba_rule { "$title - local access with same name": | ||
66 | description => 'Allow local access with same name', | ||
67 | type => 'local', | ||
68 | database => 'all', | ||
69 | user => 'all', | ||
70 | auth_method => 'ident', | ||
71 | order => "10-02", | ||
72 | } | ||
73 | |||
74 | } | ||
diff --git a/modules/profile/manifests/postgresql/master.pp b/modules/profile/manifests/postgresql/master.pp new file mode 100644 index 0000000..969905f --- /dev/null +++ b/modules/profile/manifests/postgresql/master.pp | |||
@@ -0,0 +1,20 @@ | |||
1 | define profile::postgresql::master ( | ||
2 | $letsencrypt_host = undef, | ||
3 | $backup_hosts = [], | ||
4 | ) { | ||
5 | profile::postgresql::ssl { "/var/lib/postgres/data": | ||
6 | cert => "/etc/letsencrypt/live/$letsencrypt_host/cert.pem", | ||
7 | key => "/etc/letsencrypt/live/$letsencrypt_host/privkey.pem", | ||
8 | require => Letsencrypt::Certonly[$letsencrypt_host], | ||
9 | handle_config_entry => true, | ||
10 | } | ||
11 | |||
12 | $backup_hosts.each |$backup_host| { | ||
13 | profile::postgresql::replication { $backup_host: | ||
14 | handle_config => true, | ||
15 | handle_role => true, | ||
16 | handle_slot => true, | ||
17 | add_self_role => true, | ||
18 | } | ||
19 | } | ||
20 | } | ||
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 @@ | |||
1 | class profile::postgresql::pam_ldap ( | ||
2 | String $pg_user = "postgres" | ||
3 | ) { | ||
4 | include "profile::pam_ldap" | ||
5 | |||
6 | $password_seed = lookup("base_installation::puppet_pass_seed") | ||
7 | $ldap_server = lookup("base_installation::ldap_server") | ||
8 | $ldap_base = lookup("base_installation::ldap_base") | ||
9 | $ldap_dn = lookup("base_installation::ldap_dn") | ||
10 | $ldap_password = generate_password(24, $password_seed, "ldap") | ||
11 | $ldap_attribute = "cn" | ||
12 | |||
13 | file { "/etc/pam_ldap.d/postgresql.conf": | ||
14 | ensure => "present", | ||
15 | mode => "0400", | ||
16 | owner => $pg_user, | ||
17 | group => "root", | ||
18 | content => template("profile/postgresql/pam_ldap_postgresql.conf.erb"), | ||
19 | require => File["/etc/pam_ldap.d"], | ||
20 | } -> | ||
21 | file { "/etc/pam.d/postgresql": | ||
22 | ensure => "present", | ||
23 | mode => "0644", | ||
24 | owner => "root", | ||
25 | group => "root", | ||
26 | source => "puppet:///modules/profile/postgresql/pam_postgresql" | ||
27 | } | ||
28 | } | ||
diff --git a/modules/profile/manifests/postgresql/pam_ldap_pgbouncer.pp b/modules/profile/manifests/postgresql/pam_ldap_pgbouncer.pp new file mode 100644 index 0000000..67714f2 --- /dev/null +++ b/modules/profile/manifests/postgresql/pam_ldap_pgbouncer.pp | |||
@@ -0,0 +1,33 @@ | |||
1 | class profile::postgresql::pam_ldap_pgbouncer ( | ||
2 | String $pg_user = "postgres" | ||
3 | ) { | ||
4 | include "profile::pam_ldap" | ||
5 | |||
6 | $password_seed = lookup("base_installation::puppet_pass_seed") | ||
7 | $ldap_server = lookup("base_installation::ldap_server") | ||
8 | $ldap_base = lookup("base_installation::ldap_base") | ||
9 | $ldap_dn = lookup("base_installation::ldap_dn") | ||
10 | $ldap_password = generate_password(24, $password_seed, "ldap") | ||
11 | $ldap_attribute = "uid" | ||
12 | $ldap_filter = lookup("role::backup::postgresql::pgbouncer_access_filter", { "default_value" => undef }) | ||
13 | |||
14 | if empty($ldap_filter) { | ||
15 | fail("need ldap filter for pgbouncer") | ||
16 | } | ||
17 | |||
18 | file { "/etc/pam_ldap.d/pgbouncer.conf": | ||
19 | ensure => "present", | ||
20 | mode => "0600", | ||
21 | owner => $pg_user, | ||
22 | group => "root", | ||
23 | content => template("profile/postgresql/pam_ldap_pgbouncer.conf.erb"), | ||
24 | require => File["/etc/pam_ldap.d"], | ||
25 | } -> | ||
26 | file { "/etc/pam.d/pgbouncer": | ||
27 | ensure => "present", | ||
28 | mode => "0644", | ||
29 | owner => "root", | ||
30 | group => "root", | ||
31 | source => "puppet:///modules/profile/postgresql/pam_pgbouncer" | ||
32 | } | ||
33 | } | ||
diff --git a/modules/profile/manifests/postgresql/replication.pp b/modules/profile/manifests/postgresql/replication.pp new file mode 100644 index 0000000..2fcb71c --- /dev/null +++ b/modules/profile/manifests/postgresql/replication.pp | |||
@@ -0,0 +1,72 @@ | |||
1 | define profile::postgresql::replication ( | ||
2 | Boolean $handle_role = false, | ||
3 | Boolean $handle_config = false, | ||
4 | Boolean $add_self_role = false, | ||
5 | Boolean $handle_slot = false, | ||
6 | Optional[String] $target = undef, | ||
7 | ) { | ||
8 | include "profile::postgresql::pam_ldap" | ||
9 | |||
10 | $host_cn = $title | ||
11 | $host_infos = find_host($facts["ldapvar"]["other"], $host_cn) | ||
12 | |||
13 | if empty($host_infos) { | ||
14 | fail("Unable to find host for replication") | ||
15 | } | ||
16 | |||
17 | if empty($target) { | ||
18 | $pg_version = undef | ||
19 | } else { | ||
20 | $pg_version = "10" | ||
21 | } | ||
22 | |||
23 | $host_infos["ipHostNumber"].each |$ip| { | ||
24 | $infos = split($ip, "/") | ||
25 | $ipaddress = $infos[0] | ||
26 | if (length($infos) == 1 and $ipaddress =~ /:/) { | ||
27 | $mask = "128" | ||
28 | } elsif (length($infos) == 1) { | ||
29 | $mask = "32" | ||
30 | } else { | ||
31 | $mask = $infos[1] | ||
32 | } | ||
33 | |||
34 | postgresql::server::pg_hba_rule { "allow TCP access for replication to user $host_cn from $ipaddress/$mask": | ||
35 | type => 'hostssl', | ||
36 | database => 'replication', | ||
37 | user => $host_cn, | ||
38 | address => "$ipaddress/$mask", | ||
39 | auth_method => 'pam', | ||
40 | order => "06-01", | ||
41 | target => $target, | ||
42 | postgresql_version => $pg_version, | ||
43 | } | ||
44 | } | ||
45 | |||
46 | if $handle_config { | ||
47 | ensure_resource("postgresql::server::config_entry", "wal_level", { | ||
48 | value => "logical", | ||
49 | }) | ||
50 | } | ||
51 | |||
52 | if $handle_role { | ||
53 | postgresql::server::role { $host_cn: | ||
54 | replication => true, | ||
55 | } | ||
56 | |||
57 | if $add_self_role { | ||
58 | $ldap_cn = lookup("base_installation::ldap_cn") | ||
59 | |||
60 | # Needed to be replicated to the backup and be able to recover later | ||
61 | ensure_resource("postgresql::server::role", $ldap_cn, { | ||
62 | replication => true, | ||
63 | }) | ||
64 | } | ||
65 | } | ||
66 | |||
67 | if $handle_slot { | ||
68 | postgresql_replication_slot { regsubst($host_cn, '-', "_", "G"): | ||
69 | ensure => present | ||
70 | } | ||
71 | } | ||
72 | } | ||
diff --git a/modules/profile/manifests/postgresql/ssl.pp b/modules/profile/manifests/postgresql/ssl.pp new file mode 100644 index 0000000..dc56c0b --- /dev/null +++ b/modules/profile/manifests/postgresql/ssl.pp | |||
@@ -0,0 +1,82 @@ | |||
1 | define profile::postgresql::ssl ( | ||
2 | Optional[String] $cert = undef, | ||
3 | Optional[String] $key = undef, | ||
4 | Optional[String] $certname = undef, | ||
5 | Optional[Boolean] $copy_keys = true, | ||
6 | Optional[Boolean] $handle_config_entry = false, | ||
7 | Optional[Boolean] $handle_concat_config = false, | ||
8 | Optional[String] $pg_user = "postgres", | ||
9 | Optional[String] $pg_group = "postgres", | ||
10 | ) { | ||
11 | $datadir = $title | ||
12 | |||
13 | file { "$datadir/certs": | ||
14 | ensure => directory, | ||
15 | mode => "0700", | ||
16 | owner => $pg_user, | ||
17 | group => $pg_group, | ||
18 | require => File[$datadir], | ||
19 | } | ||
20 | |||
21 | if empty($cert) or empty($key) { | ||
22 | if empty($certname) { | ||
23 | fail("A certificate name is necessary to generate ssl certificate") | ||
24 | } | ||
25 | |||
26 | ssl::self_signed_certificate { $certname: | ||
27 | common_name => $certname, | ||
28 | country => "FR", | ||
29 | days => "3650", | ||
30 | organization => "Immae", | ||
31 | owner => $pg_user, | ||
32 | group => $pg_group, | ||
33 | directory => "$datadir/certs", | ||
34 | } | ||
35 | |||
36 | $ssl_key = "$datadir/certs/$certname.key" | ||
37 | $ssl_cert = "$datadir/certs/$certname.crt" | ||
38 | } elsif $copy_keys { | ||
39 | $ssl_key = "$datadir/certs/privkey.pem" | ||
40 | $ssl_cert = "$datadir/certs/cert.pem" | ||
41 | |||
42 | file { $ssl_cert: | ||
43 | source => "file://$cert", | ||
44 | mode => "0600", | ||
45 | links => "follow", | ||
46 | owner => $pg_user, | ||
47 | group => $pg_group, | ||
48 | require => File["$datadir/certs"], | ||
49 | } | ||
50 | file { $ssl_key: | ||
51 | source => "file://$key", | ||
52 | mode => "0600", | ||
53 | links => "follow", | ||
54 | owner => $pg_user, | ||
55 | group => $pg_group, | ||
56 | require => File["$datadir/certs"], | ||
57 | } | ||
58 | } else { | ||
59 | $ssl_key = $key | ||
60 | $ssl_cert = $cert | ||
61 | } | ||
62 | |||
63 | if $handle_config_entry { | ||
64 | postgresql::server::config_entry { "ssl": | ||
65 | value => "on", | ||
66 | } | ||
67 | |||
68 | postgresql::server::config_entry { "ssl_cert_file": | ||
69 | value => $ssl_cert, | ||
70 | } | ||
71 | |||
72 | postgresql::server::config_entry { "ssl_key_file": | ||
73 | value => $ssl_key, | ||
74 | } | ||
75 | } elsif $handle_concat_config { | ||
76 | concat::fragment { "$datadir/postgresql.conf ssl config": | ||
77 | target => "$datadir/postgresql.conf", | ||
78 | content => "ssl = on\nssl_key_file = '$ssl_key'\nssl_cert_file = '$ssl_cert'\n" | ||
79 | } | ||
80 | } | ||
81 | |||
82 | } | ||
diff --git a/modules/profile/manifests/postgresql_master.pp b/modules/profile/manifests/postgresql_master.pp deleted file mode 100644 index 067345a..0000000 --- a/modules/profile/manifests/postgresql_master.pp +++ /dev/null | |||
@@ -1,121 +0,0 @@ | |||
1 | define profile::postgresql_master ( | ||
2 | $letsencrypt_host = undef, | ||
3 | $backup_hosts = [], | ||
4 | ) { | ||
5 | $password_seed = lookup("base_installation::puppet_pass_seed") | ||
6 | |||
7 | ensure_resource("file", "/var/lib/postgres/data/certs", { | ||
8 | ensure => directory, | ||
9 | mode => "0700", | ||
10 | owner => $::profile::postgresql::pg_user, | ||
11 | group => $::profile::postgresql::pg_user, | ||
12 | require => File["/var/lib/postgres"], | ||
13 | }) | ||
14 | |||
15 | ensure_resource("file", "/var/lib/postgres/data/certs/cert.pem", { | ||
16 | source => "file:///etc/letsencrypt/live/$letsencrypt_host/cert.pem", | ||
17 | mode => "0600", | ||
18 | links => "follow", | ||
19 | owner => $::profile::postgresql::pg_user, | ||
20 | group => $::profile::postgresql::pg_user, | ||
21 | require => [Letsencrypt::Certonly[$letsencrypt_host], File["/var/lib/postgres/data/certs"]] | ||
22 | }) | ||
23 | |||
24 | ensure_resource("file", "/var/lib/postgres/data/certs/privkey.pem", { | ||
25 | source => "file:///etc/letsencrypt/live/$letsencrypt_host/privkey.pem", | ||
26 | mode => "0600", | ||
27 | links => "follow", | ||
28 | owner => $::profile::postgresql::pg_user, | ||
29 | group => $::profile::postgresql::pg_user, | ||
30 | require => [Letsencrypt::Certonly[$letsencrypt_host], File["/var/lib/postgres/data/certs"]] | ||
31 | }) | ||
32 | |||
33 | ensure_resource("postgresql::server::config_entry", "wal_level", { | ||
34 | value => "logical", | ||
35 | }) | ||
36 | |||
37 | ensure_resource("postgresql::server::config_entry", "ssl", { | ||
38 | value => "on", | ||
39 | require => Letsencrypt::Certonly[$letsencrypt_host], | ||
40 | }) | ||
41 | |||
42 | ensure_resource("postgresql::server::config_entry", "ssl_cert_file", { | ||
43 | value => "/var/lib/postgres/data/certs/cert.pem", | ||
44 | require => Letsencrypt::Certonly[$letsencrypt_host], | ||
45 | }) | ||
46 | |||
47 | ensure_resource("postgresql::server::config_entry", "ssl_key_file", { | ||
48 | value => "/var/lib/postgres/data/certs/privkey.pem", | ||
49 | require => Letsencrypt::Certonly[$letsencrypt_host], | ||
50 | }) | ||
51 | |||
52 | $backup_hosts.each |$backup_host| { | ||
53 | ensure_packages(["pam_ldap"]) | ||
54 | |||
55 | $host = find_host($facts["ldapvar"]["other"], $backup_host) | ||
56 | unless empty($host) { | ||
57 | $host["ipHostNumber"].each |$ip| { | ||
58 | $infos = split($ip, "/") | ||
59 | $ipaddress = $infos[0] | ||
60 | if (length($infos) == 1 and $ipaddress =~ /:/) { | ||
61 | $mask = "128" | ||
62 | } elsif (length($infos) == 1) { | ||
63 | $mask = "32" | ||
64 | } else { | ||
65 | $mask = $infos[1] | ||
66 | } | ||
67 | |||
68 | postgresql::server::pg_hba_rule { "allow TCP access to replication user from backup for replication from $ipaddress/$mask": | ||
69 | type => 'hostssl', | ||
70 | database => 'replication', | ||
71 | user => $backup_host, | ||
72 | address => "$ipaddress/$mask", | ||
73 | auth_method => 'pam', | ||
74 | order => "06-01", | ||
75 | } | ||
76 | } | ||
77 | |||
78 | postgresql::server::role { $backup_host: | ||
79 | replication => true, | ||
80 | } | ||
81 | |||
82 | postgresql_replication_slot { regsubst($backup_host, '-', "_", "G"): | ||
83 | ensure => present | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | $ldap_server = lookup("base_installation::ldap_server") | ||
89 | $ldap_base = lookup("base_installation::ldap_base") | ||
90 | $ldap_dn = lookup("base_installation::ldap_dn") | ||
91 | $ldap_cn = lookup("base_installation::ldap_cn") | ||
92 | $ldap_password = generate_password(24, $password_seed, "ldap") | ||
93 | $ldap_attribute = "cn" | ||
94 | |||
95 | # This is to be replicated to the backup | ||
96 | postgresql::server::role { $ldap_cn: | ||
97 | replication => true, | ||
98 | } | ||
99 | |||
100 | file { "/etc/pam_ldap.d": | ||
101 | ensure => directory, | ||
102 | mode => "0755", | ||
103 | owner => "root", | ||
104 | group => "root", | ||
105 | } -> | ||
106 | file { "/etc/pam_ldap.d/postgresql.conf": | ||
107 | ensure => "present", | ||
108 | mode => "0600", | ||
109 | owner => $::profile::postgresql::pg_user, | ||
110 | group => "root", | ||
111 | content => template("profile/postgresql_master/pam_ldap_postgresql.conf.erb"), | ||
112 | } -> | ||
113 | file { "/etc/pam.d/postgresql": | ||
114 | ensure => "present", | ||
115 | mode => "0644", | ||
116 | owner => "root", | ||
117 | group => "root", | ||
118 | source => "puppet:///modules/profile/postgresql_master/pam_postgresql" | ||
119 | } | ||
120 | |||
121 | } | ||
diff --git a/modules/role/templates/backup/pam_ldap_pgbouncer.conf.erb b/modules/profile/templates/postgresql/pam_ldap_pgbouncer.conf.erb index 384a418..12fa9bb 100644 --- a/modules/role/templates/backup/pam_ldap_pgbouncer.conf.erb +++ b/modules/profile/templates/postgresql/pam_ldap_pgbouncer.conf.erb | |||
@@ -3,5 +3,5 @@ host <%= @ldap_server %> | |||
3 | base <%= @ldap_base %> | 3 | base <%= @ldap_base %> |
4 | binddn <%= @ldap_dn %> | 4 | binddn <%= @ldap_dn %> |
5 | bindpw <%= @ldap_password %> | 5 | bindpw <%= @ldap_password %> |
6 | pam_login_attribute <%= @pgbouncer_ldap_attribute %> | 6 | pam_login_attribute <%= @ldap_attribute %> |
7 | pam_filter <%= @ldap_filter %> | 7 | pam_filter <%= @ldap_filter %> |
diff --git a/modules/profile/templates/postgresql_master/pam_ldap_postgresql.conf.erb b/modules/profile/templates/postgresql/pam_ldap_postgresql.conf.erb index f3d9674..f3d9674 100644 --- a/modules/profile/templates/postgresql_master/pam_ldap_postgresql.conf.erb +++ b/modules/profile/templates/postgresql/pam_ldap_postgresql.conf.erb | |||
diff --git a/modules/role/templates/backup/postgresql_backup@.service.erb b/modules/profile/templates/postgresql/postgresql_backup@.service.erb index 245a1cb..74f5a98 100644 --- a/modules/role/templates/backup/postgresql_backup@.service.erb +++ b/modules/profile/templates/postgresql/postgresql_backup@.service.erb | |||
@@ -8,10 +8,10 @@ TimeoutSec=120 | |||
8 | User=postgres | 8 | User=postgres |
9 | Group=postgres | 9 | Group=postgres |
10 | 10 | ||
11 | Environment=PGROOT=<%= @mountpoint %>/%i/postgresql | 11 | Environment=PGROOT=<%= @base_path %>/%i/postgresql |
12 | 12 | ||
13 | SyslogIdentifier=postgres | 13 | SyslogIdentifier=postgres |
14 | PIDFile=<%= @mountpoint %>/%i/postgresql/postmaster.pid | 14 | PIDFile=<%= @base_path %>/%i/postgresql/postmaster.pid |
15 | RuntimeDirectory=postgresql | 15 | RuntimeDirectory=postgresql |
16 | RuntimeDirectoryMode=755 | 16 | RuntimeDirectoryMode=755 |
17 | 17 | ||
diff --git a/modules/role/manifests/backup.pp b/modules/role/manifests/backup.pp index 51b689d..b35c542 100644 --- a/modules/role/manifests/backup.pp +++ b/modules/role/manifests/backup.pp | |||
@@ -17,14 +17,6 @@ class role::backup ( | |||
17 | 17 | ||
18 | include "role::backup::postgresql" | 18 | include "role::backup::postgresql" |
19 | 19 | ||
20 | ensure_packages(["python", "python-pip"]) | ||
21 | package { "pylog2rotate": | ||
22 | source => "git+https://github.com/avian2/pylog2rotate", | ||
23 | ensure => present, | ||
24 | provider => "pip3", | ||
25 | require => Package["python-pip"], | ||
26 | } | ||
27 | |||
28 | ensure_packages(["rsync"]) | 20 | ensure_packages(["rsync"]) |
29 | 21 | ||
30 | ssh_keygen { $user: | 22 | ssh_keygen { $user: |
diff --git a/modules/role/manifests/backup/postgresql.pp b/modules/role/manifests/backup/postgresql.pp index ee62a00..8a65dec 100644 --- a/modules/role/manifests/backup/postgresql.pp +++ b/modules/role/manifests/backup/postgresql.pp | |||
@@ -1,381 +1,21 @@ | |||
1 | class role::backup::postgresql inherits role::backup { | 1 | class role::backup::postgresql inherits role::backup { |
2 | # This manifest is supposed to be part of the backup server | 2 | ensure_packages(["postgresql"]) |
3 | |||
4 | $password_seed = lookup("base_installation::puppet_pass_seed") | ||
5 | |||
6 | $user = lookup("role::backup::user") | ||
7 | $group = lookup("role::backup::group") | ||
8 | $pg_user = "postgres" | ||
9 | $pg_group = "postgres" | ||
10 | |||
11 | $ldap_cn = lookup("base_installation::ldap_cn") | ||
12 | $ldap_password = generate_password(24, $password_seed, "ldap") | ||
13 | $ldap_server = lookup("base_installation::ldap_server") | ||
14 | $ldap_base = lookup("base_installation::ldap_base") | ||
15 | $ldap_dn = lookup("base_installation::ldap_dn") | ||
16 | $pgbouncer_ldap_attribute = "uid" | ||
17 | |||
18 | $pg_slot = regsubst($ldap_cn, '-', "_", "G") | ||
19 | |||
20 | ensure_packages(["postgresql", "pgbouncer", "pam_ldap"]) | ||
21 | 3 | ||
22 | $pg_backup_hosts = lookup("role::backup::postgresql::backup_hosts", { "default_value" => {} }) | 4 | $pg_backup_hosts = lookup("role::backup::postgresql::backup_hosts", { "default_value" => {} }) |
23 | $ldap_filter = lookup("role::backup::postgresql::pgbouncer_access_filter", { "default_value" => undef }) | ||
24 | |||
25 | unless empty($pg_backup_hosts) { | ||
26 | file { "/etc/systemd/system/postgresql_backup@.service": | ||
27 | mode => "0644", | ||
28 | owner => "root", | ||
29 | group => "root", | ||
30 | content => template("role/backup/postgresql_backup@.service.erb"), | ||
31 | } | ||
32 | |||
33 | unless empty($ldap_filter) { | ||
34 | concat { "/etc/pgbouncer/pgbouncer.ini": | ||
35 | mode => "0644", | ||
36 | owner => "root", | ||
37 | group => "root", | ||
38 | ensure_newline => true, | ||
39 | notify => Service["pgbouncer"], | ||
40 | } | ||
41 | |||
42 | concat::fragment { "pgbouncer_head": | ||
43 | target => "/etc/pgbouncer/pgbouncer.ini", | ||
44 | order => "01", | ||
45 | content => template("role/backup/pgbouncer.ini.erb"), | ||
46 | } | ||
47 | |||
48 | file { "/etc/systemd/system/pgbouncer.service.d": | ||
49 | ensure => "directory", | ||
50 | mode => "0644", | ||
51 | owner => "root", | ||
52 | group => "root", | ||
53 | } | ||
54 | |||
55 | file { "/etc/systemd/system/pgbouncer.service.d/override.conf": | ||
56 | ensure => "present", | ||
57 | mode => "0644", | ||
58 | owner => "root", | ||
59 | group => "root", | ||
60 | content => "[Service]\nUser=\nUser=$pg_user\n", | ||
61 | notify => Service["pgbouncer"], | ||
62 | } | ||
63 | |||
64 | service { "pgbouncer": | ||
65 | ensure => "running", | ||
66 | enable => true, | ||
67 | require => [ | ||
68 | Package["pgbouncer"], | ||
69 | File["/etc/systemd/system/pgbouncer.service.d/override.conf"], | ||
70 | Concat["/etc/pgbouncer/pgbouncer.ini"] | ||
71 | ], | ||
72 | } | ||
73 | |||
74 | file { "/etc/pam_ldap.d/pgbouncer.conf": | ||
75 | ensure => "present", | ||
76 | mode => "0600", | ||
77 | owner => $pg_user, | ||
78 | group => "root", | ||
79 | content => template("role/backup/pam_ldap_pgbouncer.conf.erb"), | ||
80 | require => File["/etc/pam_ldap.d"], | ||
81 | } -> | ||
82 | file { "/etc/pam.d/pgbouncer": | ||
83 | ensure => "present", | ||
84 | mode => "0644", | ||
85 | owner => "root", | ||
86 | group => "root", | ||
87 | source => "puppet:///modules/role/backup/pam_pgbouncer" | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | $ldap_attribute = "cn" | ||
93 | |||
94 | file { "/etc/pam_ldap.d": | ||
95 | ensure => directory, | ||
96 | mode => "0755", | ||
97 | owner => "root", | ||
98 | group => "root", | ||
99 | } -> | ||
100 | file { "/etc/pam_ldap.d/postgresql.conf": | ||
101 | ensure => "present", | ||
102 | mode => "0600", | ||
103 | owner => $pg_user, | ||
104 | group => "root", | ||
105 | content => template("profile/postgresql_master/pam_ldap_postgresql.conf.erb"), | ||
106 | } -> | ||
107 | file { "/etc/pam.d/postgresql": | ||
108 | ensure => "present", | ||
109 | mode => "0644", | ||
110 | owner => "root", | ||
111 | group => "root", | ||
112 | source => "puppet:///modules/profile/postgresql_master/pam_postgresql" | ||
113 | } | ||
114 | 5 | ||
115 | $pg_backup_hosts.each |$backup_host_cn, $pg_infos| { | 6 | $pg_backup_hosts.each |$backup_host_cn, $pg_infos| { |
116 | $host = find_host($facts["ldapvar"]["other"], $backup_host_cn) | 7 | profile::postgresql::backup_replication { $backup_host_cn: |
117 | if empty($host) { | 8 | base_path => $mountpoint, |
118 | $pg_backup_host = $backup_host_cn | 9 | pg_infos => $pg_infos, |
119 | } elsif has_key($host["vars"], "host") { | ||
120 | $pg_backup_host = $host["vars"]["host"][0] | ||
121 | } else { | ||
122 | $pg_backup_host = $host["vars"]["real_hostname"][0] | ||
123 | } | ||
124 | |||
125 | $pg_path = "$mountpoint/$pg_backup_host/postgresql" | ||
126 | $pg_backup_path = "$mountpoint/$pg_backup_host/postgresql_backup" | ||
127 | $pg_host = "$pg_backup_host" | ||
128 | $pg_port = $pg_infos["dbport"] | ||
129 | |||
130 | if has_key($host["vars"], "postgresql_backup_port") { | ||
131 | $pg_listen_port = $host["vars"]["postgresql_backup_port"][0] | ||
132 | file { "$pg_path/certs": | ||
133 | ensure => directory, | ||
134 | mode => "0700", | ||
135 | owner => $pg_user, | ||
136 | group => $pg_group, | ||
137 | } -> | ||
138 | ssl::self_signed_certificate { $backup_host_cn: | ||
139 | common_name => $backup_host_cn, | ||
140 | country => "FR", | ||
141 | days => "3650", | ||
142 | organization => "Immae", | ||
143 | owner => $pg_user, | ||
144 | group => $pg_group, | ||
145 | directory => "$pg_path/certs", | ||
146 | before => File["$pg_path/postgresql.conf"], | ||
147 | } | ||
148 | $ssl_key = "$pg_path/certs/$backup_host_cn.key" | ||
149 | $ssl_cert = "$pg_path/certs/$backup_host_cn.crt" | ||
150 | } else { | ||
151 | $pg_listen_port = undef | ||
152 | $ssl_key = undef | ||
153 | $ssl_cert = undef | ||
154 | } | ||
155 | |||
156 | |||
157 | unless empty($host) { | ||
158 | $host["ipHostNumber"].each |$ip| { | ||
159 | $infos = split($ip, "/") | ||
160 | $ipaddress = $infos[0] | ||
161 | if (length($infos) == 1 and $ipaddress =~ /:/) { | ||
162 | $mask = "128" | ||
163 | } elsif (length($infos) == 1) { | ||
164 | $mask = "32" | ||
165 | } else { | ||
166 | $mask = $infos[1] | ||
167 | } | ||
168 | |||
169 | postgresql::server::pg_hba_rule { "allow TCP access for initial replication from $ipaddress/$mask": | ||
170 | type => 'hostssl', | ||
171 | database => 'replication', | ||
172 | user => $backup_host_cn, | ||
173 | address => "$ipaddress/$mask", | ||
174 | auth_method => 'pam', | ||
175 | order => "06-01", | ||
176 | target => "$pg_path/pg_hba.conf", | ||
177 | postgresql_version => "10", | ||
178 | } | ||
179 | } | ||
180 | } | 10 | } |
181 | 11 | ||
182 | if !empty($ldap_filter) and ($pg_infos["pgbouncer"]) { | 12 | if $pg_infos["pgbouncer"] { |
183 | if empty($pg_listen_port) { | 13 | profile::postgresql::backup_pgbouncer { $backup_host_cn: |
184 | $pg_listen_port_key = "" | 14 | base_path => $mountpoint, |
185 | } else { | 15 | pg_infos => $pg_infos, |
186 | $pg_listen_port_key = "port=$pg_listen_port" | ||
187 | } | ||
188 | |||
189 | concat::fragment { "pgbouncer_$pg_backup_host": | ||
190 | target => "/etc/pgbouncer/pgbouncer.ini", | ||
191 | order => 02, | ||
192 | content => "${pg_infos[pgbouncer_dbname]} = host=$mountpoint/$pg_backup_host/postgresql $pg_listen_port_key user=${pg_infos[dbuser]} dbname=${pg_infos[dbname]}", | ||
193 | } | ||
194 | |||
195 | postgresql::server::pg_hba_rule { "$pg_backup_host - local access as ${pg_infos[dbuser]} user": | ||
196 | description => "Allow local access to ${pg_infos[dbuser]} user", | ||
197 | type => 'local', | ||
198 | database => $pg_infos["dbname"], | ||
199 | user => $pg_infos["dbuser"], | ||
200 | auth_method => 'trust', | ||
201 | order => "01-00", | ||
202 | target => "$pg_path/pg_hba.conf", | ||
203 | postgresql_version => "10", | ||
204 | } | 16 | } |
205 | } | 17 | } |
206 | 18 | ||
207 | file { "$mountpoint/$pg_backup_host": | ||
208 | ensure => directory, | ||
209 | owner => $user, | ||
210 | group => $group, | ||
211 | } | ||
212 | |||
213 | file { $pg_path: | ||
214 | ensure => directory, | ||
215 | owner => $pg_user, | ||
216 | group => $pg_group, | ||
217 | mode => "0700", | ||
218 | require => File["$mountpoint/$pg_backup_host"], | ||
219 | } | ||
220 | |||
221 | file { $pg_backup_path: | ||
222 | ensure => directory, | ||
223 | owner => $pg_user, | ||
224 | group => $pg_group, | ||
225 | mode => "0700", | ||
226 | require => File["$mountpoint/$pg_backup_host"], | ||
227 | } | ||
228 | |||
229 | cron::job::multiple { "backup_psql_$pg_host": | ||
230 | ensure => "present", | ||
231 | require => [File[$pg_backup_path], File[$pg_path]], | ||
232 | jobs => [ | ||
233 | { | ||
234 | command => "/usr/bin/pg_dumpall -h $pg_path -f $pg_backup_path/\$(date -Iseconds).sql", | ||
235 | user => $pg_user, | ||
236 | hour => "22,4,10,16", | ||
237 | minute => 0, | ||
238 | description => "Backup the database", | ||
239 | }, | ||
240 | { | ||
241 | command => "/usr/bin/rm -f $(ls -1 $pg_backup_path/*.sql | grep -v 'T22:' | sort -r | sed -e '1,12d')", | ||
242 | user => $pg_user, | ||
243 | hour => 3, | ||
244 | minute => 0, | ||
245 | description => "Cleanup the database backups", | ||
246 | }, | ||
247 | { | ||
248 | command => "cd $pg_backup_path ; /usr/bin/rm -f $(ls -1 *T22*.sql | log2rotate --skip 7 --fuzz 7 --delete --format='%Y-%m-%dT%H:%M:%S+02:00.sql')", | ||
249 | user => $pg_user, | ||
250 | hour => 3, | ||
251 | minute => 1, | ||
252 | description => "Cleanup the database backups exponentially", | ||
253 | }, | ||
254 | ] | ||
255 | } | ||
256 | |||
257 | exec { "pg_basebackup $pg_path": | ||
258 | cwd => $pg_path, | ||
259 | user => $pg_user, | ||
260 | creates => "$pg_path/PG_VERSION", | ||
261 | environment => ["PGPASSWORD=$ldap_password"], | ||
262 | command => "/usr/bin/pg_basebackup -w -h $pg_host -U $ldap_cn -D $pg_path -S $pg_slot", | ||
263 | before => [ | ||
264 | Concat["$pg_path/pg_hba.conf"], | ||
265 | Concat["$pg_path/recovery.conf"], | ||
266 | File["$pg_path/postgresql.conf"], | ||
267 | ] | ||
268 | } | ||
269 | |||
270 | concat { "$pg_path/pg_hba.conf": | ||
271 | owner => $pg_user, | ||
272 | group => $pg_group, | ||
273 | mode => '0640', | ||
274 | warn => true, | ||
275 | } | ||
276 | postgresql::server::pg_hba_rule { "$pg_backup_host - local access as postgres user": | ||
277 | description => 'Allow local access to postgres user', | ||
278 | type => 'local', | ||
279 | database => 'all', | ||
280 | user => $pg_user, | ||
281 | auth_method => 'ident', | ||
282 | order => "00-01", | ||
283 | target => "$pg_path/pg_hba.conf", | ||
284 | postgresql_version => "10", | ||
285 | } | ||
286 | postgresql::server::pg_hba_rule { "$pg_backup_host - localhost access as postgres user": | ||
287 | description => 'Allow localhost access to postgres user', | ||
288 | type => 'host', | ||
289 | database => 'all', | ||
290 | user => $pg_user, | ||
291 | address => "127.0.0.1/32", | ||
292 | auth_method => 'md5', | ||
293 | order => "00-02", | ||
294 | target => "$pg_path/pg_hba.conf", | ||
295 | postgresql_version => "10", | ||
296 | } | ||
297 | postgresql::server::pg_hba_rule { "$pg_backup_host - localhost ip6 access as postgres user": | ||
298 | description => 'Allow localhost access to postgres user', | ||
299 | type => 'host', | ||
300 | database => 'all', | ||
301 | user => $pg_user, | ||
302 | address => "::1/128", | ||
303 | auth_method => 'md5', | ||
304 | order => "00-03", | ||
305 | target => "$pg_path/pg_hba.conf", | ||
306 | postgresql_version => "10", | ||
307 | } | ||
308 | postgresql::server::pg_hba_rule { "$pg_backup_host - deny access to postgresql user": | ||
309 | description => 'Deny remote access to postgres user', | ||
310 | type => 'host', | ||
311 | database => 'all', | ||
312 | user => $pg_user, | ||
313 | address => "0.0.0.0/0", | ||
314 | auth_method => 'reject', | ||
315 | order => "00-04", | ||
316 | target => "$pg_path/pg_hba.conf", | ||
317 | postgresql_version => "10", | ||
318 | } | ||
319 | |||
320 | postgresql::server::pg_hba_rule { "$pg_backup_host - local access": | ||
321 | description => 'Allow local access with password', | ||
322 | type => 'local', | ||
323 | database => 'all', | ||
324 | user => 'all', | ||
325 | auth_method => 'md5', | ||
326 | order => "10-01", | ||
327 | target => "$pg_path/pg_hba.conf", | ||
328 | postgresql_version => "10", | ||
329 | } | ||
330 | |||
331 | postgresql::server::pg_hba_rule { "$pg_backup_host - local access with same name": | ||
332 | description => 'Allow local access with same name', | ||
333 | type => 'local', | ||
334 | database => 'all', | ||
335 | user => 'all', | ||
336 | auth_method => 'ident', | ||
337 | order => "10-02", | ||
338 | target => "$pg_path/pg_hba.conf", | ||
339 | postgresql_version => "10", | ||
340 | } | ||
341 | |||
342 | $primary_conninfo = "host=$pg_host port=$pg_port user=$ldap_cn password=$ldap_password sslmode=require" | ||
343 | $primary_slot_name = regsubst($ldap_cn, '-', "_", "G") | ||
344 | $standby_mode = "on" | ||
345 | |||
346 | concat { "$pg_path/recovery.conf": | ||
347 | owner => $pg_user, | ||
348 | group => $pg_group, | ||
349 | mode => '0640', | ||
350 | warn => true, | ||
351 | } | ||
352 | concat::fragment { "$pg_path/recovery.conf": | ||
353 | target => "$pg_path/recovery.conf", | ||
354 | content => template('postgresql/recovery.conf.erb'), | ||
355 | } | ||
356 | |||
357 | file { "$pg_path/postgresql.conf": | ||
358 | owner => $pg_user, | ||
359 | group => $pg_group, | ||
360 | mode => '0640', | ||
361 | content => template("role/backup/postgresql.conf.erb"), | ||
362 | } | ||
363 | |||
364 | service { "postgresql_backup@$pg_backup_host": | ||
365 | enable => true, | ||
366 | ensure => "running", | ||
367 | require => [ | ||
368 | File["/etc/systemd/system/postgresql_backup@.service"], | ||
369 | Concat["$pg_path/pg_hba.conf"], | ||
370 | Concat["$pg_path/recovery.conf"], | ||
371 | File["$pg_path/postgresql.conf"], | ||
372 | ], | ||
373 | subscribe => [ | ||
374 | Concat["$pg_path/pg_hba.conf"], | ||
375 | Concat["$pg_path/recovery.conf"], | ||
376 | File["$pg_path/postgresql.conf"], | ||
377 | ] | ||
378 | } | ||
379 | } | 19 | } |
380 | 20 | ||
381 | } | 21 | } |
diff --git a/modules/role/manifests/cryptoportfolio/postgresql.pp b/modules/role/manifests/cryptoportfolio/postgresql.pp index 776b30f..addad67 100644 --- a/modules/role/manifests/cryptoportfolio/postgresql.pp +++ b/modules/role/manifests/cryptoportfolio/postgresql.pp | |||
@@ -2,194 +2,40 @@ class role::cryptoportfolio::postgresql inherits role::cryptoportfolio { | |||
2 | $password_seed = lookup("base_installation::puppet_pass_seed") | 2 | $password_seed = lookup("base_installation::puppet_pass_seed") |
3 | 3 | ||
4 | $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio") | 4 | $pg_password = generate_password(24, $password_seed, "postgres_cryptoportfolio") |
5 | $pg_replication_password = generate_password(24, $password_seed, "postgres_cryptoportfolio_replication") | ||
6 | 5 | ||
7 | file { "/var/lib/postgres/data/certs": | 6 | profile::postgresql::master { "postgresql master for cryptoportfolio": |
8 | ensure => directory, | 7 | letsencrypt_host => $web_host, |
9 | mode => "0700", | 8 | backup_hosts => ["backup-1"], |
10 | owner => $::profile::postgresql::pg_user, | ||
11 | group => $::profile::postgresql::pg_user, | ||
12 | require => File["/var/lib/postgres"], | ||
13 | } | ||
14 | |||
15 | file { "/var/lib/postgres/data/certs/cert.pem": | ||
16 | source => "file:///etc/letsencrypt/live/$web_host/cert.pem", | ||
17 | mode => "0600", | ||
18 | links => "follow", | ||
19 | owner => $::profile::postgresql::pg_user, | ||
20 | group => $::profile::postgresql::pg_user, | ||
21 | require => [Letsencrypt::Certonly[$web_host], File["/var/lib/postgres/data/certs"]] | ||
22 | } | ||
23 | |||
24 | file { "/var/lib/postgres/data/certs/privkey.pem": | ||
25 | source => "file:///etc/letsencrypt/live/$web_host/privkey.pem", | ||
26 | mode => "0600", | ||
27 | links => "follow", | ||
28 | owner => $::profile::postgresql::pg_user, | ||
29 | group => $::profile::postgresql::pg_user, | ||
30 | require => [Letsencrypt::Certonly[$web_host], File["/var/lib/postgres/data/certs"]] | ||
31 | } | ||
32 | |||
33 | postgresql_replication_slot { $pg_user_replication: | ||
34 | ensure => present | ||
35 | } | ||
36 | |||
37 | postgresql::server::config_entry { "wal_level": | ||
38 | value => "logical", | ||
39 | } | ||
40 | |||
41 | postgresql::server::config_entry { "ssl": | ||
42 | value => "on", | ||
43 | require => Letsencrypt::Certonly[$web_host], | ||
44 | } | ||
45 | |||
46 | postgresql::server::config_entry { "ssl_cert_file": | ||
47 | value => "/var/lib/postgres/data/certs/cert.pem", | ||
48 | require => Letsencrypt::Certonly[$web_host], | ||
49 | } | ||
50 | |||
51 | postgresql::server::config_entry { "ssl_key_file": | ||
52 | value => "/var/lib/postgres/data/certs/privkey.pem", | ||
53 | require => Letsencrypt::Certonly[$web_host], | ||
54 | } | 9 | } |
55 | 10 | ||
56 | postgresql::server::db { $pg_db: | 11 | postgresql::server::db { $pg_db: |
57 | user => $pg_user, | 12 | user => $pg_user, |
58 | password => postgresql_password($pg_user, $pg_password), | 13 | password => postgresql_password($pg_user, $pg_password), |
59 | } | 14 | } |
60 | -> | ||
61 | postgresql_psql { "CREATE PUBLICATION ${pg_db}_publication FOR ALL TABLES": | ||
62 | db => $pg_db, | ||
63 | unless => "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '${pg_db}_publication'", | ||
64 | } | ||
65 | -> | ||
66 | postgresql::server::role { $pg_user_replication: | ||
67 | db => $pg_db, | ||
68 | replication => true, | ||
69 | password_hash => postgresql_password($pg_user_replication, $pg_replication_password), | ||
70 | } | ||
71 | -> | ||
72 | postgresql::server::database_grant { $pg_user_replication: | ||
73 | db => $pg_db, | ||
74 | privilege => "CONNECT", | ||
75 | role => $pg_user_replication, | ||
76 | } | ||
77 | -> | ||
78 | postgresql::server::grant { "all tables in schema:public:$pg_user_replication": | ||
79 | db => $pg_db, | ||
80 | role => $pg_user_replication, | ||
81 | privilege => "SELECT", | ||
82 | object_type => "ALL TABLES IN SCHEMA", | ||
83 | object_name => "public", | ||
84 | } | ||
85 | -> | ||
86 | postgresql::server::grant { "all sequences in schema:public:$pg_user_replication": | ||
87 | db => $pg_db, | ||
88 | role => $pg_user_replication, | ||
89 | privilege => "SELECT", | ||
90 | object_type => "ALL SEQUENCES IN SCHEMA", | ||
91 | object_name => "public", | ||
92 | } | ||
93 | 15 | ||
94 | postgresql::server::pg_hba_rule { 'allow localhost TCP access to cryptoportfolio user': | 16 | postgresql::server::pg_hba_rule { 'allow localhost TCP access to cryptoportfolio user': |
95 | type => 'host', | 17 | type => 'local', |
96 | database => $pg_db, | 18 | database => $pg_db, |
97 | user => $pg_user, | 19 | user => $pg_user, |
98 | address => '127.0.0.1/32', | 20 | auth_method => 'ident', |
99 | auth_method => 'md5', | ||
100 | order => "05-01", | 21 | order => "05-01", |
101 | } | 22 | } |
102 | postgresql::server::pg_hba_rule { 'allow localhost ip6 TCP access to cryptoportfolio user': | ||
103 | type => 'host', | ||
104 | database => $pg_db, | ||
105 | user => $pg_user, | ||
106 | address => '::1/128', | ||
107 | auth_method => 'md5', | ||
108 | order => "05-01", | ||
109 | } | ||
110 | |||
111 | postgresql::server::pg_hba_rule { 'allow TCP access to replication user from immae.eu for replication': | ||
112 | type => 'hostssl', | ||
113 | database => 'replication', | ||
114 | user => $pg_user_replication, | ||
115 | address => 'immae.eu', | ||
116 | auth_method => 'md5', | ||
117 | order => "05-01", | ||
118 | } | ||
119 | |||
120 | postgresql::server::pg_hba_rule { 'allow TCP access to replication user from immae.eu': | ||
121 | type => 'hostssl', | ||
122 | database => $pg_db, | ||
123 | user => $pg_user_replication, | ||
124 | address => 'immae.eu', | ||
125 | auth_method => 'md5', | ||
126 | order => "05-02", | ||
127 | } | ||
128 | |||
129 | $backup_host = "backup-1" | ||
130 | 23 | ||
131 | unless empty($backup_host) { | 24 | # cleanup |
132 | ensure_packages(["pam_ldap"]) | 25 | postgresql_psql { "DROP PUBLICATION ${pg_db}_publication": |
133 | 26 | db => $pg_db, | |
134 | $facts["ldapvar"]["other"].each |$host| { | 27 | onlyif => "SELECT 1 FROM pg_catalog.pg_publication WHERE pubname = '${pg_db}_publication'", |
135 | if ($host["cn"][0] == $backup_host) { | 28 | } -> |
136 | $host["ipHostNumber"].each |$ip| { | 29 | postgresql_replication_slot { $pg_user_replication: |
137 | $infos = split($ip, "/") | 30 | ensure => absent |
138 | $ipaddress = $infos[0] | 31 | } -> |
139 | if (length($infos) == 1 and $ipaddress =~ /:/) { | 32 | postgresql_psql { "DROP OWNED BY $pg_user_replication": |
140 | $mask = "128" | 33 | db => $pg_db, |
141 | } elsif (length($infos) == 1) { | 34 | onlyif => "SELECT 1 FROM pg_user WHERE usename='$pg_user_replication'" |
142 | $mask = "32" | 35 | } -> |
143 | } else { | 36 | postgresql::server::role { $pg_user_replication: |
144 | $mask = $infos[1] | 37 | ensure => absent, |
145 | } | ||
146 | |||
147 | postgresql::server::pg_hba_rule { "allow TCP access to replication user from backup for replication from $ipaddress/$mask": | ||
148 | type => 'hostssl', | ||
149 | database => 'replication', | ||
150 | user => 'all', | ||
151 | address => "$ipaddress/$mask", | ||
152 | auth_method => 'pam', | ||
153 | order => "06-01", | ||
154 | } | ||
155 | } | ||
156 | |||
157 | postgresql::server::role { $backup_host: | ||
158 | replication => true, | ||
159 | } | ||
160 | |||
161 | postgresql_replication_slot { regsubst($backup_host, '-', "_", "G"): | ||
162 | ensure => present | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | |||
167 | $ldap_server = lookup("base_installation::ldap_server") | ||
168 | $ldap_base = lookup("base_installation::ldap_base") | ||
169 | $ldap_dn = lookup("base_installation::ldap_dn") | ||
170 | $ldap_password = generate_password(24, $password_seed, "ldap") | ||
171 | $ldap_attribute = "cn" | ||
172 | |||
173 | file { "/etc/pam_ldap.d": | ||
174 | ensure => directory, | ||
175 | mode => "0755", | ||
176 | owner => "root", | ||
177 | group => "root", | ||
178 | } -> | ||
179 | file { "/etc/pam_ldap.d/postgresql.conf": | ||
180 | ensure => "present", | ||
181 | mode => "0600", | ||
182 | owner => $::profile::postgresql::pg_user, | ||
183 | group => "root", | ||
184 | content => template("role/cryptoportfolio/pam_ldap_postgresql.conf.erb"), | ||
185 | } -> | ||
186 | file { "/etc/pam.d/postgresql": | ||
187 | ensure => "present", | ||
188 | mode => "0644", | ||
189 | owner => "root", | ||
190 | group => "root", | ||
191 | source => "puppet:///modules/role/cryptoportfolio/pam_postgresql" | ||
192 | } | ||
193 | } | 38 | } |
39 | # /cleanup | ||
194 | 40 | ||
195 | } | 41 | } |
diff --git a/modules/role/manifests/etherpad.pp b/modules/role/manifests/etherpad.pp index 109da96..28b9eb6 100644 --- a/modules/role/manifests/etherpad.pp +++ b/modules/role/manifests/etherpad.pp | |||
@@ -87,7 +87,7 @@ class role::etherpad ( | |||
87 | subscribe => Aur::Package["etherpad-lite"], | 87 | subscribe => Aur::Package["etherpad-lite"], |
88 | } | 88 | } |
89 | 89 | ||
90 | profile::postgresql_master { "postgresql master for etherpad": | 90 | profile::postgresql::master { "postgresql master for etherpad": |
91 | letsencrypt_host => $web_host, | 91 | letsencrypt_host => $web_host, |
92 | backup_hosts => ["backup-1"], | 92 | backup_hosts => ["backup-1"], |
93 | } | 93 | } |