diff options
author | Lamont Granquist <lamont@opscode.com> | 2013-04-04 15:10:39 -0700 |
---|---|---|
committer | Lamont Granquist <lamont@opscode.com> | 2013-04-04 15:10:39 -0700 |
commit | 6b373de7fe38b934ee53c6e8116cec5e96fe0a59 (patch) | |
tree | ec480a70b269f381d2a607b0817ffb070bc0618b /lib/chef | |
parent | 8c2f2011b6c334f4c5483bea3769383a63a018f4 (diff) | |
download | chef-6b373de7fe38b934ee53c6e8116cec5e96fe0a59.tar.gz |
expand and fix selinux functionality
Diffstat (limited to 'lib/chef')
-rw-r--r-- | lib/chef/config.rb | 3 | ||||
-rw-r--r-- | lib/chef/provider.rb | 10 | ||||
-rw-r--r-- | lib/chef/provider/directory.rb | 1 | ||||
-rw-r--r-- | lib/chef/provider/file.rb | 15 | ||||
-rw-r--r-- | lib/chef/provider/file/deploy/mv_unix.rb | 8 | ||||
-rw-r--r-- | lib/chef/util/selinux.rb | 118 |
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 + |