133 lines
4.2 KiB
Ruby
133 lines
4.2 KiB
Ruby
#
|
|
# 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(/.+ (?<user>.+):(?<role>.+):(?<type>.+):(?<level>.+)$/)[: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
|