Module/Rule.UserRight/Convert/Methods.ps1

# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
#region Method Functions
<#
    .SYNOPSIS
        Gets the User Rights Assignment Display Name from the check-content that are assigned to
        the User Rights Assignment policy
#>

function Get-UserRightDisplayName
{
    [CmdletBinding()]
    [OutputType([string])]
    param
    (
        [Parameter(Mandatory = $true)]
        [string[]]
        $CheckContent
    )

    Write-Verbose "[$($MyInvocation.MyCommand.Name)]"

    # Use a regular expression to pull the userright string from between the quotes
    $userRightDisplayNameSearch = ( $checkContent |
        Select-String -Pattern ([RegularExpression]::TextBetweenQuotes) -AllMatches )

    [string[]] $userRightDisplayName = $userRightDisplayNameSearch.matches.Groups.Value |
        Where-Object { $userRightNameToConstant.Keys -contains $PSItem }

    if ( $null -ne $userRightDisplayName )
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] UserRightDisplayName : $UserRightDisplayName "
        return $userRightDisplayName[0]
    }
    else
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] UserRightDisplayName : Not Found"
    }
}

<#
    .SYNOPSIS
        Enumerates User Rights Assignment Policy display names and converts them to the matching constant
#>

function Get-UserRightConstant
{
    [CmdletBinding()]
    [OutputType([string])]
    param
    (
        [Parameter(Mandatory = $true)]
        [string]
        $UserRightDisplayName
    )

    Write-Verbose "[$($MyInvocation.MyCommand.Name)]"

    $userRightConstant = $userRightNameToConstant.$UserRightDisplayName

    if ( $null -ne $userRightConstant )
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Found: $UserRightDisplayName : $userRightConstant "
        $userRightConstant
    }
    else
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Not Found : $UserRightDisplayName "
    }
}

<#
    .SYNOPSIS
        Gets the Identity from the check-content that are assigned to the User Rights Assignment policy
#>

function Get-UserRightIdentity
{
    [CmdletBinding()]
    [OutputType([string[]])]
    param
    (
        [Parameter(Mandatory = $true)]
        [string[]]
        $CheckContent
    )

    Write-Verbose "[$($MyInvocation.MyCommand.Name)]"
    <#
        Select the line that contains the User Right
        one entry contains multiple lines with the same user right so select the first index
    #>


    $return = [System.Collections.ArrayList] @()

    if ($checkContent -Match "Administrators\sAuditors\s" -and $checkContent -Match "DNS\sServer\slog\sfile" )
    {
        [void] $return.Add('Administrators')
    }
    elseif ($checkContent -Match "If (any|the following){1} (accounts or groups|groups or accounts) (other than the following|are not defined){1}.*this is a finding")
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Ensure : Present"
        # There is an edge case where multiple finding statements are made, so a zero index is needed.
        [int] $lineNumber = (($checkContent | Select-String "this is a finding")[0]).LineNumber
        # Set the negative index number of the first group to process.
        $startLine = $lineNumber - $checkContent.Count

        foreach ($line in $checkContent[$startLine..-1])
        {
            <#
                The Windows Server 2016 STIG prepends each identity with a dash space (- )
                that needs to be trimmed from the results before they are returned.
            #>

            $line = $line -replace '^\s*-\s*', ''

            if
            (
                $line.Trim() -notmatch ":|^If|^Microsoft|^Organizations|^Vendor|^The|^(Systems|Workstations)\sDedicated|Privileged Access" -and
                -not [string]::IsNullOrEmpty( $line.Trim() )
            )
            {
                <#
                    There are a few entries that add the word 'group' to the end of the group name, so
                    they need to be cleaned up.
                #>

                if ($line.Trim() -match "Hyper-V")
                {
                    [void] $return.Add("{Hyper-V}")
                }
                elseif ($line.Trim() -match "(^Enterprise|^Domain) (Admins|Admin)|^Guests")
                {
                    if ($line -match '\sAdmin\s')
                    {
                        $line = $line -replace 'Admin', 'Admins'
                    }
                    # .Trim method is case sensitive, so the replace operator is used instead
                    [void] $return.Add($($line.Trim() -replace ' Group').Trim())
                }
                elseif ($line.Trim() -match '"Local account and member of Administrators group" or "Local account"')
                {
                    [void] $return.Add('(Local account and member of Administrators group|Local account)')
                }
                else
                {
                    <#
                        The below regex with remove anything between parentheses.
                        This address the edge case where parentheses are used to add a note following the identity
                    #>

                    [void] $return.Add( ($line -replace '\([\s\S]*?\)').Trim() )
                }
            }
        }
    }
    elseif ($checkContent -Match "If any (accounts or groups|groups or accounts).*are (granted|defined).*this is a finding")
    {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Ensure : Absent"

        [void] $return.Add("NULL")
    }

    $return
}

<#
    .SYNOPSIS
        Looks in the Check-Content element to see if it matches any scrict User Rights Assignments.
#>

function Test-SetForceFlag
{
    [CmdletBinding()]
    [OutputType([bool])]
    param
    (
        [Parameter(Mandatory = $true)]
        [string[]]
        $CheckContent
    )

    if ($checkContent -match 'If any (accounts or groups|groups or accounts) other than the following')
    {
        return $true
    }
    elseif ($checkContent -match 'If any (accounts or groups|groups or accounts)\s*(\(.*\),)?\s*are (granted|defined)')
    {
        return $true
    }

    return $false
}

<#
    .SYNOPSIS
        Supports the ContainsMultipleRules statis method to test for multiple
        user rights assignment rules
#>

function Test-MultipleUserRightsAssignment
{
    [CmdletBinding()]
    [OutputType([bool])]
    param
    (
        [Parameter(Mandatory = $true)]
        [AllowEmptyString()]
        [string[]]
        $CheckContent
    )

    Write-Verbose "[$($MyInvocation.MyCommand.Name)]"

    $userRightMatches = $checkContent | Select-String -Pattern 'local computer policy'

    if ( $userRightMatches.count -gt 1 )
    {
        return $true
    }

    return $false
}

<#
    .SYNOPSIS
        Parses STIG check-content to return text pertaining to individual UserRightAssignment rules
#>

function Split-MultipleUserRightsAssignment
{
    [CmdletBinding()]
    [OutputType([string[]])]
    param
    (
        [Parameter(Mandatory = $true)]
        [AllowEmptyString()]
        [string[]]
        $CheckContent
    )

    Write-Verbose "[$($MyInvocation.MyCommand.Name)]"

    $userRightMatches = $checkContent | Select-String -Pattern 'local computer policy'
    $i = 1
    foreach ( $match in $userRightMatches )
    {
        $stringBuilder = New-Object System.Text.StringBuilder
        if ($i -ne $userRightMatches.count)
        {
            [string[]] $content = $checkContent[($match.lineNumber)..($userRightMatches[$i].lineNumber - 2 )]
        }
        else
        {
            [string[]] $content = $checkContent[($match.lineNumber)..$checkContent.Length]
        }

        foreach ( $line in $content  )
        {
            [void] $stringBuilder.Append("$line`r`n")
        }
        $i++
        $stringBuilder.ToString()
    }
}
#endregion