Version information
This version is compatible with:
- Puppet Enterprise >= 3.2.0 < 3.4.0
- Puppet >= 3.4.0
Start using this module
Add this module to your Puppetfile:
mod 'puppetlabs-acl', '1.0.1'
Learn more about managing modules with a PuppetfileDocumentation
ACL (Access Control List)
####Table of Contents
- Overview - What is the acl module?
- Module Description - What does the module do?
- Setup - The basics of getting started with acl
- Usage - The custom type available for configuration
- Limitations - Known issues in acl
- Development - Guide for contributing to the module
##Overview
The acl module uses Puppet to manage Access Control Lists on Windows.
##Module Description
The acl module adds a type and provider for managing permissions through Windows ACLs.
ACLs typically contain a list of access control entries (ACEs). An ACE is a defined trustee (identity) with a set of rights. For each ACE, the ACL contains an allowed/denied status, as well as the ACE's inheritance and propagation strategy. The order of ACEs within the ACL determines what allowed/denied status is applied first.
##Setup
The best way to install this module is by executing the following command on your puppet master or local Puppet install:
$ puppet module install [--modulepath <path>] puppetlabs/acl
The above command also includes the optional argument to specify your puppet master's modulepath
as the location to install the module.
###Beginning with acl
Each ACE has one of four possible statuses and the order you list the ACEs in is important for which status is applied first. The allow/deny types available are: 'explicit deny', 'explicit allow', 'inherited deny', and 'inherited allow'.
You cannot specify inherited ACEs in a manifest; you can only specify 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. The acl
type does not enforce or complain about ACE order.
For a basic implementation of the acl module, 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.
acl { 'c:/tempperms':
permissions => [
{ identity => 'Administrator', rights => ['full'] },
{ identity => 'Users', rights => ['read','execute'] }
],
}
##Usage
###Defined Type: acl
The acl
type contains two means of customization: parameters and properties. Parameters guide how the module operates. Properties guide ACL itself.
Below is an example of the acl
type with all parameters and properties.
acl { 'name':
target => 'absolute/path',
target_type => '<file>',
purge => '<true| false | listed_permissions>',
permissions => [
{ identity => '<identity>',
rights => [<rights>],
type => '<type>',
affects => '<affects>',
child_types => '<child_types>'
}
],
owner => '<owner>',
group => '<group>',
inherit_parent_permissions => '<true | false>',
}
####Parameters
#####name
The name of the ACL resource; will be used for target
if target
is not set.
#####purge
Specifies whether to remove other explicit permissions if not specified in the permissions
property. Valid values are 'true', 'false', and 'listed_permissions'. Default is 'false'.
You can use this parameter to ensure specific permissions are absent from the ACL with purge => 'listed_permissions'
.
This parameter does not impact permissions inherited from parents. To remove parent permissions, combine purge => 'false'
with inherit_parent_permissions => 'false'
. Note: Be VERY careful when removing parent permissions, as it is possible to lock out Puppet from managing the resource, which will require manual intervention.
#####target
The location of the ACL resource. Defaults to name
value. If you're using the first release of ACL, the value needs to be a file system location.
#####target_type
The type of target for the ACL resource. The only valid value is 'file'.
####Properties
#####group
The entity or entities that have access to a particular ACL descriptor. The group identity is also known as a trustee or principal. Valid inputs can be in the form of:
- User - e.g. 'Bob' or 'TheNet\Bob'
- Group - e.g. 'Administrators' or 'BUILTIN\Administrators'
- SID (Security ID) - e.g. 'S-1-5-18'
No default value will be enforced by Puppet. Using the default will allow the group to stay set to whatever it is currently set to (group can vary depending on the original CREATOR GROUP). Since the identity must exist on the system in order to be used, Puppet will make sure they exist by creating them as needed.
NOTE: On Windows the CREATOR GROUP inherited ACE must be set for the creator's primary group to be set as an ACE automatically. Group is not always widely used. By default the group will also need to be specifically set as an explicit managed ACE. See Microsoft's page for instructions on enabling CREATOR GROUP.
#####inherit_parent_permissions
Specifies whether to inherit permissions from parent ACLs. Valid values are 'true' and 'false'. Default is 'true'.
#####owner
The entity/entities that owns the particular ACL descriptor. The owner entity is also known as a trustee or principal. Valid inputs can be in the form of:
- User - e.g. 'Bob' or 'TheNet\Bob'
- Group e.g. 'Administrators' or 'BUILTIN\Administrators'
- SID (Security ID) e.g. 'S-1-5-18'
No default value will be enforced by Puppet. Using the default will allow the owner to stay set to whatever it is currently set to (owner can vary depending on the original CREATOR OWNER). Since the identity must exist on the system in order to be used, Puppet will make sure they exist by creating them as needed.
#####permissions
An array containing Access Control Entries (ACEs). The ACEs must be in explicit order. The elements must be presented in a hash that minimally requires identity
and rights
values.
…
permissions => [
{ identity => 'Administrators', rights => ['full'] }
]
The available elements in the hash are: identity
, rights
, type
, child_types
, affects
, and mask
. The mask
entry should only be specified with rights => ['mask_specific']
. For instance,
…
permissions => [
{ identity => 'Administrators', rights => ['full'], type=> 'allow', child_types => 'all', affects => 'all' }
]
Each permission (ACE) is determined to be unique based on identity
, 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 some_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.
Elements in permissions
identity
is a group, user, or SID. It must exist on the system and will auto-require on user and group resources.identity
can be in the form of:- User - e.g. 'Bob' or 'TheNet\Bob'
- Group e.g. 'Administrators' or 'BUILTIN\Administrators'
- SID (Security ID) e.g. 'S-1-5-18'
rights
is an array that can have the following values: 'full', 'modify', 'mask_specific', 'write', 'read', and 'execute'. The 'full', 'modify', and 'mask_specific' values are mutually exclusive and must be the only value specified inrights
. The 'full' value indicates all rights. The 'modify' value is cumulative, implying 'write', 'read', 'execute' and DELETE all in one. If you specify 'full' or 'modify' as part of a set of rights with other rights, e.g.rights => ['full','read']
, theacl
type will issue a warning and remove the other items. You can specify any combination of 'write', 'read', and 'execute'. If you specify 'mask_specific', you must also specify themask
element in thepermissions
hash with an integer passed as a string.
acl { 'c:/tempperms':
permissions => [
{ identity => 'Administrators', rights => ['full'] },
{ identity => 'Administrator', rights => ['modify'] },
{ identity => 'Authenticated Users', rights => ['write','read','execute'] },
{ identity => 'Users', rights => ['read','execute'] }
{ identity => 'Everyone', rights => ['read'] }
],
inherit_parent_permissions => 'false',
}
mask
is an element that only works if 'mask_specific' is set in therights
element. The value must be an integer representing mask permissions passed in a string.type
can be 'allow' or 'deny', and defaults to 'allow'.child_types
determines how an ACE is inherited downstream from the target. Valid values are 'all', 'objects', 'containers' or 'none'. Defaults to 'all'.affects
determines how the downstream inheritance is propagated. Valid values are 'all', 'self_only', 'children_only', 'self_and_direct_children_only', or 'direct_children_only'. Defaults to 'all'.
###Examples
####Fully expressed ACL
The fully expressed ACL in the sample below produces the same settings as the minimal sample in the Setup section.
acl { 'c:/tempperms':
target => 'c:/tempperms',
target_type => 'file',
purge => 'false',
permissions => [
{ identity => 'Administrator', rights => ['full'], type=> 'allow', child_types => 'all', affects => 'all' },
{ identity => 'Users', rights => ['read','execute'], 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',
}
####SID/FQDN Users can be specified with SIDs (Security Identifiers) or as fully qualified domain names (FQDN).
acl { 'c:/tempperms':
permissions => [
{ identity => 'NT AUTHORITY\SYSTEM', rights => ['modify'] },
{ identity => 'BUILTIN\Users', rights => ['read','execute'] },
{ identity => 'S-1-5-32-544', rights => ['write','read','execute'] }
],
}
####Same target, multiple resources
You can manage the same target across multiple ACL resources with some caveats: the title of the resource needs to be unique, and you should only do so when you absolutely need to since it can get confusing quickly.
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 on every catalog application. Use this feature with care.
acl { 'c:/tempperms':
permissions => [
{ identity => 'Administrator', rights => ['full'] }
],
}
acl { 'tempperms_Users':
target => 'c:/tempperms',
permissions => [
{ identity => 'Users', rights => ['read','execute'] }
],
}
####Protect
Removing upstream inheritance is known as protecting the target. When an item is protected without purge => true
, the inherited ACEs will be copied into the target as unmanaged ACEs.
acl { 'c:/tempperms':
permissions => [
{ identity => 'Administrators', rights => ['full'] },
{ identity => 'Users', rights => ['full'] }
],
inherit_parent_permissions => 'false',
}
####Purge
You cannot purge inherited permissions; you can only purge explicit permissions. To lock down a folder to managed explicit ACEs, you want to set purge => true
. This will only remove other explicit ACEs from the folder that are unmanaged by this resource. All inherited ACEs will remain (see next example).
acl { 'c:/tempperms':
purge => 'true',
permissions => [
{ identity => 'Administrators', rights => ['full'] },
{ identity => 'Users', rights => ['full'] }
],
}
####Protect with purge
To lock down a folder and only allow the permissions specified explicitly in the manifest resource, you want to protect the folder and set purge => 'true'
.
Warning: While managing ACLs, you can completely lock the user running Puppet out of managing resources. Extreme care should be taken when using purge => true
with inherit_parent_permissions => false
in the acl
type. If Puppet is locked out of managing the resource, manual intervention on affected nodes will be required.
acl { 'c:/tempperms':
purge => 'true',
permissions => [
{ identity => 'Administrators', rights => ['full'] },
{ identity => 'Users', rights => ['full'] }
],
inherit_parent_permissions => 'false',
}
####ACE mask_specific rights
Enabling rights => ['mask_specific']
indicates that rights are passed as part of an ACE mask, so the mask is all that will be evaluated. In these cases you must also specify 'mask' with an integer (passed as a string) that represents the permissions mask. You must not combine values, such as read permissions, with the mask. The acl
provider will error if you attempt to do this.
NOTE: 'mask_specific' should ONLY be used when other rights are not specific enough. If you specify 'mask_specific' with the equivalent of 'full' rights (2032127), and it finds the property to be 'full', it will report making changes to the resource even though nothing is different.
acl { 'c:/tempperms':
purge => 'true',
permissions => [
{ identity => 'Administrators', rights => ['full'] }, #full is same as - 2032127 aka 0x1f01ff but you should use 'full'
{ identity => 'SYSTEM', rights => ['modify'] }, #modify is same as 1245631 aka 0x1301bf but you should use 'modify'
{ identity => 'Users', rights => ['mask_specific'], mask => '1180073' }, #RX WA #0x1201a9
{ identity => 'Administrator', rights => ['mask_specific'], mask => '1180032' } #RA,S,WA,Rc #1180032 #0x120180
],
inherit_parent_permissions => 'false',
}
References
- File/Directory Access Mask Constants - http://msdn.microsoft.com/en-us/library/aa394063(v=vs.85).aspx
- File Generic Access Rights - http://msdn.microsoft.com/en-us/library/windows/desktop/aa364399(v=vs.85).aspx
- Access Mask Format - http://msdn.microsoft.com/en-us/library/windows/desktop/aa374896(v=vs.85).aspx
####Deny ACE
ACEs can be of type
'allow' or 'deny'. Deny ACEs should be listed first before allow ACEs.
acl { 'c:/tempperms':
permissions => [
{ identity => 'SYSTEM', rights => ['full'], type=> 'deny', affects => 'self_only' },
{ identity => 'Administrators', rights => ['full'] }
],
}
####ACE inheritance
ACEs have inheritance structures controlled by child_types
, which determine how sub-folders and files will inherit each particular ACE.
acl { 'c:/tempperms':
purge => 'true',
permissions => [
{ identity => 'SYSTEM', rights => ['full'], child_types => 'all' },
{ identity => 'Administrators', rights => ['full'], child_types => 'containers' },
{ identity => 'Administrator', rights => ['full'], child_types => 'objects' },
{ identity => 'Users', rights => ['full'], child_types => 'none' }
],
inherit_parent_permissions => 'false',
}
####ACE propagation
ACEs have propagation rules which guide how they apply permissions to containers, objects, children and grandchildren. Propagation is determined by affects
, which can take the value of: 'all', 'self_only', 'children_only', 'direct_children_only', and 'self_and_direct_children_only'. Microsoft has a good matrix that outlines when and why you might use each of these values.
acl { 'c:/tempperms':
purge => 'true',
permissions => [
{ identity => 'Administrators', rights => ['modify'], affects => 'all' },
{ identity => 'Administrators', rights => ['full'], affects => 'self_only' },
{ identity => 'Administrator', rights => ['full'], affects => 'direct_children_only' },
{ identity => 'Users', rights => ['full'], affects => 'children_only' },
{ identity => 'Authenticated Users', rights => ['read'], affects => 'self_and_direct_children_only' }
],
inherit_parent_permissions => 'false',
}
####Removing ACE permissions
Removing permissions is done by using purge => listed_permissions
. This will remove explicit permissions from the ACL. When the example below is done, it will ensure that 'Administrator' and 'Authenticated Users' are not on the ACL. This comparison is done based on identity
, type
, child_types
and affects
.
#set permissions
acl { 'c:/tempperms/remove':
purge => 'true',
permissions => [
{ identity => 'Administrators', rights => ['full'] },
{ identity => 'Administrator', rights => ['write'] },
{ identity => 'Users', rights => ['write','execute'] },
{ identity => 'Everyone', rights => ['execute'] },
{ identity => 'Authenticated Users', rights => ['full'] }
],
inherit_parent_permissions => 'false',
}
#now remove some permissions
acl { 'remove_tempperms/remove':
target => 'c:/tempperms/remove',
purge => 'listed_permissions',
permissions => [
{ identity => 'Administrator', rights => ['write'] },
{ identity => 'Authenticated Users', rights => ['full'] }
],
inherit_parent_permissions => 'false',
require => Acl['c:/tempperms/remove'],
}
####Same identity, multiple ACEs
With Windows, you can specify the same identity
with different inheritance and propagation and each of those items will actually be managed as separate ACEs.
acl { 'c:/tempperms':
purge => 'true',
permissions => [
{ identity => 'SYSTEM', rights => ['modify'], child_types => 'none' },
{ identity => 'SYSTEM', rights => ['modify'], child_types => 'containers' },
{ identity => 'SYSTEM', rights => ['modify'], child_types => 'objects' },
{ identity => 'SYSTEM', rights => ['full'], affects => 'self_only' },
{ identity => 'SYSTEM', rights => ['read','execute'], affects => 'direct_children_only' },
{ identity => 'SYSTEM', rights => ['read','execute'], child_types=>'containers', affects => 'direct_children_only' },
{ identity => 'SYSTEM', rights => ['read','execute'], child_types=>'objects', affects => 'direct_children_only' },
{ identity => 'SYSTEM', rights => ['full'], affects => 'children_only' },
{ identity => 'SYSTEM', rights => ['full'], child_types=>'containers', affects => 'children_only' },
{ identity => 'SYSTEM', rights => ['full'], child_types=>'objects', affects => 'children_only' },
{ identity => 'SYSTEM', rights => ['read'], affects => 'self_and_direct_children_only' },
{ identity => 'SYSTEM', rights => ['read'], child_types=>'containers', affects => 'self_and_direct_children_only' },
{ identity => 'SYSTEM', rights => ['read'], child_types=>'objects', affects => 'self_and_direct_children_only' }
],
inherit_parent_permissions => 'false',
}
##Limitations
- The Windows Provider in the first release (at least) will not handle permissions with Symlinks. Please explicitly manage the permissions of the target.
- Each permission (ACE) is determined to be unique based on
identity
,type
,child_types
, andaffects
. While you can technically create more than one ACE that differs from other ACEs only inrights
, the 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.
!!!DO NOT DO THIS!!!
acl { 'c:/tempperms':
permissions => [
{ identity => 'SYSTEM', rights => ['full']},
{ identity => 'SYSTEM', rights => ['read']}
],
}
!!!SERIOUSLY, DON'T DO THIS.
- Windows 8.3 short name format for files/directories is not supported.
- Using Cygwin to run puppet with ACLs could result in undesirable behavior (on Windows 2008 'Administrator' identity might be translated to 'cyg_server', but may behave fine on other systems like Windows 2012). We wouldn't recommend using Cygwin to run Puppet with ACL manifests due to this and other possible edge cases. This tends to happen when using Cygwin SSHD with public key authentication.
- Unicode for identities, group, and owner may not work appropriately or at all in the first release.
- When using SIDs for identities, autorequire will attempt to match to users with fully qualified names (User[BUILTIN\Administrators]) in addition to SIDs (User[S-1-5-32-544]). The limitation is that it won't match against 'User[Administrators]' as that could cause issues if attempting to match domain accounts versus local accounts with the same name e.g. 'Domain\Bob' vs 'LOCAL\Bob'.
Please log tickets and issues at our Module Issue Tracker.
##Development
Puppet Labs modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad of hardware, software, and deployment configurations that Puppet is intended to serve.
We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
You can read the complete module contribution guide on the Puppet Labs wiki.
Licensed under Apache License, Version 2.0
Types in this module release
##2014-03-04 - Supported Release 1.0.1 ###Summary
Add metadata compatibility for PE 3.2.
##2014-03-04 - Supported Release 1.0.0 ###Summary
This is the initial supported release of the ACL module.
Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} 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.