Skip to content

Commit 7ee8e5c

Browse files
(FM-8971) allow deferred function for role pwd
This change allows the postgresql::server::role to accept a deferred function for the $password_hash parameter. With this change, the compiler can defer this sensitive value to a deferred function that the agent applying the catalog will execute.
1 parent 821b5c5 commit 7ee8e5c

File tree

4 files changed

+86
-8
lines changed

4 files changed

+86
-8
lines changed

Diff for: lib/puppet/functions/postgresql/postgresql_password.rb

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
end
2929

3030
def default_impl(username, password, sensitive = false, hash = 'md5', salt = nil)
31+
if password.is_a?(String) && password.match?(%r{^(md5|SCRAM-SHA-256).+})
32+
return password
33+
end
3134
password = password.unwrap if password.respond_to?(:unwrap)
3235
pass = if hash == 'md5'
3336
'md5' + Digest::MD5.hexdigest(password.to_s + username.to_s)
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# @summary This function exists for usage of a role password that is a deferred function
2+
Puppet::Functions.create_function(:'postgresql::prepend_sql_password') do
3+
# @param password
4+
# The clear text `password`
5+
dispatch :default_impl do
6+
required_param 'String', :password
7+
return_type 'String'
8+
end
9+
def default_impl(password)
10+
"ENCRYPTED PASSWORD '#{password}'"
11+
end
12+
end

Diff for: manifests/server/role.pp

+39-8
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,31 @@
8484
$createdb_sql = $createdb ? { true => 'CREATEDB', default => 'NOCREATEDB' }
8585
$superuser_sql = $superuser ? { true => 'SUPERUSER', default => 'NOSUPERUSER' }
8686
$replication_sql = $replication ? { true => 'REPLICATION', default => '' }
87-
if ($password_hash_unsensitive != false) {
88-
$password_sql = "ENCRYPTED PASSWORD '${password_hash_unsensitive}'"
87+
88+
if $password_hash_unsensitive =~ Deferred {
89+
$password_sql = Deferred('postgresql::prepend_sql_password', [$password_hash_unsensitive])
90+
} elsif ($password_hash_unsensitive != false) {
91+
$password_sql = postgresql::prepend_sql_password($password_hash_unsensitive)
8992
} else {
9093
$password_sql = ''
9194
}
9295

96+
if $password_sql =~ Deferred {
97+
$create_role_command = Deferred('sprintf', ["CREATE ROLE \"%s\" %s %s %s %s %s %s CONNECTION LIMIT %s",
98+
$username,
99+
$password_sql,
100+
$login_sql,
101+
$createrole_sql,
102+
$createdb_sql,
103+
$superuser_sql,
104+
$replication_sql,
105+
$connection_limit])
106+
} else {
107+
$create_role_command = "CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}"
108+
}
109+
93110
postgresql_psql { "CREATE ROLE ${username} ENCRYPTED PASSWORD ****":
94-
command => Sensitive("CREATE ROLE \"${username}\" ${password_sql} ${login_sql} ${createrole_sql} ${createdb_sql} ${superuser_sql} ${replication_sql} CONNECTION LIMIT ${connection_limit}"),
111+
command => Sensitive($create_role_command),
95112
unless => "SELECT 1 FROM pg_roles WHERE rolname = '${username}'",
96113
require => undef,
97114
sensitive => true,
@@ -134,9 +151,14 @@
134151
}
135152

136153
if $password_hash_unsensitive and $update_password {
137-
if($password_hash_unsensitive =~ /^(md5|SCRAM-SHA-256).+/) {
138-
$pwd_hash_sql = $password_hash_unsensitive
139-
} else {
154+
if $password_hash_unsensitive =~ Deferred {
155+
$pwd_hash_sql = Deferred('postgresql::postgresql_password',[$username,
156+
$password_hash,
157+
false,
158+
$hash,
159+
$salt])
160+
}
161+
else {
140162
$pwd_hash_sql = postgresql::postgresql_password(
141163
$username,
142164
$password_hash,
@@ -145,9 +167,18 @@
145167
$salt,
146168
)
147169
}
170+
if $pwd_hash_sql =~ Deferred {
171+
$pw_command = Deferred('sprintf', ["ALTER ROLE \"%s\" ENCRYPTED PASSWORD '%s'", $username, $pwd_hash_sql])
172+
$unless_pw_command = Deferred('sprintf', ["SELECT 1 FROM pg_shadow WHERE usename = '%s' AND passwd = '%s'",
173+
$username,
174+
$pwd_hash_sql])
175+
} else {
176+
$pw_command = "ALTER ROLE \"${username}\" ENCRYPTED PASSWORD '${pwd_hash_sql}'"
177+
$unless_pw_command = "SELECT 1 FROM pg_shadow WHERE usename = '${username}' AND passwd = '${pwd_hash_sql}'"
178+
}
148179
postgresql_psql { "ALTER ROLE ${username} ENCRYPTED PASSWORD ****":
149-
command => Sensitive("ALTER ROLE \"${username}\" ENCRYPTED PASSWORD '${pwd_hash_sql}'"),
150-
unless => Sensitive("SELECT 1 FROM pg_shadow WHERE usename = '${username}' AND passwd = '${pwd_hash_sql}'"),
180+
command => Sensitive($pw_command),
181+
unless => Sensitive($unless_pw_command),
151182
sensitive => true,
152183
}
153184
}

Diff for: spec/acceptance/server/deferred_pw_role_spec.rb

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# frozen_string_literal: true
2+
3+
require 'spec_helper_acceptance'
4+
5+
describe 'postgresql::server::role:' do
6+
let(:user) { 'deferred_user_test' }
7+
let(:password) { 'test_password' }
8+
9+
let(:pp_one) do
10+
<<-MANIFEST.unindent
11+
$user = #{user}
12+
$password = #{password}
13+
14+
class { 'postgresql::server': }
15+
$deferred_func = Deferred('new', [String, $password])
16+
17+
postgresql::server::role { $user:
18+
password_hash => $deferred_func,
19+
}
20+
MANIFEST
21+
end
22+
23+
it 'creates a role with the password in the deferred function' do
24+
if run_shell('puppet --version').stdout[0].to_i < 7
25+
skip # Deferred function fixes only in puppet 7, see https://tickets.puppetlabs.com/browse/PUP-11518
26+
end
27+
apply_manifest(pp_one)
28+
psql_cmd = "PGPASSWORD=#{password} PGUSER=#{user} psql -h 127.0.0.1 -d postgres -c '\\q'"
29+
run_shell("cd /tmp; su #{shellescape('postgres')} -c #{shellescape(psql_cmd)}",
30+
acceptable_exit_codes: [0])
31+
end
32+
end

0 commit comments

Comments
 (0)