Public/Get-HDTShareCredential.ps1
|
function Get-HDTShareCredential { <# .SYNOPSIS Reads the deployment account credential back out of the workspace. .DESCRIPTION The read half of the embedded credential. It is what runs inside WinPE: the booted machine reads Control\share-credential.json out of the boot image or the share, recovers the password, and hands it to New-HDTSmbContentProvider. It reads through an injected IFileSystem, never Get-Content, so the whole path is provable under Pester with no share and no boot image. A missing file is an HDTConfigurationError naming the file AND the command that writes it, because "no credential" is the single most likely reason a PXE-booted machine cannot reach its share. THE PASSWORD IT RETURNS IS PLAIN TEXT. That is what New-SmbMapping takes, and HDT is explicit that the value is recoverable by anyone holding the boot image; wrapping it in a SecureString here would unwrap one call later and protect nothing. .PARAMETER WorkspaceRoot The workspace root - a local path or a UNC share. .PARAMETER FileSystem An IFileSystem. Defaults to the real adapter. .INPUTS None. This command does not accept pipeline input. .OUTPUTS System.Management.Automation.PSCustomObject with UserName and Password. .EXAMPLE $secret = Get-HDTShareCredential -WorkspaceRoot 'X:\Deploy' $secret.UserName .EXAMPLE $secret = Get-HDTShareCredential -WorkspaceRoot $root -FileSystem $fs $secure = New-Object System.Security.SecureString foreach ($character in $secret.Password.ToCharArray()) { $secure.AppendChar($character) } $credential = New-Object System.Management.Automation.PSCredential $secret.UserName, $secure The shape New-HDTSmbContentProvider -Credential takes. #> [CmdletBinding()] [OutputType([pscustomobject])] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $WorkspaceRoot, [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' if (-not $FileSystem.TestPath($path)) { $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -Path $path ` -Message 'there is no deployment credential in this workspace. Write one with Set-HDTShareCredential; a booted machine has no other way to authenticate to the share.' ` -Category ObjectNotFound)) } $text = $FileSystem.ReadAllText($path) try { # Assigned first, wrapped second: under Windows PowerShell 5.1 # ConvertFrom-Json does not enumerate a top-level array (README F12). $document = ConvertFrom-Json -InputObject $text } catch { $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -Path $path ` -Message ("the deployment credential could not be read as JSON: {0}. Rewrite it with Set-HDTShareCredential." -f $_.Exception.Message))) } $userName = '' $protected = '' if ($null -ne $document.PSObject.Properties['username']) { $userName = [string] $document.username } if ($null -ne $document.PSObject.Properties['password']) { $protected = [string] $document.password } if ([string]::IsNullOrWhiteSpace($userName) -or [string]::IsNullOrWhiteSpace($protected)) { $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -Path $path ` -Message 'the deployment credential is missing its username or its password. Rewrite it with Set-HDTShareCredential.')) } try { $plain = Unprotect-HDTShareSecret -Protected $protected } catch { $PSCmdlet.ThrowTerminatingError((New-HDTErrorRecord -Path $path ` -Message ("the deployment credential could not be decoded: {0}. Rewrite it with Set-HDTShareCredential." -f $_.Exception.Message))) } return [pscustomobject] @{ UserName = $userName Password = $plain } } |