Python 扫描 ICACL

Python Scan for ICACL

我正在努力解决我公司目前遇到的一个问题,我们有一个非常大的共享驱动器,已经有 20 多年的历史了。这些文件夹中有很多安全组以及不再存在并显示为乱码文本的个人用户。

我们想扫描整个目录并将所有权限输出到一个 excel 文件。

我想出了这个解决方案,但是,我认为我没有像我认为的那样有效地完成它。

这是整个脚本:

import os
import subprocess
import xlsxwriter
import win32com.client as win32

# *** IMPORTANT ****
# MUST INSTALL XLSXWRITER AND PYWIN32 IN VENV
# PIP INSTALL XLSXWRITER
# PIP INSTALL PYWIN32


def CheckPerms(t, save_dir):

    global firstDir

    # LOOP THROUGH ALL PATHS IN ROOT DIRECTORY
    for path in os.listdir(t):

        # VARIABLE HOLDS FULL PATH OF THE ROOT DIRECTORY
        full_root_path = os.path.join(t, path)

        # CHECKS IF PATH IS A FILE, IF IT IS A FILE, SKIP AND CONTINUE WITH SCAN
        if not os.path.isfile(full_root_path):

            # VARIABLE HOLDS ROOT NAME OF FULL ROOT PATH
            # EXAMPLE: INPUT - C:\TEST, RETURNS - C:\
            firstDir = os.path.split(full_root_path)

            # PRINTS CURRENT DIRECTORY THAT IS BEING SCANNED
            print("Working on: " + firstDir[1])

            # PREPARE EXCEL WORKBOOK IN SPECIFIED LOCATION
            # SAVES AS NAME OF DIR BEING SCANNED
            workbook = xlsxwriter.Workbook(f'{save_dir}\{firstDir[1]}.xlsx')
            worksheet = workbook.add_worksheet()
            worksheet.write("A1", "Directory Path")
            worksheet.write("B1", "Security Groups")
            row = 1
            col = 0

            # LOOP THOUGH A WALK OF EACH ROOT PATH
            # THIS WILL SCAN FRONT TO BACK, TOP TO BOTTOM OF THE ENTIRE TREE
            for r, d, f in os.walk(full_root_path):

                # CAPTURE THE OUTPUT OF THE SYSTEM CMD ICALCS COMMAND ON DIRECTORY BEING SCANNED
                sub_return = subprocess.check_output(["icacls", r])
                try:
                    # TRY TO DECODE OUTPUT AS UTF-8
                    sub_return = sub_return.decode('utf-8')
                except:
                    # SOMETIMES CANNOT DECODE, THIS WILL CATCH ERROR AND CONTINUE
                    print("Decode Error: Skipping a line")
                    continue

                # SPLIT THE LINES OF THE RETURNED STRING
                split_icacl_lines = sub_return.splitlines()

                # ICACLS RETURNS A STATUS LINE AFTER COMPLETE
                # THIS WILL REMOVE THE LAST LINE, EXAMPLE:
                # "Successfully processed 1 files; Failed processing 0 files"
                del split_icacl_lines[-1:]

                # FIRST LINE OF ICACLS INCLUDES THE DIRECTORY AS WELL AS FIRST LINE OF ICACLS
                # THIS WILL REVERSE SPLIT BY FIRST EMPTY SPACE TO SEPARATE THE LINES
                # AND DELETE IT FROM THE ORIGINAL LIST
                firstLine = split_icacl_lines[0].rsplit(" ", 1)
                del split_icacl_lines[0]

                # THERE HAPPENS TO BE AN EMPTY LINE, SO WE REMOVE IT HERE
                del split_icacl_lines[-1:]

                # ADD THE FIRST ELEMENT OF THE FIRST LINE BACK INTO THE BEGINNING OF THE LIST
                split_icacl_lines.insert(0, firstLine[0].lstrip())
                # APPEND THE SECOND ELEMENT OF THE FIRST LINE TO END OF LIST
                split_icacl_lines.append(firstLine[1].lstrip())

                # FIRST ELEMENT OF LIST IS THE TARGET DIRECTORY
                target_directory = split_icacl_lines[0]

                # DELETE TARGET DIRECTORY FROM LIST
                del split_icacl_lines[0]

                # ADD TARGET DIRECTORY TO EXCEL FILE
                worksheet.write(row, col, target_directory)
                # MOVE OVER EXCEL COLUMN BY 1
                col += 1

                # LOOP THROUGH EACH LINE IN THE FINAL ICACL DATA AND
                # OUTPUT IT TO EXCEL FILE NEXT TO THE DIRECTORY IT
                # BELONGS TO
                for lines in split_icacl_lines:
                    # STRIP LINES OF ALL ABNORMAL CHARACTERS
                    output = lines.lstrip()
                    # INSERT LINE INTO WORKBOOK
                    worksheet.write(row, col, output)
                    row += 1
                # EMPTY LINE BETWEEN EACH SCAN OUTPUT
                row += 1
                # RESET COLUMN TO 0
                col = 0
            # CLOSE WORKBOOK, SAVING IT
            workbook.close()

        # OPEN WORKBOOK IN WIN32, AUTO-FIT EACH COLUMN AND SAVE IT
        excel = win32.gencache.EnsureDispatch('Excel.Application')
        wb = excel.Workbooks.Open(f'C:\Test\{firstDir[1]}.xlsx')
        ws = wb.Worksheets("Sheet1")
        ws.Columns.AutoFit()
        wb.Save()
        excel.Application.Quit()

        # REPEAT ALL ABOVE FOR EACH DIRECTORY


CheckPerms("C:\", "C:\Test")

我遇到的问题是,当 ICACLS 在 windows 中是 运行 时,它的第一行 returns 包括目录以及第一个权限,例如:

C:\Users\Michael>icacls C:\
C:\ BUILTIN\Administrators:(OI)(CI)(F)
     NT AUTHORITY\SYSTEM:(OI)(CI)(F)
     BUILTIN\Users:(OI)(CI)(RX)
     NT AUTHORITY\Authenticated Users:(OI)(CI)(IO)(M)
     NT AUTHORITY\Authenticated Users:(AD)
     Mandatory Label\High Mandatory Level:(OI)(NP)(IO)(NW)

这就是为什么我必须在将输出拆分为列表后对输出做一些奇怪的事情。

拆分原始输出后,我将该输出的第一行拆分为空 space 并将每个元素添加回列表中,但是,对于目录“Program Files”中的某些文件我得到这样奇怪的输出:

Image of excel output file

任何人都可以建议更好的方法吗?

非常感谢。

评论太长了。消除第一行的所有复杂操作(请参阅以下代码片段中的 ## 注释)并尝试它是否有效。

主要看下面几行:

  • split_icacl_lines[0] = split_icacl_lines[0].replace( r, '', 1)
  • target_directory = r

代码:

        # LOOP THOUGH A WALK OF EACH ROOT PATH
        # THIS WILL SCAN FRONT TO BACK, TOP TO BOTTOM OF THE ENTIRE TREE
        for r, d, f in os.walk(full_root_path):

            # CAPTURE THE OUTPUT OF THE SYSTEM CMD ICALCS COMMAND ON DIRECTORY BEING SCANNED
            sub_return = subprocess.check_output(["icacls", r])
            try:
                # TRY TO DECODE OUTPUT AS UTF-8
                sub_return = sub_return.decode('utf-8')
            except:
                # SOMETIMES CANNOT DECODE, THIS WILL CATCH ERROR AND CONTINUE
                print("Decode Error: Skipping a line")
                continue

            # SPLIT THE LINES OF THE RETURNED STRING
            split_icacl_lines = sub_return.splitlines()

            # ICACLS RETURNS A STATUS LINE AFTER COMPLETE
            # THIS WILL REMOVE THE LAST LINE, EXAMPLE:
            # "Successfully processed 1 files; Failed processing 0 files"
            del split_icacl_lines[-1:]

            # FIRST LINE OF ICACLS INCLUDES THE DIRECTORY AS WELL AS FIRST LINE OF ICACLS
            # THIS WILL REVERSE SPLIT BY FIRST EMPTY SPACE TO SEPARATE THE LINES
            # AND DELETE IT FROM THE ORIGINAL LIST
            ## firstLine = split_icacl_lines[0].rsplit(" ", 1)
            ## del split_icacl_lines[0]
            split_icacl_lines[0] = split_icacl_lines[0].replace( r, '', 1)

            # THERE HAPPENS TO BE AN EMPTY LINE, SO WE REMOVE IT HERE
            del split_icacl_lines[-1:]

            # ADD THE FIRST ELEMENT OF THE FIRST LINE BACK INTO THE BEGINNING OF THE LIST
            ## split_icacl_lines.insert(0, firstLine[0].lstrip())
            # APPEND THE SECOND ELEMENT OF THE FIRST LINE TO END OF LIST
            ## split_icacl_lines.append(firstLine[1].lstrip())

            # FIRST ELEMENT OF LIST IS THE TARGET DIRECTORY
            ## target_directory = split_icacl_lines[0]
            target_directory = r

            # DELETE TARGET DIRECTORY FROM LIST
            ## del split_icacl_lines[0]

            # ADD TARGET DIRECTORY TO EXCEL FILE
            worksheet.write(row, col, target_directory)
            # MOVE OVER EXCEL COLUMN BY 1
            col += 1

            # LOOP THROUGH EACH LINE IN THE FINAL ICACL DATA AND
            # OUTPUT IT TO EXCEL FILE NEXT TO THE DIRECTORY IT
            # BELONGS TO
            for lines in split_icacl_lines:
                # STRIP LINES OF ALL ABNORMAL CHARACTERS
                output = lines.lstrip()
                # INSERT LINE INTO WORKBOOK
                worksheet.write(row, col, output)
                row += 1
            # EMPTY LINE BETWEEN EACH SCAN OUTPUT
            row += 1
            # RESET COLUMN TO 0
            col = 0