Private/Kinds/DomainAccountElevated.ps1

# The DomainAccountElevated Kind: the account and logon type of every scheduled task, read with admin rights.
#
# A scheduled task that runs as the User's domain account with a stored password sends the
# old password after a change and locks the account again. The DomainAccount Kind runs in
# the Main Part, and without admin rights Windows lists only the tasks the User may see: a
# task somebody else set up to run as the User stays unread. This Kind reads every task's
# path and principal with admin rights and judges nothing: the Domain account Check is
# handed its reading as $Observed['DomainAccountElevated'] and judges from it in place of
# its own.
#
# Names and principals only: the task's path, the account it runs as and its logon type.
# Never its actions, arguments or triggers, and never a secret (ADR-0016).
#
# Its one Finding says that the reading was taken, so that the Check is accounted for in
# the Report like any other.

$script:DomainAccountElevatedNeedsAdmin = $true

# What Get-DomainAccountElevatedData hands its Judge. See Private/DataShape.ps1.
$script:DomainAccountElevatedDataShape = @{
    Tasks      = 'List'
    TasksError = 'Value'
    GatheredAt = 'Answered'
}

function Get-DomainAccountElevatedData {
    <#
    .SYNOPSIS
        Every scheduled task of the machine with the account it runs as and its logon type,
        as an administrator may read them. Decides nothing.
    .DESCRIPTION
        Read as the DomainAccount Kind reads its own, by the same function, so that the two
        readings have one shape and one can stand in for the other.
    #>

    [CmdletBinding()]
    [OutputType([psobject])]
    param([hashtable]$Parameters = @{})

    $tasks = $null
    $problem = $null
    try { $tasks = @(Read-DomainAccountTask) } catch { $problem = (Get-DomainAccountErrorText -Exception $_.Exception) }

    [pscustomobject]@{
        PSTypeName = 'Gutcheck.Data.DomainAccountElevated'
        Tasks      = $tasks
        TasksError = $problem
        GatheredAt = Get-Date
    }
}

function ConvertTo-DomainAccountElevatedFinding {
    <#
    .SYNOPSIS
        One Finding saying how many scheduled tasks were read with admin rights. Pure.
    .DESCRIPTION
        No judgement: which task holds the User's password is the Domain account Check's to
        say, with the User's account it knows.
    #>

    [CmdletBinding()]
    [OutputType([psobject])]
    param([AllowNull()]$Data, [hashtable]$Parameters = @{})

    $check = Get-Text 'Check.DomainAccountElevated.Reading'
    $problem = Format-DomainAccountError -Problem "$(Get-DataProperty $Data 'TasksError')"
    if ($problem) {
        return New-Finding -Category User -Check $check -Severity INFO -Value ((Get-Text 'Value.DomainAccount.HeldUnread') -f $problem) `
            -Hint (Get-Text 'Hint.DomainAccount.HeldTasksUnread')
    }
    if (-not (Test-DataPropertyPresent -InputObject $Data -Name 'Tasks')) {
        return New-UnavailableFinding -Category User -Check $check -Hint (Get-Text 'Hint.DomainAccount.HeldTasksUnread')
    }
    $count = @(Get-DataCollection $Data 'Tasks' | ForEach-Object { $_ }).Count
    New-Finding -Category User -Check $check -Severity OK -Value ((Get-Text 'Value.DomainAccountElevated.Reading') -f $count)
}