better way to do long comparison?

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of Noah Sparks Noah Sparks 3 years ago.

  • Author
    Posts
  • #15797
    Profile photo of Noah Sparks
    Noah Sparks
    Participant

    Hello,

    Writing a script to do ACL checks and I have a section where I have a really long comparison which you can see a sample of below. That section is pretty ugly and I am wondering if anyone has an idea on how to better accomplish that or clean it up in terms of using a technique like splatting?

    If ($Entry.FileSystemRights -like "*write*" -or $Entry.FileSystemRights -like "*Full*" -or $Entry.FileSystemRights -like "*Modify*" -or $Entry.FileSystemRights -like "*Create*" `
    -and $Entry.IdentityReference -notmatch $AdminRegex -and $Entry.IdentityReference -notlike "NT AUTHORITY\SYSTEM" -and $Entry.IdentityReference -ne "NT SERVICE\TrustedInstaller" `
    -and $Entry.IdentityReference -ne "CREATOR OWNER")

  • #15800
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    The FileSystemRights attribute is an enumerated type which uses bitflags for its values. To shorten that part of the expression, you could use the bitwise AND operator to test for any of those flags. For example:

    $rights = [System.Security.AccessControl.FileSystemRights] 'WriteData, CreateFiles, CreateDirectories, WriteExtendedAttributes, WriteAttributes, Write, Modify, FullControl'
    
    if (($Entry.FileSystemRights -band $rights) -ne 0)
    {
        # One or more of those rights is set in $Entry.FileSystemRights
    }
    

    For the IdentityReference comparison, you're already using a regular expression for part of it, but since I don't know what's in there, it's tricky to tell you how to add to it. Here's how I would build a regex based on the other values, if you want to stick with string comparisons. (Using SIDs instead would probably be faster, but you probably won't notice the difference unless you're doing this many thousands of times.)

    $rights = [System.Security.AccessControl.FileSystemRights] 'WriteData, CreateFiles, CreateDirectories, WriteExtendedAttributes, WriteAttributes, Write, Modify, FullControl'
    
    $IgnoreUsers = 'NT AUTHORITY\SYSTEM', 'NT SERVICE\TrustedInstaller', 'CREATOR OWNER'
    $pattern = ($IgnoreUsers | ForEach-Object { [regex]::Escape($_) }) -join '|'
    
    if (($Entry.FileSystemRights -band $rights) -ne 0 -and $Entry.IdentityReference.Value -notmatch $pattern)
    {
        # One or more of those rights is set in $Entry.FileSystemRights, and the IdentityReference value
        # isn't one of the ones you're filtering out.
    }
    
  • #15807
    Profile photo of Noah Sparks
    Noah Sparks
    Participant

    Hey Dave,

    Thanks for the reply. This prompted me to realize I was durping on the regex and could just put everything into a couple arguments. I was already searching for all possible admin accounts in the regex variable you saw in my sample script so I just need to add the rest like you pointed out.

    The bitflags stuff is interesting...I might look into changing some things to utilize it. Anyways thanks for the help.

You must be logged in to reply to this topic.