specified exceotion when trying to change type.
[puppet_sudo.git] / lib / puppet / type / sudoers.rb
1 Puppet::Type.newtype(:sudoers) do
2   @doc = "Manage the contents of /etc/sudoers
3
4 Author:: Dan Bode (dan@reductivelabs.com)
5 Copyright:: BLAH!!
6 License:: GPL3
7
8 = Summary
9
10 The sudoers type supports managing individual lines from the sudoers file.
11
12 = Record Types
13
14 There are 3 types of records that are supported:
15
16 == Aliases:
17  
18 Manages an alias line of a sudoers file.
19
20 Example:
21  
22 sudoers{'ALIAS_NAME':
23   ensure => present,
24   sudo_alias => 'Cmnd',
25   items => ['/bin/true', '/usr/bin/su - bob'],
26 }
27
28 creates the following line:
29
30 Cmnd_Alias ALIAS_NAME=/bin/true,/usr/bin/su - bob
31
32 == User Specification
33
34 sudoers line that specifies how users can run commands.
35
36 This there is no way to clearly determine uniqueness, a comment line is added above user spec lines that contains the namevar.
37
38 Example:
39
40 sudoers{'NAME':
41   ensure => present,
42   users => ['dan1', 'dan2'],
43   hosts => 'ALL',
44   commands => [
45     '(root) /usr/bin/su - easapp',
46     '(easapp)/usr/local/eas-ts/bin/appctl',
47   ],
48 }
49
50 creates the following line:  
51
52 #Puppet NAMEVAR NAME
53 dan1,dan2 ALL=(root) /usr/bin/su - easapp,(easapp)/usr/local/eas-ts/bin/appctl
54
55 Defaults:
56
57 the default name is used to determine uniqueness.
58
59 sudoers{'Defaults@host':
60   parameters => ['x=y', 'one=1', 'two=2'],
61 }
62
63 Defaults@host x=y,one=1,two=2
64
65 == Notes:
66
67 - parsing of multi-line sudoers records is not currently supported.
68 - ordering only applies when records are created.
69
70             "
71   # support absent and present (also purge -> true)
72   ensurable
73
74   newparam(:name) do
75     desc "Either the name of the alias, default, or arbitrary unique string for user specifications"
76     isnamevar
77     munge do |value|
78       #puts "params \n#{resource.original_parameters.to_yaml}\n"
79       value
80     end
81   end
82
83   newproperty(:type) do
84     desc "optional parameter used to determine what the record type is"
85   end
86
87   newproperty(:sudo_alias) do
88     desc "Type of alias. Options are Cmnd, Host, User, and Runas"
89     newvalue(/^(Cmnd|Host|User|Runas)(_Alias)?$/)
90     # add _Alias if it was ommitted
91     munge do |value|
92       if(value =~ /^(Cmnd|Host|User|Runas)$/) 
93         value << '_Alias'
94       end
95       value
96     end
97     # this is now an alias type
98   end
99
100   newproperty(:items, :array_matching => :all) do
101     desc "list of items applied to an alias"
102   end
103
104   newproperty(:target) do
105     desc "Location of the shells file"
106
107     defaultto do
108       if
109         @resource.class.defaultprovider.ancestors.include?(Puppet::Provider::ParsedFile)
110         @resource.class.defaultprovider.default_target
111       else
112         nil
113       end
114     end
115   end
116
117 # single user is namevar
118   newproperty(:users, :array_matching => :all) do
119     desc "list of users for user spec"
120   end
121
122   newproperty(:hosts, :array_matching => :all) do
123     desc "list of hosts for user spec"
124   end
125
126   newproperty(:commands, :array_matching => :all) do
127     desc "commands to run"
128   end
129
130   newproperty(:parameters, :array_matching => :all) do
131     desc "default parameters"
132   end
133
134   # make sure that we only have attributes for either default, alias, or user_spec
135   SUDOERS_DEFAULT = [:parameters]
136   SUDOERS_ALIAS = [:sudo_alias, :items]
137   SUDOERS_SPEC = [:users, :hosts, :commands]
138   validate do
139     if self[:sudo_alias] 
140       self[:type] = 'alias'
141       checkprops(SUDOERS_DEFAULT, SUDOERS_SPEC)
142     elsif self[:parameters]
143       checkprops(SUDOERS_ALIAS, SUDOERS_SPEC)
144     elsif self[:users]
145       self[:type] = 'user_spec'
146       checkprops(SUDOERS_ALIAS, SUDOERS_DEFAULT)
147     else
148       # these are parsed records, do nothing 
149     end
150     #puts self.should('sudo_alias')
151     #puts self.to_yaml  
152     #puts self.eachproperty do |x| puts x end
153   end
154
155   private
156
157   # check that we dont have any conflicting attributes
158   def checkprops(array_one, array_two)
159     combined = Array.new.concat(array_one).concat(array_two)
160     combined.each do |item|
161       if self[item.to_sym]
162         raise Puppet::Error, "Unexpected attribute #{item} for sudo record type #{self[:type]}"
163       end
164     end 
165   end
166 end
167