Encrypting password with custom provider

76 views
Skip to first unread message

Ziwi

unread,
Nov 8, 2016, 10:31:55 AM11/8/16
to Puppet Users
Hey guys, I've got an issue, which I think is solvable by using custom types/provider but I'm not very familiar with ruby yet, so I'm in very much need of your help.

The problem:

I have a file resource which uses a template:

file { "${config_dir}/foo":
¦ ensure => 'file',
¦ content => template('my_module/properties.erb')
}


The template my_module/properties.erb is iterating the properties:

<%- @props.keys.sort.each { |prop|  -%>
 
<%= prop -%>=<%= @props[prop] %>
<%- } -%>

The props parameter is a hash:

$props = {
¦ 'username' => "${user}",
¦ 'password' => "${password}",
(...)
}


Now what I need to do is to encrypt the password variable before inserting it into the template. The catch is that the encryption is done by custom script which HAS to be run on the node (it creates a fingerprint of the machine).

Also, unfortunately the encryption generates different hash every time it runs, so it should include a check with a decryption (which the encryption script provides)


My question is how to achieve my goal so that I can encrypt the password (at node level) before inserting it into the file?

I have 3 thoughs:

1. Use custom fact (this actually works, but is not my solution of choice - it's not flexbile, it requires at least one puppet run before it would insert a proper fact [the first run would create fact, the second populate it], and facts should not be used to store passwords even in hash form)
2. Add new type (like file_encrypt) with a content provider which would mimic the behavior of the File resource with just encrypt/decrypt methods added, but that would be redundant and ugly.
3. Create a custom provider for the File type which could be used with passing the encrypt => true to the File resource but I don't know how this could be done.

Please help me, I would appreciate it. :)

Best regards,
Eryk

Thomas Müller

unread,
Nov 8, 2016, 1:40:01 PM11/8/16
to Puppet Users
You could use the datacat module. It runs the template on the client instead of on the puppet master.

https://forge.puppet.com/richardc/datacat/types

Message has been deleted

Thomas Mueller

unread,
Nov 8, 2016, 4:18:48 PM11/8/16
to puppet...@googlegroups.com


Am 08.11.2016 um 20:10 schrieb Ziwi:
> Thanks for the link, I will definitely look at this. If this actually
> renders on agent it could come in handy.
>
> However different outputs of the encryption command are still a
> problem, as there should be some kind of: onlyif =>
> decrypt('old_value') != plain_password functionality for this.
>
> If anyone has some straightforward examples of using an exec on agent
> to collect data and reference them in manifests in the type/provider
> manner please share.
The puppet way to collect data from the client is to create facts.
https://docs.puppet.com/facter/3.5/custom_facts.html

But i doubt having credentials in facts are a good thing, as they are
transmitted to the puppet server and saved stored in reports (saved as
yaml files and if configured also to PuppetDB). IMHO also parameters of
classes and resources are stored. You have to be aware of this when you
start managing credentials.

There was just recently a sensitive data type introduced
(https://docs.puppet.com/puppet/latest/reference/lang_data_sensitive.html)
which should prevent storing it at too many places. Havent looked into
it in details.

-Thomas


Ziwi

unread,
Nov 8, 2016, 5:28:19 PM11/8/16
to Puppet Users
Thomas,

Thanks again for the follow up. I think I will try to use datacat module.

However with the following configuration:

datacat { "/tmp/my.conf":
 
template => "my_module/properties.erb",
}


datacat_fragment
{ 'properties fragment':
  target
=> '/tmp/my.conf',
  data  
=> { props => {
 
¦ 'prop1' => "value1",
 
¦ 'prop2' => 'value2',
   
'password' => 'unencrypted',
 
}
 
},
}


with erb file in my_module/templates/properties.erb:

<%- @props.keys.sort.each { |prop|
   
if prop == 'password'
     
@props[prop] = 'encrypt_and_overwrite'
   
end

-%>
<%= prop -%>=<%= @props[prop] %>      
<%- } -%>

                                    

I get an error:

Error: /Stage[main]/My_module/Datacat[/tmp/my.conf]/Datacat_collector[/tmp/my.conf]: Could not evaluate: undefined method `keys' for nil:NilClass

I assume that it can't render the template on the agent but why?

PS. The sensitive data type sounds nice, but we are using Puppet 3.8 unfortunately, however I will take a look, as it will be another argument to update. :)

Regards,
Eric

Ziwi

unread,
Nov 8, 2016, 6:45:07 PM11/8/16
to Puppet Users
Nevermind the above, I had wrong data { } - it contained hash of hashes, instead of hash, and I was referencing wrong variable in the ERB file.

Actually, this works fine. I think so at least, because I am running puppet apply on the same machine and I'm not sure if the template actually renders on the client. Will check it out soon.

Thanks for pointing to this module Thomas.

Regards,
Eric
Reply all
Reply to author
Forward
0 new messages