diff options
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/property/list.rb | 78 | ||||
-rw-r--r-- | lib/puppet/provider/user/user_role_add.rb | 89 | ||||
-rwxr-xr-x | lib/puppet/type/user.rb | 88 |
3 files changed, 206 insertions, 49 deletions
diff --git a/lib/puppet/property/list.rb b/lib/puppet/property/list.rb new file mode 100644 index 000000000..4e7f6ec90 --- /dev/null +++ b/lib/puppet/property/list.rb @@ -0,0 +1,78 @@ +require 'puppet/property' + +module Puppet + class Property + class List < Property + + def should_to_s(should_value) + #just return the should value + should_value + end + + def is_to_s(currentvalue) + currentvalue.join(delimiter) + end + + def membership + :membership + end + + def add_should_with_current(should, current) + if current.is_a?(Array) + should += current + end + should.uniq + end + + def inclusive? + @resource[membership] == :inclusive + end + + def should + unless defined? @should and @should + return nil + end + + members = @should + #inclusive means we are managing everything so if it isn't in should, its gone + if ! inclusive? + members = add_should_with_current(members, retrieve) + end + + members.sort.join(delimiter) + end + + def delimiter + "," + end + + def retrieve + #ok, some 'convention' if the list property is named groups, provider should implement a groups method + if tmp = provider.send(name) and tmp != :absent + return tmp.split(delimiter) + else + return :absent + end + end + + def prepare_is_for_comparison(is) + if is.is_a? Array + is = is.sort.join(delimiter) + end + is + end + + def insync?(is) + unless defined? @should and @should + return true + end + + unless is + return true + end + + return (prepare_is_for_comparison(is) == self.should) + end + end + end +end diff --git a/lib/puppet/provider/user/user_role_add.rb b/lib/puppet/provider/user/user_role_add.rb new file mode 100644 index 000000000..23581abbb --- /dev/null +++ b/lib/puppet/provider/user/user_role_add.rb @@ -0,0 +1,89 @@ +require 'puppet/util/user_attr' + +Puppet::Type.type(:user).provide :user_role_add, :parent => Puppet::Type::User::ProviderUseradd do + + desc "User management inherits ``useradd`` and adds logic to manage roles on Solaris using roleadd." + + defaultfor :operatingsystem => :solaris + + commands :add => "useradd", :delete => "userdel", :modify => "usermod", :role_add => "roleadd", :role_delete => "roledel", :role_modify => "rolemod" + options :home, :flag => "-d", :method => :dir + options :comment, :method => :gecos + options :groups, :flag => "-G" + options :roles, :flag => "-R" + + verify :gid, "GID must be an integer" do |value| + value.is_a? Integer + end + + verify :groups, "Groups must be comma-separated" do |value| + value !~ /\s/ + end + + has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac + + if Puppet.features.libshadow? + has_feature :manages_passwords + end + + def user_attributes + @user_attributes ||= UserAttr.get_attributes_by_name(@resource[:name]) + end + + def flush + @user_attributes = nil + end + + def command(cmd) + if is_role? or (!exists? and @resource[:ensure] == :role) + cmd = ("role_" + cmd.to_s).intern + end + super(cmd) + end + + def is_role? + user_attributes and user_attributes[:type] == "role" + end + + def run(cmd, msg) + begin + execute(cmd) + rescue Puppet::ExecutionFailure => detail + raise Puppet::Error, "Could not %s %s %s: %s" % + [msg, @resource.class.name, @resource.name, detail] + end + end + + def transition(type) + cmd = [command(:modify)] + cmd << "-K" << "type=#{type}" + cmd << @resource[:name] + end + + def create + if is_role? + run(transition("normal"), "transition role to") + else + run(addcmd, "create") + end + end + + def destroy + run(deletecmd, "delete "+ (is_role? ? "role" : "user")) + end + + def create_role + if exists? and !is_role? + run(transition("role"), "transition user to") + else + run(addcmd, "create role") + end + end + + def roles + if user_attributes + user_attributes[:roles] + end + end +end + diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb index bb0a86fd0..74c4c6a33 100755 --- a/lib/puppet/type/user.rb +++ b/lib/puppet/type/user.rb @@ -1,5 +1,6 @@ require 'etc' require 'facter' +require 'puppet/property/list' module Puppet newtype(:user) do @@ -21,6 +22,9 @@ module Puppet "The provider can modify user passwords, by accepting a password hash." + feature :manages_solaris_rbac, + "The provider can manage roles and normal users" + newproperty(:ensure, :parent => Puppet::Property::Ensure) do newvalue(:present, :event => :user_created) do provider.create @@ -30,6 +34,10 @@ module Puppet provider.delete end + newvalue(:role, :event => :role_created, :required_features => :manages_solaris_rbac) do + provider.create_role + end + desc "The basic state that the object should be in." # If they're talking about the thing at all, they generally want to @@ -44,7 +52,11 @@ module Puppet def retrieve if provider.exists? - return :present + if provider.respond_to?(:is_role?) and provider.is_role? + return :role + else + return :present + end else return :absent end @@ -125,68 +137,36 @@ module Puppet end end - newproperty(:groups) do + newproperty(:groups, :parent => Puppet::Property::List) do desc "The groups of which the user is a member. The primary group should not be listed. Multiple groups should be specified as an array." - def should_to_s(newvalue) - self.should - end - - def is_to_s(currentvalue) - currentvalue.join(",") - end - - # We need to override this because the groups need to - # be joined with commas - def should - current_value = retrieve - - unless defined? @should and @should - return nil - end - - if @resource[:membership] == :inclusive - return @should.sort.join(",") - else - members = @should - if current_value.is_a?(Array) - members += current_value - end - return members.uniq.sort.join(",") + validate do |value| + if value =~ /^\d+$/ + raise ArgumentError, "Group names must be provided, not numbers" end - end - - def retrieve - if tmp = provider.groups and tmp != :absent - return tmp.split(",") - else - return :absent + if value.include?(",") + puts value + raise ArgumentError, "Group names must be provided as an array, not a comma-separated list" end end + end - def insync?(is) - unless defined? @should and @should - return true - end - unless defined? is and is - return true - end - tmp = is - if is.is_a? Array - tmp = is.sort.join(",") - end + newproperty(:roles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do + desc "The roles of which the user the user has. The roles should be + specified as an array." - return tmp == self.should + def membership + :role_membership end validate do |value| if value =~ /^\d+$/ - raise ArgumentError, "Group names must be provided, not numbers" + raise ArgumentError, "Role names must be provided, not numbers" end if value.include?(",") - raise ArgumentError, "Group names must be provided as an array, not a comma-separated list" + raise ArgumentError, "Role names must be provided as an array, not a comma-separated list" end end end @@ -202,7 +182,17 @@ module Puppet desc "Whether specified groups should be treated as the only groups of which the user is a member or whether they should merely be treated as the minimum membership list." - + + newvalues(:inclusive, :minimum) + + defaultto :minimum + end + + newparam(:role_membership) do + desc "Whether specified roles should be treated as the only roles + of which the user is a member or whether they should merely + be treated as the minimum membership list." + newvalues(:inclusive, :minimum) defaultto :minimum |