diff options
Diffstat (limited to 'lib/puppet')
-rw-r--r-- | lib/puppet/application/agent.rb | 8 | ||||
-rw-r--r-- | lib/puppet/application/apply.rb | 7 | ||||
-rw-r--r-- | lib/puppet/application/ca.rb | 5 | ||||
-rw-r--r-- | lib/puppet/application/device.rb | 8 | ||||
-rw-r--r-- | lib/puppet/defaults.rb | 2 | ||||
-rw-r--r-- | lib/puppet/face/ca.rb | 233 | ||||
-rw-r--r-- | lib/puppet/interface.rb | 5 | ||||
-rw-r--r-- | lib/puppet/interface/action.rb | 3 | ||||
-rw-r--r-- | lib/puppet/interface/face_collection.rb | 49 | ||||
-rw-r--r-- | lib/puppet/interface/option_manager.rb | 3 | ||||
-rw-r--r-- | lib/puppet/module.rb | 5 | ||||
-rw-r--r-- | lib/puppet/ssl/inventory.rb | 2 | ||||
-rwxr-xr-x | lib/puppet/type/file/source.rb | 2 | ||||
-rw-r--r-- | lib/puppet/util.rb | 1 | ||||
-rw-r--r-- | lib/puppet/util/settings.rb | 2 |
15 files changed, 271 insertions, 64 deletions
diff --git a/lib/puppet/application/agent.rb b/lib/puppet/application/agent.rb index f0442648b..ea7cbdfb5 100644 --- a/lib/puppet/application/agent.rb +++ b/lib/puppet/application/agent.rb @@ -187,10 +187,10 @@ configuration options can also be generated by running puppet agent with should always at least contain MD5, MD2, SHA1 and SHA256. * --detailed-exitcodes: - Provide transaction information via exit codes. If this is enabled, an - exit code of '2' means there were changes, and an exit code of '4' - means that there were failures during the transaction. This option - only makes sense in conjunction with --onetime. + Provide transaction information via exit codes. If this is enabled, an exit + code of '2' means there were changes, an exit code of '4' means there were + failures during the transaction, and an exit code of '6' means there were both + changes and failures. * --disable: Disable working on the local system. This puts a lock file in place, diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb index 5562a9b09..200309b7d 100644 --- a/lib/puppet/application/apply.rb +++ b/lib/puppet/application/apply.rb @@ -82,9 +82,10 @@ configuration options can also be generated by running puppet with Enable full debugging. * --detailed-exitcodes: - Provide transaction information via exit codes. If this is enabled, an - exit code of '2' means there were changes, and an exit code of '4' - means that there were failures during the transaction. + Provide transaction information via exit codes. If this is enabled, an exit + code of '2' means there were changes, an exit code of '4' means there were + failures during the transaction, and an exit code of '6' means there were both + changes and failures. * --help: Print this help message diff --git a/lib/puppet/application/ca.rb b/lib/puppet/application/ca.rb new file mode 100644 index 000000000..d1ec2502e --- /dev/null +++ b/lib/puppet/application/ca.rb @@ -0,0 +1,5 @@ +require 'puppet/application/face_base' + +class Puppet::Application::Ca < Puppet::Application::FaceBase + run_mode :master +end diff --git a/lib/puppet/application/device.rb b/lib/puppet/application/device.rb index 3e2dec98c..977c5c023 100644 --- a/lib/puppet/application/device.rb +++ b/lib/puppet/application/device.rb @@ -113,10 +113,10 @@ parameter, so you can specify '--server <servername>' as an argument. Enable full debugging. * --detailed-exitcodes: - Provide transaction information via exit codes. If this is enabled, an - exit code of '2' means there were changes, and an exit code of '4' means - that there were failures during the transaction. This option only makes - sense in conjunction with --onetime. + Provide transaction information via exit codes. If this is enabled, an exit + code of '2' means there were changes, an exit code of '4' means there were + failures during the transaction, and an exit code of '6' means there were both + changes and failures. * --help: Print this help message diff --git a/lib/puppet/defaults.rb b/lib/puppet/defaults.rb index e6beb512e..637ee8fdd 100644 --- a/lib/puppet/defaults.rb +++ b/lib/puppet/defaults.rb @@ -472,7 +472,7 @@ module Puppet :desc => "The directory in which to store reports received from the client. Each client gets a separate subdirectory."}, - :reporturl => ["http://localhost:3000/reports", + :reporturl => ["http://localhost:3000/reports/upload", "The URL used by the http reports processor to send reports"], :fileserverconfig => ["$confdir/fileserver.conf", "Where the fileserver configuration is stored."], :strict_hostname_checking => [false, "Whether to only search for the complete diff --git a/lib/puppet/face/ca.rb b/lib/puppet/face/ca.rb new file mode 100644 index 000000000..e643530f0 --- /dev/null +++ b/lib/puppet/face/ca.rb @@ -0,0 +1,233 @@ +require 'puppet/face' + +Puppet::Face.define(:ca, '0.1.0') do + copyright "Puppet Labs", 2011 + license "Apache 2 license; see COPYING" + + summary "Local Puppet Certificate Authority management." + + description <<TEXT +This provides local management of the Puppet Certificate Authority. + +You can use this subcommand to sign outstanding certificate requests, list +and manage local certificates, and inspect the state of the CA. +TEXT + + action :list do + summary "List certificates and/or certificate requests." + + description <<-end +This will list the current certificates and certificate signing requests +in the Puppet CA. You will also get the fingerprint, and any certificate +verification failure reported. + end + + option "--[no-]all" do + summary "Include all certificates and requests." + end + + option "--[no-]pending" do + summary "Include pending certificate signing requests." + end + + option "--[no-]signed" do + summary "Include signed certificates." + end + + option "--subject PATTERN" do + summary "Only list if the subject matches PATTERN." + + description <<TEXT +Only include certificates or requests where subject matches PATTERN. + +PATTERN is interpreted as a regular expression, allowing complex +filtering of the content. +TEXT + end + + when_invoked do |options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + pattern = options[:subject].nil? ? nil : + Regexp.new(options[:subject], Regexp::IGNORECASE) + + pending = options[:pending].nil? ? options[:all] : options[:pending] + signed = options[:signed].nil? ? options[:all] : options[:signed] + + # By default we list pending, so if nothing at all was requested... + unless pending or signed then pending = true end + + hosts = [] + + pending and hosts += ca.waiting? + signed and hosts += ca.list + + pattern and hosts = hosts.select {|hostname| pattern.match hostname } + + hosts.sort.map {|host| Puppet::SSL::Host.new(host) } + end + + when_rendering :console do |hosts| + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + length = hosts.map{|x| x.name.length }.max + 1 + + hosts.map do |host| + name = host.name.ljust(length) + if host.certificate_request then + " #{name} (#{host.certificate_request.fingerprint})" + else + begin + ca.verify(host.certificate) + "+ #{name} (#{host.certificate.fingerprint})" + rescue Puppet::SSL::CertificateAuthority::CertificateVerificationError => e + "- #{name} (#{host.certificate.fingerprint}) (#{e.to_s})" + end + end + end.join("\n") + end + end + + action :destroy do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + ca.destroy host + end + end + + action :revoke do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.revoke host + rescue ArgumentError => e + # This is a bit naff, but it makes the behaviour consistent with the + # destroy action. The underlying tools could be nicer for that sort + # of thing; they have fairly inconsistent reporting of failures. + raise unless e.to_s =~ /Could not find a serial number for / + "Nothing was revoked" + end + end + end + + action :generate do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.generate host + rescue RuntimeError => e + if e.to_s =~ /already has a requested certificate/ + "#{host} already has a certificate request; use sign instead" + else + raise + end + rescue ArgumentError => e + if e.to_s =~ /A Certificate already exists for / + "#{host} already has a certificate" + else + raise + end + end + end + end + + action :sign do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.sign host + rescue ArgumentError => e + if e.to_s =~ /Could not find certificate request/ + e.to_s + else + raise + end + end + end + end + + action :print do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + ca.print host + end + end + + action :fingerprint do + option "--digest ALGORITHM" do + summary "The hash algorithm to use when displaying the fingerprint" + end + + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + # I want the default from the CA, not to duplicate it, but passing + # 'nil' explicitly means that we don't get that. This works... + if options.has_key? :digest + ca.fingerprint host, options[:digest] + else + ca.fingerprint host + end + rescue ArgumentError => e + raise unless e.to_s =~ /Could not find a certificate or csr for/ + nil + end + end + end + + action :verify do + when_invoked do |host, options| + raise "Not a CA" unless Puppet::SSL::CertificateAuthority.ca? + unless ca = Puppet::SSL::CertificateAuthority.instance + raise "Unable to fetch the CA" + end + + begin + ca.verify host + { :host => host, :valid => true } + rescue ArgumentError => e + raise unless e.to_s =~ /Could not find a certificate for/ + { :host => host, :valid => false, :error => e.to_s } + rescue Puppet::SSL::CertificateAuthority::CertificateVerificationError => e + { :host => host, :valid => false, :error => e.to_s } + end + end + + when_rendering :console do |value| + if value[:valid] + nil + else + "Could not verify #{value[:host]}: #{value[:error]}" + end + end + end +end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 6be8b6930..6c288f3c0 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -2,6 +2,7 @@ require 'puppet' require 'puppet/util/autoload' require 'puppet/interface/documentation' require 'prettyprint' +require 'semver' class Puppet::Interface include FullDocs @@ -84,12 +85,12 @@ class Puppet::Interface attr_reader :name, :version def initialize(name, version, &block) - unless Puppet::Interface::FaceCollection.validate_version(version) + unless SemVer.valid?(version) raise ArgumentError, "Cannot create face #{name.inspect} with invalid version number '#{version}'!" end @name = Puppet::Interface::FaceCollection.underscorize(name) - @version = version + @version = SemVer.new(version) # The few bits of documentation we actually demand. The default license # is a favour to our end users; if you happen to get that in a core face diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index 185302b07..fe77a9658 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -227,8 +227,9 @@ WRAPPER end end + @options << option.name + option.aliases.each do |name| - @options << name @options_hash[name] = option end diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb index 12d3c56b1..4522824fd 100644 --- a/lib/puppet/interface/face_collection.rb +++ b/lib/puppet/interface/face_collection.rb @@ -1,8 +1,6 @@ require 'puppet/interface' module Puppet::Interface::FaceCollection - SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ - @faces = Hash.new { |hash, key| hash[key] = {} } def self.faces @@ -17,55 +15,18 @@ module Puppet::Interface::FaceCollection @faces.keys.select {|name| @faces[name].length > 0 } end - def self.validate_version(version) - !!(SEMVER_VERSION =~ version.to_s) - end - - def self.semver_to_array(v) - parts = SEMVER_VERSION.match(v).to_a[1..4] - parts[0..2] = parts[0..2].map { |e| e.to_i } - parts - end - - def self.cmp_semver(a, b) - a, b = [a, b].map do |x| semver_to_array(x) end - - cmp = a[0..2] <=> b[0..2] - if cmp == 0 - cmp = a[3] <=> b[3] - cmp = +1 if a[3].empty? && !b[3].empty? - cmp = -1 if b[3].empty? && !a[3].empty? - end - cmp - end - - def self.prefix_match?(desired, target) - # Can't meaningfully do a prefix match with current on either side. - return false if desired == :current - return false if target == :current - - # REVISIT: Should probably fail if the matcher is not valid. - prefix = desired.split('.').map {|x| x =~ /^\d+$/ and x.to_i } - have = semver_to_array(target) - - while want = prefix.shift do - return false unless want == have.shift - end - return true - end - def self.[](name, version) name = underscorize(name) get_face(name, version) or load_face(name, version) end # get face from memory, without loading. - def self.get_face(name, desired_version) + def self.get_face(name, pattern) return nil unless @faces.has_key? name + return @faces[name][:current] if pattern == :current - return @faces[name][:current] if desired_version == :current - - found = @faces[name].keys.select {|v| prefix_match?(desired_version, v) }.sort.last + versions = @faces[name].keys - [ :current ] + found = SemVer.find_matching(pattern, versions) return @faces[name][found] end @@ -108,7 +69,7 @@ module Puppet::Interface::FaceCollection # versions here and return the last item in that set. # # --daniel 2011-04-06 - latest_ver = @faces[name].keys.sort {|a, b| cmp_semver(a, b) }.last + latest_ver = @faces[name].keys.sort.last @faces[name][:current] = @faces[name][latest_ver] end rescue LoadError => e diff --git a/lib/puppet/interface/option_manager.rb b/lib/puppet/interface/option_manager.rb index 326a91d92..a1f300e8e 100644 --- a/lib/puppet/interface/option_manager.rb +++ b/lib/puppet/interface/option_manager.rb @@ -26,8 +26,9 @@ module Puppet::Interface::OptionManager end end + @options << option.name + option.aliases.each do |name| - @options << name @options_hash[name] = option end diff --git a/lib/puppet/module.rb b/lib/puppet/module.rb index 059591ed8..00468df96 100644 --- a/lib/puppet/module.rb +++ b/lib/puppet/module.rb @@ -42,7 +42,10 @@ class Puppet::Module def has_metadata? return false unless metadata_file - FileTest.exist?(metadata_file) + return false unless FileTest.exist?(metadata_file) + + metadata = PSON.parse File.read(metadata_file) + return metadata.is_a?(Hash) && !metadata.keys.empty? end def initialize(name, environment = nil) diff --git a/lib/puppet/ssl/inventory.rb b/lib/puppet/ssl/inventory.rb index e094da100..c210fdc35 100644 --- a/lib/puppet/ssl/inventory.rb +++ b/lib/puppet/ssl/inventory.rb @@ -48,5 +48,7 @@ class Puppet::SSL::Inventory return Integer($1) end + + return nil end end diff --git a/lib/puppet/type/file/source.rb b/lib/puppet/type/file/source.rb index 76c646baf..49e885865 100755 --- a/lib/puppet/type/file/source.rb +++ b/lib/puppet/type/file/source.rb @@ -42,7 +42,7 @@ module Puppet on the local host, whereas `agent` will connect to the puppet server that it received the manifest from. - See the [fileserver configuration documentation](http://projects.puppetlabs.com/projects/puppet/wiki/File_Serving_Configuration) for information on how to configure + See the [fileserver configuration documentation](http://docs.puppetlabs.com/guides/file_serving.html) for information on how to configure and use file services within Puppet. If you specify multiple file sources for a file, then the first diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index ce9d4642b..ff09221a2 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -30,7 +30,6 @@ module Util end end - def self.synchronize_on(x,type) sync_object,users = 0,1 begin diff --git a/lib/puppet/util/settings.rb b/lib/puppet/util/settings.rb index f243b8691..4559e9af3 100644 --- a/lib/puppet/util/settings.rb +++ b/lib/puppet/util/settings.rb @@ -721,7 +721,7 @@ if @config.include?(:run_mode) end Puppet::Util::SUIDManager.asuser(*chown) do - mode = obj.mode || 0640 + mode = obj.mode ? obj.mode.to_i : 0640 args << "w" if args.empty? args << mode |