Skip to content

Commit 56b35f9

Browse files
committed
(PUP-12050) Check for nested Sensitive arguments
Previously, a manifest containing nested Deferred values did not mark the corresponding parameter as sensitive, resulting in the following: $ cat manifest.pp $vars = {'token' => Deferred('new', [Sensitive, "password"])} file { '/tmp/a.sh': ensure => file, content => Deferred('inline_epp', ['<%= $token %>', $vars]) } $ truncate --size 0 /tmp/a.sh $ puppet apply --show_diff manifest.pp Notice: Compiled catalog for localhost in environment production in 0.01 seconds Notice: /Stage[main]/Main/File[/tmp/a.sh]/content: --- /tmp/a.sh 2024-07-03 17:30:37.024543314 -0700 +++ /tmp/puppet-file20240703-1784698-2cu5s9 2024-07-03 17:30:41.880572413 -0700 @@ -0,0 +1 @@ +password \ No newline at end of file The issue occurred because we were only checking if the outermost DeferredValue contained any Sensitive arguments, in this case the arguments passed to `inline_epp` function, but not the `password` passed to the `new` function. This is not an issue when deferred values are preprocessed, because Deferred values are completely resolved and we can check if resolved value is Sensitive.
1 parent 7739378 commit 56b35f9

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

lib/puppet/pops/evaluator/deferred_resolver.rb

+30-6
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,25 @@ def resolve_futures(catalog)
8989
overrides = {}
9090
r.parameters.each_pair do |k, v|
9191
resolved = resolve(v)
92-
# If the value is instance of Sensitive - assign the unwrapped value
93-
# and mark it as sensitive if not already marked
94-
#
9592
case resolved
9693
when Puppet::Pops::Types::PSensitiveType::Sensitive
94+
# If the resolved value is instance of Sensitive - assign the unwrapped value
95+
# and mark it as sensitive if not already marked
96+
#
9797
resolved = resolved.unwrap
9898
mark_sensitive_parameters(r, k)
99-
# If the value is a DeferredValue and it has an argument of type PSensitiveType, mark it as sensitive
100-
# The DeferredValue.resolve method will unwrap it during catalog application
99+
101100
when Puppet::Pops::Evaluator::DeferredValue
102-
if v.arguments.any? { |arg| arg.is_a?(Puppet::Pops::Types::PSensitiveType) }
101+
# If the resolved value is a DeferredValue and it has an argument of type
102+
# PSensitiveType, mark it as sensitive. Since DeferredValues can nest,
103+
# we must walk all arguments, e.g. the DeferredValue may call the `epp`
104+
# function, where one of its arguments is a DeferredValue to call the
105+
# `vault:lookup` function.
106+
#
107+
# The DeferredValue.resolve method will unwrap the sensitive during
108+
# catalog application
109+
#
110+
if contains_sensitive_args(v)
103111
mark_sensitive_parameters(r, k)
104112
end
105113
end
@@ -109,6 +117,22 @@ def resolve_futures(catalog)
109117
end
110118
end
111119

120+
# Return true if x contains an argument of type PSensitiveType. It
121+
# short-circuits as soon as a value is found.
122+
#
123+
def contains_sensitive_args(x)
124+
if x.instance_of?(@deferred_class)
125+
contains_sensitive_args(x.arguments)
126+
elsif x.is_a?(Array)
127+
x.any? { |v| contains_sensitive_args(v) }
128+
elsif x.is_a?(Hash)
129+
x.any? { |k, v| contains_sensitive_args(k) || contains_sensitive_args(v) }
130+
elsif x.is_a?(Puppet::Pops::Types::PSensitiveType)
131+
true
132+
end
133+
end
134+
private :contains_sensitive_args
135+
112136
def mark_sensitive_parameters(r, k)
113137
unless r.sensitive_parameters.include?(k.to_sym)
114138
r.sensitive_parameters = (r.sensitive_parameters + [k.to_sym]).freeze

0 commit comments

Comments
 (0)