FILE: C:\Users\All Users\PuppetLabs\puppet\var\lib\puppet\type\acl.rb

--
require 'puppet/type' require 'pathname' Puppet::Type.newtype(:acl) do require Pathname.new(__FILE__).dirname + '../../' + 'puppet/type/acl/ace' @doc = <<-'EOT' Manages access control lists (ACLs). The `acl` type is typically used when you need more complex management of permissions e.g. Windows. ACLs typically contain access control entries (ACEs) that define a trustee (identity) with a set of rights, whether the type is allow or deny, and how inheritance and propagation of those ACEs are applied to the resource target and child types under it. The order that ACEs are listed in is important on Windows as it determines what is applied first. Order of ACE application on Windows is explicit deny, explicit allow, inherited deny, then inherited allow. You cannot specify inherited ACEs in a manifest, only whether to allow upstream inheritance to flow into the managed target location (known as security descriptor). Please ensure your modeled resources follow this order or Windows will complain. NOTE: `acl` type does not enforce or complain about ACE order. For very specific examples, see the readme[1] and learn about the different features of the `acl` type. [1] https://github.com/puppetlabs/puppetlabs-acl/blob/master/README.md **Autorequires:** If Puppet is managing the user, group or target of an acl resource, the acl type will autorequire them. At a minimum, you need to provide the target and at least one permission (access control entry or ACE). It will default the other settings to sensible defaults. Minimally expressed sample usage: acl { 'c:/tempperms': permissions => [ { identity => 'Administrator', rights => ['full'] }, { identity => 'Users', rights => ['read','execute'] } ], } If you want you can provide a fully expressed ACL. The fully expressed acl in the sample below produces the same settings as the minimal sample above. Fully expressed sample usage: acl { 'c:/tempperms': target => 'c:/tempperms', target_type => 'file', purge => 'false', permissions => [ { identity => 'Administrator', rights => ['full'], perm_type=> 'allow', child_types => 'all', affects => 'all' }, { identity => 'Users', rights => ['read','execute'], perm_type=> 'allow', child_types => 'all', affects => 'all' } ], owner => 'Administrators', #Creator_Owner specific, doesn't manage unless specified group => 'Users', #Creator_Group specific, doesn't manage unless specified inherit_parent_permissions => 'true', } You can manage the same target across multiple acl resources with some caveats. The title of the resource needs to be unique. It is suggested that you only do this when you would need to (can get confusing). You should not set purge => 'true' on any of the resources that apply to the same target or you will see thrashing in reports as the permissions will be added and removed every catalog application. Use this feature with care. Manage same ACL resource multiple acls sample usage: acl { 'c:/tempperms': permissions => [ { identity => 'Administrator', rights => ['full'] } ], } acl { 'tempperms_Users': target => 'c:/tempperms', permissions => [ { identity => 'Users', rights => ['read','execute'] } ], } Removing upstream inheritance with purge sample usage: acl { 'c:/tempperms': purge => 'true', permissions => [ { identity => 'Administrators', rights => ['full'] }, { identity => 'Users', rights => ['full'] } ], inherit_parent_permissions => 'false', } Warning: While managing ACLs you could lock the user running Puppet completely out of managing resources using purge => 'true' with inherit_parent_permissions => 'false'. If Puppet is locked out of managing the resource, manual intervention on affected nodes will be required. EOT feature :ace_order_required, "The provider determines if the order of access control entries (ACE) is required." feature :can_inherit_parent_permissions, "The provider can inherit permissions from the parent." def initialize(*args) super # if target is unset, use the title if self[:target].nil? then self[:target] = self[:name] end end newparam(:name) do desc "The name of the acl resource. Used for uniqueness. Will set the target to this value if target is unset." validate do |value| if value.nil? or value.empty? raise ArgumentError, "A non-empty name must be specified." end end isnamevar end newparam(:target) do desc "The location the acl resource is pointing to. In the first release of ACL, this will be a file system location. The default is the name." validate do |value| if value.nil? or value.empty? raise ArgumentError, "A non-empty target must be specified." end end end newparam(:target_type) do desc "The type of target for the Acl resource. In the first release of ACL, only `file` is allowed. Defaults to `file`." newvalues(:file) defaultto(:file) end newparam(:purge) do desc "Purge specifies whether to remove other explicit permissions if not specified in the permissions set. This doesn't do anything with permissions inherited from parents (to remove those you should combine `purge => 'false', inherit_parent_permissions => 'false'` - be VERY careful in doing so, you could lock out Puppet from managing the resource and manual intervention will be required). This also allows you to ensure the permissions listed are not on the ACL with `purge => listed_permissions`. The default is `false`." newvalues(:true, :false, :listed_permissions) defaultto(:false) end newproperty(:permissions, :array_matching => :all) do desc "Permissions is an array containing Access Control Entries (ACEs). Certain Operating Systems require these ACEs to be in explicit order (Windows). Every element in the array is a hash that will at the very least need `identity` and `rights` e.g `{ identity => 'Administrators', rights => ['full'] }` and at the very most can include `perm_type`, `child_types`, `affects`, and `mask` (mask should only be specified be with `rights => ['mask_specific']`) e.g. `{ identity => 'Administrators', rights => ['full'], type=> 'allow', child_types => 'all', affects => 'all' }`. `identity` is a group, user or ID (SID on Windows). The identity must exist on the system and will auto-require on user and group resources. This can be in the form of: 1. User - e.g. `'Bob'` or `'TheNet\\Bob'` 2. Group e.g. `'Administrators'` or `'BUILTIN\\Administrators'` 3. SID (Security ID) e.g. `'S-1-5-18'`. `rights` is an array that contains `'full'`, `'modify'`, `'mask_specific'` or some combination of `'write'`, `'read'`, and `'execute'`. If you specify `'mask_specific'` you must also specify `mask` with an integer (passed as a string) that represents the permissions mask. It is the numeric representation of the binary flags. `perm_type` is represented as `'allow'` (default) or `'deny'`. `child_types` determines how an ACE is inherited downstream from the target. Valid values are `'all'` (default), `'objects'`, `'containers'` or `'none'`. `affects` determines how the downstream inheritance is propagated. Valid values are `'all'` (default), `'self_only'`, `'children_only'`, `'self_and_direct_children_only'` or `'direct_children_only'`. Each permission (ACE) is determined to be unique based on identity, perm_type, child_types, and affects. While you can technically create more than one ACE that differs from other ACEs only in rights, acl module is not able to tell the difference between those so it will appear that the resource is out of sync every run when it is not. While you will see `is_inherited => 'true'` when running puppet resource acl path, puppet will not be able to manage the inherited permissions so those will need to be removed if using that to build a manifest." validate do |value| if value.nil? || value.empty? raise ArgumentError, "A non-empty permissions must be specified." end if value['is_inherited'] raise ArgumentError, "Puppet can not manage inherited ACEs. If you used puppet resource acl to build your manifest, please remove any is_inherited => true entries in permissions when adding the resource to the manifest. Reference: #{value.inspect}" end end munge do |permission| Puppet::Type::Acl::Ace.new(permission, provider) end def insync?(current) if provider.respond_to?(:permissions_insync?) return provider.permissions_insync?(current, @should) end super(current) end def is_to_s(currentvalue) if provider.respond_to?(:permissions_to_s) return provider.permissions_to_s(currentvalue) end super(currentvalue) end def should_to_s(shouldvalue) if provider.respond_to?(:permissions_should_to_s) return provider.permissions_should_to_s(shouldvalue) elsif provider.respond_to?(:permissions_to_s) return provider.permissions_to_s(shouldvalue) end super(shouldvalue) end def self.format_value_for_display(value) if value.is_a? Array formatted_values = value.collect {|value| format_value_for_display(value)}.join(', ') "[#{formatted_values}\n]" elsif value.is_a? Puppet::Type::Acl::Ace "#{value.inspect}" elsif value.is_a? Hash hash = value.keys.sort {|a,b| a.to_s <=> b.to_s}.collect do |k| "#{k} => #{format_value_for_display(value[k])}" end.join(', ') "\n { #{hash} }" else "'#{value}'" end end end newproperty(:owner) do desc "The owner identity is also known as a trustee or principal that is said to own the particular acl/security descriptor. This can be in the form of: 1. User - e.g. `'Bob'` or `'TheNet\\Bob'` 2. Group e.g. `'Administrators'` or `'BUILTIN\\Administrators'` 3. SID (Security ID) e.g. `'S-1-5-18'`. Defaults to not specified on Windows. This allows owner to stay set to whatever it is currently set to (owner can vary depending on the original CREATOR OWNER). The trustee must exist on the system and will auto-require on user and group resources." validate do |value| if value.nil? || value.empty? raise ArgumentError, "A non-empty owner must be specified." end end def insync?(current) return true if should.nil? if provider.respond_to?(:owner_insync?) return provider.owner_insync?(current, should) end super(current) end def is_to_s(currentvalue) if provider.respond_to?(:owner_to_s) return provider.owner_to_s(currentvalue) end super(currentvalue) end alias :should_to_s :is_to_s end newproperty(:group) do desc "The group identity is also known as a trustee or principal that is said to have access to the particular acl/security descriptor. This can be in the form of: 1. User - e.g. `'Bob'` or `'TheNet\\Bob'` 2. Group e.g. `'Administrators'` or `'BUILTIN\\Administrators'` 3. SID (Security ID) e.g. `'S-1-5-18'`. Defaults to not specified on Windows. This allows group to stay set to whatever it is currently set to (group can vary depending on the original CREATOR GROUP). The trustee must exist on the system and will auto-require on user and group resources." validate do |value| if value.nil? || value.empty? raise ArgumentError, "A non-empty group must be specified." end end def insync?(current) return true if should.nil? if provider.respond_to?(:group_insync?) return provider.group_insync?(current, should) end super(current) end def is_to_s(currentvalue) if provider.respond_to?(:group_to_s) return provider.group_to_s(currentvalue) end super(currentvalue) end alias :should_to_s :is_to_s end newproperty(:inherit_parent_permissions, :boolean => true, :required_features=> :can_inherit_parent_permissions) do desc "Inherit Parent Permissions specifies whether to inherit permissions from parent ACLs or not. The default is `true`." newvalues(:true,:false) defaultto(true) def insync?(current) super(resource.munge_boolean(current)) end end validate do if self[:permissions] == [] raise ArgumentError, "Value for permissions should be an array with at least one element specified." end if provider.respond_to?(:validate) provider.validate end end autorequire(:file) do required_file = [] if self[:target] && self[:target_type] == :file target_path = File.expand_path(self[:target]).to_s required_file << target_path end required_file end autorequire(:user) do required_users = [] if provider.respond_to?(:get_account_name) has_account_name_method = true else has_account_name_method = false end if self[:owner] if has_account_name_method required_users << "#{provider.get_account_name(self[:owner])}" end # add the unqualified item whether qualified is found or not required_users << "#{self[:owner]}" end if self[:group] if has_account_name_method required_users << "#{provider.get_account_name(self[:group])}" end # add the unqualified item whether qualified is found or not required_users << "#{self[:group]}" end permissions = self[:permissions] unless permissions.nil? permissions.each do |permission| if has_account_name_method required_users << "#{provider.get_account_name(permission.identity)}" end required_users << "#{permission.identity}" end end required_users.uniq end autorequire(:group) do required_groups = [] if provider.respond_to?(:get_group_name) has_account_group_method = true else has_account_group_method = false end if self[:owner] if has_account_group_method required_groups << "#{provider.get_group_name(self[:owner])}" end # add the unqualified item whether qualified is found or not required_groups << "#{self[:owner]}" end if self[:group] if has_account_group_method required_groups << "#{provider.get_group_name(self[:group])}" end # add the unqualified item whether qualified is found or not required_groups << "#{self[:group]}" end permissions = self[:permissions] unless permissions.nil? permissions.each do |permission| if has_account_group_method required_groups << "#{provider.get_group_name(permission.identity)}" end required_groups << "#{permission.identity}" end end required_groups.uniq end def munge_boolean(value) case value when true, "true", :true :true when false, "false", :false :false else fail("munge_boolean only takes booleans") end end end
--