Public/Set-HDTShareCredential.ps1

function Set-HDTShareCredential {
    <#
        .SYNOPSIS
            Writes the deployment account credential a boot image will carry.
 
        .DESCRIPTION
            THE ONLY WRITER OF THE DEPLOYMENT SECRET. It writes
            Control\share-credential.json inside the workspace, and 05-01 made a
            password: key in workspace.yaml a validation error that names this
            command - because workspace.yaml is the document an administrator
            hand-edits and commits, and a secret in it ends up in git.
 
            THE STORED VALUE IS OBFUSCATED AND IS NOT CLAIMED TO BE SECURE, and
            the file says so itself: it carries a 'warning' field whose sentence
            states that anyone who can read this file or the boot image can
            recover the password - "obfuscation is not claimed as
            security ... the docs say so plainly rather than implying the image
            is safe to hand out". docs/share-account.md says it again in prose,
            with the least-privilege setup that makes the account worth as
            little as possible.
 
            IT IS NOT DPAPI. DPAPI is user- and machine-bound, and this file has
            to be readable inside WinPE on a machine that has never seen the one
            that wrote it - which is the whole reason the credential is embedded
            at all.
 
            The path is built with Get-HDTWorkspacePath, never a literal: the
            workspace layout is written down in exactly one place, and
            Start-HDTResume once built a path from the literal 'Sequences' while
            everything else said 'TaskSequences'.
 
            It carries SupportsShouldProcess because it overwrites a secret.
 
        .PARAMETER WorkspaceRoot
            The workspace root - a local path or a UNC share.
 
        .PARAMETER Credential
            The deployment account. Its password must not be empty: an empty
            password is an anonymous logon, which is what
            New-HDTSmbContentProvider refuses at Connect.
 
        .PARAMETER FileSystem
            An IFileSystem. Defaults to the real adapter.
 
        .INPUTS
            None. This command does not accept pipeline input.
 
        .OUTPUTS
            None. A cmdlet that echoed the credential would put it in a
            transcript.
 
        .EXAMPLE
            Set-HDTShareCredential -WorkspaceRoot '\\server\HdtShare' -Credential (Get-Credential)
 
        .EXAMPLE
            Set-HDTShareCredential -WorkspaceRoot 'C:\HDTLab\Share' -Credential $credential -WhatIf
 
            What it would overwrite, without overwriting it.
    #>

    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([void])]
    param(
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string] $WorkspaceRoot,

        [Parameter(Mandatory = $true)]
        [ValidateNotNull()]
        [pscredential] $Credential,

        [Parameter()]
        [AllowNull()]
        [object] $FileSystem
    )

    Set-StrictMode -Version Latest
    $ErrorActionPreference = 'Stop'

    if ($null -eq $FileSystem) {
        $FileSystem = New-HDTFileSystem
    }

    $path = Get-HDTWorkspacePath -Root $WorkspaceRoot -Kind Control -ChildPath 'share-credential.json'

    $plain = [string] $Credential.GetNetworkCredential().Password

    if ([string]::IsNullOrEmpty($plain)) {
        $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -Path $path `
                    -Message ("the credential for '{0}' has an empty password. An empty password is an anonymous logon, and the Smb content provider refuses one at Connect." -f $Credential.UserName)))
    }

    $document = [ordered] @{
        schemaVersion = 1
        username      = [string] $Credential.UserName
        password      = (Protect-HDTShareSecret -Secret $plain)
        warning       = 'This password is obfuscated, not encrypted: the key is a constant in the Hephaestus module, so anyone who can read this file - or the boot image, the ISO or the Boot folder that carry it - can recover the password. Treat all of them as credentials, and keep the account least-privileged (docs/share-account.md).'
    }

    # ConvertTo-Json, then IFileSystem: the adapter writes UTF-8 with no BOM on
    # both engines, which Set-Content does not (tests/helpers/README.md F11).
    $text = ConvertTo-Json -InputObject $document -Depth 3

    if (-not $PSCmdlet.ShouldProcess($path, ("Write the deployment credential for '{0}'" -f $Credential.UserName))) {
        return
    }

    $FileSystem.WriteAllText($path, $text)
}