Skip to content

Commit c66c097

Browse files
Filipovici-Andreiaustb
authored andcommitted
(PDB-4764) Implement SSL connection between PuppetDB and PostgreSQL.
1 parent 11dc0df commit c66c097

20 files changed

+607
-25
lines changed

Gemfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ group :development do
3030
gem "puppet-module-win-dev-r#{minor_version}", '~> 0.4', require: false, platforms: [:mswin, :mingw, :x64_mingw]
3131
end
3232
group :system_tests do
33-
gem "puppet-module-posix-system-r#{minor_version}", require: false, platforms: [:ruby]
34-
gem "puppet-module-win-system-r#{minor_version}", require: false, platforms: [:mswin, :mingw, :x64_mingw]
33+
gem "puppet-module-posix-system-r#{minor_version}", '~> 0.5', require: false, platforms: [:ruby]
34+
gem "puppet-module-win-system-r#{minor_version}", '~> 0.5', require: false, platforms: [:mswin, :mingw, :x64_mingw]
3535
gem "nokogiri", require: false, platforms: [:ruby]
3636
gem "serverspec", require: false, platforms: [:ruby]
3737
end

lib/puppet/type/puppetdb_conn_validator.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
end
2424

2525
newparam(:use_ssl) do
26-
desc 'Whether the connection will be attemped using https'
26+
desc 'Whether the connection will be attempted using https'
2727
defaultto true
2828
end
2929

manifests/database/postgresql.pp

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
# Class for creating the PuppetDB postgresql database. See README.md for more
22
# information.
33
class puppetdb::database::postgresql(
4-
$listen_addresses = $puppetdb::params::database_host,
5-
$database_name = $puppetdb::params::database_name,
6-
$database_username = $puppetdb::params::database_username,
7-
$database_password = $puppetdb::params::database_password,
8-
$database_port = $puppetdb::params::database_port,
9-
$manage_database = $puppetdb::params::manage_database,
10-
$manage_server = $puppetdb::params::manage_dbserver,
11-
$manage_package_repo = $puppetdb::params::manage_pg_repo,
12-
$postgres_version = $puppetdb::params::postgres_version,
4+
$listen_addresses = $puppetdb::params::database_host,
5+
$database_name = $puppetdb::params::database_name,
6+
$database_username = $puppetdb::params::database_username,
7+
$database_password = $puppetdb::params::database_password,
8+
$database_port = $puppetdb::params::database_port,
9+
$manage_database = $puppetdb::params::manage_database,
10+
$manage_server = $puppetdb::params::manage_dbserver,
11+
$manage_package_repo = $puppetdb::params::manage_pg_repo,
12+
$postgres_version = $puppetdb::params::postgres_version,
13+
$postgresql_ssl_on = $puppetdb::params::postgresql_ssl_on,
14+
$postgresql_ssl_key_path = $puppetdb::params::postgresql_ssl_key_path,
15+
$postgresql_ssl_cert_path = $puppetdb::params::postgresql_ssl_cert_path,
16+
$postgresql_ssl_ca_cert_path = $puppetdb::params::postgresql_ssl_ca_cert_path
1317
) inherits puppetdb::params {
1418

1519
if $manage_server {
@@ -24,6 +28,18 @@
2428
port => scanf($database_port, '%i')[0],
2529
}
2630

31+
# configure PostgreSQL communication with Puppet Agent SSL certificates if
32+
# postgresql_ssl_on is set to true
33+
if $postgresql_ssl_on {
34+
class { 'puppetdb::database::ssl_configuration':
35+
database_name => $database_name,
36+
database_username => $database_username,
37+
postgresql_ssl_key_path => $postgresql_ssl_key_path,
38+
postgresql_ssl_cert_path => $postgresql_ssl_cert_path,
39+
postgresql_ssl_ca_cert_path => $postgresql_ssl_ca_cert_path
40+
}
41+
}
42+
2743
# Only install pg_trgm extension, if database it is actually managed by the module
2844
if $manage_database {
2945

@@ -45,4 +61,4 @@
4561
grant => 'all',
4662
}
4763
}
48-
}
64+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Class for configuring SSL connection for the PuppetDB postgresql database. See README.md for more
2+
# information.
3+
class puppetdb::database::ssl_configuration(
4+
$database_name = $puppetdb::params::database_name,
5+
$database_username = $puppetdb::params::database_username,
6+
$postgresql_ssl_key_path = $puppetdb::params::postgresql_ssl_key_path,
7+
$postgresql_ssl_cert_path = $puppetdb::params::postgresql_ssl_cert_path,
8+
$postgresql_ssl_ca_cert_path = $puppetdb::params::postgresql_ssl_ca_cert_path
9+
) inherits puppetdb::params {
10+
11+
file {'postgres private key':
12+
ensure => present,
13+
path => "${postgresql::server::datadir}/server.key",
14+
source => $postgresql_ssl_key_path,
15+
owner => 'postgres',
16+
mode => '0600',
17+
require => Package['postgresql-server'],
18+
}
19+
20+
file {'postgres public key':
21+
ensure => present,
22+
path => "${postgresql::server::datadir}/server.crt",
23+
source => $postgresql_ssl_cert_path,
24+
owner => 'postgres',
25+
mode => '0600',
26+
require => Package['postgresql-server'],
27+
}
28+
29+
postgresql::server::config_entry {'ssl':
30+
ensure => present,
31+
value => 'on',
32+
require => [File['postgres private key'], File['postgres public key']]
33+
}
34+
35+
postgresql::server::config_entry {'ssl_cert_file':
36+
ensure => present,
37+
value => "${postgresql::server::datadir}/server.crt",
38+
require => [File['postgres private key'], File['postgres public key']]
39+
}
40+
41+
postgresql::server::config_entry {'ssl_key_file':
42+
ensure => present,
43+
value => "${postgresql::server::datadir}/server.key",
44+
require => [File['postgres private key'], File['postgres public key']]
45+
}
46+
47+
postgresql::server::config_entry {'ssl_ca_file':
48+
ensure => present,
49+
value => $postgresql_ssl_ca_cert_path,
50+
require => [File['postgres private key'], File['postgres public key']]
51+
}
52+
53+
$identity_map_key = "${database_name}-${database_username}-map"
54+
55+
postgresql::server::pg_hba_rule { "Allow certificate mapped connections to ${database_name} as ${database_username} (ipv4)":
56+
type => 'hostssl',
57+
database => $database_name,
58+
user => $database_username,
59+
address => '0.0.0.0/0',
60+
auth_method => 'cert',
61+
order => 0,
62+
auth_option => "map=${identity_map_key} clientcert=1"
63+
}
64+
65+
postgresql::server::pg_hba_rule { "Allow certificate mapped connections to ${database_name} as ${database_username} (ipv6)":
66+
type => 'hostssl',
67+
database => $database_name,
68+
user => $database_username,
69+
address => '::0/0',
70+
auth_method => 'cert',
71+
order => 0,
72+
auth_option => "map=${identity_map_key} clientcert=1"
73+
}
74+
75+
postgresql::server::pg_ident_rule {"Map the SSL certificate of the server as a ${database_username} user":
76+
map_name => $identity_map_key,
77+
system_username => $::fqdn,
78+
database_username => $database_username,
79+
}
80+
}

manifests/init.pp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,18 @@
1313
$ssl_set_cert_paths = $puppetdb::params::ssl_set_cert_paths,
1414
$ssl_cert_path = $puppetdb::params::ssl_cert_path,
1515
$ssl_key_path = $puppetdb::params::ssl_key_path,
16+
$ssl_key_pk8_path = $puppetdb::params::ssl_key_pk8_path,
1617
$ssl_ca_cert_path = $puppetdb::params::ssl_ca_cert_path,
1718
$ssl_deploy_certs = $puppetdb::params::ssl_deploy_certs,
1819
$ssl_key = $puppetdb::params::ssl_key,
1920
$ssl_cert = $puppetdb::params::ssl_cert,
2021
$ssl_ca_cert = $puppetdb::params::ssl_ca_cert,
2122
$ssl_protocols = $puppetdb::params::ssl_protocols,
23+
$postgresql_ssl_on = $puppetdb::params::postgresql_ssl_on,
24+
$postgresql_ssl_folder = $puppetdb::params::postgresql_ssl_folder,
25+
$postgresql_ssl_cert_path = $puppetdb::params::postgresql_ssl_cert_path,
26+
$postgresql_ssl_key_path = $puppetdb::params::postgresql_ssl_key_path,
27+
$postgresql_ssl_ca_cert_path = $puppetdb::params::postgresql_ssl_ca_cert_path,
2228
$cipher_suites = $puppetdb::params::cipher_suites,
2329
$migrate = $puppetdb::params::migrate,
2430
$manage_dbserver = $puppetdb::params::manage_dbserver,
@@ -98,12 +104,14 @@
98104
ssl_set_cert_paths => $ssl_set_cert_paths,
99105
ssl_cert_path => $ssl_cert_path,
100106
ssl_key_path => $ssl_key_path,
107+
ssl_key_pk8_path => $ssl_key_pk8_path,
101108
ssl_ca_cert_path => $ssl_ca_cert_path,
102109
ssl_deploy_certs => $ssl_deploy_certs,
103110
ssl_key => $ssl_key,
104111
ssl_cert => $ssl_cert,
105112
ssl_ca_cert => $ssl_ca_cert,
106113
ssl_protocols => $ssl_protocols,
114+
postgresql_ssl_on => $postgresql_ssl_on,
107115
cipher_suites => $cipher_suites,
108116
migrate => $migrate,
109117
database => $database,
@@ -183,6 +191,7 @@
183191
manage_database => $manage_database,
184192
manage_package_repo => $manage_package_repo,
185193
postgres_version => $postgres_version,
194+
postgresql_ssl_on => $postgresql_ssl_on,
186195
before => $database_before
187196
}
188197
}

manifests/params.pp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@
180180
$cleanup_timer_interval = "*-*-* ${fqdn_rand(24)}:${fqdn_rand(60)}:00"
181181
$dlo_max_age = 90
182182

183+
# certificats used for PostgreSQL SSL configuration. Puppet certificates are used
184+
$postgresql_ssl_on = false
185+
$postgresql_ssl_folder = "${puppet_confdir}/ssl"
186+
$postgresql_ssl_cert_path = "${postgresql_ssl_folder}/certs/${trusted['certname']}.pem"
187+
$postgresql_ssl_key_path = "${postgresql_ssl_folder}/private_keys/${trusted['certname']}.pem"
188+
$postgresql_ssl_ca_cert_path = "${postgresql_ssl_folder}/certs/ca.pem"
189+
190+
# certificats used for Jetty configuration
183191
$ssl_set_cert_paths = false
184192
$ssl_cert_path = "${ssl_dir}/public.pem"
185193
$ssl_key_path = "${ssl_dir}/private.pem"
@@ -189,6 +197,9 @@
189197
$ssl_cert = undef
190198
$ssl_ca_cert = undef
191199

200+
# certificate used by PuppetDB SSL Configuration
201+
$ssl_key_pk8_path = regsubst($ssl_key_path, '.pem', '.pk8')
202+
192203
$certificate_whitelist_file = "${etcdir}/certificate-whitelist"
193204
# the default is free access for now
194205
$certificate_whitelist = [ ]

manifests/server.pp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
Boolean $ssl_set_cert_paths = $puppetdb::params::ssl_set_cert_paths,
1313
Stdlib::Absolutepath $ssl_cert_path = $puppetdb::params::ssl_cert_path,
1414
Stdlib::Absolutepath $ssl_key_path = $puppetdb::params::ssl_key_path,
15+
Stdlib::Absolutepath $ssl_key_pk8_path = $puppetdb::params::ssl_key_pk8_path,
1516
Stdlib::Absolutepath $ssl_ca_cert_path = $puppetdb::params::ssl_ca_cert_path,
1617
Boolean $ssl_deploy_certs = $puppetdb::params::ssl_deploy_certs,
1718
$ssl_key = $puppetdb::params::ssl_key,
1819
$ssl_cert = $puppetdb::params::ssl_cert,
1920
$ssl_ca_cert = $puppetdb::params::ssl_ca_cert,
2021
$ssl_protocols = $puppetdb::params::ssl_protocols,
22+
$postgresql_ssl_on = $puppetdb::params::postgresql_ssl_on,
2123
$cipher_suites = $puppetdb::params::cipher_suites,
2224
$migrate = $puppetdb::params::migrate,
2325
$database = $puppetdb::params::database,
@@ -168,6 +170,10 @@
168170
database_password => $database_password,
169171
database_name => $database_name,
170172
manage_db_password => $manage_db_password,
173+
postgresql_ssl_on => $postgresql_ssl_on,
174+
ssl_key_pk8_path => $ssl_key_pk8_path,
175+
ssl_cert_path => $ssl_cert_path,
176+
ssl_ca_cert_path => $ssl_ca_cert_path,
171177
database_max_pool_size => $database_max_pool_size,
172178
jdbc_ssl_properties => $jdbc_ssl_properties,
173179
database_validate => $database_validate,
@@ -197,6 +203,10 @@
197203
database_password => $read_database_password,
198204
database_name => $read_database_name,
199205
manage_db_password => $manage_read_db_password,
206+
postgresql_ssl_on => $postgresql_ssl_on,
207+
ssl_key_pk8_path => $ssl_key_pk8_path,
208+
ssl_cert_path => $ssl_cert_path,
209+
ssl_ca_cert_path => $ssl_ca_cert_path,
200210
jdbc_ssl_properties => $read_database_jdbc_ssl_properties,
201211
database_validate => $read_database_validate,
202212
log_slow_statements => $read_log_slow_statements,
@@ -241,6 +251,26 @@
241251
}
242252
}
243253

254+
if $postgresql_ssl_on {
255+
exec { $ssl_key_pk8_path:
256+
path => [ '/opt/puppetlabs/puppet/bin', $facts['path'] ],
257+
command => "openssl pkcs8 -topk8 -inform PEM -outform DER -in ${ssl_key_path} -out ${ssl_key_pk8_path} -nocrypt",
258+
# Generate a .pk8 key if one doesn't exist or is older than the .pem input.
259+
# NOTE: bash file time checks, like -ot, can't always discern sub-second
260+
# differences.
261+
onlyif => "test ! -e '${ssl_key_pk8_path}' -o '${ssl_key_pk8_path}' -ot '${ssl_key_path}'",
262+
before => File[$ssl_key_pk8_path]
263+
}
264+
265+
file { $ssl_key_pk8_path:
266+
ensure => present,
267+
owner => $puppetdb_user,
268+
group => $puppetdb_group,
269+
mode => '0600',
270+
notify => Service[$puppetdb_service]
271+
}
272+
}
273+
244274
class { 'puppetdb::server::jetty':
245275
listen_address => $listen_address,
246276
listen_port => $listen_port,

manifests/server/database.pp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
$puppetdb_group = $puppetdb::params::puppetdb_group,
2626
$database_max_pool_size = $puppetdb::params::database_max_pool_size,
2727
$migrate = $puppetdb::params::migrate,
28+
$postgresql_ssl_on = $puppetdb::params::postgresql_ssl_on,
29+
$ssl_cert_path = $puppetdb::params::ssl_cert_path,
30+
$ssl_key_pk8_path = $puppetdb::params::ssl_key_pk8_path,
31+
$ssl_ca_cert_path = $puppetdb::params::ssl_ca_cert_path
2832
) inherits puppetdb::params {
2933

3034
if str2bool($database_validate) {
@@ -85,7 +89,23 @@
8589
$database_suffix = ''
8690
}
8791

88-
$subname = "//${database_host}:${database_port}/${database_name}${database_suffix}"
92+
$subname_default = "//${database_host}:${database_port}/${database_name}${database_suffix}"
93+
94+
if $postgresql_ssl_on and !empty($jdbc_ssl_properties)
95+
{
96+
fail("Variables 'postgresql_ssl_on' and 'jdbc_ssl_properties' can not be used at the same time!")
97+
}
98+
99+
if $postgresql_ssl_on {
100+
$subname = @("EOT"/L)
101+
${subname_default}?\
102+
ssl=true&sslfactory=org.postgresql.ssl.LibPQFactory&\
103+
sslmode=verify-full&sslrootcert=${ssl_ca_cert_path}&\
104+
sslkey=${ssl_key_pk8_path}&sslcert=${ssl_cert_path}\
105+
| EOT
106+
} else {
107+
$subname = $subname_default
108+
}
89109

90110
##Only setup for postgres
91111
ini_setting {'puppetdb_psdatabase_username':

manifests/server/read_database.pp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
$puppetdb_user = $puppetdb::params::puppetdb_user,
1818
$puppetdb_group = $puppetdb::params::puppetdb_group,
1919
$database_max_pool_size = $puppetdb::params::read_database_max_pool_size,
20+
$postgresql_ssl_on = $puppetdb::params::postgresql_ssl_on,
21+
$ssl_cert_path = $puppetdb::params::ssl_cert_path,
22+
$ssl_key_pk8_path = $puppetdb::params::ssl_key_pk8_path,
23+
$ssl_ca_cert_path = $puppetdb::params::ssl_ca_cert_path
2024
) inherits puppetdb::params {
2125

2226
# Only add the read database configuration if database host is defined.
@@ -73,7 +77,23 @@
7377
$database_suffix = ''
7478
}
7579

76-
$subname = "//${database_host}:${database_port}/${database_name}${database_suffix}"
80+
$subname_default = "//${database_host}:${database_port}/${database_name}${database_suffix}"
81+
82+
if $postgresql_ssl_on and !empty($jdbc_ssl_properties)
83+
{
84+
fail("Variables 'postgresql_ssl_on' and 'jdbc_ssl_properties' can not be used at the same time!")
85+
}
86+
87+
if $postgresql_ssl_on {
88+
$subname = @("EOT"/L)
89+
${subname_default}?\
90+
ssl=true&sslfactory=org.postgresql.ssl.LibPQFactory&\
91+
sslmode=verify-full&sslrootcert=${ssl_ca_cert_path}&\
92+
sslkey=${ssl_key_pk8_path}&sslcert=${ssl_cert_path}\
93+
| EOT
94+
} else {
95+
$subname = $subname_default
96+
}
7797

7898
ini_setting { 'puppetdb_read_database_username':
7999
setting => 'username',

spec/acceptance/basic_spec.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,38 @@ class { 'puppetdb::master::config': puppetdb_port => '8080', puppetdb_server =>
2525
end
2626
end
2727

28+
describe 'single node with ssl' do
29+
ssl_config = <<-EOS
30+
class { 'puppetdb': postgresql_ssl_on => true,
31+
database_listen_address => '0.0.0.0',
32+
database_host => $facts['fqdn'],}
33+
EOS
34+
35+
it 'make sure it runs without error' do
36+
apply_manifest(ssl_config, catch_errors: true)
37+
apply_manifest(ssl_config, catch_changes: true)
38+
end
39+
40+
change_password = <<-EOS
41+
ini_setting { "puppetdb password":
42+
ensure => present,
43+
path => '/etc/puppetlabs/puppetdb/conf.d/database.ini',
44+
section => 'database',
45+
setting => 'password',
46+
value => 'random_password',
47+
notify => Service[puppetdb]
48+
}
49+
50+
service { 'puppetdb':
51+
ensure => 'running',
52+
}
53+
EOS
54+
it 'make sure it starts with wrong password' do
55+
apply_manifest(change_password, catch_errors: true)
56+
apply_manifest(change_password, catch_changes: true)
57+
end
58+
end
59+
2860
describe 'enabling report processor' do
2961
pp = <<-EOS
3062
class { 'puppetdb': disable_ssl => true, } ->

0 commit comments

Comments
 (0)