The directory resource always changes Windows directory permissions when given a permission bitmask
Description
group 'p_logs_writers'
directory 'C:\Logs' do
# 0x20089 000100000000010001001 Read
# 0x00116 000000000000100010110 Write
# 0x10000 000010000000000000000 Delete
# 0x3019F 000110000000110011111 Read, Write, Delete
rights 0x3019F, 'p_logs_writers'
end
Converge the above twice. Note that everytime Chef runs, it updates the DACL.
I tried turning on debug and trace logging to see the state Chef thinks the directory permissions are in, but the resource doesn't output any information about why it thinks the permissions are out-of-date.
Chef Version
18.8.54
Platform Version
Windows 11
Client Output
$ kitchen converge
-----> Starting Test Kitchen (v3.7.0)
Kitchen driver: Vagrant
-----> Converging <********>...
Preparing files for transfer
Preparing dna.json
Resolving cookbook dependencies with Berkshelf 8.0.22...
Removing non-cookbook files before transfer
Preparing data_bags
Preparing validation.pem
Preparing client.rb
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 0.0 Omnitruck {Get-ProjectMetadata, Install-Project, install}
install_strategy set to 'once'
Nothing to install
Transferring files to <********>
[2025-11-19T19:54:27+00:00] INFO: Started Cinc Zero at chefzero://localhost:1 with repository at C:/Users/vagrant/AppData/Local/Temp/kitchen, C:/Users/vagrant/AppData/Local/Temp/kitchen (One version per cookbook)
Cinc Client, version 18.8.54
Patents: https://www.chef.io/patents
Infra Phase starting
[2025-11-19T19:54:27+00:00] INFO: *** Chef Client 18.8.54 ***
[2025-11-19T19:54:27+00:00] INFO: Platform: x64-mingw-ucrt
[2025-11-19T19:54:27+00:00] INFO: Chef -client pid: 2196
[2025-11-19T19:54:31+00:00] INFO: Setting the run_list to ["recipe[********::default]"] from CLI options
[2025-11-19T19:54:31+00:00] INFO: Run List is [recipe[********::default]]
[2025-11-19T19:54:31+00:00] INFO: Run List expands to [********::default]
[2025-11-19T19:54:31+00:00] INFO: Starting Chef Client Run for ********
[2025-11-19T19:54:31+00:00] INFO: Running start handlers
[2025-11-19T19:54:31+00:00] INFO: Start handlers complete.
Resolving cookbooks for run list: ["********"]
[2025-11-19T19:54:31+00:00] INFO: Loading cookbooks [********@3.0.0, [email protected], ********@8.7.2]
Synchronizing cookbooks:
- ******** (3.0.0)
- iis (8.0.2)
- ******** (8.7.2)
Installing cookbook gem dependencies:
Compiling cookbooks...
Loading Chef Auditor profile files:
Loading Chef Auditor input files:
Loading Chef Auditor waiver files:
Converging 2 resources
Recipe: ********::_shared
* group[p_logs_writers] action create[2025-11-19T19:54:32+00:00] INFO: Processing group[p_logs_writers] action create (********::_shared line 27)
(up to date)
* directory[C:\Logs] action create[2025-11-19T19:54:32+00:00] INFO: Processing directory[C:\Logs] action create (********::_shared line 35)
[2025-11-19T19:54:32+00:00] INFO: directory[C:\Logs] permissions changed to [VAGRANT-76BQAGJ\p_logs_writers/flags:3/mask:3019f]
- change dacl
[2025-11-19T19:54:32+00:00] INFO: Chef Client Run complete in 1.2483214 seconds
Running handlers:
[2025-11-19T19:54:32+00:00] INFO: Running report handlers
Running handlers complete
[2025-11-19T19:54:32+00:00] INFO: Report handlers complete
Infra Phase complete, 1/2 resources updated in 05 seconds
[2025-11-19T19:54:36+00:00] INFO: Started Cinc Zero at chefzero://localhost:1 with repository at C:/Users/vagrant/AppData/Local/Temp/kitchen, C:/Users/vagrant/AppData/Local/Temp/kitchen (One version per cookbook)
Chef Client, version 18.8.54
Patents: https://www.chef.io/patents
Infra Phase starting
[2025-11-19T19:54:36+00:00] INFO: *** Chef Client 18.8.54 ***
[2025-11-19T19:54:36+00:00] INFO: Platform: x64-mingw-ucrt
[2025-11-19T19:54:36+00:00] INFO: Chef-client pid: 3320
[2025-11-19T19:54:40+00:00] INFO: Setting the run_list to ["recipe[********::default]"] from CLI options
[2025-11-19T19:54:40+00:00] INFO: Run List is [recipe[********::default]]
[2025-11-19T19:54:40+00:00] INFO: Run List expands to [********::default]
[2025-11-19T19:54:40+00:00] INFO: Starting Chef Client Run for devtools-windows-2019
[2025-11-19T19:54:40+00:00] INFO: Running start handlers
[2025-11-19T19:54:40+00:00] INFO: Start handlers complete.
Resolving cookbooks for run list: ["********::default"]
[2025-11-19T19:54:41+00:00] INFO: Loading cookbooks [********@3.0.0, [email protected], ********@8.7.2]
Synchronizing cookbooks:
- ******** (3.0.0)
- iis (8.0.2)
- ******** (8.7.2)
Installing cookbook gem dependencies:
Compiling cookbooks...
Loading Chef Auditor profile files:
Loading Chef Auditor input files:
Loading Chef Auditor waiver files:
Converging 2 resources
Recipe: ********::_shared
* group[p_logs_writers] action create[2025-11-19T19:54:42+00:00] INFO: Processing group[p_logs_writers] action create (********::_shared line 27)
(up to date)
* directory[C:\Logs] action create[2025-11-19T19:54:42+00:00] INFO: Processing directory[C:\Logs] action create (********::_shared line 35)
[2025-11-19T19:54:42+00:00] INFO: directory[C:\Logs] permissions changed to [VAGRANT-76BQAGJ\p_logs_writers/flags:3/mask:3019f]
- change dacl
[2025-11-19T19:54:42+00:00] INFO: Chef Client Run complete in 1.4242492 seconds
Running handlers:
[2025-11-19T19:54:42+00:00] INFO: Running report handlers
First chef run should have reached a converged state.
Resources updated in a second chef-client run:
- directory[C:\Logs]
>>>>>> ------Exception-------
>>>>>> Class: Kitchen::ActionFailed
>>>>>> Message: 1 actions failed.
>>>>>> Converge failed on instance <********>. Please see .kitchen/logs/********.log for more details
>>>>>> ----------------------
>>>>>> Please see .kitchen/logs/kitchen.log for more details
>>>>>> Also try running `kitchen diagnose --all` for configuration
Digging in a little deeper, it looks like acls_equal thinks the new ACE should be two ACEs? When I add this debugging code to the end of acls_equal:
Chef::Log.info "actual_acl"
actual_acl.each { |ace| Chef::Log.info(" #{ace}") }
Chef::Log.info "new_target_acl"
new_target_acl.each { |ace| Chef::Log.info(" #{ace}") }
I get this output:
[2025-11-19T21:00:42+00:00] INFO: actual_acl
[2025-11-19T21:00:42+00:00] INFO: VAGRANT-76BQAGJ\p_logs_writers/flags:3/mask:3019f
[2025-11-19T21:00:42+00:00] INFO: new_target_acl
[2025-11-19T21:00:42+00:00] INFO: VAGRANT-76BQAGJ\p_logs_writers/flags:0/mask:3019f
[2025-11-19T21:00:42+00:00] INFO: VAGRANT-76BQAGJ\p_logs_writers/flags:b/mask:3019f
For some reason, acls_equal is converting my single right into two rights.
I don't understand why acls_equal is so complicated? The comments are terse and don't make sense.
Shouldn't it be:
def acls_equal(target_acl, actual_acl)
if actual_acl.nil?
return target_acl.nil?
end
actual_acl = actual_acl.select { |ace| !ace.inherited? }
actual_acl == target_acl
end
This comment may be true:
# 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.
but we're not looking at child ACLs. In fact, the code is actually explicitly excluding inherited ACLs, to the work done after this comment is unnecessary.
And I think this comment is just blatantly not true?
# As there is no inheritance needed in case of WRITE permissions.
I've never seen any exceptions to write permission inheritance when working with ACLs.
When I switch to :modify so workaround this issue, Chef applies to ACEs to my directory:
> (get-acl C:\Logs\).access
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : VAGRANT-76BQAGJ\p_logs_writers
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : -536805376
AccessControlType : Allow
IdentityReference : VAGRANT-76BQAGJ\p_logs_writers
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
So now my tests fail:
describe directory('C:\\Logs') do
it { should exist }
its('user_permissions') { should include "#{sys_info.hostname}\\p_logs_writers" => 'Modify, Synchronize' }
end
[FAIL] user_permissions is expected to include {"VAGRANT-76BQAGJ\\p_logs_writers" => "Modify, Synchronize"}
expected {"BUILTIN\\Administrators" => "FullControl", "BUILTIN\\Users" => "CreateFiles", "CREATOR OWNER" => "2684354...T-76BQAGJ\\p_d_drive_readers" => "Read, Synchronize", "VAGRANT-76BQAGJ\\p_logs_writers" => "-536805376"} to include {"VAGRANT-76BQAGJ\\p_logs_writers" => "Modify, Synchronize"}