puppet 2.7.17 → 2.7.18

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (41) hide show
  1. data/CHANGELOG +16 -0
  2. data/conf/redhat/puppet.spec +4 -1
  3. data/lib/puppet.rb +1 -1
  4. data/lib/puppet/application/master.rb +26 -8
  5. data/lib/puppet/defaults.rb +4 -4
  6. data/lib/puppet/face/file/download.rb +1 -1
  7. data/lib/puppet/file_bucket/file.rb +6 -7
  8. data/lib/puppet/file_serving/configuration.rb +2 -1
  9. data/lib/puppet/file_serving/content.rb +1 -2
  10. data/lib/puppet/file_serving/metadata.rb +1 -2
  11. data/lib/puppet/file_serving/mount/modules.rb +4 -5
  12. data/lib/puppet/file_serving/{indirection_hooks.rb → terminus_selector.rb} +2 -5
  13. data/lib/puppet/indirector/file_bucket_file/selector.rb +49 -0
  14. data/lib/puppet/indirector/file_content/selector.rb +30 -0
  15. data/lib/puppet/indirector/file_metadata/selector.rb +30 -0
  16. data/lib/puppet/network/authstore.rb +10 -2
  17. data/lib/puppet/reports/store.rb +13 -6
  18. data/lib/puppet/ssl/base.rb +8 -0
  19. data/lib/puppet/ssl/certificate_authority.rb +10 -0
  20. data/lib/puppet/ssl/certificate_authority/interface.rb +4 -2
  21. data/lib/puppet/ssl/host.rb +1 -0
  22. data/spec/integration/file_bucket/file_spec.rb +44 -0
  23. data/spec/integration/file_serving/content_spec.rb +3 -8
  24. data/spec/integration/file_serving/metadata_spec.rb +4 -9
  25. data/spec/integration/network/rest_authconfig_spec.rb +22 -3
  26. data/spec/shared_behaviours/file_serving.rb +70 -58
  27. data/spec/shared_behaviours/file_serving_model.rb +73 -0
  28. data/spec/unit/file_serving/configuration_spec.rb +37 -29
  29. data/spec/unit/file_serving/content_spec.rb +1 -5
  30. data/spec/unit/file_serving/metadata_spec.rb +1 -5
  31. data/spec/unit/file_serving/mount/modules_spec.rb +8 -0
  32. data/spec/unit/file_serving/{indirection_hooks_spec.rb → terminus_selector_spec.rb} +10 -11
  33. data/spec/unit/indirector/file_bucket_file/selector_spec.rb +29 -0
  34. data/spec/unit/indirector/file_content/selector_spec.rb +10 -0
  35. data/spec/unit/indirector/file_metadata/selector_spec.rb +11 -0
  36. data/spec/unit/network/handler/ca_spec.rb +1 -0
  37. data/spec/unit/reports/store_spec.rb +28 -0
  38. data/spec/unit/ssl/certificate_authority/interface_spec.rb +17 -17
  39. data/spec/unit/ssl/certificate_authority_spec.rb +76 -11
  40. metadata +15 -8
  41. data/lib/puppet/file_bucket/file/indirection_hooks.rb +0 -9
data/CHANGELOG CHANGED
@@ -1,3 +1,19 @@
1
+ 2.7.18
2
+ ===
3
+ d804782 Reject directory traversal in store report processor
4
+ fd44bf5 Tighten permissions on classfile, resourcefile, lastrunfile, and lastrunreport.
5
+ 4d7c9fd Use "inspect" when listing certificates
6
+ bd2820e Don't allow the creation of SSL objects with invalid certnames
7
+ f341962 Validate CSR CN and provided certname before signing
8
+ 38c5a4e Add specs for selector terminuses of file_{content,metadata}
9
+ 9e920a8 Fix whitespace inside parentheses
10
+ 2d01c2b Use head method to determine if file is in file bucket
11
+ 40ee670 Always use the local file_bucket on master
12
+ d881b4b Fail more gracefully when finding module files if no file is specified
13
+ 20ab0e9 Reject file requests containing ..
14
+ 10f6cb8 Add Selector terminus for file_content/file_metadata
15
+ ab9150b Deprecate IP-based authentication
16
+
1
17
  2.7.17
2
18
  ===
3
19
  30d89d3 (maint) Add symlink stub to gentoo service provider spec
@@ -5,7 +5,7 @@
5
5
  %global confdir conf/redhat
6
6
 
7
7
  Name: puppet
8
- Version: 2.7.17
8
+ Version: 2.7.18
9
9
  #Release: 0.1rc1.2%{?dist}
10
10
  Release: 1%{?dist}
11
11
  Summary: A network tool for managing many disparate systems
@@ -289,6 +289,9 @@ fi
289
289
  rm -rf %{buildroot}
290
290
 
291
291
  %changelog
292
+ * Mon Jul 9 2012 Moses Mendoza <moses@puppetlabs.com> - 2.7.18-1
293
+ - Update for 2.7.18
294
+
292
295
  * Tue Jun 19 2012 Matthaus Litteken <matthaus@puppetlabs.com> - 2.7.17-1
293
296
  - Update for 2.7.17
294
297
 
@@ -24,7 +24,7 @@ require 'puppet/util/run_mode'
24
24
  # it's also a place to find top-level commands like 'debug'
25
25
 
26
26
  module Puppet
27
- PUPPETVERSION = '2.7.17'
27
+ PUPPETVERSION = '2.7.18'
28
28
 
29
29
  def Puppet.version
30
30
  PUPPETVERSION
@@ -163,8 +163,6 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
163
163
 
164
164
  def main
165
165
  require 'etc'
166
- require 'puppet/file_serving/content'
167
- require 'puppet/file_serving/metadata'
168
166
 
169
167
  xmlrpc_handlers = [:Status, :FileServer, :Master, :Report, :Filebucket]
170
168
 
@@ -205,9 +203,7 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
205
203
  end
206
204
  end
207
205
 
208
- def setup
209
- raise Puppet::Error.new("Puppet master is not supported on Microsoft Windows") if Puppet.features.microsoft_windows?
210
-
206
+ def setup_logs
211
207
  # Handle the logging settings.
212
208
  if options[:debug] or options[:verbose]
213
209
  if options[:debug]
@@ -223,14 +219,22 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
223
219
  end
224
220
 
225
221
  Puppet::Util::Log.newdestination(:syslog) unless options[:setdest]
222
+ end
226
223
 
227
- exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
228
-
229
- Puppet.settings.use :main, :master, :ssl, :metrics
224
+ def setup_terminuses
225
+ require 'puppet/file_serving/content'
226
+ require 'puppet/file_serving/metadata'
230
227
 
231
228
  # Cache our nodes in yaml. Currently not configurable.
232
229
  Puppet::Node.indirection.cache_class = :yaml
233
230
 
231
+ Puppet::FileServing::Content.indirection.terminus_class = :file_server
232
+ Puppet::FileServing::Metadata.indirection.terminus_class = :file_server
233
+
234
+ Puppet::FileBucket::File.indirection.terminus_class = :file
235
+ end
236
+
237
+ def setup_ssl
234
238
  # Configure all of the SSL stuff.
235
239
  if Puppet::SSL::CertificateAuthority.ca?
236
240
  Puppet::SSL::Host.ca_location = :local
@@ -240,4 +244,18 @@ Copyright (c) 2011 Puppet Labs, LLC Licensed under the Apache 2.0 License
240
244
  Puppet::SSL::Host.ca_location = :none
241
245
  end
242
246
  end
247
+
248
+ def setup
249
+ raise Puppet::Error.new("Puppet master is not supported on Microsoft Windows") if Puppet.features.microsoft_windows?
250
+
251
+ setup_logs
252
+
253
+ exit(Puppet.settings.print_configs ? 0 : 1) if Puppet.settings.print_configs?
254
+
255
+ Puppet.settings.use :main, :master, :ssl, :metrics
256
+
257
+ setup_terminuses
258
+
259
+ setup_ssl
260
+ end
243
261
  end
@@ -599,14 +599,14 @@ EOT
599
599
  :client_datadir => {:default => "$vardir/client_data", :mode => "750", :desc => "The directory in which serialized data is stored on the client."},
600
600
  :classfile => { :default => "$statedir/classes.txt",
601
601
  :owner => "root",
602
- :mode => 0644,
602
+ :mode => 0640,
603
603
  :desc => "The file in which puppet agent stores a list of the classes
604
604
  associated with the retrieved configuration. Can be loaded in
605
605
  the separate `puppet` executable using the `--loadclasses`
606
606
  option."},
607
607
  :resourcefile => { :default => "$statedir/resources.txt",
608
608
  :owner => "root",
609
- :mode => 0644,
609
+ :mode => 0640,
610
610
  :desc => "The file in which puppet agent stores a list of the resources
611
611
  associated with the retrieved configuration." },
612
612
  :puppetdlog => { :default => "$logdir/puppetd.log",
@@ -713,11 +713,11 @@ EOT
713
713
  "Whether to send reports after every transaction."
714
714
  ],
715
715
  :lastrunfile => { :default => "$statedir/last_run_summary.yaml",
716
- :mode => 0644,
716
+ :mode => 0640,
717
717
  :desc => "Where puppet agent stores the last run report summary in yaml format."
718
718
  },
719
719
  :lastrunreport => { :default => "$statedir/last_run_report.yaml",
720
- :mode => 0644,
720
+ :mode => 0640,
721
721
  :desc => "Where puppet agent stores the last run report in yaml format."
722
722
  },
723
723
  :graph => [false, "Whether to create dot graph files for the different
@@ -35,7 +35,7 @@ Puppet::Face.define(:file, '0.0.1') do
35
35
  key = "#{type}/#{sumdata}"
36
36
 
37
37
  Puppet::FileBucket::File.indirection.terminus_class = :file
38
- if Puppet::FileBucket::File.indirection.find(key)
38
+ if Puppet::FileBucket::File.indirection.head(key)
39
39
  Puppet.info "Content for '#{sum}' already exists"
40
40
  return
41
41
  end
@@ -8,13 +8,12 @@ class Puppet::FileBucket::File
8
8
  # There are mechanisms to save and load this file locally and remotely in puppet/indirector/filebucketfile/*
9
9
  # There is a compatibility class that emulates pre-indirector filebuckets in Puppet::FileBucket::Dipper
10
10
  extend Puppet::Indirector
11
- require 'puppet/file_bucket/file/indirection_hooks'
12
- indirects :file_bucket_file, :terminus_class => :file, :extend => Puppet::FileBucket::File::IndirectionHooks
11
+ indirects :file_bucket_file, :terminus_class => :selector
13
12
 
14
13
  attr :contents
15
14
  attr :bucket_path
16
15
 
17
- def initialize( contents, options = {} )
16
+ def initialize(contents, options = {})
18
17
  raise ArgumentError.new("contents must be a String, got a #{contents.class}") unless contents.is_a?(String)
19
18
  @contents = contents
20
19
 
@@ -42,15 +41,15 @@ class Puppet::FileBucket::File
42
41
  "#{checksum_type}/#{checksum_data}"
43
42
  end
44
43
 
45
- def self.from_s( contents )
46
- self.new( contents )
44
+ def self.from_s(contents)
45
+ self.new(contents)
47
46
  end
48
47
 
49
48
  def to_pson
50
49
  { "contents" => contents }.to_pson
51
50
  end
52
51
 
53
- def self.from_pson( pson )
54
- self.new( pson["contents"] )
52
+ def self.from_pson(pson)
53
+ self.new(pson["contents"])
55
54
  end
56
55
  end
@@ -64,7 +64,8 @@ class Puppet::FileServing::Configuration
64
64
 
65
65
  mount_name, path = request.key.split(File::Separator, 2)
66
66
 
67
- raise(ArgumentError, "Cannot find file: Invalid path '#{mount_name}'") unless mount_name =~ %r{^[-\w]+$}
67
+ raise(ArgumentError, "Cannot find file: Invalid mount '#{mount_name}'") unless mount_name =~ %r{^[-\w]+$}
68
+ raise(ArgumentError, "Cannot find file: Invalid relative path '#{path}'") if path and path.split('/').include?('..')
68
69
 
69
70
  return nil unless mount = find_mount(mount_name, request.environment)
70
71
  if mount.name == "modules" and mount_name != "modules"
@@ -1,14 +1,13 @@
1
1
  require 'puppet/indirector'
2
2
  require 'puppet/file_serving'
3
3
  require 'puppet/file_serving/base'
4
- require 'puppet/file_serving/indirection_hooks'
5
4
 
6
5
  # A class that handles retrieving file contents.
7
6
  # It only reads the file when its content is specifically
8
7
  # asked for.
9
8
  class Puppet::FileServing::Content < Puppet::FileServing::Base
10
9
  extend Puppet::Indirector
11
- indirects :file_content, :extend => Puppet::FileServing::IndirectionHooks
10
+ indirects :file_content, :terminus_class => :selector
12
11
 
13
12
  attr_writer :content
14
13
 
@@ -3,7 +3,6 @@ require 'puppet/indirector'
3
3
  require 'puppet/file_serving'
4
4
  require 'puppet/file_serving/base'
5
5
  require 'puppet/util/checksums'
6
- require 'puppet/file_serving/indirection_hooks'
7
6
 
8
7
  # A class that handles retrieving file metadata.
9
8
  class Puppet::FileServing::Metadata < Puppet::FileServing::Base
@@ -11,7 +10,7 @@ class Puppet::FileServing::Metadata < Puppet::FileServing::Base
11
10
  include Puppet::Util::Checksums
12
11
 
13
12
  extend Puppet::Indirector
14
- indirects :file_metadata, :extend => Puppet::FileServing::IndirectionHooks
13
+ indirects :file_metadata, :terminus_class => :selector
15
14
 
16
15
  attr_reader :path, :owner, :group, :mode, :checksum_type, :checksum, :ftype, :destination
17
16
 
@@ -5,6 +5,7 @@ require 'puppet/file_serving/mount'
5
5
  class Puppet::FileServing::Mount::Modules < Puppet::FileServing::Mount
6
6
  # Return an instance of the appropriate class.
7
7
  def find(path, request)
8
+ raise "No module specified" if path.to_s.empty?
8
9
  module_name, relative_path = path.split("/", 2)
9
10
  return nil unless mod = request.environment.module(module_name)
10
11
 
@@ -12,11 +13,9 @@ class Puppet::FileServing::Mount::Modules < Puppet::FileServing::Mount
12
13
  end
13
14
 
14
15
  def search(path, request)
15
- module_name, relative_path = path.split("/", 2)
16
- return nil unless mod = request.environment.module(module_name)
17
-
18
- return nil unless path = mod.file(relative_path)
19
- [path]
16
+ if result = find(path, request)
17
+ [result]
18
+ end
20
19
  end
21
20
 
22
21
  def valid?
@@ -1,15 +1,12 @@
1
- require 'uri'
2
1
  require 'puppet/file_serving'
3
- require 'puppet/util'
4
2
 
5
3
  # This module is used to pick the appropriate terminus
6
4
  # in file-serving indirections. This is necessary because
7
5
  # the terminus varies based on the URI asked for.
8
- module Puppet::FileServing::IndirectionHooks
6
+ module Puppet::FileServing::TerminusSelector
9
7
  PROTOCOL_MAP = {"puppet" => :rest, "file" => :file}
10
8
 
11
- # Pick an appropriate terminus based on the protocol.
12
- def select_terminus(request)
9
+ def select(request)
13
10
  # We rely on the request's parsing of the URI.
14
11
 
15
12
  # Short-circuit to :file if it's a fully-qualified path or specifies a 'file' protocol.
@@ -0,0 +1,49 @@
1
+ require 'puppet/indirector/code'
2
+
3
+ module Puppet::FileBucketFile
4
+ class Selector < Puppet::Indirector::Code
5
+ desc "Select the terminus based on the request"
6
+
7
+ def select(request)
8
+ if request.protocol == 'https'
9
+ :rest
10
+ else
11
+ :file
12
+ end
13
+ end
14
+
15
+ def get_terminus(request)
16
+ indirection.terminus(select(request))
17
+ end
18
+
19
+ def head(request)
20
+ get_terminus(request).head(request)
21
+ end
22
+
23
+ def find(request)
24
+ get_terminus(request).find(request)
25
+ end
26
+
27
+ def save(request)
28
+ get_terminus(request).save(request)
29
+ end
30
+
31
+ def search(request)
32
+ get_terminus(request).search(request)
33
+ end
34
+
35
+ def destroy(request)
36
+ get_terminus(request).destroy(request)
37
+ end
38
+
39
+ def authorized?(request)
40
+ terminus = get_terminus(request)
41
+ if terminus.respond_to?(:authorized?)
42
+ terminus.authorized?(request)
43
+ else
44
+ true
45
+ end
46
+ end
47
+ end
48
+ end
49
+
@@ -0,0 +1,30 @@
1
+ require 'puppet/file_serving/content'
2
+ require 'puppet/indirector/file_content'
3
+ require 'puppet/indirector/code'
4
+ require 'puppet/file_serving/terminus_selector'
5
+
6
+ class Puppet::Indirector::FileContent::Selector < Puppet::Indirector::Code
7
+ desc "Select the terminus based on the request"
8
+ include Puppet::FileServing::TerminusSelector
9
+
10
+ def get_terminus(request)
11
+ indirection.terminus(select(request))
12
+ end
13
+
14
+ def find(request)
15
+ get_terminus(request).find(request)
16
+ end
17
+
18
+ def search(request)
19
+ get_terminus(request).search(request)
20
+ end
21
+
22
+ def authorized?(request)
23
+ terminus = get_terminus(request)
24
+ if terminus.respond_to?(:authorized?)
25
+ terminus.authorized?(request)
26
+ else
27
+ true
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ require 'puppet/file_serving/metadata'
2
+ require 'puppet/indirector/file_metadata'
3
+ require 'puppet/indirector/code'
4
+ require 'puppet/file_serving/terminus_selector'
5
+
6
+ class Puppet::Indirector::FileMetadata::Selector < Puppet::Indirector::Code
7
+ desc "Select the terminus based on the request"
8
+ include Puppet::FileServing::TerminusSelector
9
+
10
+ def get_terminus(request)
11
+ indirection.terminus(select(request))
12
+ end
13
+
14
+ def find(request)
15
+ get_terminus(request).find(request)
16
+ end
17
+
18
+ def search(request)
19
+ get_terminus(request).search(request)
20
+ end
21
+
22
+ def authorized?(request)
23
+ terminus = get_terminus(request)
24
+ if terminus.respond_to?(:authorized?)
25
+ terminus.authorized?(request)
26
+ else
27
+ true
28
+ end
29
+ end
30
+ end
@@ -150,7 +150,16 @@ module Puppet
150
150
 
151
151
  # Does this declaration match the name/ip combo?
152
152
  def match?(name, ip)
153
- ip? ? pattern.include?(IPAddr.new(ip)) : matchname?(name)
153
+ if ip?
154
+ if pattern.include?(IPAddr.new(ip))
155
+ Puppet.deprecation_warning "Authentication based on IP address is deprecated; please use certname-based rules instead"
156
+ true
157
+ else
158
+ false
159
+ end
160
+ else
161
+ matchname?(name)
162
+ end
154
163
  end
155
164
 
156
165
  # Set the pattern appropriately. Also sets the name and length.
@@ -212,7 +221,6 @@ module Puppet
212
221
 
213
222
  # Convert the name to a common pattern.
214
223
  def munge_name(name)
215
- # LAK:NOTE http://snurl.com/21zf8 [groups_google_com]
216
224
  # Change to name.downcase.split(".",-1).reverse for FQDN support
217
225
  name.downcase.split(".").reverse
218
226
  end
@@ -2,6 +2,8 @@ require 'puppet'
2
2
  require 'fileutils'
3
3
  require 'tempfile'
4
4
 
5
+ SEPARATOR = [Regexp.escape(File::SEPARATOR.to_s), Regexp.escape(File::ALT_SEPARATOR.to_s)].join
6
+
5
7
  Puppet::Reports.register_report(:store) do
6
8
  desc "Store the yaml report on disk. Each host sends its report as a YAML dump
7
9
  and this just stores the file on disk, in the `reportdir` directory.
@@ -13,9 +15,11 @@ Puppet::Reports.register_report(:store) do
13
15
  def process
14
16
  # We don't want any tracking back in the fs. Unlikely, but there
15
17
  # you go.
16
- client = self.host.gsub("..",".")
18
+ if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/)
19
+ raise ArgumentError, "Invalid node name #{host.inspect}"
20
+ end
17
21
 
18
- dir = File.join(Puppet[:reportdir], client)
22
+ dir = File.join(Puppet[:reportdir], host)
19
23
 
20
24
  if ! FileTest.exists?(dir)
21
25
  FileUtils.mkdir_p(dir)
@@ -42,17 +46,20 @@ Puppet::Reports.register_report(:store) do
42
46
  FileUtils.mv(f.path, file)
43
47
  rescue => detail
44
48
  puts detail.backtrace if Puppet[:trace]
45
- Puppet.warning "Could not write report for #{client} at #{file}: #{detail}"
49
+ Puppet.warning "Could not write report for #{host} at #{file}: #{detail}"
46
50
  end
47
51
 
48
52
  # Only testing cares about the return value
49
53
  file
50
54
  end
51
55
 
52
- # removes all reports for a given host
56
+ # removes all reports for a given host?
53
57
  def self.destroy(host)
54
- client = host.gsub("..",".")
55
- dir = File.join(Puppet[:reportdir], client)
58
+ if host =~ Regexp.union(/[#{SEPARATOR}]/, /\A\.\.?\Z/)
59
+ raise ArgumentError, "Invalid node name #{host.inspect}"
60
+ end
61
+
62
+ dir = File.join(Puppet[:reportdir], host)
56
63
 
57
64
  if File.exists?(dir)
58
65
  Dir.entries(dir).each do |file|