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
@@ -5,6 +5,9 @@ class Puppet::SSL::Base
5
5
  # For now, use the YAML separator.
6
6
  SEPARATOR = "\n---\n"
7
7
 
8
+ # Only allow printing ascii characters, excluding /
9
+ VALID_CERTNAME = /\A[ -.0-~]+\Z/
10
+
8
11
  def self.from_multiple_s(text)
9
12
  text.split(SEPARATOR).collect { |inst| from_s(inst) }
10
13
  end
@@ -22,6 +25,10 @@ class Puppet::SSL::Base
22
25
  @wrapped_class
23
26
  end
24
27
 
28
+ def self.validate_certname(name)
29
+ raise "Certname #{name.inspect} must not contain unprintable or non-ASCII characters" unless name =~ VALID_CERTNAME
30
+ end
31
+
25
32
  attr_accessor :name, :content
26
33
 
27
34
  # Is this file for the CA?
@@ -35,6 +42,7 @@ class Puppet::SSL::Base
35
42
 
36
43
  def initialize(name)
37
44
  @name = name.to_s.downcase
45
+ self.class.validate_certname(@name)
38
46
  end
39
47
 
40
48
  # Read content from disk appropriately.
@@ -303,6 +303,16 @@ class Puppet::SSL::CertificateAuthority
303
303
  raise CertificateSigningError.new(hostname), "CSR has request extensions that are not permitted: #{names}"
304
304
  end
305
305
 
306
+ # Do not sign misleading CSRs
307
+ cn = csr.content.subject.to_a.assoc("CN")[1]
308
+ if hostname != cn
309
+ raise CertificateSigningError.new(hostname), "CSR subject common name #{cn.inspect} does not match expected certname #{hostname.inspect}"
310
+ end
311
+
312
+ if hostname !~ Puppet::SSL::Base::VALID_CERTNAME
313
+ raise CertificateSigningError.new(hostname), "CSR #{hostname.inspect} subject contains unprintable or non-ASCII characters"
314
+ end
315
+
306
316
  # Wildcards: we don't allow 'em at any point.
307
317
  #
308
318
  # The stringification here makes the content visible, and saves us having
@@ -88,6 +88,8 @@ module Puppet
88
88
  names = certs.values.map(&:keys).flatten
89
89
 
90
90
  name_width = names.sort_by(&:length).last.length rescue 0
91
+ # We quote these names, so account for those characters
92
+ name_width += 2
91
93
 
92
94
  output = [:request, :signed, :invalid].map do |type|
93
95
  next if certs[type].empty?
@@ -113,11 +115,11 @@ module Puppet
113
115
 
114
116
  alt_names.delete(host)
115
117
 
116
- alt_str = "(alt names: #{alt_names.join(', ')})" unless alt_names.empty?
118
+ alt_str = "(alt names: #{alt_names.map(&:inspect).join(', ')})" unless alt_names.empty?
117
119
 
118
120
  glyph = {:signed => '+', :request => ' ', :invalid => '-'}[type]
119
121
 
120
- name = host.ljust(width)
122
+ name = host.inspect.ljust(width)
121
123
  fingerprint = "(#{ca.fingerprint(host, @digest)})"
122
124
 
123
125
  explanation = "(#{verify_error})" if verify_error
@@ -236,6 +236,7 @@ ERROR_STRING
236
236
 
237
237
  def initialize(name = nil)
238
238
  @name = (name || Puppet[:certname]).downcase
239
+ Puppet::SSL::Base.validate_certname(@name)
239
240
  @key = @certificate = @certificate_request = nil
240
241
  @ca = (name == self.class.ca_name)
241
242
  end
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'puppet/file_bucket/file'
6
+
7
+ describe Puppet::FileBucket::File do
8
+ describe "#indirection" do
9
+ before :each do
10
+ # Never connect to the network, no matter what
11
+ described_class.indirection.terminus(:rest).class.any_instance.stubs(:find)
12
+ end
13
+
14
+ describe "when running the master application" do
15
+ before :each do
16
+ Puppet::Application[:master].setup_terminuses
17
+ end
18
+
19
+ {
20
+ "md5/d41d8cd98f00b204e9800998ecf8427e" => :file,
21
+ "https://puppetmaster:8140/production/file_bucket_file/md5/d41d8cd98f00b204e9800998ecf8427e" => :file,
22
+ }.each do |key, terminus|
23
+ it "should use the #{terminus} terminus when requesting #{key.inspect}" do
24
+ described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
25
+
26
+ described_class.indirection.find(key)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "when running another application" do
32
+ {
33
+ "md5/d41d8cd98f00b204e9800998ecf8427e" => :file,
34
+ "https://puppetmaster:8140/production/file_bucket_file/md5/d41d8cd98f00b204e9800998ecf8427e" => :rest,
35
+ }.each do |key, terminus|
36
+ it "should use the #{terminus} terminus when requesting #{key.inspect}" do
37
+ described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
38
+
39
+ described_class.indirection.find(key)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,14 +1,9 @@
1
1
  #!/usr/bin/env rspec
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  require 'puppet/file_serving/content'
5
- require 'shared_behaviours/file_serving'
6
-
7
- describe Puppet::FileServing::Content, " when finding files" do
8
- it_should_behave_like "Puppet::FileServing::Files"
9
6
 
10
- before do
11
- @test_class = Puppet::FileServing::Content
12
- @indirection = Puppet::FileServing::Content.indirection
13
- end
7
+ describe Puppet::FileServing::Content do
8
+ it_should_behave_like "a file_serving model"
14
9
  end
@@ -1,15 +1,10 @@
1
1
  #!/usr/bin/env rspec
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  require 'puppet/file_serving/metadata'
5
- require 'shared_behaviours/file_serving'
6
- require 'puppet/indirector/file_metadata/file_server'
7
-
8
- describe Puppet::FileServing::Metadata, " when finding files" do
9
- it_should_behave_like "Puppet::FileServing::Files"
10
6
 
11
- before do
12
- @test_class = Puppet::FileServing::Metadata
13
- @indirection = Puppet::FileServing::Metadata.indirection
14
- end
7
+ describe Puppet::FileServing::Metadata do
8
+ it_should_behave_like "a file_serving model"
15
9
  end
10
+
@@ -44,12 +44,31 @@ describe Puppet::Network::RestAuthConfig do
44
44
  end
45
45
 
46
46
  def request(args = {})
47
- { :ip => '10.1.1.1', :node => 'host.domain.com', :key => 'key', :authenticated => true }.each do |k,v|
48
- args[k] ||= v
49
- end
47
+ args = {
48
+ :key => 'key',
49
+ :node => 'host.domain.com',
50
+ :ip => '10.1.1.1',
51
+ :authenticated => true
52
+ }.merge(args)
50
53
  ['test', :find, args[:key], args]
51
54
  end
52
55
 
56
+ it "should warn when matching against IP addresses" do
57
+ add_rule("allow 10.1.1.1")
58
+
59
+ @auth.should allow(request)
60
+
61
+ @logs.should be_any {|log| log.level == :warning and log.message =~ /Authentication based on IP address is deprecated/}
62
+ end
63
+
64
+ it "should not warn when matches against IP addresses fail" do
65
+ add_rule("allow 10.1.1.2")
66
+
67
+ @auth.should_not allow(request)
68
+
69
+ @logs.should_not be_any {|log| log.level == :warning and log.message =~ /Authentication based on IP address is deprecated/}
70
+ end
71
+
53
72
  it "should support IPv4 address" do
54
73
  add_rule("allow 10.1.1.1")
55
74
 
@@ -1,68 +1,80 @@
1
1
  #!/usr/bin/env rspec
2
- shared_examples_for "Puppet::FileServing::Files" do
3
- it "should use the rest terminus when the 'puppet' URI scheme is used and a host name is present" do
4
- uri = "puppet://myhost/fakemod/my/file"
5
-
6
- # It appears that the mocking somehow interferes with the caching subsystem.
7
- # This mock somehow causes another terminus to get generated.
8
- term = @indirection.terminus(:rest)
9
- @indirection.stubs(:terminus).with(:rest).returns term
10
- term.expects(:find)
11
- @indirection.find(uri)
12
- end
13
2
 
14
- it "should use the rest terminus when the 'puppet' URI scheme is used, no host name is present, and the process name is not 'puppet' or 'apply'" do
15
- uri = "puppet:///fakemod/my/file"
16
- Puppet.settings.stubs(:value).returns "foo"
17
- Puppet.settings.stubs(:value).with(:name).returns("puppetd")
18
- Puppet.settings.stubs(:value).with(:modulepath).returns("")
19
- @indirection.terminus(:rest).expects(:find)
20
- @indirection.find(uri)
21
- end
3
+ shared_examples_for "Puppet::FileServing::Files" do |indirection|
4
+ %w[find search].each do |method|
5
+ let(:request) { Puppet::Indirector::Request.new(indirection, method, 'foo') }
22
6
 
23
- it "should use the file_server terminus when the 'puppet' URI scheme is used, no host name is present, and the process name is 'puppet'" do
24
- uri = "puppet:///fakemod/my/file"
25
- Puppet::Node::Environment.stubs(:new).returns(stub("env", :name => "testing", :module => nil, :modulepath => []))
26
- Puppet.settings.stubs(:value).returns ""
27
- Puppet.settings.stubs(:value).with(:name).returns("puppet")
28
- Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever")
29
- @indirection.terminus(:file_server).expects(:find)
30
- @indirection.terminus(:file_server).stubs(:authorized?).returns(true)
31
- @indirection.find(uri)
32
- end
7
+ before :each do
8
+ # Stub this so we can set the :name setting
9
+ Puppet::Util::Settings::ReadOnly.stubs(:include?)
10
+ end
33
11
 
34
- it "should use the file_server terminus when the 'puppet' URI scheme is used, no host name is present, and the process name is 'apply'" do
35
- uri = "puppet:///fakemod/my/file"
36
- Puppet::Node::Environment.stubs(:new).returns(stub("env", :name => "testing", :module => nil, :modulepath => []))
37
- Puppet.settings.stubs(:value).returns ""
38
- Puppet.settings.stubs(:value).with(:name).returns("apply")
39
- Puppet.settings.stubs(:value).with(:fileserverconfig).returns("/whatever")
40
- @indirection.terminus(:file_server).expects(:find)
41
- @indirection.terminus(:file_server).stubs(:authorized?).returns(true)
42
- @indirection.find(uri)
43
- end
12
+ describe "##{method}" do
13
+ it "should proxy to file terminus if the path is absolute" do
14
+ request.key = make_absolute('/tmp/foo')
44
15
 
45
- it "should use the file terminus when the 'file' URI scheme is used" do
46
- uri = Puppet::Util.path_to_uri(File.expand_path('/fakemod/my/other file'))
47
- uri.scheme.should == 'file'
48
- @indirection.terminus(:file).expects(:find)
49
- @indirection.find(uri.to_s)
50
- end
16
+ described_class.indirection.terminus(:file).class.any_instance.expects(method).with(request)
51
17
 
52
- it "should use the file terminus when a fully qualified path is provided" do
53
- uri = File.expand_path("/fakemod/my/file")
54
- @indirection.terminus(:file).expects(:find)
55
- @indirection.find(uri)
56
- end
18
+ subject.send(method, request)
19
+ end
20
+
21
+ it "should proxy to file terminus if the protocol is file" do
22
+ request.protocol = 'file'
23
+
24
+ described_class.indirection.terminus(:file).class.any_instance.expects(method).with(request)
25
+
26
+ subject.send(method, request)
27
+ end
28
+
29
+ describe "when the protocol is puppet" do
30
+ before :each do
31
+ request.protocol = 'puppet'
32
+ end
33
+
34
+ describe "and a server is specified" do
35
+ before :each do
36
+ request.server = 'puppet_server'
37
+ end
38
+
39
+ it "should proxy to rest terminus if we're 'apply'" do
40
+ Puppet[:name] = 'apply'
41
+
42
+ described_class.indirection.terminus(:rest).class.any_instance.expects(method).with(request)
43
+
44
+ subject.send(method, request)
45
+ end
46
+
47
+ it "should proxy to rest terminus if we aren't 'apply'" do
48
+ Puppet[:name] = 'not_apply'
49
+
50
+ described_class.indirection.terminus(:rest).class.any_instance.expects(method).with(request)
51
+
52
+ subject.send(method, request)
53
+ end
54
+ end
55
+
56
+ describe "and no server is specified" do
57
+ before :each do
58
+ request.server = nil
59
+ end
60
+
61
+ it "should proxy to file_server if we're 'apply'" do
62
+ Puppet[:name] = 'apply'
63
+
64
+ described_class.indirection.terminus(:file_server).class.any_instance.expects(method).with(request)
65
+
66
+ subject.send(method, request)
67
+ end
68
+
69
+ it "should proxy to rest if we're not 'apply'" do
70
+ Puppet[:name] = 'not_apply'
57
71
 
58
- it "should use the configuration to test whether the request is allowed" do
59
- uri = "fakemod/my/file"
60
- mount = mock 'mount'
61
- config = stub 'configuration', :split_path => [mount, "eh"]
62
- @indirection.terminus(:file_server).stubs(:configuration).returns config
72
+ described_class.indirection.terminus(:rest).class.any_instance.expects(method).with(request)
63
73
 
64
- @indirection.terminus(:file_server).expects(:find)
65
- mount.expects(:allowed?).returns(true)
66
- @indirection.find(uri, :node => "foo", :ip => "bar")
74
+ subject.send(method, request)
75
+ end
76
+ end
77
+ end
78
+ end
67
79
  end
68
80
  end
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env rspec
2
+
3
+ shared_examples_for "a file_serving model" do
4
+ include PuppetSpec::Files
5
+
6
+ describe "#indirection" do
7
+ before :each do
8
+ # Never connect to the network, no matter what
9
+ described_class.indirection.terminus(:rest).class.any_instance.stubs(:find)
10
+ end
11
+
12
+ describe "when running the master application" do
13
+ before :each do
14
+ Puppet::Application[:master].setup_terminuses
15
+ end
16
+
17
+ {
18
+ "/etc/sudoers" => :file_server,
19
+ "file:///etc/sudoers" => :file_server,
20
+ "puppet:///modules/foo/bar" => :file_server,
21
+ "puppet://server/modules/foo/bar" => :file_server,
22
+ }.each do |key, terminus|
23
+ it "should use the #{terminus} terminus when requesting #{key.inspect}" do
24
+ described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
25
+
26
+ described_class.indirection.find(key)
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "when running the apply application" do
32
+ before :each do
33
+ # Stub this so we can set the 'name' setting
34
+ Puppet::Util::Settings::ReadOnly.stubs(:include?)
35
+ Puppet[:name] = 'apply'
36
+ end
37
+
38
+ {
39
+ "/etc/sudoers" => :file,
40
+ "file:///etc/sudoers" => :file,
41
+ "puppet:///modules/foo/bar" => :file_server,
42
+ "puppet://server/modules/foo/bar" => :rest,
43
+ }.each do |key, terminus|
44
+ it "should use the #{terminus} terminus when requesting #{key.inspect}" do
45
+ described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
46
+
47
+ described_class.indirection.find(key)
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "when running another application" do
53
+ before :each do
54
+ # Stub this so we can set the 'name' setting
55
+ Puppet::Util::Settings::ReadOnly.stubs(:include?)
56
+ Puppet[:name] = 'agent'
57
+ end
58
+
59
+ {
60
+ "/etc/sudoers" => :file,
61
+ "file:///etc/sudoers" => :file,
62
+ "puppet:///modules/foo/bar" => :rest,
63
+ "puppet://server/modules/foo/bar" => :rest,
64
+ }.each do |key, terminus|
65
+ it "should use the #{terminus} terminus when requesting #{key.inspect}" do
66
+ described_class.indirection.terminus(terminus).class.any_instance.expects(:find)
67
+
68
+ described_class.indirection.find(key)
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -158,80 +158,88 @@ describe Puppet::FileServing::Configuration do
158
158
  end
159
159
  end
160
160
 
161
- describe "when finding the mount name and relative path in a request key" do
162
- before do
163
- @config = Puppet::FileServing::Configuration.configuration
164
- @config.stubs(:find_mount)
161
+ describe "#split_path" do
162
+ let(:config) { Puppet::FileServing::Configuration.configuration }
163
+ let(:request) { stub 'request', :key => "foo/bar/baz", :options => {}, :node => nil, :environment => mock("env") }
165
164
 
166
- @request = stub 'request', :key => "foo/bar/baz", :options => {}, :node => nil, :environment => mock("env")
165
+ before do
166
+ config.stubs(:find_mount)
167
167
  end
168
168
 
169
169
  it "should reread the configuration" do
170
- @config.expects(:readconfig)
170
+ config.expects(:readconfig)
171
171
 
172
- @config.split_path(@request)
172
+ config.split_path(request)
173
173
  end
174
174
 
175
175
  it "should treat the first field of the URI path as the mount name" do
176
- @config.expects(:find_mount).with { |name, node| name == "foo" }
176
+ config.expects(:find_mount).with { |name, node| name == "foo" }
177
177
 
178
- @config.split_path(@request)
178
+ config.split_path(request)
179
179
  end
180
180
 
181
181
  it "should fail if the mount name is not alpha-numeric" do
182
- @request.expects(:key).returns "foo&bar/asdf"
182
+ request.expects(:key).returns "foo&bar/asdf"
183
183
 
184
- lambda { @config.split_path(@request) }.should raise_error(ArgumentError)
184
+ lambda { config.split_path(request) }.should raise_error(ArgumentError)
185
185
  end
186
186
 
187
187
  it "should support dashes in the mount name" do
188
- @request.expects(:key).returns "foo-bar/asdf"
188
+ request.expects(:key).returns "foo-bar/asdf"
189
189
 
190
- lambda { @config.split_path(@request) }.should_not raise_error(ArgumentError)
190
+ lambda { config.split_path(request) }.should_not raise_error(ArgumentError)
191
191
  end
192
192
 
193
193
  it "should use the mount name and environment to find the mount" do
194
- @config.expects(:find_mount).with { |name, env| name == "foo" and env == @request.environment }
195
- @request.stubs(:node).returns("mynode")
194
+ config.expects(:find_mount).with { |name, env| name == "foo" and env == request.environment }
195
+ request.stubs(:node).returns("mynode")
196
196
 
197
- @config.split_path(@request)
197
+ config.split_path(request)
198
198
  end
199
199
 
200
200
  it "should return nil if the mount cannot be found" do
201
- @config.expects(:find_mount).returns nil
201
+ config.expects(:find_mount).returns nil
202
202
 
203
- @config.split_path(@request).should be_nil
203
+ config.split_path(request).should be_nil
204
204
  end
205
205
 
206
206
  it "should return the mount and the relative path if the mount is found" do
207
207
  mount = stub 'mount', :name => "foo"
208
- @config.expects(:find_mount).returns mount
208
+ config.expects(:find_mount).returns mount
209
209
 
210
- @config.split_path(@request).should == [mount, "bar/baz"]
210
+ config.split_path(request).should == [mount, "bar/baz"]
211
211
  end
212
212
 
213
213
  it "should remove any double slashes" do
214
- @request.stubs(:key).returns "foo/bar//baz"
214
+ request.stubs(:key).returns "foo/bar//baz"
215
215
  mount = stub 'mount', :name => "foo"
216
- @config.expects(:find_mount).returns mount
216
+ config.expects(:find_mount).returns mount
217
+
218
+ config.split_path(request).should == [mount, "bar/baz"]
219
+ end
220
+
221
+ it "should fail if the path contains .." do
222
+ request.stubs(:key).returns 'module/foo/../../bar'
217
223
 
218
- @config.split_path(@request).should == [mount, "bar/baz"]
224
+ expect do
225
+ config.split_path(request)
226
+ end.to raise_error(ArgumentError, /Invalid relative path/)
219
227
  end
220
228
 
221
229
  it "should return the relative path as nil if it is an empty string" do
222
- @request.expects(:key).returns "foo"
230
+ request.expects(:key).returns "foo"
223
231
  mount = stub 'mount', :name => "foo"
224
- @config.expects(:find_mount).returns mount
232
+ config.expects(:find_mount).returns mount
225
233
 
226
- @config.split_path(@request).should == [mount, nil]
234
+ config.split_path(request).should == [mount, nil]
227
235
  end
228
236
 
229
237
  it "should add 'modules/' to the relative path if the modules mount is used but not specified, for backward compatibility" do
230
- @request.expects(:key).returns "foo/bar"
238
+ request.expects(:key).returns "foo/bar"
231
239
  mount = stub 'mount', :name => "modules"
232
- @config.expects(:find_mount).returns mount
240
+ config.expects(:find_mount).returns mount
233
241
 
234
- @config.split_path(@request).should == [mount, "foo/bar"]
242
+ config.split_path(request).should == [mount, "foo/bar"]
235
243
  end
236
244
  end
237
245
  end