diff --git a/REFERENCE.md b/REFERENCE.md index 4281a86..ead264b 100644 --- a/REFERENCE.md +++ b/REFERENCE.md @@ -164,11 +164,13 @@ Data type: Optional[Variant[ String, Numeric, - Array[String] + Array[String], + Sensitive[String] ]] ``` -The data to place inside the registry value. +The data to place inside the registry value. Can be a String, Numeric, Array[String], +or Sensitive[String] for sensitive data like passwords. Default value: `undef` diff --git a/examples/sensitive_example.pp b/examples/sensitive_example.pp new file mode 100644 index 0000000..f3291b2 --- /dev/null +++ b/examples/sensitive_example.pp @@ -0,0 +1,26 @@ +# Example demonstrating Sensitive[String] support in registry::value +# This example shows how to use Sensitive types for sensitive data like passwords + +# Create a sensitive password value +$sensitive_password = Sensitive('mysecretpassword123') + +# Use the sensitive password in a registry value +registry::value { 'DefaultPassword': + key => 'HKLM\Software\MyApp', + data => $sensitive_password, + type => 'string', +} + +# You can also use it directly inline +registry::value { 'ApiKey': + key => 'HKLM\Software\MyApp', + data => Sensitive('sk-1234567890abcdef'), + type => 'string', +} + +# For array types, you can mix sensitive and non-sensitive values +registry::value { 'MixedArray': + key => 'HKLM\Software\MyApp', + data => ['public_value', Sensitive('secret_value'), 'another_public'], + type => 'array', +} \ No newline at end of file diff --git a/lib/puppet/provider/registry_value/registry.rb b/lib/puppet/provider/registry_value/registry.rb index 8a8fe53..42ec798 100644 --- a/lib/puppet/provider/registry_value/registry.rb +++ b/lib/puppet/provider/registry_value/registry.rb @@ -117,18 +117,27 @@ def to_native(ptype, pdata) # array to something usable by the Win API. raise Puppet::Error, 'Data should be an Array (ErrorID 37D9BBAB-52E8-4A7C-9F2E-D7BF16A59050)' unless pdata.is_a?(Array) + # Unwrap Sensitive values if present + unwrapped_data = pdata.map do |item| + if item.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive) + item.unwrap + else + item + end + end + ndata = case ptype when :binary - pdata.first.scan(%r{[a-f\d]{2}}i).map { |byte| [byte].pack('H2') }.join + unwrapped_data.first.scan(%r{[a-f\d]{2}}i).map { |byte| [byte].pack('H2') }.join when :array # We already have an array, and the native API write method takes an # array, so send it thru. - pdata + unwrapped_data else # Since we have an array, take the first element and send it to the # native API which is expecting a scalar. - pdata.first + unwrapped_data.first end [PuppetX::Puppetlabs::Registry.name2type(ptype), ndata] diff --git a/lib/puppet/type/registry_value.rb b/lib/puppet/type/registry_value.rb index 88f05c6..3f47745 100644 --- a/lib/puppet/type/registry_value.rb +++ b/lib/puppet/type/registry_value.rb @@ -115,18 +115,25 @@ def self.title_patterns end munge do |value| + # Unwrap Sensitive values if present + unwrapped_value = if value.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive) + value.unwrap + else + value + end + case resource[:type] when :dword, :qword begin - Integer(value) + Integer(unwrapped_value) rescue StandardError nil end when :binary - munged = if (value.respond_to?(:length) && value.length == 1) || (value.is_a?(Integer) && value <= 9) - "0#{value}" + munged = if (unwrapped_value.respond_to?(:length) && unwrapped_value.length == 1) || (unwrapped_value.is_a?(Integer) && unwrapped_value <= 9) + "0#{unwrapped_value}" else - value + unwrapped_value end # First, strip out all spaces from the string in the manfest. Next, @@ -138,7 +145,7 @@ def self.title_patterns .rstrip .downcase else # :string, :expand, :array - value + unwrapped_value end end diff --git a/manifests/value.pp b/manifests/value.pp index 674181c..13efd60 100644 --- a/manifests/value.pp +++ b/manifests/value.pp @@ -17,7 +17,8 @@ # `puppet describe registry_value` for a list of supported types in the # "type" parameter. # @param data -# The data to place inside the registry value. +# The data to place inside the registry value. Can be a String, Numeric, Array[String], +# or Sensitive[String] for sensitive data like passwords. # # Actions: # - Manage the parent key if not already managed. @@ -36,6 +37,15 @@ # } # } # +# @example This example shows how to use Sensitive types for sensitive data like passwords. +# class myapp { +# registry::value { 'DefaultPassword': +# key => 'HKLM\Software\MyApp', +# data => Sensitive('mysecretpassword123'), +# type => 'string', +# } +# } +# define registry::value ( Pattern[/^\w+/] $key, Optional[String] $value = undef, @@ -43,7 +53,8 @@ Optional[Variant[ String, Numeric, - Array[String] + Array[String], + Sensitive[String] ]] $data = undef, ) { # ensure windows os diff --git a/spec/unit/puppet/type/registry_value_spec.rb b/spec/unit/puppet/type/registry_value_spec.rb index 1c390ff..e37d76a 100644 --- a/spec/unit/puppet/type/registry_value_spec.rb +++ b/spec/unit/puppet/type/registry_value_spec.rb @@ -237,5 +237,31 @@ end end end + + context 'when sensitive data' do + it 'supports Sensitive[String] for string type' do + value[:type] = :string + sensitive_data = Puppet::Pops::Types::PSensitiveType::Sensitive.new('secret_password') + expect(value[:data] = sensitive_data) + end + + it 'supports Sensitive[String] for expand type' do + value[:type] = :expand + sensitive_data = Puppet::Pops::Types::PSensitiveType::Sensitive.new('secret_path') + expect(value[:data] = sensitive_data) + end + + it 'supports Sensitive[String] in array type' do + value[:type] = :array + sensitive_data = ['public_value', Puppet::Pops::Types::PSensitiveType::Sensitive.new('secret_value'), 'another_public'] + expect(value[:data] = sensitive_data) + end + + it 'supports Sensitive[String] for binary type' do + value[:type] = :binary + sensitive_data = Puppet::Pops::Types::PSensitiveType::Sensitive.new('CAFEBEEF') + expect(value[:data] = sensitive_data) + end + end end end