Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Train reports directories with the archive bit set as files on the windows platform #274

Closed
srb3 opened this issue Mar 28, 2018 · 1 comment

Comments

@srb3
Copy link
Contributor

srb3 commented Mar 28, 2018

Description

On the windows platform programs like xcopy set the archive bit on folders
as well as files.

The Inspec directory and file resources use the train backend for file when making assertions,
Train can either use remote or local implimentation for the windows platform.

Using trains local file class for windows, a directory with the archive bit set is correctly identified as directory. (it uses rubys ::File.stat(path) to get attributes about the path)

When Inspec is used remotely and Trains remote file class for windows is used, directories with the archive bit set are identified as files. (it uses powershell's 'Get-ItemProperty -Path' to get attribute information)

Expected behaviour:
Train should report that directories with the archive bit set are directories and not files

relevant code in Train
https://github.com/chef/train/blob/master/lib/train/file/remote/windows.rb#L41-L50

        def type
          if attributes.include?('Archive')
            return :file
          elsif attributes.include?('ReparsePoint')
            return :symlink
          elsif attributes.include?('Directory')
            return :directory
          end
          :unknown
        end

windows remote file gets the attributes via

        def attributes
          return @attributes if defined?(@attributes)
          @attributes = @backend.run_command(
            "(Get-ItemProperty -Path \"#{@spath}\").attributes.ToString()").stdout.chomp.split(/\s*,\s*/)
        end

you can test this on the command line:

PS C:\> mkdir test_folder
    Directory: C:\
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         3/28/2018  11:41 AM            test_folder
PS C:\> attrib.exe .\test_folder
             C:\test_folder
PS C:\> attrib +A .\test_folder
PS C:\> attrib.exe .\test_folder
A            C:\test_folder
PS C:\> (Get-ItemProperty -Path C:\test_folder).attributes.ToString()
Directory, Archive
PS C:\>
PS C:\> attrib.exe -A .\test_folder
PS C:\> attrib.exe .\test_folder
             C:\test_folder
PS C:\> (Get-ItemProperty -Path C:\test_folder).attributes.ToString()
Directory

when Get-ItemProperty is called on a directory with the Archive bit set the logic fails and it is
reported as a file.

This causes controls to fail that are expecting a directory

control 'test folder' do
    title 'Checking c:\test_folder directory'  
    describe directory ('c:\test_folder') do
      it { should be_directory }
      its('type') { should eq :directory }
    end
  end

Train and Platform Version

Train 0.29.1
Windows 2012 R2

Replication Case

Windows 2012
another server to run Inspec from (the remote server)

create a folder with the archive bit set

PS C:\> mkdir test_folder
    Directory: C:\
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         3/28/2018  11:41 AM            test_folder
PS C:\> attrib.exe .\test_folder
             C:\test_folder
PS C:\> attrib +A .\test_folder
PS C:\> attrib.exe .\test_folder
A            C:\test_folder
PS C:\> (Get-ItemProperty -Path C:\test_folder).attributes.ToString()
Directory, Archive
PS C:\>

on the remote server
install inspec
and create a control

control 'test folder' do
    title 'Checking c:\test_folder directory'  
    describe directory ('c:\test_folder') do
      it { should be_directory }
      its('type') { should eq :directory }
    end
  end

run the control against the windows server

Possible Solutions

        def type
          if attributes.include?('Archive') && attributes.include?('Directory')
            return :directory
          elsif attributes.include?('Archive')
            return :file
          elsif attributes.include?('ReparsePoint')
            return :symlink
          elsif attributes.include?('Directory')
            return :directory
          end
          :unknown
        end

or possibly

        def type
          if attributes.include?('Archive') && !attributes.include?('Directory')
            return :file
          elsif attributes.include?('ReparsePoint')
            return :symlink
          elsif attributes.include?('Directory')
            return :directory
          end
          :unknown
        end

PR #275

Stacktrace

@chris-rock
Copy link
Contributor

Fixed by #275

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants