# # Cookbook:: selinux # Resource:: fcontext # # 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. # unified_mode true property :file_spec, String, name_property: true, description: 'Path to or regex matching the files or directoriesto label' property :secontext, String, required: %i(add modify manage), description: 'SELinux context to assign' property :file_type, String, default: 'a', equal_to: %w(a f d c b s l p), description: 'The type of the file being labeled' action_class do include SELinux::Cookbook::StateHelpers def current_file_context file_hash = { 'a' => 'all files', 'f' => 'regular file', 'd' => 'directory', 'c' => 'character device', 'b' => 'block device', 's' => 'socket', 'l' => 'symbolic link', 'p' => 'named pipe', } contexts = shell_out!('semanage fcontext -l').stdout.split("\n") # pull out file label from user:role:type:level context string contexts.grep(/^#{Regexp.escape(new_resource.file_spec)}\s+#{file_hash[new_resource.file_type]}/) do |c| c.match(/.+ (?.+):(?.+):(?.+):(?.+)$/)[:type] # match returns ['foo'] or [], shift converts that to 'foo' or nil end.shift end # Run restorecon to fix label # https://github.com/sous-chefs/selinux_policy/pull/72#issuecomment-338718721 def relabel_files spec = new_resource.file_spec escaped = Regexp.escape spec # find common path between regex and string common = if spec == escaped spec else index = spec.size.times { |i| break i if spec[i] != escaped[i] } ::File.dirname spec[0...index] end # if path is not absolute, ignore it and search everything common = '/' if common[0] != '/' if ::File.exist? common shell_out!("find #{common.shellescape} -ignore_readdir_race -regextype posix-egrep -regex #{spec.shellescape} -prune -print0 | xargs -0 restorecon -iRv") end end end action :manage do run_action(:add) run_action(:modify) end action :addormodify do Chef::Log.warn('The :addormodify action for selinux_fcontext is deprecated and will be removed in a future release. Use the :manage action instead.') run_action(:manage) end # Create if doesn't exist, do not touch if fcontext is already registered action :add do if selinux_disabled? Chef::Log.warn("Unable to add SELinux fcontext #{new_resource.name} as SELinux is disabled") return end unless current_file_context converge_by "adding label #{new_resource.secontext} to #{new_resource.file_spec}" do shell_out!("semanage fcontext -a -f #{new_resource.file_type} -t #{new_resource.secontext} '#{new_resource.file_spec}'") relabel_files end end end # Only modify if fcontext exists & doesn't have the correct label already action :modify do if selinux_disabled? Chef::Log.warn("Unable to modify SELinux fcontext #{new_resource.name} as SELinux is disabled") return end if current_file_context && current_file_context != new_resource.secontext converge_by "modifying label #{new_resource.secontext} to #{new_resource.file_spec}" do shell_out!("semanage fcontext -m -f #{new_resource.file_type} -t #{new_resource.secontext} '#{new_resource.file_spec}'") relabel_files end end end # Delete if exists action :delete do if selinux_disabled? Chef::Log.warn("Unable to delete SELinux fcontext #{new_resource.name} as SELinux is disabled") return end if current_file_context converge_by "deleting label for #{new_resource.file_spec}" do shell_out!("semanage fcontext -d -f #{new_resource.file_type} '#{new_resource.file_spec}'") relabel_files end end end