From 9882c5ddb540ce1e36e7b72a47fe578abe79c9b4 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 11 Mar 2010 20:23:27 -0600 Subject: First commit for sudoers module. This doesnt work... yet. --- lib/puppet/provider/sudoers/parsed.rb | 123 ++++++++++++++++++++++++++++++++++ lib/puppet/type/sudoers.rb | 94 ++++++++++++++++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 lib/puppet/provider/sudoers/parsed.rb create mode 100644 lib/puppet/type/sudoers.rb (limited to 'lib') diff --git a/lib/puppet/provider/sudoers/parsed.rb b/lib/puppet/provider/sudoers/parsed.rb new file mode 100644 index 0000000..520eef5 --- /dev/null +++ b/lib/puppet/provider/sudoers/parsed.rb @@ -0,0 +1,123 @@ +require 'puppet/provider/parsedfile' +sudoers = "/etc/sudoers" + +# +# crontab does the same thing, it uses a comment to specify uniqueness +# + +Puppet::Type.type(:sudoers).provide( + :parsed, + :parent => Puppet::Provider::ParsedFile, + :default_target => '/etc/sudoers', + # what the heck does this mean? + :filetype => :flat +) do + + desc "The sudoers provider that uses the ParsedFile class" + + commands :visudo => 'visudo' + + # this is just copied from hosts + text_line :comment, :match => %r{^#}, :post_parse => proc { |record| + # we determine the name from the comment above user spec lines + if record[:line] =~ /Puppet Name: (.+)\s*$/ +# ok, we set record name, but how is this applied to the next line? + record[:name] = $1 + end + } + + text_line :blank, :match => /^\s*$/; + + # ignore for now, I will support this line later + text_line :defaults, :match => /^Defaults/ + +# I need to parse the , delim list into an array +# I am pretty sure that I would do this with a block statement + +# +# it seems like I have to put type here for it to be accessible to +# to_line +# + + +# not bothering to specify match or fields, I will determine all of this +# in post_parse + +# parse everything else? + record_line :parsed, :fields => %w{line}, + :match => /(.*)/, + :post_parse => proc { |hash| + puts "\npost_parse" + puts hash[:line] + if (hash[:line] =~ /^\s*(User_Alias|Runas_Alias|Host_Alias|Cmnd_Alias)\s+(\S+)\s*=\s*(.+)$/) + hash[:sudo_alias] = $1 + hash[:name] = $2 + hash[:items] = $3 + hash[:items]=hash[:items].gsub(/\s/, '').split(',') + #puts hash.to_yaml + elsif (hash[:line] =~ /^(.*)?=(.*)$/) + # should name already be set when get get here? + hash = parse_user_spec($1, $2) + else + raise ArgumentError, "unexpected line #{hash[:line]}" + end + } + + def self.parse_user_spec(lhs, rhs) + lhs_array = lhs.split(',') + end + + def self.to_line(hash) + puts "\nEntering self.to_line for #{hash[:name]}" + puts hash.to_yaml + # dynamically call a function based on the value of hash[:type] + if(hash[:type] == 'alias') + self.alias_to_line(hash) + elsif(hash[:type] == 'spec') + spec_to_line(hash) + elsif(hash[:type] == 'default') + default_to_line(hash) + end + end + + def self.spec_to_line(hash) + "spec" + end + + def self.alias_to_line(hash) + # do I need to ensure that the required elements are here? + # shouldnt the type do that? check file, its similar + # since different attributes make sense based on ensure value (dir/file/symlink) + items=hash[:items] + items=items.join(',') if items.class == Array + "#{hash[:sudo_alias]} #{hash[:name]}=#{items}" + end + + def default_to_line(hash) + "default" + end + + def self.flush(record) +# a little pre-flush host visudo action +# + super(record) + end + +# lets assume that runas is always there and lets not deal with options yet +# record_line :spec, :fields => %w{users hosts runas specs type}, +# :match => %r{(\S+)\s+(\S+)=(\(\S+\))\s+(.+)}, +# :post_parse => proc { |hash| +# puts 'spec' +# } + +# I dont know if I can properly support multiple commands +# because they are composite, one command, one runas, multiple tags +# record_line :spec, :fields => %w{user host runas tags commands name}, +# :match => %r{^\s*(\S+)\s+(\S+)\s*=\s*(\(\S+\))?(.+)$}, +# :optional => %w{runas tags} + +# I need to override flush to validate sudoers +# +# +# +end diff --git a/lib/puppet/type/sudoers.rb b/lib/puppet/type/sudoers.rb new file mode 100644 index 0000000..6c94269 --- /dev/null +++ b/lib/puppet/type/sudoers.rb @@ -0,0 +1,94 @@ +Puppet::Type.newtype(:sudoers) do + @doc = "Manage the contents of /etc/sudoers + +there are two types of things here: + + sudoer{'NAME': + ensure => (absent|present) + type => (alias|spec) # required?? + alias => (User_alias|Runas_alias|Host_alias|Cmnd_alias), + items => [] # this is only for aliases + user_list => [] + host_list => [] + operator_list => [] + # NOPASSWD, PASSWD, NOEXEC, EXEC, SETENV and NOSETENV + tag_list => [] + command_list => [] + } + + alias NAME - starts with CAP ([A-Z]([A-Z][0-9]_)*) + +aliases, user specifications + User_alias + Runas_alias + Host_alias + Cmnd_alias + +alias spec: + + Alias_Type NAME = item1, item2, item3 : NAME = item4, item5 + + +order matters!! + + + " + # we can either remove or add lines + # they should also be purgable?(whats the namesvar for specs?) + ensurable + + newparam(:name) do + desc "Either the name of the alias to create + or for user specification, a random string in a comment that serves as a place holder (kind of ugly, but its true) + " + + isnamevar + end + +# +# this has to be a property to be found by parsedfile, but +# its really a parameter + + newproperty(:type) do + desc "Either determines which type of sudo configuration line is + is being managed. Either user_spec or alias" + end + + newproperty(:sudo_alias) do + desc "Types of alias." + end + + newproperty(:items, :array_matching => :all) do + desc "list of items applied to an alias" + end + + newproperty(:target) do + desc "Location of the shells file" + + defaultto do + if + @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile) + @resource.class.defaultprovider.default_target + else + nil + end + end + end + + newproperty(:users, :array_matching => :all) do + desc "list of users for user spec" + end + + newproperty(:hosts, :array_matching => :all) do + desc "list of hosts for user spec" + end + + newproperty(:runas, :array_matching => :all) do + desc "user to run commands as" + end + newproperty(:commands, :array_matching => :all) do + desc "commands to run" + end + +end + -- cgit v1.2.3