65.9K
CodeProject 正在变化。 阅读更多。
Home

文件服务器审计

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (4投票s)

2011年6月4日

GPL3

6分钟阅读

viewsIcon

42865

downloadIcon

1504

审计 Windows 卷上的 NTFS ACL 权限。

引言

文件服务器审计解决了在大型文件服务器上查找用户可访问内容的原始数据获取问题,方法是枚举所有文件夹的所有 NTFS(新技术文件系统)ACL(访问控制列表)。通过文本实用工具或 SQL 查询,可以将原始数据转换为有用的报告,以查找用户具有访问权限的内容。还可以使用 文件服务器查看器 来帮助查看输出。文件服务器审计可以通过允许其他人快速为其文件服务器创建自己的审计流程来帮助他们。代码片段是一个用于读取自由访问控制列表(ACL)的子程序。这在查找谁有权访问文件夹时很有帮助。

屏幕截图

 

背景

 

我编写此程序是为了进行文件服务器迁移和清理项目的一部分,以告知我所有有权访问文件和文件夹的人。该程序在显示所有有权访问文件夹的不同人员方面非常有用。

Using the Code

该程序的工作原理是枚举卷上的每个文件夹,然后枚举有权访问每个文件夹的每个用户和组。然后,程序将处理组,枚举该组中的所有用户以及嵌套组中的所有用户。通过这样做,它将为您提供一个完整的用户列表,了解他们对文件或文件夹的访问权限。代码片段是枚举文件夹的所有 ACL(访问控制列表)的子程序。此代码需要在域帐户中运行,以便进行正确的枚举。程序源代码中有一个名为 RecursiveGroupSub 的子程序,用于枚举嵌套组。调用该子程序并为其提供一个有效的文件夹路径。该程序会输出大量数据,这些数据很难排序和分析。

全局变量;使用字典作为本地缓存来加速 AD 记录。

Dim blnShowOutput As Boolean = True 'Used to show output
Dim blnInherited As Boolean = False 'Used to remove inherited ACLs
Dim strDate As String = TodayFileDate() 'Holds Date in string format
'Hold Cache for AD Users/Groups (AD sAMAccountName, AD Object Type)
Dim dicADUserType As New Dictionary(Of String, String)
'Holds Group sAMAccountName and Array of Users sAMAccountName
Dim dicADGroup As New Dictionary(Of String, Array)
'Holds Group sAMAccountName and Managed By name
Dim dicADGroupManager As New Dictionary(Of String, String)
'Holds Group sAMAccountName and Sub-Group sAMAccountName
Dim dicADGroupSubGroup As New Dictionary(Of String, Array)

用于读取实际 ACL 的 ReadACLs 子程序的设置。在设置中,DirInfo 绑定到输入目录,以便 DirSec 可以获取 ACL 列表。然后将此列表设置在对象 ACL 中。

Public Sub ReadACLs(ByVal strInput As String, _
           Optional ByVal blnRemoveInherited As Boolean = True)
    'strInput is the full path to a folder
    'blnRemoveInherited is used to remove inherited ACLs to reduce output

    'Bindings:

    'Binds to the Directory using the string provided 
    Dim DirInfo As System.IO.DirectoryInfo = _
      New System.IO.DirectoryInfo(strInput) 'Directory is already binded
    'Binds to Directory Security
    'This allows user to read ACLs
    Dim DirSec As System.Security.AccessControl.DirectorySecurity = _
               DirInfo.GetAccessControl()
    'Gets Directory Access Control Lists
    'Collection is returned with ACLs so we can enumerate later
    Dim ACLs As System.Security.AccessControl.AuthorizationRuleCollection = _
        DirSec.GetAccessRules(True, True, _
        GetType(System.Security.Principal.NTAccount))
    'Access Contol List Entry
    'Varible to hold a ACL
    Dim ACL As System.Security.AccessControl.FileSystemAccessRule
    'Gets Folder owner ID
    Dim Owner As System.Security.Principal.IdentityReference = _
        DirSec.GetOwner(GetType(System.Security.Principal.NTAccount))
    'Binds to the default domain
    'For this to work this will have to run under a domain account
    Dim DomainContext As New _
        System.DirectoryServices.ActiveDirectory.DirectoryContext(_
        System.DirectoryServices.ActiveDirectory.DirectoryContextType.Domain)
    'Binds to AD to get account and group info
    Dim objMember As New System.DirectoryServices.DirectoryEntry

    'Declarations:

    'Used to hold domain and user ex domain\user
    Dim arrDUSplit(1) As String
    Dim strTemp As String = "" 'Holds working String
    Dim strSAMA As String = "" 'Users Username ("sAMAccountName")
    Dim strClass As String = "" ' AD Object type Group or User
    Dim strGroupSAMA As String = "" 'The Group Users is in
    Dim strManagedBy As String = "" 'Person that manages that AD Group.
    'Holds Owners name as string. Converts folders Owners Object to String
    Dim strOwner As String = Owner.ToString
    'Holds ACL.IdentityReference.ToString Properties 
    Dim StrACLIdentityReference As String = ""
    'Holds ACL.InheritanceFlags.ToString Properties
    Dim StrInheritanceFlags As String = ""
    'Holds ACL.FileSystemRights.ToString Properties
    Dim StrFileSystemRights As String = ""
    'Holds ACL.IsInherited.ToString Properties
    Dim StrIsInherited As String = ""
    Dim StrArrayLoopSubGroup As String 'Allows Looping thru all sub-group
    Dim StrArrayLoopUser As String 'Allows Looping thru all Users

    On Error GoTo ErrorHandle

    'Main Section of sub

现在,我们遍历所有 ACL,因为每个文件夹都可能有许多 ACL。我们还必须处理所有本地用户、计算机和已删除的帐户。已删除的帐户仅显示为 SID(S-1-5-21-...)。一旦我们获得了 ACL,我们就会将所有想要的属性写入 LogWrite,该函数会将记录写入日志、SQL 或屏幕。

'Loops through all the Access Control Lists For the Folder
    For Each ACL In ACLs
        'Setup Most Used ACL Properties
        StrACLIdentityReference = ACL.IdentityReference.ToString
        StrInheritanceFlags = ACL.InheritanceFlags.ToString
        StrFileSystemRights = ACL.FileSystemRights.ToString
        StrIsInherited = ACL.IsInherited.ToString

        If Str.Left(StrACLIdentityReference, 2) = "S-" Then
            'Used to catch Deleted Accounts.
            strSAMA = "Unknown"
            strGroupSAMA = StrACLIdentityReference
            strManagedBy = "Unknown"
            strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
            If blnRemoveInherited Then
                If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
            Else
                LogWrite(strTemp)
            End If
        Else
            'Splits Domain and User or Group a part.
            'This cleans up the output alittle.
            arrDUSplit = Split(StrACLIdentityReference, "\")
            'Formats the output differently depending on the domain.
            Select Case arrDUSplit(0)
                'Built-in security principals need special treatment   
                Case "BUILTIN"
                    strSAMA = arrDUSplit(1)
                    strGroupSAMA = "System"
                    strManagedBy = "Systems Administrators"
                    strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                        strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                    If blnRemoveInherited Then
                        If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                    Else
                        LogWrite(strTemp)
                    End If
                Case "NT AUTHORITY"
                    strSAMA = arrDUSplit(1)
                    strGroupSAMA = "System"
                    strManagedBy = "Systems Administrators"
                    strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                        strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                    If blnRemoveInherited Then
                        If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                    Else
                        LogWrite(strTemp)
                    End If
                Case "CREATOR OWNER"
                    strSAMA = arrDUSplit(0)
                    strGroupSAMA = "System"
                    strManagedBy = "Systems Administrators"
                    strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                        strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                    If blnRemoveInherited Then
                        If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                    Else
                        LogWrite(strTemp)
                    End If
                Case "Everyone"
                    strSAMA = arrDUSplit(0)
                    strGroupSAMA = "Everyone"
                    strManagedBy = "Systems Administrators"
                    strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                        strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                    If blnRemoveInherited Then
                        If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                    Else
                        LogWrite(strTemp)
                    End If

                Case Environment.MachineName.ToString
                    'Used for Local Users that have the Domain of the computer name.
                    strSAMA = arrDUSplit(1)
                    strGroupSAMA = "Local"
                    strManagedBy = "Systems Administrators"
                    strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                        strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                    If blnRemoveInherited Then
                        If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                    Else
                        LogWrite(strTemp)
                    End If

以下是我们如何处理域帐户。首先,我们检查记录是否在缓存中;如果不在,我们就查询 AD 并将其添加到缓存中。在确定帐户类型后,我们可以调用 LogWrite,如果它是用户或计算机帐户,否则我们枚举组。现在,我们检查组是否在缓存中;如果在,我们就使用缓存。但是,如果子组不在缓存中,我们就会调用 RecursiveGroupSub 来获取该组及其所有子组中的所有成员;然后我们将这些成员添加到缓存中。

Case Environment.UserDomainName.ToString
    'Uses Currently login domain to enumerate groups
    'Checks to see if the account type is is in the Cache
    If dicADUserType.ContainsKey(arrDUSplit(1)) Then
        strSAMA = arrDUSplit(1)
        strClass = dicADUserType(arrDUSplit(1)).ToString
    Else
        'If AD Users are not in the Cache Dictionary Check AD and Put them in the Cache
        objMember = GetUser(arrDUSplit(1))
        If objMember Is Nothing Then
            CurrentRecord_Event("Error Number: " & Err.Number & " " & Err.Description & vbCrLf _
                & " Sub GetUser: " & vbCrLf _
                & vbTab & "DirInfo.FullName: " & DirInfo.FullName & vbCrLf _
                & vbTab & "NTFS ACL: " & StrACLIdentityReference & vbCrLf _
                & vbTab & "Domain: " & arrDUSplit(0) & vbCrLf _
                & vbTab & "User: " & arrDUSplit(1) & vbCrLf)
        Else
            strClass = objMember.SchemaClassName.ToString 'Get Record AD Type User or Group
            strSAMA = objMember.Properties("sAMAccountName").Value.ToString 'Get AD UserName
            dicADUserType.Add(strSAMA, strClass) 'sets username in Dictionary,'sets class in Dictionary
        End If
    End If

    'Do different actions based on AD Class
    Select Case strClass
        'Write out Each User
        'Each of this Users has explicit permissions
        Case "user", "computer"
            strGroupSAMA = "Direct"
            strManagedBy = "Systems Administrators " & Environment.UserDomainName.ToString & " Domain Accounts"
            strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
            If blnRemoveInherited Then
                If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
            Else
                LogWrite(strTemp)
            End If

        Case "group"
            'For Groups do a recursive search for all sub groups and users
            'Check to see of Group is in Dictionary.
            If dicADGroup.ContainsKey(arrDUSplit(1)) Then
                'Set Manager Of Group
                strManagedBy = ""
                If dicADGroupManager.ContainsKey(arrDUSplit(1)) Then strManagedBy = dicADGroupManager(arrDUSplit(1))
                'Loop thru all users in that group.
                For Each StrArrayLoopUser In dicADGroup(arrDUSplit(1)) 'Loops thru all user in a group
                    'AD Group was Found in Cache.
                    strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                        strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                    If blnRemoveInherited Then
                        If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                    Else
                        LogWrite(strTemp)
                    End If
                Next
                'Loop thru all sub Groups
                If dicADGroupSubGroup.ContainsKey(arrDUSplit(1)) Then
                    For Each StrArrayLoopSubGroup In dicADGroupSubGroup(arrDUSplit(1)) 'Loops thru all sub-group
                        strManagedBy = ""
                        If dicADGroupManager.ContainsKey(StrArrayLoopSubGroup) Then strManagedBy = dicADGroupManager(arrDUSplit(1))
                        'Test SubGroup to see if the are in cache
                        If Not dicADGroup.ContainsKey(StrArrayLoopSubGroup) Then
                            If Not RecursiveGroupSub(objMember) = StrArrayLoopSubGroup Then GoTo ErrorHandle
                        End If
                        For Each StrArrayLoopUser In dicADGroup(StrArrayLoopSubGroup) 'Loops thru all user in a group
                            'AD Group was Found in Cache.
                            strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                                strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                            If blnRemoveInherited Then
                                If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                            Else
                                LogWrite(strTemp)
                            End If
                        Next
                    Next
                Else

                End If

如果组不在缓存中,我们就会通过调用 RecursiveGroupSub 来添加它。这也会将所有子组和 AD 用户添加到缓存中。RecursiveGroupSub 子程序具有打破循环依赖项的逻辑。当您有两个互相作为成员的组时,就会发生这种情况。最后,只需写出任何未解析的记录;这可能是来自受信任域的帐户或组。

Else
                    'Group is not is Cache so start RecursiveGroupSub to put it in Cache
                    'RecursiveGroupSub should return the group it is worked on
                    If RecursiveGroupSub(objMember) = arrDUSplit(1) Then
                        If Not dicADGroup.ContainsKey(arrDUSplit(1)) Then GoTo ErrorHandle
                    Else
                        If Not dicADGroup.ContainsKey(RecursiveGroupSub(objMember)) Then GoTo ErrorHandle
                    End If
                    'Set the Manager of the group
                    If dicADGroupManager.ContainsKey(arrDUSplit(1)) Then strManagedBy = dicADGroupManager(objMember.Properties("sAMAccountName").Value.ToString)
                    'Loop thru all user on the Group
                    For Each StrArrayLoopUser In dicADGroup(arrDUSplit(1)) 'Loops thru all user in a group
                        'AD Group was Found in Cache.
                        strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                            strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                        If blnRemoveInherited Then
                            If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                        Else
                            LogWrite(strTemp)
                        End If
                    Next
                    'Loop thru all sub Groups
                    If dicADGroupSubGroup.ContainsKey(arrDUSplit(1)) Then
                        For Each StrArrayLoopSubGroup In dicADGroupSubGroup(arrDUSplit(1)) 'Loops thru all sub-group
                            strManagedBy = ""
                            If dicADGroupManager.ContainsKey(StrArrayLoopSubGroup) Then strManagedBy = dicADGroupManager(StrArrayLoopSubGroup)
                            For Each StrArrayLoopUser In dicADGroup(StrArrayLoopSubGroup) 'Loops thru all user in a group
                                'AD Group was Found in Cache.
                                strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                                                    strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
                                If blnRemoveInherited Then
                                    If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
                                Else
                                    LogWrite(strTemp)
                                End If
                            Next
                        Next
                    Else

                    End If
                End If
            Case "contact"

            Case Else
                MsgBox("Unexpected strClass: " & strClass)
        End Select
    Case Else
        'Catch all just Write out Entries without group enumeration
        'If you have multiple domains in your forest the domain you are not logon on too will show up here.
        strSAMA = arrDUSplit(1)
        strGroupSAMA = arrDUSplit(0)
        strManagedBy = arrDUSplit(1) & " Administrators"
        strTemp = String.Format("{0};{1};{2};{3};{4};{5};{6};{7};{8};{9}", Str.Replace(DirInfo.FullName, ";", ","), strSAMA, strGroupSAMA, _
                            strManagedBy, StrInheritanceFlags, StrFileSystemRights, strOwner, strDate, Environment.MachineName.ToString, StrIsInherited)
        If blnRemoveInherited Then
            If ACL.IsInherited = False Or Str.Len(strInput) >= 3 Then LogWrite(strTemp)
        Else
            LogWrite(strTemp)
        End If
End Select

带错误处理程序的子程序结束。

        End If
    Next
    Exit Sub
ErrorHandle:
    Select Case Err.Number
        Case 0
            strTemp = "Error Number:" & Err.Number & " " & Err.Description & vbCrLf _
                & " Sub ReadACLs: " & vbCrLf _
                & vbTab & "DirInfo.FullName: " & strInput & vbCrLf _
                & vbTab & "NTFS ACL:" & StrACLIdentityReference & vbCrLf _
                & vbTab & "User:" & strSAMA & vbCrLf _
                & vbTab & "arrDUSplit(0): " & arrDUSplit(0) & vbCrLf _
                & vbTab & "arrDUSplit(1): " & arrDUSplit(1) & vbCrLf
            CurrentRecord_Event(strTemp)
            Threading.Thread.Sleep(0)
            Err.Clear()
        Case 5 'The given key was not present in the dictionary.
            'Log error in the GUI
            strTemp = "Error Number:" & Err.Number & " " & Err.Description & vbCrLf _
                & " Sub ReadACLs: " & vbCrLf _
                & vbTab & "DirInfo.FullName: " & strInput & vbCrLf _
                & vbTab & "NTFS ACL:" & StrACLIdentityReference & vbCrLf _
                & vbTab & "User:" & strSAMA & vbCrLf _
                & vbTab & "arrDUSplit(0): " & arrDUSplit(0) & vbCrLf _
                & vbTab & "arrDUSplit(1): " & arrDUSplit(1) & vbCrLf
            CurrentRecord_Event(strTemp)
            Threading.Thread.Sleep(0)
            Err.Clear()
            Resume Next
        Case 91 'Object reference not set to an instance of an object
            'Log error in the GUI
            strTemp = "Error Number:" & Err.Number & " " & Err.Description & vbCrLf _
                & " Sub ReadACLs: " & vbCrLf _
                & vbTab & "DirInfo.FullName: " & strInput & vbCrLf _
                & vbTab & "NTFS ACL:" & StrACLIdentityReference & vbCrLf _
                & vbTab & "User:" & strSAMA & vbCrLf _
                & vbTab & "arrDUSplit(0): " & arrDUSplit(0) & vbCrLf _
                & vbTab & "arrDUSplit(1): " & arrDUSplit(1) & vbCrLf
            CurrentRecord_Event(strTemp)
            Threading.Thread.Sleep(0)
            Err.Clear()
            Resume Next
        Case Else
            'Log error in the GUI
            strTemp = "Error Number:" & Err.Number & " " & Err.Description & vbCrLf _
                & " Sub ReadACLs: " & vbCrLf _
                & vbTab & "DirInfo.FullName: " & strInput & vbCrLf _
                & vbTab & "NTFS ACL:" & StrACLIdentityReference & vbCrLf _
                & vbTab & "User:" & strSAMA & vbCrLf _
                & vbTab & "arrDUSplit(0): " & arrDUSplit(0) & vbCrLf _
                & vbTab & "arrDUSplit(1): " & arrDUSplit(1) & vbCrLf
            CurrentRecord_Event(strTemp)
            Threading.Thread.Sleep(0)
            'Message Box about the error click ok to quit or X to continue
            If MsgBox("Error Number:" & Err.Number & " " & Err.Description & vbCrLf _
                & " Sub ReadACLs: " & vbCrLf _
                & vbTab & "Input Directory: " & strInput & vbCrLf _
                & vbTab & "NTFS ACL:" & StrACLIdentityReference & vbCrLf _
                & vbTab & "User:" & strSAMA & vbCrLf _
                & vbTab & "arrDUSplit(0): " & arrDUSplit(0) & vbCrLf _
                & vbTab & "arrDUSplit(1): " & arrDUSplit(1) & vbCrLf _
                , MsgBoxStyle.Critical, "Critical Error File Server Audit 2 Quitting") Then
                Err.Clear()
                Main.Close()
            Else
                Err.Clear()
                Exit Sub
            End If
    End Select
End Sub

关注点

代码中总会有错误,输入也一样,你无法规避所有这些;但你可以让它按你想要的方式工作。感谢所有帮助我学习的人。

历史

  • 版本 2.2.1 (2015-06-24)
    • 为数据库添加了计算机名字段。这使得报告更加出色
    • 更新了 MySQL 驱动程序
    • 添加了 SQL 缓存,以便一次批处理 500 条记录,从而减少 SQL 服务器和本地计算机的负载。
    • 其他 bug 修复
    • 更新至 .Net 4.5(MySQL 驱动程序需要)

MSSQL 表名:FileAudit

列名 数据类型
ID int
FolderPath nvarchar(MAX)
AccountSAMAccountName nvarchar(MAX)
GroupSAMAccountName nvarchar(MAX)
ManagedBy nvarchar(MAX)
继承 nvarchar(MAX)
IsInherited nvarchar(MAX)
权限 nvarchar(MAX)
Owner nvarchar(MAX)
电脑 nvarchar(MAX)
RunDate bigint

MySQL 表名:FileAudit

列名 数据类型
ID int
FolderPath LONGTEXT
AccountSAMAccountName LONGTEXT
GroupSAMAccountName LONGTEXT
ManagedBy LONGTEXT
继承 LONGTEXT
IsInherited LONGTEXT
权限 LONGTEXT
Owner LONGTEXT
电脑 LONGTEXT
RunDate bigint
  • 版本 2.2.0 (2011-10-28)
    • 移除了硬编码的数据库名称。
    • 增加了对 MySQL 的支持。
    • 移除了所有日志文件输出。
    • 清理了界面。
  • 版本 2.1.1 (2011-05-02)
    • 修复了错误:循环组依赖关系消息。
    • 更改了分组,因此标记为“直接”的帐户更少,系统帐户被标记为“系统”。
  • 版本 2.1.0
    dicADUserType '存储 AD 用户/组的缓存(AD sAMAccountName,AD 对象类型)
    dicADGroup '存储组 sAMAccountName 和用户 sAMAccountName 的数组
    dicADGroupManager '存储组 sAMAccountName 和管理者的姓名
    dicADGroupSubGroup '存储组 sAMAccountName 和子组 sAMAccountName
    • 添加了循环依赖检查。这可以避免无限循环;还会将它们记录为错误。
    • 将计算机与 User 类合并。这意味着计算机的 ACL 被视为用户 ACL。
    • Contact 类添加了异常。
    • 将数组替换为 Dictionary。这样可以更轻松地理解缓存并减少循环。
  • 版本 2.0.9
    • 修复了已删除帐户的问题。
    • 修复了 AD 缓存问题。
    • 修复了启动按钮问题。
    • 添加了一个删除所有 SQL 记录的功能。
  • 版本 2.0.8
    • 更新了 SQL Server。
  • 版本 2.0.7
    • 修复了程序在只有一个子文件夹时会跳过该文件夹的问题。
    • 更改为将所有错误打印到“输出”选项卡。
    • 修复了插入 SQL Server 时可能导致数组越界的错误。
    • 修复了向 GUI 报告错误的错误。
    • 更改了更新目录至 \\ucpg-files.uchicago.edu\Installs\CustomTools\File Server Audit
    • 添加了一个功能,用于删除当前日期的旧 SQL 记录。
    • 尝试修复“取消”按钮。
  • 版本 2.0.6
    • 添加了总执行时间,并在结束时通知。
  • 版本 2.0.5
    • 在文本输出中添加了 IsInherited 字段。
    • 添加了表字段:IsInherited varchar(50)
  • 版本 2.0.4

    表名:FileAudit

    列名 数据类型
    ID int
    FolderPath nvarchar(MAX)
    AccountSAMAccountName nvarchar(MAX)
    GroupSAMAccountName nvarchar(MAX)
    ManagedBy nvarchar(MAX)
    继承 nvarchar(MAX)
    权限 nvarchar(MAX)
    Owner nvarchar(MAX)
    RunDate bigint
    • 修复了零个子目录会产生错误的数组问题。
    • 未知域不进行组枚举。
    • 为组管理添加了 Managed By。
    • 添加了直接将数据插入 SQL 数据库的功能。
  • 版本 2.0.3
    • 添加了“移除继承”功能,该功能仅显示非继承的权限。
  • 版本 2.0.2
    • 注释掉了大部分代码。
    • 更新了单独的文件日志类。
  • 版本 2.0.1
    • 为 AD 组添加了缓存,以加快枚举速度。
    • 为 AD 用户添加了缓存,以加快枚举速度。
    • 修复了 RecursiveSearch 子程序的逻辑问题。
© . All rights reserved.