summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Dibowitz <phil@ipom.com>2015-08-11 11:21:27 -0700
committerPhil Dibowitz <phil@ipom.com>2015-08-11 11:21:27 -0700
commit2999d552880ff8fe2d056f89205114ab7c3c9979 (patch)
treea0f01db1bd3ba19cfac6cc1455813645e3feb5c4
parent3a5e1819c4439836767a001182c1e19de1cfb7e9 (diff)
parent55b584bd808ffce4e9fd54e4a65a9964a75e7c07 (diff)
downloadchef-2999d552880ff8fe2d056f89205114ab7c3c9979.tar.gz
Merge pull request #3704 from natewalck/elcap-sipfix
Add support for OS X 10.11 SIP paths
-rw-r--r--chef-config/lib/chef-config/path_helper.rb31
-rw-r--r--lib/chef/provider/directory.rb16
-rw-r--r--spec/unit/provider/directory_spec.rb34
3 files changed, 79 insertions, 2 deletions
diff --git a/chef-config/lib/chef-config/path_helper.rb b/chef-config/lib/chef-config/path_helper.rb
index acc6b76377..45f451479a 100644
--- a/chef-config/lib/chef-config/path_helper.rb
+++ b/chef-config/lib/chef-config/path_helper.rb
@@ -228,6 +228,37 @@ module ChefConfig
joined_paths
end
end
+
+ # Determine if the given path is protected by OS X System Integrity Protection.
+ def self.is_sip_path?(path, node)
+ if node['platform'] == 'mac_os_x' and Gem::Version.new(node['platform_version']) >= Gem::Version.new('10.11')
+ # todo: parse rootless.conf for this?
+ sip_paths= [
+ '/System', '/bin', '/sbin', '/usr',
+ ]
+ sip_paths.each do |sip_path|
+ ChefConfig.logger.info("This is a SIP path, checking if it in exceptions list.")
+ return true if path.start_with?(sip_path)
+ end
+ false
+ else
+ false
+ end
+ end
+ # Determine if the given path is on the exception list for OS X System Integrity Protection.
+ def self.writable_sip_path?(path)
+ # todo: parse rootless.conf for this?
+ sip_exceptions = [
+ '/System/Library/Caches', '/System/Library/Extensions',
+ '/System/Library/Speech', '/System/Library/User Template',
+ '/usr/libexec/cups', '/usr/local', '/usr/share/man'
+ ]
+ sip_exceptions.each do |exception_path|
+ return true if path.start_with?(exception_path)
+ end
+ ChefConfig.logger.error("Cannot write to a SIP Path on OS X 10.11+")
+ false
+ end
end
end
diff --git a/lib/chef/provider/directory.rb b/lib/chef/provider/directory.rb
index 4d5423d0e8..8892d3a73d 100644
--- a/lib/chef/provider/directory.rb
+++ b/lib/chef/provider/directory.rb
@@ -64,7 +64,13 @@ class Chef
is_parent_writable = lambda do |base_dir|
base_dir = ::File.dirname(base_dir)
if ::File.exists?(base_dir)
- Chef::FileAccessControl.writable?(base_dir)
+ if Chef::FileAccessControl.writable?(base_dir)
+ true
+ elsif Chef::Util::PathHelper.is_sip_path?(base_dir, node)
+ Chef::Util::PathHelper.writable_sip_path?(base_dir)
+ else
+ false
+ end
else
is_parent_writable.call(base_dir)
end
@@ -74,7 +80,13 @@ class Chef
# in why run mode & parent directory does not exist no permissions check is required
# If not in why run, permissions must be valid and we rely on prior assertion that dir exists
if !whyrun_mode? || ::File.exists?(parent_directory)
- Chef::FileAccessControl.writable?(parent_directory)
+ if Chef::FileAccessControl.writable?(parent_directory)
+ true
+ elsif Chef::Util::PathHelper.is_sip_path?(parent_directory, node)
+ Chef::Util::PathHelper.writable_sip_path?(@new_resource.path)
+ else
+ false
+ end
else
true
end
diff --git a/spec/unit/provider/directory_spec.rb b/spec/unit/provider/directory_spec.rb
index 38d6db8320..e79f41d9f4 100644
--- a/spec/unit/provider/directory_spec.rb
+++ b/spec/unit/provider/directory_spec.rb
@@ -197,6 +197,40 @@ describe Chef::Provider::Directory do
expect { directory.run_action(:create) }.to raise_error(Chef::Exceptions::EnclosingDirectoryDoesNotExist)
end
end
+
+ describe "on OS X" do
+ before do
+ allow(node).to receive(:[]).with("platform").and_return('mac_os_x')
+ new_resource.path "/usr/bin/chef_test"
+ new_resource.recursive false
+ end
+
+ it "os x 10.10 can write to sip locations" do
+ allow(node).to receive(:[]).with("platform_version").and_return('10.10')
+ allow(Dir).to receive(:mkdir).and_return([true], [])
+ allow(::File).to receive(:directory?).and_return(true)
+ allow(Chef::FileAccessControl).to receive(:writable?).and_return(true)
+ directory.run_action(:create)
+ expect(new_resource).to be_updated
+ end
+
+ it "os x 10.11 cannot write to sip locations" do
+ allow(node).to receive(:[]).with("platform_version").and_return('10.11')
+ allow(::File).to receive(:directory?).and_return(true)
+ allow(Chef::FileAccessControl).to receive(:writable?).and_return(false)
+ expect {directory.run_action(:create) }.to raise_error(Chef::Exceptions::InsufficientPermissions)
+ end
+
+ it "os x 10.11 can write to sip exlcusions" do
+ new_resource.path "/usr/local/chef_test"
+ allow(node).to receive(:[]).with("platform_version").and_return('10.11')
+ allow(::File).to receive(:directory?).and_return(true)
+ allow(Dir).to receive(:mkdir).and_return([true], [])
+ allow(Chef::FileAccessControl).to receive(:writable?).and_return(false)
+ directory.run_action(:create)
+ expect(new_resource).to be_updated
+ end
+ end
end
describe "#run_action(:create)" do