Skip to main content

LIBRARY

Constant LIBRARY 

Source
pub const LIBRARY: &str = "# SPDX-License-Identifier: Apache-2.0\n#\n# Isoloom\'s configuration library for Windows: one function per step kind of the configuration\n# model. A recipe dot-sources it, then calls one function per step, in order. Each function\n# ensures a state behind its guard: a second apply changes nothing. Every change writes\n# `isoloom: changed <what>` and marks the file $env:ISOLOOM_CHANGED names (when set), which a\n# later service step reads to restart its service. A failure throws `isoloom: <why>`.\n\n[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12\n\n# Reports a change: its line, and the mark the restart rule reads.\nfunction Write-IsoloomChange {\n    param([Parameter(Mandatory)][string] $What)\n    Write-Output \"isoloom: changed $What\"\n    if ($env:ISOLOOM_CHANGED) {\n        New-Item -ItemType Directory -Force -Path (Split-Path -Parent $env:ISOLOOM_CHANGED) | Out-Null\n        Set-Content -LiteralPath $env:ISOLOOM_CHANGED -Value \'changed\'\n    }\n}\n\n# Whether an earlier step changed something during this apply: a service restarts then.\nfunction Test-IsoloomRestartDue {\n    return [bool]($env:ISOLOOM_CHANGED -and (Test-Path -LiteralPath $env:ISOLOOM_CHANGED))\n}\n\n# The SHA-256 of a file, in lowercase hex.\nfunction Get-IsoloomHash {\n    param([Parameter(Mandatory)][string] $Path)\n    return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()\n}\n\n# The packages step: each Windows feature installed (a server\'s role or feature, or a client\'s\n# optional feature).\nfunction Install-IsoloomFeature {\n    param([Parameter(Mandatory)][string[]] $Name)\n    $server = [bool](Get-Command -Name Get-WindowsFeature -ErrorAction SilentlyContinue)\n    foreach ($feature in $Name) {\n        if ($server) {\n            if ((Get-WindowsFeature -Name $feature).Installed) { continue }\n            $result = Install-WindowsFeature -Name $feature -IncludeManagementTools\n            if (-not $result.Success) { throw \"isoloom: installing the feature $feature failed\" }\n        } else {\n            if ((Get-WindowsOptionalFeature -Online -FeatureName $feature).State -eq \'Enabled\') { continue }\n            Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart | Out-Null\n        }\n        Write-IsoloomChange -What \"feature $feature\"\n    }\n}\n\n# A file at To with From\'s content (To written when it differs).\nfunction Copy-IsoloomFile {\n    param([Parameter(Mandatory)][string] $From, [Parameter(Mandatory)][string] $To)\n    if ((Test-Path -LiteralPath $To -PathType Leaf) -and ((Get-IsoloomHash -Path $From) -eq (Get-IsoloomHash -Path $To))) {\n        return\n    }\n    $parent = Split-Path -Parent $To\n    if ($parent) { New-Item -ItemType Directory -Force -Path $parent | Out-Null }\n    Copy-Item -LiteralPath $From -Destination $To -Force\n    Write-IsoloomChange -What $To\n}\n\n# The copy step: From (from the current folder) at To; a folder puts what it holds into To.\nfunction Copy-IsoloomItem {\n    param([Parameter(Mandatory)][string] $From, [Parameter(Mandatory)][string] $To)\n    if (-not (Test-Path -LiteralPath $From -PathType Container)) {\n        Copy-IsoloomFile -From $From -To $To\n        return\n    }\n    $root = (Resolve-Path -LiteralPath $From).Path.TrimEnd(\'\\\', \'/\')\n    if (-not (Test-Path -LiteralPath $To -PathType Container)) {\n        New-Item -ItemType Directory -Force -Path $To | Out-Null\n        Write-IsoloomChange -What $To\n    }\n    foreach ($entry in Get-ChildItem -LiteralPath $root -Recurse -Force) {\n        $target = Join-Path -Path $To -ChildPath $entry.FullName.Substring($root.Length).TrimStart(\'\\\', \'/\')\n        if ($entry.PSIsContainer) {\n            if (Test-Path -LiteralPath $target -PathType Container) { continue }\n            New-Item -ItemType Directory -Force -Path $target | Out-Null\n            Write-IsoloomChange -What $target\n        } else {\n            Copy-IsoloomFile -From $entry.FullName -To $target\n        }\n    }\n}\n\n# The template step: the file Isoloom filled in (its bytes, in base64) at To.\nfunction Install-IsoloomTemplate {\n    param([Parameter(Mandatory)][string] $To, [Parameter(Mandatory)][AllowEmptyString()][string] $Base64)\n    $temporary = [IO.Path]::GetTempFileName()\n    try {\n        [IO.File]::WriteAllBytes($temporary, [Convert]::FromBase64String($Base64))\n        Copy-IsoloomFile -From $temporary -To $To\n    } finally {\n        Remove-Item -LiteralPath $temporary -Force -ErrorAction SilentlyContinue\n    }\n}\n\n# The file step: Path made a folder, absent, or a download of Url pinned by Sha256.\nfunction Install-IsoloomFile {\n    param(\n        [Parameter(Mandatory)][string] $Path,\n        [Parameter(Mandatory)][ValidateSet(\'directory\', \'absent\', \'download\')][string] $State,\n        [string] $Url,\n        [string] $Sha256\n    )\n    switch ($State) {\n        \'directory\' {\n            if (Test-Path -LiteralPath $Path -PathType Container) { return }\n            New-Item -ItemType Directory -Force -Path $Path | Out-Null\n        }\n        \'absent\' {\n            if (-not (Test-Path -LiteralPath $Path)) { return }\n            Remove-Item -LiteralPath $Path -Recurse -Force\n        }\n        \'download\' {\n            if ((Test-Path -LiteralPath $Path -PathType Leaf) -and ((Get-IsoloomHash -Path $Path) -eq $Sha256)) { return }\n            $parent = Split-Path -Parent $Path\n            if ($parent) { New-Item -ItemType Directory -Force -Path $parent | Out-Null }\n            $temporary = \"$Path.isoloom-download\"\n            Invoke-WebRequest -UseBasicParsing -Uri $Url -OutFile $temporary\n            $got = Get-IsoloomHash -Path $temporary\n            if ($got -ne $Sha256) {\n                Remove-Item -LiteralPath $temporary -Force\n                throw \"isoloom: $Url has SHA-256 $got, not ${Sha256}: the file changed upstream, or the pin is wrong\"\n            }\n            Move-Item -LiteralPath $temporary -Destination $Path -Force\n        }\n    }\n    Write-IsoloomChange -What $Path\n}\n\n# A password as a SecureString, built a character at a time.\nfunction ConvertTo-IsoloomSecure {\n    param([Parameter(Mandatory)][string] $Phrase)\n    $secure = New-Object -TypeName System.Security.SecureString\n    foreach ($character in $Phrase.ToCharArray()) { $secure.AppendChar($character) }\n    return $secure\n}\n\n# Whether local user Name\'s password is Phrase.\nfunction Test-IsoloomPhrase {\n    param([Parameter(Mandatory)][string] $Name, [Parameter(Mandatory)][string] $Phrase)\n    Add-Type -AssemblyName System.DirectoryServices.AccountManagement\n    $machine = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList \'Machine\'\n    try { return $machine.ValidateCredentials($Name, $Phrase) } finally { $machine.Dispose() }\n}\n\n# Local user Name is a member of local group Group.\nfunction Add-IsoloomMember {\n    param([Parameter(Mandatory)][string] $Group, [Parameter(Mandatory)][string] $Name)\n    $members = Get-LocalGroupMember -Group $Group | ForEach-Object { ($_.Name -split \'\\\\\')[-1] }\n    if ($members -contains $Name) { return }\n    Add-LocalGroupMember -Group $Group -Member $Name\n    Write-IsoloomChange -What \"$Name in $Group\"\n}\n\n# The user step: local user Name, with its password (Phrase, when given) and in Groups.\nfunction Add-IsoloomUser {\n    param([Parameter(Mandatory)][string] $Name, [string] $Phrase, [string[]] $Groups = @())\n    if (-not (Get-LocalUser -Name $Name -ErrorAction SilentlyContinue)) {\n        if ($Phrase) {\n            New-LocalUser -Name $Name -Password (ConvertTo-IsoloomSecure -Phrase $Phrase) -PasswordNeverExpires | Out-Null\n        } else {\n            New-LocalUser -Name $Name -NoPassword | Out-Null\n        }\n        Write-IsoloomChange -What \"user $Name\"\n    } elseif ($Phrase -and -not (Test-IsoloomPhrase -Name $Name -Phrase $Phrase)) {\n        Set-LocalUser -Name $Name -Password (ConvertTo-IsoloomSecure -Phrase $Phrase)\n        Write-IsoloomChange -What \"password of $Name\"\n    }\n    foreach ($group in $Groups) { Add-IsoloomMember -Group $group -Name $Name }\n}\n\n# The group step: local group Name.\nfunction Add-IsoloomGroup {\n    param([Parameter(Mandatory)][string] $Name)\n    if (Get-LocalGroup -Name $Name -ErrorAction SilentlyContinue) { return }\n    New-LocalGroup -Name $Name | Out-Null\n    Write-IsoloomChange -What \"group $Name\"\n}\n\n# A service Isoloom defines: a startup task (as SYSTEM) running Run (a program and its\n# arguments) in Directory, registered again when it changed.\nfunction Register-IsoloomTask {\n    param([Parameter(Mandatory)][string] $Name, [Parameter(Mandatory)][string[]] $Run, [string] $Directory)\n    $arguments = ($Run | Select-Object -Skip 1 | ForEach-Object { \'\"\' + ($_ -replace \'\"\', \'\\\"\') + \'\"\' }) -join \' \'\n    $settings = @{ Execute = $Run[0] }\n    if ($arguments) { $settings.Argument = $arguments }\n    if ($Directory) { $settings.WorkingDirectory = $Directory }\n    $action = New-ScheduledTaskAction @settings\n    $task = Get-ScheduledTask -TaskName \"isoloom-$Name\" -ErrorAction SilentlyContinue\n    $same = $task -and $task.Actions[0].Execute -eq $action.Execute -and $task.Actions[0].Arguments -eq $action.Arguments -and\n        $task.Actions[0].WorkingDirectory -eq $action.WorkingDirectory\n    if ($same) { return }\n    $trigger = New-ScheduledTaskTrigger -AtStartup\n    Register-ScheduledTask -TaskName \"isoloom-$Name\" -Action $action -Trigger $trigger -User \'SYSTEM\' -RunLevel Highest -Force | Out-Null\n    Write-IsoloomChange -What \"task isoloom-$Name\"\n}\n\n# The service step for a service Isoloom defines: its startup task enabled and running, or\n# disabled and stopped.\nfunction Register-IsoloomTaskState {\n    param([Parameter(Mandatory)][string] $Name, [Parameter(Mandatory)][bool] $Enabled)\n    $task = Get-ScheduledTask -TaskName \"isoloom-$Name\"\n    if (-not $Enabled) {\n        if ($task.State -eq \'Running\') { Stop-ScheduledTask -TaskName \"isoloom-$Name\"; Write-IsoloomChange -What \"isoloom-$Name stopped\" }\n        if ($task.State -ne \'Disabled\') { Disable-ScheduledTask -TaskName \"isoloom-$Name\" | Out-Null; Write-IsoloomChange -What \"isoloom-$Name disabled\" }\n        return\n    }\n    if ($task.State -eq \'Disabled\') { Enable-ScheduledTask -TaskName \"isoloom-$Name\" | Out-Null; Write-IsoloomChange -What \"isoloom-$Name enabled\" }\n    if ((Get-ScheduledTask -TaskName \"isoloom-$Name\").State -ne \'Running\') {\n        Start-ScheduledTask -TaskName \"isoloom-$Name\"\n        Write-IsoloomChange -What \"isoloom-$Name started\"\n    } elseif (Test-IsoloomRestartDue) {\n        Stop-ScheduledTask -TaskName \"isoloom-$Name\"\n        Start-ScheduledTask -TaskName \"isoloom-$Name\"\n        Write-Output \"isoloom: restarted isoloom-$Name\"\n    }\n}\n\n# The service step: Windows service Name started automatically and running (restarted when an\n# earlier step changed something), or disabled and stopped.\nfunction Register-IsoloomService {\n    param([Parameter(Mandatory)][string] $Name, [Parameter(Mandatory)][bool] $Enabled)\n    $service = Get-Service -Name $Name -ErrorAction SilentlyContinue\n    if (-not $service) { throw \"isoloom: no Windows service ${Name}: install what provides it in an earlier step\" }\n    if (-not $Enabled) {\n        if ($service.StartType -ne \'Disabled\') { Set-Service -Name $Name -StartupType Disabled; Write-IsoloomChange -What \"$Name disabled\" }\n        if ($service.Status -ne \'Stopped\') { Stop-Service -Name $Name -Force; Write-IsoloomChange -What \"$Name stopped\" }\n        return\n    }\n    if ($service.StartType -ne \'Automatic\') { Set-Service -Name $Name -StartupType Automatic; Write-IsoloomChange -What \"$Name enabled\" }\n    if ($service.Status -ne \'Running\') {\n        Start-Service -Name $Name\n        Write-IsoloomChange -What \"$Name started\"\n    } elseif (Test-IsoloomRestartDue) {\n        Restart-Service -Name $Name -Force\n        Write-Output \"isoloom: restarted $Name\"\n    }\n}\n\n# The command step: Run (a script block\'s text) after its guard, unless the guard says it\n# already ran: Creates (a path whose existence says so) or Unless (a check that succeeds).\nfunction Invoke-IsoloomCommand {\n    param([Parameter(Mandatory)][string] $Run, [string] $Creates, [string] $Unless)\n    if ($Creates -and (Test-Path -LiteralPath $Creates)) { return }\n    if ($Unless -and (Test-IsoloomScript -Text $Unless)) { return }\n    if (-not (Test-IsoloomScript -Text $Run -Loud)) { throw \"isoloom: the command failed: $Run\" }\n    Write-IsoloomChange -What \'command\'\n}\n\n# Whether script Text succeeds: no error, and a native program\'s exit code 0. Its output is\n# shown with Loud, else dropped.\nfunction Test-IsoloomScript {\n    param([Parameter(Mandatory)][string] $Text, [switch] $Loud)\n    Set-Variable -Name LASTEXITCODE -Scope Global -Value 0\n    try {\n        if ($Loud) { & ([scriptblock]::Create($Text)) } else { & ([scriptblock]::Create($Text)) | Out-Null }\n    } catch {\n        if ($Loud) { Write-Error -Message $_ -ErrorAction Continue }\n        return $false\n    }\n    return (Get-Variable -Name LASTEXITCODE -Scope Global -ValueOnly) -eq 0\n}\n\n# The firewall step: Port (with Protocol) open in Windows Firewall.\nfunction Enable-IsoloomFirewallPort {\n    param([Parameter(Mandatory)][int] $Port, [Parameter(Mandatory)][ValidateSet(\'TCP\', \'UDP\')][string] $Protocol)\n    $name = \"isoloom-$Port-$Protocol\"\n    if (Get-NetFirewallRule -Name $name -ErrorAction SilentlyContinue) { return }\n    New-NetFirewallRule -Name $name -DisplayName \"Isoloom $Port/$Protocol\" -Direction Inbound -Action Allow -Protocol $Protocol -LocalPort $Port | Out-Null\n    Write-IsoloomChange -What \"firewall $Port/$Protocol\"\n}\n";
Expand description

The library, as Isoloom ships it.