module Chef::FileAccessControl::Windows
Constants
- ACE
- ACL
- SID
- Security
Public Class Methods
included(base)
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 42 def self.included(base) # When this file is mixed in, make sure we also add the class methods base.send :extend, ClassMethods end
Public Instance Methods
define_resource_requirements()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 59 def define_resource_requirements # windows FAC has no assertions end
describe_changes()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 67 def describe_changes # FIXME: describe what these are changing from and to changes = [] changes << "change dacl" if should_update_dacl? changes << "change owner" if should_update_owner? changes << "change group" if should_update_group? changes end
requires_changes?()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 63 def requires_changes? should_update_dacl? || should_update_owner? || should_update_group? end
set_all()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 53 def set_all set_owner set_group set_dacl end
set_all!()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 47 def set_all! set_owner! set_group! set_dacl end
Private Instance Methods
acls_equal(target_acl, actual_acl)
click to toggle source
Compare the actual ACL
on a resource with the ACL
we want. This ignores explicit ACLs on the target, and does mask prediction (if you set GENERIC_WRITE, Windows
will flip on a whole bunch of other rights on the file when you save the ACL
)
# File lib/chef/file_access_control/windows.rb, line 82 def acls_equal(target_acl, actual_acl) if actual_acl.nil? return target_acl.nil? end actual_acl = actual_acl.select { |ace| !ace.inherited? } # When ACLs apply to children, Windows splits them on the file system into two ACLs: # one specific applying to this container, and one generic applying to children. new_target_acl = [] target_acl.each do |target_ace| if target_ace.flags & INHERIT_ONLY_ACE == 0 self_ace = target_ace.dup # We need flag value which is already being set in case of WRITE permissions as 3, so we will not be overwriting it with the hard coded value. self_ace.flags = 0 unless target_ace.mask == Chef::ReservedNames::Win32::API::Security::WRITE self_ace.mask = securable_object.predict_rights_mask(target_ace.mask) new_target_acl << self_ace end # As there is no inheritance needed in case of WRITE permissions. if target_ace.mask != Chef::ReservedNames::Win32::API::Security::WRITE && target_ace.flags & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE) != 0 children_ace = target_ace.dup children_ace.flags |= INHERIT_ONLY_ACE new_target_acl << children_ace end end actual_acl == new_target_acl end
calculate_flags(rights)
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 244 def calculate_flags(rights) # Handle inheritance flags flags = 0 # # Configure child inheritance only if the resource is some # type of a directory. # if resource.is_a? Chef::Resource::Directory case rights[:applies_to_children] when :containers_only flags |= CONTAINER_INHERIT_ACE when :objects_only flags |= OBJECT_INHERIT_ACE when true, nil flags |= CONTAINER_INHERIT_ACE flags |= OBJECT_INHERIT_ACE end end if rights[:applies_to_self] == false flags |= INHERIT_ONLY_ACE end if rights[:one_level_deep] flags |= NO_PROPAGATE_INHERIT_ACE end flags end
calculate_mask(permissions)
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 222 def calculate_mask(permissions) mask = 0 [ permissions ].flatten.each do |permission| case permission when :full_control mask |= GENERIC_ALL when :modify mask |= GENERIC_WRITE | GENERIC_READ | GENERIC_EXECUTE | DELETE when :read mask |= GENERIC_READ when :read_execute mask |= GENERIC_READ | GENERIC_EXECUTE when :write mask |= WRITE else # Otherwise, assume it's an integer specifying the actual flags mask |= permission end end mask end
existing_descriptor()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 109 def existing_descriptor securable_object.security_descriptor end
get_sid(value)
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 113 def get_sid(value) if value.is_a?(String) begin Security.convert_string_sid_to_sid(value) rescue Chef::Exceptions::Win32APIError SID.from_account(value) end elsif value.is_a?(SID) value else raise "Must specify username, group or SID: #{value}" end end
mode_ace(sid, mode)
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 212 def mode_ace(sid, mode) mask = 0 mask |= GENERIC_READ if mode & 4 != 0 mask |= (GENERIC_WRITE | DELETE) if mode & 2 != 0 mask |= GENERIC_EXECUTE if mode & 1 != 0 return [] if mask == 0 [ ACE.access_allowed(sid, mask) ] end
securable_object()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 127 def securable_object @securable_object ||= begin if file.is_a?(String) so = Chef::ReservedNames::Win32::Security::SecurableObject.new(file.dup) end raise ArgumentError, "'file' must be a valid path or object of type 'Chef::ReservedNames::Win32::Security::SecurableObject'" unless so.is_a? Chef::ReservedNames::Win32::Security::SecurableObject so end end
set_dacl()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 151 def set_dacl dacl = target_dacl existing_dacl = existing_descriptor.dacl inherits = target_inherits if ! inherits.nil? && inherits != existing_descriptor.dacl_inherits? # We have to set DACL along with inherits. If rights were not # specified, we need to change only inherited ACLs and leave # explicit ACLs alone. if dacl.nil? && !existing_dacl.nil? dacl = ACL.create(existing_dacl.select { |ace| !ace.inherited? }) end securable_object.set_dacl(dacl, inherits) Chef::Log.info("#{log_string} permissions changed to #{dacl} with inherits of #{inherits}") modified elsif dacl && !acls_equal(dacl, existing_dacl) securable_object.dacl = dacl Chef::Log.info("#{log_string} permissions changed to #{dacl}") modified end end
set_dacl!()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 147 def set_dacl! set_dacl end
set_group()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 186 def set_group if (group = target_group) && (group != existing_descriptor.group) set_group! end end
set_group!()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 178 def set_group! if (group = target_group) Chef::Log.info("#{log_string} group changed to #{group}") securable_object.group = group modified end end
set_owner()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 206 def set_owner if (owner = target_owner) && (owner != existing_descriptor.owner) set_owner! end end
set_owner!()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 198 def set_owner! if owner = target_owner Chef::Log.info("#{log_string} owner changed to #{owner}") securable_object.owner = owner modified end end
should_update_dacl?()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 138 def should_update_dacl? return true unless ::File.exist?(file) || ::File.symlink?(file) dacl = target_dacl existing_dacl = existing_descriptor.dacl inherits = target_inherits ( ! inherits.nil? && inherits != existing_descriptor.dacl_inherits? ) || ( dacl && !acls_equal(dacl, existing_dacl) ) end
should_update_group?()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 172 def should_update_group? return true unless ::File.exist?(file) || ::File.symlink?(file) (group = target_group) && (group != existing_descriptor.group) end
should_update_owner?()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 192 def should_update_owner? return true unless ::File.exist?(file) || ::File.symlink?(file) (owner = target_owner) && (owner != existing_descriptor.owner) end
target_dacl()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 274 def target_dacl return nil if resource.rights.nil? && resource.deny_rights.nil? && resource.mode.nil? acls = nil unless resource.deny_rights.nil? acls = [] if acls.nil? resource.deny_rights.each do |rights| mask = calculate_mask(rights[:permissions]) [ rights[:principals] ].flatten.each do |principal| sid = get_sid(principal) flags = calculate_flags(rights) acls.push ACE.access_denied(sid, mask, flags) end end end unless resource.rights.nil? acls = [] if acls.nil? resource.rights.each do |rights| mask = calculate_mask(rights[:permissions]) [ rights[:principals] ].flatten.each do |principal| sid = get_sid(principal) flags = calculate_flags(rights) acls.push ACE.access_allowed(sid, mask, flags) end end end unless resource.mode.nil? acls = [] if acls.nil? mode = (resource.mode.respond_to?(:oct) ? resource.mode.oct : resource.mode.to_i) & 0777 owner = target_owner if owner acls += mode_ace(owner, (mode & 0700) >> 6) elsif mode & 0700 != 0 Chef::Log.warn("Mode #{sprintf("%03o", mode)} includes bits for the owner, but owner is not specified") end group = target_group if group acls += mode_ace(group, (mode & 070) >> 3) elsif mode & 070 != 0 Chef::Log.warn("Mode #{sprintf("%03o", mode)} includes bits for the group, but group is not specified") end acls += mode_ace(SID.Everyone, (mode & 07)) end # 'acls.nil?' is true if uninitialized, but false if the initial empty array value. # 'acls.empty?' cannot be called if acls is nil but successfully guards against using the empty array value. # either case should return nil from this method. (acls.nil? || acls.empty?) ? nil : Chef::ReservedNames::Win32::Security::ACL.create(acls) end
target_group()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 333 def target_group return nil if resource.group.nil? get_sid(resource.group) end
target_inherits()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 339 def target_inherits resource.inherits end
target_owner()
click to toggle source
# File lib/chef/file_access_control/windows.rb, line 343 def target_owner return nil if resource.owner.nil? get_sid(resource.owner) end