diff options
author | danielsdeleo <dan@opscode.com> | 2013-07-02 15:44:57 -0700 |
---|---|---|
committer | danielsdeleo <dan@opscode.com> | 2013-07-02 19:04:02 -0700 |
commit | c2407b4187f16747979956b90a6dc98f3997b01c (patch) | |
tree | e8c17f1147683eac995291486400f8accdb1dcd1 | |
parent | a3565d9d674c777d9988bcbaa778862a02da5466 (diff) | |
download | chef-c2407b4187f16747979956b90a6dc98f3997b01c.tar.gz |
Use symlink source when inspecting current permissions
Fixes CHEF-4341 http://tickets.opscode.com/browse/CHEF-4341
When manage_symlink_source is enabled, File providers update
current_resource with the security attributes of the source file.
Subsequent actions (e.g., running FileAccessControl) use the values set
on current_resource to determine if they need to modify the system, so
setting them incorrect leads to a file resource being (not) updated
incorrectly.
-rw-r--r-- | lib/chef/provider/file.rb | 3 | ||||
-rw-r--r-- | lib/chef/resource/file.rb | 2 | ||||
-rw-r--r-- | lib/chef/scan_access_control.rb | 7 | ||||
-rw-r--r-- | spec/support/shared/functional/file_resource.rb | 60 | ||||
-rw-r--r-- | spec/unit/scan_access_control_spec.rb | 6 |
5 files changed, 64 insertions, 14 deletions
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb index 012073f674..e727aa9ec1 100644 --- a/lib/chef/provider/file.rb +++ b/lib/chef/provider/file.rb @@ -74,7 +74,7 @@ class Chef # Let children resources override constructing the @current_resource @current_resource ||= Chef::Resource::File.new(@new_resource.name) @current_resource.path(@new_resource.path) - if real_file?(@current_resource.path) && ::File.exists?(@current_resource.path) + if ::File.exists?(@current_resource.path) && ::File.file?(::File.realpath(@current_resource.path)) if @action != :create_if_missing && @current_resource.respond_to?(:checksum) @current_resource.checksum(checksum(@current_resource.path)) end @@ -292,6 +292,7 @@ class Chef converge_by(description) do unlink(@new_resource.path) end + @current_resource.checksum = nil @file_unlinked = true end end diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb index 15adb9dae8..676cbf200a 100644 --- a/lib/chef/resource/file.rb +++ b/lib/chef/resource/file.rb @@ -36,6 +36,8 @@ class Chef state_attrs :checksum, :owner, :group, :mode end + attr_writer :checksum + provides :file, :on_platforms => :all def initialize(name, run_context=nil) diff --git a/lib/chef/scan_access_control.rb b/lib/chef/scan_access_control.rb index 1384656a8b..01630a7254 100644 --- a/lib/chef/scan_access_control.rb +++ b/lib/chef/scan_access_control.rb @@ -127,7 +127,12 @@ class Chef end def stat - @stat ||= @new_resource.instance_of?(Chef::Resource::Link) ? ::File.lstat(@new_resource.path) : ::File.stat(@new_resource.path) + @stat ||= if @new_resource.instance_of?(Chef::Resource::Link) + ::File.lstat(@new_resource.path) + else + realpath = ::File.realpath(@new_resource.path) + ::File.stat(realpath) + end end end end diff --git a/spec/support/shared/functional/file_resource.rb b/spec/support/shared/functional/file_resource.rb index 83947f8afb..30f012bb0d 100644 --- a/spec/support/shared/functional/file_resource.rb +++ b/spec/support/shared/functional/file_resource.rb @@ -523,15 +523,8 @@ shared_examples_for "a configured file resource" do resource.path(link_path) # create symlinks for test context File.symlink(path, link_path) - - # Create source (real) file - File.open(path, "wb") { |f| f.write(wrong_content) } end - include_context "setup broken permissions" - - include_examples "a securable resource with existing target" - after(:each) do # shared examples should not change our test setup of a file resource # pointing at a symlink: @@ -539,9 +532,56 @@ shared_examples_for "a configured file resource" do FileUtils.rm_rf(link_path) end - it "does not replace the symlink with a real file" do - resource.run_action(:create) - File.should be_symlink(link_path) + context "and the permissions are incorrect" do + before do + # Create source (real) file + File.open(path, "wb") { |f| f.write(expected_content) } + end + + + include_context "setup broken permissions" + + include_examples "a securable resource with existing target" + + it "does not replace the symlink with a real file" do + resource.run_action(:create) + File.should be_symlink(link_path) + end + + end + + context "and the content is incorrect" do + before do + # Create source (real) file + File.open(path, "wb") { |f| f.write(wrong_content) } + end + + it "updates the source file content" do + pending + end + + it "marks the resource as updated" do + resource.run_action(:create) + resource.should be_updated_by_last_action + end + + it "does not replace the symlink with a real file" do + resource.run_action(:create) + File.should be_symlink(link_path) + end + end + + context "and the content and permissions are correct" do + let(:expect_updated?) { false } + + before do + # Create source (real) file + File.open(path, "wb") { |f| f.write(expected_content) } + end + include_context "setup correct permissions" + + include_examples "a securable resource with existing target" + end end diff --git a/spec/unit/scan_access_control_spec.rb b/spec/unit/scan_access_control_spec.rb index 8fcda0edb1..c83a552626 100644 --- a/spec/unit/scan_access_control_spec.rb +++ b/spec/unit/scan_access_control_spec.rb @@ -21,7 +21,8 @@ require 'chef/scan_access_control' describe Chef::ScanAccessControl do before do - @new_resource = Chef::Resource::File.new("/tmp/foo/bar/baz/qux") + @new_resource = Chef::Resource::File.new("/tmp/foo/bar/baz/link") + @real_file = "/tmp/foo/bar/real/file" @current_resource = Chef::Resource::File.new(@new_resource.path) @scanner = Chef::ScanAccessControl.new(@new_resource, @current_resource) end @@ -49,7 +50,8 @@ describe Chef::ScanAccessControl do before do @stat = mock("File::Stat for #{@new_resource.path}", :uid => 0, :gid => 0, :mode => 00100644) - File.should_receive(:stat).with(@new_resource.path).and_return(@stat) + File.should_receive(:realpath).with(@new_resource.path).and_return(@real_file) + File.should_receive(:stat).with(@real_file).and_return(@stat) File.should_receive(:exist?).with(@new_resource.path).and_return(true) end |