summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJesse Wolfe <jes5199@gmail.com>2010-10-04 20:11:56 -0700
committerJesse Wolfe <jes5199@gmail.com>2010-10-04 21:46:59 -0700
commit7bdbd132634f61d91aeee401de15248d936ce71e (patch)
tree146bb43d90478d373f9bb1c5ed3e04bd9d04dbbc /lib
parent163ec172e06a2b8aab9f9c9247dd45bc0dea3f72 (diff)
parent917c520f1abc0c72d7065531cffcef88259e32e0 (diff)
downloadpuppet-7bdbd132634f61d91aeee401de15248d936ce71e.tar.gz
puppet-7bdbd132634f61d91aeee401de15248d936ce71e.tar.xz
puppet-7bdbd132634f61d91aeee401de15248d936ce71e.zip
Merge commit '2.6.2rc1' into next
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet.rb2
-rw-r--r--lib/puppet/external/event-loop/event-loop.rb26
-rw-r--r--lib/puppet/network/http/webrick/rest.rb1
-rw-r--r--lib/puppet/network/http_pool.rb12
-rw-r--r--lib/puppet/parser/functions/extlookup.rb2
-rw-r--r--lib/puppet/parser/lexer.rb2
-rw-r--r--lib/puppet/parser/resource.rb1
-rw-r--r--lib/puppet/provider/nameservice.rb1
-rw-r--r--lib/puppet/provider/nameservice/objectadd.rb3
-rw-r--r--lib/puppet/provider/service/launchd.rb25
-rw-r--r--lib/puppet/provider/user/hpux.rb1
-rw-r--r--lib/puppet/provider/user/user_role_add.rb30
-rw-r--r--lib/puppet/provider/user/useradd.rb47
-rw-r--r--lib/puppet/reports/rrdgraph.rb2
-rwxr-xr-xlib/puppet/type/user.rb55
-rw-r--r--lib/puppet/util/zaml.rb1
16 files changed, 160 insertions, 51 deletions
diff --git a/lib/puppet.rb b/lib/puppet.rb
index 18c1e8cbd..0a90cf50c 100644
--- a/lib/puppet.rb
+++ b/lib/puppet.rb
@@ -24,7 +24,7 @@ require 'puppet/util/run_mode'
# it's also a place to find top-level commands like 'debug'
module Puppet
- PUPPETVERSION = '2.6.1'
+ PUPPETVERSION = '2.6.2'
def Puppet.version
PUPPETVERSION
diff --git a/lib/puppet/external/event-loop/event-loop.rb b/lib/puppet/external/event-loop/event-loop.rb
index dc51a55ae..3b40f6e71 100644
--- a/lib/puppet/external/event-loop/event-loop.rb
+++ b/lib/puppet/external/event-loop/event-loop.rb
@@ -75,8 +75,10 @@ class EventLoop
@notify_src, @notify_snk = IO.pipe
# prevent file descriptor leaks
- @notify_src.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
- @notify_snk.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+ if @notify_src.respond_to?(:fcntl) and defined?(Fcntl) and defined?(Fcntl::F_SETFD) and defined?(Fcntl::FD_CLOEXEC)
+ @notify_src.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+ @notify_snk.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
+ end
@notify_src.will_block = false
@notify_snk.will_block = false
@@ -234,19 +236,21 @@ class IO
end
def will_block?
- require "fcntl"
- fcntl(Fcntl::F_GETFL, 0) & Fcntl::O_NONBLOCK == 0
+ if respond_to?(:fcntl) and defined?(Fcntl) and defined?(Fcntl::F_GETFL) and defined?(Fcntl::O_NONBLOCK)
+ fcntl(Fcntl::F_GETFL, 0) & Fcntl::O_NONBLOCK == 0
+ end
end
def will_block= (wants_blocking)
- require "fcntl"
- flags = fcntl(Fcntl::F_GETFL, 0)
- if wants_blocking
- flags &= ~Fcntl::O_NONBLOCK
- else
- flags |= Fcntl::O_NONBLOCK
+ if respond_to?(:fcntl) and defined?(Fcntl) and defined?(Fcntl::F_GETFL) and defined?(Fcntl::O_NONBLOCK)
+ flags = fcntl(Fcntl::F_GETFL, 0)
+ if wants_blocking
+ flags &= ~Fcntl::O_NONBLOCK
+ else
+ flags |= Fcntl::O_NONBLOCK
+ end
+ fcntl(Fcntl::F_SETFL, flags)
end
- fcntl(Fcntl::F_SETFL, flags)
end
end
diff --git a/lib/puppet/network/http/webrick/rest.rb b/lib/puppet/network/http/webrick/rest.rb
index 91008aa1a..d5c146d88 100644
--- a/lib/puppet/network/http/webrick/rest.rb
+++ b/lib/puppet/network/http/webrick/rest.rb
@@ -1,5 +1,6 @@
require 'puppet/network/http/handler'
require 'resolv'
+require 'webrick'
class Puppet::Network::HTTP::WEBrickREST < WEBrick::HTTPServlet::AbstractServlet
diff --git a/lib/puppet/network/http_pool.rb b/lib/puppet/network/http_pool.rb
index a3b055572..7d227b4d4 100644
--- a/lib/puppet/network/http_pool.rb
+++ b/lib/puppet/network/http_pool.rb
@@ -58,18 +58,6 @@ module Puppet::Network::HttpPool
http.cert = ssl_host.certificate.content
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.key = ssl_host.key.content
- http.verify_callback = self.method(:ssl_verify_callback).to_proc if Puppet[:debug]
- end
-
- def self.ssl_verify_callback(peer_ok, x509_store_ctx)
- if not peer_ok
- Puppet.debug "OpenSSL: Error(#{x509_store_ctx.error}): #{x509_store_ctx.error_string}"
- Puppet.debug "OpenSSL: Cert: #{x509_store_ctx.current_cert.issuer}"
- Puppet.debug "OpenSSL: Current CRL: #{x509_store_ctx.current_crl}"
- Puppet.debug "OpenSSL: Chain:"
- x509_store_ctx.chain.each_index { |i| Puppet.debug "OpenSSL: \t#{i} #{x509_store_ctx.chain[i].issuer}" }
- end
- peer_ok
end
# Retrieve a cached http instance if caching is enabled, else return
diff --git a/lib/puppet/parser/functions/extlookup.rb b/lib/puppet/parser/functions/extlookup.rb
index 63d49e563..bc55410b9 100644
--- a/lib/puppet/parser/functions/extlookup.rb
+++ b/lib/puppet/parser/functions/extlookup.rb
@@ -52,7 +52,7 @@ the exact same outcome:
$snmp_contact = extlookup(\"snmp_contact\")
-The obove code shows some other features, you can use any fact or variable that
+The above code shows some other features, you can use any fact or variable that
is in scope by simply using %{varname} in your data files, you can return arrays
by just having multiple values in the csv after the initial variable name.
diff --git a/lib/puppet/parser/lexer.rb b/lib/puppet/parser/lexer.rb
index a25a17e3f..9036d652e 100644
--- a/lib/puppet/parser/lexer.rb
+++ b/lib/puppet/parser/lexer.rb
@@ -520,7 +520,7 @@ class Puppet::Parser::Lexer
def slurpstring(terminators,escapes=%w{ \\ $ ' " n t s }+["\n"],ignore_invalid_escapes=false)
# we search for the next quote that isn't preceded by a
# backslash; the caret is there to match empty strings
- str = @scanner.scan_until(/([^\\]|^)[#{terminators}]/) or lex_error "Unclosed quote after '#{last}' in '#{rest}'"
+ str = @scanner.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]/) or lex_error "Unclosed quote after '#{last}' in '#{rest}'"
@line += str.count("\n") # literal carriage returns add to the line count.
str.gsub!(/\\(.)/) {
ch = $1
diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb
index e34f284fc..c007d4dbe 100644
--- a/lib/puppet/parser/resource.rb
+++ b/lib/puppet/parser/resource.rb
@@ -64,6 +64,7 @@ class Puppet::Parser::Resource < Puppet::Resource
# Retrieve the associated definition and evaluate it.
def evaluate
+ return if evaluated?
@evaluated = true
if klass = resource_type and ! builtin_type?
finish
diff --git a/lib/puppet/provider/nameservice.rb b/lib/puppet/provider/nameservice.rb
index 7339b646e..9830fab54 100644
--- a/lib/puppet/provider/nameservice.rb
+++ b/lib/puppet/provider/nameservice.rb
@@ -165,6 +165,7 @@ class Puppet::Provider::NameService < Puppet::Provider
begin
execute(self.addcmd)
+ execute(self.passcmd) if self.feature? :manages_password_age
rescue Puppet::ExecutionFailure => detail
raise Puppet::Error, "Could not create #{@resource.class.name} #{@resource.name}: #{detail}"
end
diff --git a/lib/puppet/provider/nameservice/objectadd.rb b/lib/puppet/provider/nameservice/objectadd.rb
index 80c142982..dbb9f306f 100644
--- a/lib/puppet/provider/nameservice/objectadd.rb
+++ b/lib/puppet/provider/nameservice/objectadd.rb
@@ -13,7 +13,8 @@ class ObjectAdd < Puppet::Provider::NameService
end
def modifycmd(param, value)
- cmd = [command(:modify), flag(param), value]
+ cmd = [command(param.to_s =~ /password_.+_age/ ? :password : :modify)]
+ cmd << flag(param) << value
if @resource.allowdupe? && ((param == :uid) || (param == :gid and self.class.name == :groupadd))
cmd << "-o"
end
diff --git a/lib/puppet/provider/service/launchd.rb b/lib/puppet/provider/service/launchd.rb
index 970359539..b296e0a38 100644
--- a/lib/puppet/provider/service/launchd.rb
+++ b/lib/puppet/provider/service/launchd.rb
@@ -38,6 +38,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
commands :launchctl => "/bin/launchctl"
commands :sw_vers => "/usr/bin/sw_vers"
+ commands :plutil => "/usr/bin/plutil"
defaultfor :operatingsystem => :darwin
confine :operatingsystem => :darwin
@@ -52,6 +53,12 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
Launchd_Overrides = "/var/db/launchd.db/com.apple.launchd/overrides.plist"
+ # Read a plist, whether its format is XML or in Apple's "binary1"
+ # format.
+ def self.read_plist(path)
+ Plist::parse_xml(plutil('-convert', 'xml1', '-o', '-', path))
+ end
+
# returns a label => path map for either all jobs, or just a single
# job if the label is specified
def self.jobsearch(label=nil)
@@ -62,8 +69,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
next if f =~ /^\..*$/
next if FileTest.directory?(f)
fullpath = File.join(path, f)
- job = Plist::parse_xml(fullpath)
- if job and job.has_key?("Label")
+ if FileTest.file?(fullpath) and job = read_plist(fullpath) and job.has_key?("Label")
if job["Label"] == label
return { label => fullpath }
else
@@ -118,8 +124,11 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
def plist_from_label(label)
job = self.class.jobsearch(label)
job_path = job[label]
- job_plist = Plist::parse_xml(job_path)
- raise Puppet::Error.new("Unable to parse launchd plist at path: #{job_path}") if not job_plist
+ if FileTest.file?(job_path)
+ job_plist = self.class.read_plist(job_path)
+ else
+ raise Puppet::Error.new("Unable to parse launchd plist at path: #{job_path}")
+ end
[job_path, job_plist]
end
@@ -200,9 +209,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
job_plist_disabled = job_plist["Disabled"] if job_plist.has_key?("Disabled")
if self.class.get_macosx_version_major == "10.6":
- overrides = Plist::parse_xml(Launchd_Overrides)
-
- unless overrides.nil?
+ if FileTest.file?(Launchd_Overrides) and overrides = self.class.read_plist(Launchd_Overrides)
if overrides.has_key?(resource[:name])
overrides_disabled = overrides[resource[:name]]["Disabled"] if overrides[resource[:name]].has_key?("Disabled")
end
@@ -227,7 +234,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
# versions this is stored in the job plist itself.
def enable
if self.class.get_macosx_version_major == "10.6"
- overrides = Plist::parse_xml(Launchd_Overrides)
+ overrides = self.class.read_plist(Launchd_Overrides)
overrides[resource[:name]] = { "Disabled" => false }
Plist::Emit.save_plist(overrides, Launchd_Overrides)
else
@@ -242,7 +249,7 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
def disable
if self.class.get_macosx_version_major == "10.6"
- overrides = Plist::parse_xml(Launchd_Overrides)
+ overrides = self.class.read_plist(Launchd_Overrides)
overrides[resource[:name]] = { "Disabled" => true }
Plist::Emit.save_plist(overrides, Launchd_Overrides)
else
diff --git a/lib/puppet/provider/user/hpux.rb b/lib/puppet/provider/user/hpux.rb
index 50506c4cd..983970935 100644
--- a/lib/puppet/provider/user/hpux.rb
+++ b/lib/puppet/provider/user/hpux.rb
@@ -26,5 +26,4 @@ Puppet::Type.type(:user).provide :hpuxuseradd, :parent => :useradd do
def modifycmd(param,value)
super.insert(1,"-F")
end
-
end
diff --git a/lib/puppet/provider/user/user_role_add.rb b/lib/puppet/provider/user/user_role_add.rb
index c13125925..7e7ad78e5 100644
--- a/lib/puppet/provider/user/user_role_add.rb
+++ b/lib/puppet/provider/user/user_role_add.rb
@@ -6,13 +6,15 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
defaultfor :operatingsystem => :solaris
- commands :add => "useradd", :delete => "userdel", :modify => "usermod", :role_add => "roleadd", :role_delete => "roledel", :role_modify => "rolemod"
+ commands :add => "useradd", :delete => "userdel", :modify => "usermod", :password => "chage", :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"
options :auths, :flag => "-A"
options :profiles, :flag => "-P"
+ options :password_min_age, :flag => "-m"
+ options :password_max_age, :flag => "-M"
verify :gid, "GID must be an integer" do |value|
value.is_a? Integer
@@ -22,14 +24,14 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
value !~ /\s/
end
- has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac, :manages_passwords
+ has_features :manages_homedir, :allows_duplicates, :manages_solaris_rbac, :manages_passwords, :manages_password_age
#must override this to hand the keyvalue pairs
def add_properties
cmd = []
Puppet::Type.type(:user).validproperties.each do |property|
#skip the password because we can't create it with the solaris useradd
- next if [:ensure, :password].include?(property)
+ next if [:ensure, :password, :password_min_age, :password_max_age].include?(property)
# 1680 Now you can set the hashed passwords on solaris:lib/puppet/provider/user/user_role_add.rb
# the value needs to be quoted, mostly because -c might
# have spaces in it
@@ -79,6 +81,7 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
run(transition("normal"), "transition role to")
else
run(addcmd, "create")
+ run(passcmd, "change password policy for")
end
# added to handle case when password is specified
self.password = @resource[:password] if @resource[:password]
@@ -140,14 +143,23 @@ Puppet::Type.type(:user).provide :user_role_add, :parent => :useradd, :source =>
run([command(:modify)] + build_keys_cmd(keys_hash) << @resource[:name], "modify attribute key pairs")
end
- #Read in /etc/shadow, find the line for this user (skipping comments, because who knows) and return the hashed pw (the second entry)
+ #Read in /etc/shadow, find the line for this user (skipping comments, because who knows) and return it
#No abstraction, all esoteric knowledge of file formats, yay
+ def shadow_entry
+ return @shadow_entry if defined? @shadow_entry
+ @shadow_entry = File.readlines("/etc/shadow").reject { |r| r =~ /^[^\w]/ }.collect { |l| l.chomp.split(':') }.find { |user, _| user == @resource[:name] }
+ end
+
def password
- #got perl?
- if ary = File.readlines("/etc/shadow").reject { |r| r =~ /^[^\w]/}.collect { |l| l.split(':')[0..1] }.find { |user, passwd| user == @resource[:name] }
- pass = ary[1]
- end
- pass
+ shadow_entry[1] if shadow_entry
+ end
+
+ def min_age
+ shadow_entry ? shadow_entry[3] : :absent
+ end
+
+ def max_age
+ shadow_entry ? shadow_entry[4] : :absent
end
#Read in /etc/shadow, find the line for our used and rewrite it with the new pw
diff --git a/lib/puppet/provider/user/useradd.rb b/lib/puppet/provider/user/useradd.rb
index 7ef217d9e..9a62db464 100644
--- a/lib/puppet/provider/user/useradd.rb
+++ b/lib/puppet/provider/user/useradd.rb
@@ -3,11 +3,13 @@ require 'puppet/provider/nameservice/objectadd'
Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameService::ObjectAdd do
desc "User management via `useradd` and its ilk. Note that you will need to install the `Shadow Password` Ruby library often known as ruby-libshadow to manage user passwords."
- commands :add => "useradd", :delete => "userdel", :modify => "usermod"
+ commands :add => "useradd", :delete => "userdel", :modify => "usermod", :password => "chage"
options :home, :flag => "-d", :method => :dir
options :comment, :method => :gecos
options :groups, :flag => "-G"
+ options :password_min_age, :flag => "-m"
+ options :password_max_age, :flag => "-M"
verify :gid, "GID must be an integer" do |value|
value.is_a? Integer
@@ -17,9 +19,9 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
value !~ /\s/
end
- has_features :manages_homedir, :allows_duplicates
+ has_features :manages_homedir, :allows_duplicates, :manages_expiry
- has_feature :manages_passwords if Puppet.features.libshadow?
+ has_features :manages_passwords, :manages_password_age if Puppet.features.libshadow?
def check_allow_dup
@resource.allowdupe? ? ["-o"] : []
@@ -35,10 +37,20 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
cmd
end
+ def check_manage_expiry
+ cmd = []
+ if @resource[:expiry]
+ cmd << "-e #{@resource[:expiry]}"
+ end
+
+ cmd
+ end
+
def add_properties
cmd = []
Puppet::Type.type(:user).validproperties.each do |property|
next if property == :ensure
+ next if property.to_s =~ /password_.+_age/
# the value needs to be quoted, mostly because -c might
# have spaces in it
if value = @resource.should(property) and value != ""
@@ -53,9 +65,38 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
cmd += add_properties
cmd += check_allow_dup
cmd += check_manage_home
+ cmd += check_manage_expiry
cmd << @resource[:name]
end
+ def passcmd
+ cmd = [command(:password)]
+ [:password_min_age, :password_max_age].each do |property|
+ if value = @resource.should(property)
+ cmd << flag(property) << value
+ end
+ end
+ cmd << @resource[:name]
+ end
+
+ def min_age
+ if Puppet.features.libshadow?
+ if ent = Shadow::Passwd.getspnam(@resource.name)
+ return ent.sp_min
+ end
+ end
+ :absent
+ end
+
+ def max_age
+ if Puppet.features.libshadow?
+ if ent = Shadow::Passwd.getspnam(@resource.name)
+ return ent.sp_max
+ end
+ end
+ :absent
+ end
+
# Retrieve the password using the Shadow Password library
def password
if Puppet.features.libshadow?
diff --git a/lib/puppet/reports/rrdgraph.rb b/lib/puppet/reports/rrdgraph.rb
index 2357e233e..517fa8f03 100644
--- a/lib/puppet/reports/rrdgraph.rb
+++ b/lib/puppet/reports/rrdgraph.rb
@@ -122,7 +122,7 @@ Puppet::Reports.register_report(:rrdgraph) do
# that means we record the total time, the config time, and that's about
# it. We should probably send each type's time as a separate metric.
def timeclean(metric)
- metric.values = metric.values.find_all { |name, label, value| [:total, :config_retrieval].include?(name) }
+ metric.values = metric.values.find_all { |name, label, value| ['total', 'config_retrieval'].include?(name.to_s) }
end
end
diff --git a/lib/puppet/type/user.rb b/lib/puppet/type/user.rb
index 007b760bc..c8110bb69 100755
--- a/lib/puppet/type/user.rb
+++ b/lib/puppet/type/user.rb
@@ -24,9 +24,16 @@ module Puppet
"The provider can modify user passwords, by accepting a password
hash."
+ feature :manages_password_age,
+ "The provider can set age requirements and restrictions for
+ passwords."
+
feature :manages_solaris_rbac,
"The provider can manage roles and normal users"
+ feature :manages_expiry,
+ "The provider can manage the expiry date for a user."
+
newproperty(:ensure, :parent => Puppet::Property::Ensure) do
newvalue(:present, :event => :user_created) do
provider.create
@@ -157,6 +164,43 @@ module Puppet
end
end
+ newproperty(:password_min_age, :required_features => :manages_password_age) do
+ desc "The minimum amount of time in days a password must be used before it may be changed"
+
+ munge do |value|
+ case value
+ when String
+ Integer(value)
+ else
+ value
+ end
+ end
+
+ validate do |value|
+ if value.to_s !~ /^\d+$/
+ raise ArgumentError, "Password minimum age must be provided as a number"
+ end
+ end
+ end
+
+ newproperty(:password_max_age, :required_features => :manages_password_age) do
+ desc "The maximum amount of time in days a password may be used before it must be changed"
+
+ munge do |value|
+ case value
+ when String
+ Integer(value)
+ else
+ value
+ end
+ end
+
+ validate do |value|
+ if value.to_s !~ /^\d+$/
+ raise ArgumentError, "Password maximum age must be provided as a number"
+ end
+ end
+ end
newproperty(:groups, :parent => Puppet::Property::List) do
desc "The groups of which the user is a member. The primary
@@ -210,6 +254,17 @@ module Puppet
end
end
+ newproperty(:expiry, :required_features => :manages_expiry) do
+ desc "The expiry date for this user. Must be provided in
+ a zero padded YYYY-MM-DD format - e.g 2010-02-19."
+
+ validate do |value|
+ if value !~ /^\d{4}-\d{2}-\d{2}$/
+ raise ArgumentError, "Expiry dates must be YYYY-MM-DD"
+ end
+ end
+ end
+
# Autorequire the group, if it's around
autorequire(:group) do
autos = []
diff --git a/lib/puppet/util/zaml.rb b/lib/puppet/util/zaml.rb
index b60e639ff..ae4da8612 100644
--- a/lib/puppet/util/zaml.rb
+++ b/lib/puppet/util/zaml.rb
@@ -242,7 +242,6 @@ class String
when self =~ /\n/
if self[-1..-1] == "\n" then z.emit('|+') else z.emit('|-') end
z.nested { split("\n",-1).each { |line| z.nl; z.emit(line.chomp("\n")) } }
- z.nl
else
z.emit(self)
end