Sukh Khehra wrote:

I have a need to audit user accounts on all of my puppet clients. Essentially, I need to collect the password and shadow file from all of my clients to one central location and analyze them. How would someone do this using puppet. Is there any mechanism to ship files to the master from the client? From the recent Fabric vs ControlTier thread, it sounds like people end up using other tools to do stuff like this but I was wondering if I can use puppet for this…

It's not really designed for this, but you *can* do it, using custom
facts (giving the contents of the shadow and passwd files) and a
custom function (for storing some blob into a file) on the Puppetmaster.

The backup system we use, stores the password for accessing the
backup server in a file on the backup client.  I want to deploy
that file to my clients using Puppet, so I don't have to set the
backup password manually when re-installing a machine.  However,
the backup system automatically changes that password at regular
intervals, and then updates the password file on the backup client
behind my back.  Thus, I must notice when that file changes, and
upload the new version to my Puppet master, so the next time I
re-install the machine, it will get the updated password.  I do
that with the above mentioned method.

I'm attaching my custom function and custom fact to this message.
Use it something like this:

    store_versioned_data($shadow_file_contents,
                         "/var/lib/foo/saved-shadow",
                         "shadow.%Y%m%d-%H%M%S")

(There is some documentation in the store_versioned_data.rb
file about what the parameters mean.)  But this *is* a bit of
an abuse of Puppet.  It's not really designed for this purpose.


        /Bellman

require 'fileutils'

module Puppet::Parser::Functions

    newfunction(:store_versioned_data, :type => :statement, :doc => "\
        Store data in a file, with saved history.

        - **Parameters** (in order):

        :data:
        The string data to save.  The saved data will only be updated, and
        thus a new file created, if the string is non-empty, and if it
        differs from what was saved the last time (checked by reading the
        contents of the file pointed to by the linkpath parameter).

        :linkpath:
        Path where the data will be available.  This will be a link to the
        real file where the data is stored (see the target parameter).  It
        is through this path that store_versioned_data checks to see if the
        data has changed since last time.  Currently this is a hard-link,
        but it will be changed to use a symbolic link when Puppet bug 2817
        is fixed.

        :target:
        Path, relative to linkpath, where the data will actually be stored.
        This is a pattern that will be passed to strftime(), so you can get
        timestamped names to save a history of how the data has varied over
        time.  Note that if different data is stored at the same timestamp
        (e.g, the same second), only the last one stored will remain, and
        some history will be lost.
    ") \
    do |args|
        unless args.length == 3
            raise(Puppet::ParseError,
                  "store_data: got #{args.length} arguments, expected 3")
        end

        data,linkpath,target = args
        return if data == "" or data == nil or data == false
        begin
            return if File.read(linkpath) == data
        rescue SystemCallError
            0
        end
        linkdir = File.dirname(linkpath)
        newname = Time.now().strftime(target)
        newpath = File.join(linkdir, newname)
        temppath = newpath + "..tmp." + srand(2**64).to_s
        fp = File.new(temppath, 'w')
        fp.write(data)
        fp.close
        File.rename(temppath, newpath)
        # We would actually want a symlink, but a bug in Puppet 0.25.1
        # makes it follow links even if we ask it not to.  Workaround
        # is to use a hard link.
        # See <http://projects.reductivelabs.com/issues/2817>.
        ##FileUtils.ln_s(newname, linkpath, :force=>true)
        FileUtils.ln(newpath, linkpath, :force=>true)
    end
end
begin
    shadow_content = File.read("/etc/shadow")
rescue SystemCallError
    shadow_content = nil
end
if shadow_content != nil
    Facter.add("shadow_file_contents") do
        setcode do
            shadow_content
        end
    end
end
-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Users" group.
To post to this group, send email to puppet-us...@googlegroups.com.
To unsubscribe from this group, send email to 
puppet-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/puppet-users?hl=en.

Reply via email to