summaryrefslogtreecommitdiff
path: root/lib/chef
diff options
context:
space:
mode:
authorLamont Granquist <lamont@opscode.com>2013-04-04 15:10:39 -0700
committerLamont Granquist <lamont@opscode.com>2013-04-04 15:10:39 -0700
commit6b373de7fe38b934ee53c6e8116cec5e96fe0a59 (patch)
treeec480a70b269f381d2a607b0817ffb070bc0618b /lib/chef
parent8c2f2011b6c334f4c5483bea3769383a63a018f4 (diff)
downloadchef-6b373de7fe38b934ee53c6e8116cec5e96fe0a59.tar.gz
expand and fix selinux functionality
Diffstat (limited to 'lib/chef')
-rw-r--r--lib/chef/config.rb3
-rw-r--r--lib/chef/provider.rb10
-rw-r--r--lib/chef/provider/directory.rb1
-rw-r--r--lib/chef/provider/file.rb15
-rw-r--r--lib/chef/provider/file/deploy/mv_unix.rb8
-rw-r--r--lib/chef/util/selinux.rb118
6 files changed, 145 insertions, 10 deletions
diff --git a/lib/chef/config.rb b/lib/chef/config.rb
index f18265a830..71a4827436 100644
--- a/lib/chef/config.rb
+++ b/lib/chef/config.rb
@@ -20,6 +20,7 @@
require 'chef/log'
require 'mixlib/config'
+require 'chef/util/selinux'
class Chef
class Config
@@ -348,7 +349,7 @@ class Chef
# selinux command to restore file contexts
selinux_restorecon_command "/sbin/restorecon -R"
# guess if you're running selinux or not -- override this if it guesses wrong
- selinux_enabled system( "/usr/sbin/selinuxenabled" )
+ selinux_enabled Chef::Util::Selinux.new.selinuxenabled?
# set this to something like Chef::Provider::File::Deploy::CpUnix if you want to override behavior globally
file_deployment_strategy nil
diff --git a/lib/chef/provider.rb b/lib/chef/provider.rb
index 302a9fb106..2d1c28ab1a 100644
--- a/lib/chef/provider.rb
+++ b/lib/chef/provider.rb
@@ -128,8 +128,16 @@ class Chef
requirements.run(@action)
end
+ def resource_updated?
+ !converge_actions.empty? || @new_resource.updated_by_last_action?
+ end
+
+ def resource_up_to_date?
+ !resource_updated?
+ end
+
def set_updated_status
- if converge_actions.empty? && !@new_resource.updated_by_last_action?
+ if resource_up_to_date?
events.resource_up_to_date(@new_resource, @action)
else
events.resource_updated(@new_resource, @action)
diff --git a/lib/chef/provider/directory.rb b/lib/chef/provider/directory.rb
index 3de970ab1d..e4b4b42898 100644
--- a/lib/chef/provider/directory.rb
+++ b/lib/chef/provider/directory.rb
@@ -102,6 +102,7 @@ class Chef
end
end
do_acl_changes
+ do_selinux("-r")
load_resource_attributes_from_file(@new_resource)
end
diff --git a/lib/chef/provider/file.rb b/lib/chef/provider/file.rb
index da328c8771..ce611869e4 100644
--- a/lib/chef/provider/file.rb
+++ b/lib/chef/provider/file.rb
@@ -25,6 +25,7 @@ require 'etc'
require 'fileutils'
require 'chef/scan_access_control'
require 'chef/mixin/checksum'
+require 'chef/mixin/shell_out'
require 'chef/util/backup'
require 'chef/util/diff'
@@ -43,6 +44,7 @@ class Chef
class File < Chef::Provider
include Chef::Mixin::EnforceOwnershipAndPermissions
include Chef::Mixin::Checksum
+ include Chef::Mixin::ShellOut
attr_reader :deployment_strategy
@@ -94,6 +96,7 @@ class Chef
do_create_file
do_contents_changes
do_acl_changes
+ do_selinux
load_resource_attributes_from_file(@new_resource)
end
@@ -211,6 +214,18 @@ class Chef
tempfile.unlink
end
+ # this might be made into some kind of generic platform-dependent post-converge hook for
+ # file-like resources, but for now we only have the single selinux use case.
+ def do_selinux(command_args = nil)
+ if Chef::Config[:selinux_enabled] && resource_updated?
+ cmd = "#{Chef::Config[:selinux_restorecon_command]} #{command_args} #{@new_resource.path}"
+ converge_by("fix selinux context with #{cmd}") do
+ Chef::Log.debug("running #{cmd}")
+ shell_out!(cmd)
+ end
+ end
+ end
+
def do_acl_changes
if access_controls.requires_changes?
converge_by(access_controls.describe_changes) do
diff --git a/lib/chef/provider/file/deploy/mv_unix.rb b/lib/chef/provider/file/deploy/mv_unix.rb
index be80d77d06..770f8aa8d3 100644
--- a/lib/chef/provider/file/deploy/mv_unix.rb
+++ b/lib/chef/provider/file/deploy/mv_unix.rb
@@ -68,14 +68,6 @@ class Chef
rescue Errno::EPERM
Chef::Log.warn("Could not set gid = #{gid} on #{dst}, file modes not preserved")
end
-
-
- # handle selinux if we need to run restorecon
- if Chef::Config[:selinux_enabled]
- Chef::Log.debug("selinux is enabled, fixing selinux permissions")
- cmd = "#{Chef::Config[:selinux_restorecon_comand]} #{dst}"
- shell_out!(cmd)
- end
end
end
end
diff --git a/lib/chef/util/selinux.rb b/lib/chef/util/selinux.rb
new file mode 100644
index 0000000000..408ed4aa0a
--- /dev/null
+++ b/lib/chef/util/selinux.rb
@@ -0,0 +1,118 @@
+#
+# Author:: Sean O'Meara
+# Author:: Kevin Keane
+# Author:: Lamont Granquist (<lamont@opscode.com>)
+#
+# Copyright:: Copyright (c) 2011 Opscode, Inc.
+# Copyright:: Copyright (c) 2013, North County Tech Center, LLC
+#
+# License:: Apache License, Version 2.0
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+require 'chef/mixin/shell_out'
+
+#
+# NB: We take the approach that provisioning an selinux enabled server
+# without installing the selinux utilities is completely incoherent
+# and needs to be fixed in the provisioner / base image.
+#
+
+class Chef
+ class Util
+ class Selinux
+
+ include Chef::Mixin::ShellOut
+
+ attr_accessor :setenforce_path
+ attr_accessor :getenforce_path
+ attr_accessor :selinuxenabled_path
+
+ def setenforce_path
+ @setenforce_path ||= which("setenforce")
+ end
+
+ def getenforce_path
+ @getenforce_path ||= which("getenforce")
+ end
+
+ def selinuxenabled_path
+ @selinuxenabled_path ||= which("selinuxenabled")
+ end
+
+ def setenforce(state)
+ if setenforce_path
+ case state
+ when :enforcing
+ shell_out!("#{setenforce_path} 1")
+ when :permissive
+ shell_out!("#{setenforce_path} 0")
+ else
+ raise ArgumentError, "Bad argument to Chef::Util::Seliux#setenforce: #{state}"
+ end
+ else
+ # FIXME?: manually roll our own setenforce
+ end
+ raise RuntimeError, "Called setenforce but binary does not exist (try installing selinux-utils or libselinux-utils)"
+ end
+
+ def getenforce
+ if getenforce_path
+ cmd = shell_out!(getenforce_path)
+ case cmd.stdout
+ when /Permissive/i
+ return :permissive
+ when /Enforcing/i
+ return :enforcing
+ when /Disabled/i
+ return :disabled
+ else
+ raise RuntimeError, "Unknown output from getenforce: #{cmd.stdout}"
+ end
+ else
+ # FIXME?: manually roll our own getenforce
+ end
+ raise RuntimeError, "Called getenforce but binary does not exist (try installing selinux-utils or libselinux-utils)"
+ end
+
+ def selinuxenabled?
+ if selinuxenabled_path
+ cmd = shell_out(selinuxenabled_path)
+ case cmd.exitstatus
+ when 1
+ return false
+ when 0
+ return true
+ else
+ raise RuntimeError, "Unknown exit code from selinuxenabled: #{cmd.exitstatus}"
+ end
+ else
+ # FIXME?: manually roll our own selinuxenabled
+ end
+ false
+ end
+
+ private
+
+ def which(cmd)
+ paths = ENV['PATH'].split(File::PATH_SEPARATOR) + [ '/bin', '/usr/bin', '/sbin', '/usr/sbin' ]
+ paths.each do |path|
+ filename = File.join(path, cmd)
+ return filename if File.executable?(filename)
+ end
+ false
+ end
+ end
+ end
+end
+