summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorAndrew Shafer <andrew@reductivelabs.com>2008-10-21 12:20:12 -0600
committerJames Turnbull <james@lovedthanlost.net>2008-10-22 16:34:50 +1100
commitc09d0cc128aa3f6a0b741422ae45326b258bae7d (patch)
treee357696bb317f3ac63d0649ed9ad1f5d8bc980b1 /lib/puppet
parent6d05cbc1e1a22d4316e18fb22d5cff9c7a42d3cf (diff)
downloadpuppet-c09d0cc128aa3f6a0b741422ae45326b258bae7d.tar.gz
puppet-c09d0cc128aa3f6a0b741422ae45326b258bae7d.tar.xz
puppet-c09d0cc128aa3f6a0b741422ae45326b258bae7d.zip
Solaris RBAC Attributes
Adding support to user type for: profiles auths project key/value pairs Refactored useradd.addcmd so I could override how properties get added in the subclass Added keyvalue property to manage generic keyvalues
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/property/keyvalue.rb96
-rw-r--r--lib/puppet/provider/user/user_role_add.rb67
-rw-r--r--lib/puppet/provider/user/useradd.rb37
-rwxr-xr-xlib/puppet/type/user.rb148
4 files changed, 303 insertions, 45 deletions
diff --git a/lib/puppet/property/keyvalue.rb b/lib/puppet/property/keyvalue.rb
new file mode 100644
index 000000000..6c0800c79
--- /dev/null
+++ b/lib/puppet/property/keyvalue.rb
@@ -0,0 +1,96 @@
+#This subclass of property manages string key value pairs.
+
+#In order to use this property:
+# - the @should value must be an array of keyvalue pairs separated by the 'separator'
+# - the retrieve method should return a hash with the keys as symbols
+# IMPORTANT NOTE: In order for this property to work there must also be a 'membership' parameter
+# The class that inherits from property should override that method with the symbol for the membership
+
+require 'puppet/property'
+
+module Puppet
+ class Property
+ class KeyValue < Property
+
+ def hash_to_key_value_s(hash)
+ hash.select { |k,v| true }.map { |pair| pair.join(separator) }.join(delimiter)
+ end
+
+ def should_to_s(should_value)
+ hash_to_key_value_s(should_value)
+ end
+
+ def is_to_s(current_value)
+ hash_to_key_value_s(current_value)
+ end
+
+ def membership
+ :key_value_membership
+ end
+
+ def inclusive?
+ @resource[membership] == :inclusive
+ end
+
+ def hashify(key_value_array)
+ #turns string array into a hash
+ key_value_array.inject({}) do |hash, key_value|
+ tmp = key_value.split(separator)
+ hash[tmp[0].intern] = tmp[1]
+ hash
+ end
+ end
+
+ def process_current_hash(current)
+ return {} if current == :absent
+
+ #inclusive means we are managing everything so if it isn't in should, its gone
+ if inclusive?
+ current.each_key { |key| current[key] = nil }
+ end
+ current
+ end
+
+ def should
+ unless defined? @should and @should
+ return nil
+ end
+
+ members = hashify(@should)
+ current = process_current_hash(retrieve)
+
+ #shared keys will get overwritten by members
+ current.merge(members)
+ end
+
+ def separator
+ "="
+ end
+
+ def delimiter
+ ";"
+ end
+
+ def retrieve
+ #ok, some 'convention' if the keyvalue property is named properties, provider should implement a properties method
+ if key_hash = provider.send(name) and key_hash != :absent
+ return key_hash
+ else
+ return :absent
+ end
+ end
+
+ def insync?(is)
+ unless defined? @should and @should
+ return true
+ end
+
+ unless is
+ return true
+ end
+
+ return (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
index 819516dc4..00fc24b3a 100644
--- a/lib/puppet/provider/user/user_role_add.rb
+++ b/lib/puppet/provider/user/user_role_add.rb
@@ -11,6 +11,8 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd do
options :comment, :method => :gecos
options :groups, :flag => "-G"
options :roles, :flag => "-R"
+ options :auths, :flag => "-A"
+ options :profiles, :flag => "-P"
verify :gid, "GID must be an integer" do |value|
value.is_a? Integer
@@ -26,6 +28,24 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd do
has_feature :manages_passwords
end
+ #must override this to hand the keyvalue pairs
+ def add_properties
+ cmd = []
+ Puppet::Type.type(:user).validproperties.each do |property|
+ next if property == :ensure
+ # the value needs to be quoted, mostly because -c might
+ # have spaces in it
+ if value = @resource.should(property) and value != ""
+ if property == :keys
+ cmd += build_keys_cmd(value)
+ else
+ cmd << flag(property) << value
+ end
+ end
+ end
+ cmd
+ end
+
def user_attributes
@user_attributes ||= UserAttr.get_attributes_by_name(@resource[:name])
end
@@ -57,6 +77,7 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd do
def transition(type)
cmd = [command(:modify)]
cmd << "-K" << "type=#{type}"
+ cmd += add_properties
cmd << @resource[:name]
end
@@ -85,5 +106,51 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd do
user_attributes[:roles]
end
end
+
+ def auths
+ if user_attributes
+ user_attributes[:auths]
+ end
+ end
+
+ def profiles
+ if user_attributes
+ user_attributes[:profiles]
+ end
+ end
+
+ def project
+ if user_attributes
+ user_attributes[:project]
+ end
+ end
+
+ def managed_attributes
+ [:name, :type, :roles, :auths, :profiles, :project]
+ end
+
+ def remove_managed_attributes
+ managed = managed_attributes
+ user_attributes.select { |k,v| !managed.include?(k) }.inject({}) { |hash, array| hash[array[0]] = array[1]; hash }
+ end
+
+ def keys
+ if user_attributes
+ #we have to get rid of all the keys we are managing another way
+ remove_managed_attributes
+ end
+ end
+
+ def build_keys_cmd(keys_hash)
+ cmd = []
+ keys_hash.each do |k,v|
+ cmd << "-K" << "#{k}=#{v}"
+ end
+ cmd
+ end
+
+ def keys=(keys_hash)
+ run([command(:modify)] + build_keys_cmd(keys_hash) << @resource[:name], "modify attribute key pairs")
+ end
end
diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb
index b327db384..6996dd69a 100644
--- a/lib/puppet/provider/user/useradd.rb
+++ b/lib/puppet/provider/user/useradd.rb
@@ -23,8 +23,22 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
has_feature :manages_passwords
end
- def addcmd
- cmd = [command(:add)]
+ def check_allow_dup
+ @resource.allowdupe? ? ["-o"] : []
+ end
+
+ def check_manage_home
+ cmd = []
+ if @resource.managehome?
+ cmd << "-m"
+ elsif %w{Fedora RedHat}.include?(Facter.value("operatingsystem"))
+ cmd << "-M"
+ end
+ cmd
+ end
+
+ def add_properties
+ cmd = []
Puppet::Type.type(:user).validproperties.each do |property|
next if property == :ensure
# the value needs to be quoted, mostly because -c might
@@ -33,20 +47,15 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
cmd << flag(property) << value
end
end
+ cmd
+ end
- if @resource.allowdupe?
- cmd << "-o"
- end
-
- if @resource.managehome?
- cmd << "-m"
- elsif %w{Fedora RedHat}.include?(Facter.value("operatingsystem"))
- cmd << "-M"
- end
-
+ def addcmd
+ cmd = [command(:add)]
+ cmd += add_properties
+ cmd += check_allow_dup
+ cmd += check_manage_home
cmd << @resource[:name]
-
- cmd
end
# Retrieve the password using the Shadow Password library
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 29f4880c1..929e45d14 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -1,6 +1,7 @@
require 'etc'
require 'facter'
require 'puppet/property/list'
+require 'puppet/property/keyvalue'
module Puppet
newtype(:user) do
@@ -137,6 +138,7 @@ module Puppet
end
end
+
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
@@ -147,25 +149,7 @@ module Puppet
raise ArgumentError, "Group names must be provided, not numbers"
end
if value.include?(",")
- raise ArgumentError, "Group names must be provided as an array, not as a comma-separated list '%s'" % value
- end
- end
- 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."
-
- def membership
- :role_membership
- end
-
- validate do |value|
- if value =~ /^\d+$/
- raise ArgumentError, "Role names must be provided, not numbers"
- end
- if value.include?(",")
- raise ArgumentError, "Role names must be provided as an array, not a comma-separated list"
+ raise ArgumentError, "Group names must be provided as an array, not a comma-separated list"
end
end
end
@@ -187,19 +171,9 @@ module Puppet
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
- end
-
newparam(:allowdupe, :boolean => true) do
desc "Whether to allow duplicate UIDs."
-
+
newvalues(:true, :false)
defaultto false
@@ -240,7 +214,7 @@ module Puppet
gobj.should(:gid) == group
}
autos << obj
-
+
end
else
autos << group
@@ -273,6 +247,118 @@ module Puppet
prophash
}
end
+
+ newproperty(:roles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
+ desc "The roles the user has. Multiple roles should be
+ specified as an array."
+
+ def membership
+ :role_membership
+ end
+
+ validate do |value|
+ if value =~ /^\d+$/
+ raise ArgumentError, "Role names must be provided, not numbers"
+ end
+ if value.include?(",")
+ raise ArgumentError, "Role names must be provided as an array, not a comma-separated list"
+ end
+ end
+ 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
+ end
+
+ newproperty(:auths, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
+ desc "The auths the user has. Multiple auths should be
+ specified as an array."
+
+ def membership
+ :auth_membership
+ end
+
+ validate do |value|
+ if value =~ /^\d+$/
+ raise ArgumentError, "Auth names must be provided, not numbers"
+ end
+ if value.include?(",")
+ raise ArgumentError, "Auth names must be provided as an array, not a comma-separated list"
+ end
+ end
+ end
+
+ newparam(:auth_membership) do
+ desc "Whether specified auths should be treated as the only auths
+ 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
+
+ newproperty(:profiles, :parent => Puppet::Property::List, :required_features => :manages_solaris_rbac) do
+ desc "The profiles the user has. Multiple profiles should be
+ specified as an array."
+
+ def membership
+ :profile_membership
+ end
+
+ validate do |value|
+ if value =~ /^\d+$/
+ raise ArgumentError, "Profile names must be provided, not numbers"
+ end
+ if value.include?(",")
+ raise ArgumentError, "Profile names must be provided as an array, not a comma-separated list"
+ end
+ end
+ end
+
+ newparam(:profile_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
+ end
+
+ newproperty(:keys, :parent => Puppet::Property::KeyValue, :required_features => :manages_solaris_rbac) do
+ desc "Specify user attributes in an array of keyvalue pairs"
+
+ def membership
+ :key_membership
+ end
+
+ validate do |value|
+ unless value.include?("=")
+ raise ArgumentError, "key value pairs must be seperated by an ="
+ end
+ end
+ end
+
+ newparam(:key_membership) do
+ desc "Whether specified key value pairs should be treated as the only attributes
+ of the user or whether they should merely
+ be treated as the minimum list."
+
+ newvalues(:inclusive, :minimum)
+
+ defaultto :minimum
+ end
+
+ newproperty(:project, :required_features => :manages_solaris_rbac) do
+ desc "The name of the project associated with a user"
+ end
end
end