Skip to content

Commit 33217a0

Browse files
authored
Merge pull request #648 from limiteddenial/issue423
xRemoteFile: Added Checksum support - Issue423
2 parents 055319f + 48779e9 commit 33217a0

9 files changed

Lines changed: 494 additions & 11 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- Added MOF descriptions.
1010
- Corrected minor style issues.
1111
- Fix minor style issues in hashtable layout.
12+
- Added support for Checksum on xRemoteFile - [issue #423](https://github.com/PowerShell/PSDscResources/issues/423)
1213

1314
## 8.10.0.0
1415

DSCResources/MSFT_xRemoteFile/MSFT_xRemoteFile.psm1

Lines changed: 130 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ $script:cacheLocation = "$env:ProgramData\Microsoft\Windows\PowerShell\Configura
2121
.PARAMETER Uri
2222
Uri of a file which should be copied or downloaded. This parameter
2323
supports HTTP and HTTPS values.
24+
25+
.PARAMETER ChecksumType
26+
The algorithm used to calculate the checksum of the file.
2427
#>
2528
function Get-TargetResource
2629
{
@@ -36,19 +39,32 @@ function Get-TargetResource
3639
[Parameter(Mandatory = $true)]
3740
[ValidateNotNullOrEmpty()]
3841
[System.String]
39-
$Uri
42+
$Uri,
43+
44+
[Parameter()]
45+
[System.String]
46+
[ValidateSet('None', 'SHA1', 'SHA256', 'SHA384', 'SHA512', 'MACTripleDES', 'MD5', 'RIPEMD160')]
47+
$ChecksumType = 'None'
48+
4049
)
4150

4251
# Check whether DestinationPath is existing file
4352
$ensure = 'Absent'
4453
$pathItemType = Get-PathItemType -Path $DestinationPath
54+
$checksumValue = ''
4555

4656
switch ($pathItemType)
4757
{
4858
'File'
4959
{
5060
Write-Verbose -Message ($script:localizedData.DestinationPathIsExistingFile -f $DestinationPath)
5161
$ensure = 'Present'
62+
63+
if ($ChecksumType -ine 'None')
64+
{
65+
$getFileHash = Get-FileHash -Path $DestinationPath -Algorithm $ChecksumType
66+
$checksumValue = $getFileHash.Hash
67+
}
5268
}
5369

5470
'Directory'
@@ -63,6 +79,12 @@ function Get-TargetResource
6379
{
6480
Write-Verbose -Message ($script:localizedData.FileExistsInDestinationPath -f $uriFileName)
6581
$ensure = 'Present'
82+
83+
if ($ChecksumType -ine 'None')
84+
{
85+
$getFileHash = Get-FileHash -Path $expectedDestinationPath -Algorithm $ChecksumType
86+
$checksumValue = $getFileHash.Hash
87+
}
6688
}
6789
}
6890

@@ -81,6 +103,7 @@ function Get-TargetResource
81103
DestinationPath = $DestinationPath
82104
Uri = $Uri
83105
Ensure = $ensure
106+
Checksum = $checksumValue
84107
}
85108
}
86109

@@ -123,6 +146,12 @@ function Get-TargetResource
123146
.PARAMETER ProxyCredential
124147
Specifies a user account that has permission to use the proxy server that
125148
is specified by the Proxy parameter.
149+
150+
.PARAMETER Checksum
151+
Specifies the expected checksum value of downloaded file.
152+
153+
.PARAMETER ChecksumType
154+
The algorithm used to calculate the checksum of the file.
126155
#>
127156
function Set-TargetResource
128157
{
@@ -167,7 +196,16 @@ function Set-TargetResource
167196
[Parameter()]
168197
[System.Management.Automation.Credential()]
169198
[System.Management.Automation.PSCredential]
170-
$ProxyCredential
199+
$ProxyCredential,
200+
201+
[Parameter()]
202+
[System.String]
203+
[ValidateSet('None', 'SHA1', 'SHA256', 'SHA384', 'SHA512', 'MACTripleDES', 'MD5', 'RIPEMD160')]
204+
$ChecksumType = 'None',
205+
206+
[Parameter()]
207+
[System.String]
208+
$Checksum
171209
)
172210

173211
# Validate Uri
@@ -198,7 +236,7 @@ function Set-TargetResource
198236
}
199237

200238
# Validate DestinationPath does not contain invalid characters
201-
@('*', '?', '"', '<', '>', '|') | Foreach-Object -Process {
239+
@('*', '?', '"', '<', '>', '|') | ForEach-Object -Process {
202240
if ($DestinationPath.Contains($_))
203241
{
204242
$errorMessage = $script:localizedData.DestinationPathHasInvalidCharactersError -f $DestinationPath
@@ -233,6 +271,10 @@ function Set-TargetResource
233271
$DestinationPath = Join-Path -Path $DestinationPath -ChildPath $uriFileName
234272
}
235273

274+
# Remove ChecksumType and Checksum from parameters as they are not parameters of Invoke-WebRequest.
275+
$null = $PSBoundParameters.Remove('ChecksumType')
276+
$null = $PSBoundParameters.Remove('Checksum')
277+
236278
# Remove DestinationPath and MatchSource from parameters as they are not parameters of Invoke-WebRequest
237279
$null = $PSBoundParameters.Remove('DestinationPath')
238280
$null = $PSBoundParameters.Remove('MatchSource')
@@ -301,13 +343,34 @@ function Set-TargetResource
301343
$ProgressPreference = $currentProgressPreference
302344
}
303345

346+
# Check checksum
347+
if ($ChecksumType -ine 'None' -and -not [String]::IsNullOrEmpty($Checksum))
348+
{
349+
$fileHashSplat = @{
350+
Path = $DestinationPath
351+
Algorithm = $ChecksumType
352+
}
353+
354+
$getFileHash = Get-FileHash @fileHashSplat
355+
$fileHash = $getFileHash.Hash
356+
357+
if ($fileHash -ine $Checksum)
358+
{
359+
# the checksum failed
360+
$errorMessage = $script:localizedData.ChecksumDoesNotMatch -f $Checksum, $fileHash
361+
New-InvalidDataException `
362+
-ErrorId 'ChecksumDoesNotMatch' `
363+
-ErrorMessage $errorMessage
364+
}
365+
}
366+
304367
# Update cache
305368
if (Test-Path -Path $DestinationPath)
306369
{
307370
$downloadedFile = Get-Item -Path $DestinationPath
308371
$lastWriteTime = $downloadedFile.LastWriteTimeUtc
309372
$filesize = $downloadedFile.Length
310-
$inputObject = @{}
373+
$inputObject = @{ }
311374
$inputObject['LastWriteTime'] = $lastWriteTime
312375
$inputObject['FileSize'] = $filesize
313376
Update-Cache -DestinationPath $DestinationPath -Uri $Uri -InputObject $inputObject
@@ -352,6 +415,12 @@ function Set-TargetResource
352415
.PARAMETER ProxyCredential
353416
Specifies a user account that has permission to use the proxy server that
354417
is specified by the Proxy parameter.
418+
419+
.PARAMETER Checksum
420+
Specifies the expected checksum value of downloaded file.
421+
422+
.PARAMETER ChecksumType
423+
The algorithm used to calculate the checksum of the file.
355424
#>
356425
function Test-TargetResource
357426
{
@@ -397,7 +466,16 @@ function Test-TargetResource
397466
[Parameter()]
398467
[System.Management.Automation.Credential()]
399468
[System.Management.Automation.PSCredential]
400-
$ProxyCredential
469+
$ProxyCredential,
470+
471+
[Parameter()]
472+
[System.String]
473+
[ValidateSet('None', 'SHA1', 'SHA256', 'SHA384', 'SHA512', 'MACTripleDES', 'MD5', 'RIPEMD160')]
474+
$ChecksumType = 'None',
475+
476+
[Parameter()]
477+
[System.String]
478+
$Checksum
401479
)
402480

403481
# Check whether DestinationPath points to existing file or directory
@@ -434,6 +512,28 @@ function Test-TargetResource
434512
Write-Verbose -Message $script:localizedData.MatchSourceFalse
435513
$fileExists = $true
436514
}
515+
516+
if ($ChecksumType -ine 'None' `
517+
-and -not [String]::IsNullOrEmpty($Checksum) `
518+
-and $fileExists -eq $true)
519+
{
520+
$fileHashSplat = @{
521+
Path = $DestinationPath
522+
Algorithm = $ChecksumType
523+
}
524+
$getFileHash = Get-FileHash @fileHashSplat
525+
$fileHash = $getFileHash.Hash
526+
527+
if ($fileHash -ieq $Checksum)
528+
{
529+
$fileExists = $true
530+
}
531+
else
532+
{
533+
# The checksum does not match. The file may match what is in the cached data. Resetting it to false.
534+
$fileExists = $false
535+
}
536+
}
437537
}
438538

439539
'Directory'
@@ -464,6 +564,28 @@ function Test-TargetResource
464564
Write-Verbose -Message $script:localizedData.MatchSourceFalse
465565
$fileExists = $true
466566
}
567+
568+
if ($ChecksumType -ine 'None' `
569+
-and -not [String]::IsNullOrEmpty($Checksum) `
570+
-and $fileExists -eq $true)
571+
{
572+
$fileHashSplat = @{
573+
Path = $expectedDestinationPath
574+
Algorithm = $ChecksumType
575+
}
576+
$getFileHash = Get-FileHash @fileHashSplat
577+
$fileHash = $getFileHash.Hash
578+
579+
if ($fileHash -ieq $Checksum)
580+
{
581+
$fileExists = $true
582+
}
583+
else
584+
{
585+
# The checksum does not match. The file may match what is in the cached data. Resetting it to false.
586+
$fileExists = $false
587+
}
588+
}
467589
}
468590
}
469591

@@ -586,7 +708,7 @@ function Convert-KeyValuePairArrayToHashtable
586708
$Array
587709
)
588710

589-
$hashtable = @{}
711+
$hashtable = @{ }
590712

591713
foreach ($item in $Array)
592714
{
@@ -638,7 +760,7 @@ function Get-Cache
638760
}
639761
else
640762
{
641-
$cacheContent = Import-CliXml -Path $path
763+
$cacheContent = Import-Clixml -Path $path
642764
Write-Verbose -Message ($script:localizedData.CacheFoundForPath -f $DestinationPath, $Uri, $Key)
643765
}
644766

@@ -688,7 +810,7 @@ function Update-Cache
688810

689811
Write-Verbose -Message ($script:localizedData.UpdatingCache -f $DestinationPath, $Uri, $Key)
690812

691-
Export-CliXml -Path $path -InputObject $InputObject -Force
813+
Export-Clixml -Path $path -InputObject $InputObject -Force
692814
}
693815

694816
<#

DSCResources/MSFT_xRemoteFile/MSFT_xRemoteFile.schema.mof

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ class MSFT_xRemoteFile : OMI_BaseResource
88
[Write, Description("Headers of the web request."), EmbeddedInstance("MSFT_KeyValuePair")] String Headers[];
99
[Write, Description("Specifies a user account that has permission to send the request."), EmbeddedInstance("MSFT_Credential")] String Credential;
1010
[Write, Description("A boolean value to indicate whether the remote file should be re-downloaded if the file in the DestinationPath was modified locally. The default value is true.")] Boolean MatchSource;
11+
[Write, Description("Specifies the checksum type to verify the downloaded file"), ValueMap{"None","SHA1","SHA256","SHA384","SHA512","MACTripleDES","MD5","RIPEMD160"}, Values{"None","SHA1","SHA256","SHA384","SHA512","MACTripleDES","MD5","RIPEMD160"}] String ChecksumType;
12+
[Write, Description("Specifies the checksum value to compare against the downloaded file")] String Checksum;
1113
[Write, Description("Specifies how long the request can be pending before it times out.")] Uint32 TimeoutSec;
1214
[Write, Description("Uses a proxy server for the request, rather than connecting directly to the Internet resource. Should be the URI of a network proxy server (e.g 'http://10.20.30.1').")] String Proxy;
1315
[Write, Description("Specifies a user account that has permission to use the proxy server that is specified by the Proxy parameter."), EmbeddedInstance("MSFT_Credential")] String ProxyCredential;

DSCResources/MSFT_xRemoteFile/en-us/MSFT_xRemoteFile.strings.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ ConvertFrom-StringData @'
1919
CacheLookingForPath=Looking for cache path '{0}'.
2020
CacheNotFoundForPath=No cache found for DestinationPath '{0}' and Uri '{1}' CacheKey '{2}'.
2121
CacheFoundForPath=Found cache found for DestinationPath '{0}' and Uri '{1}' CacheKey '{2}'.
22+
ChecksumDoesNotMatch=Checksum does not match specified value - Desired: '{0}', Actual: '{1}'.
2223
UpdatingCache=Updating cache for DestinationPath '{0}' and Uri '{1}' CacheKey '{2}'.
2324
'@

0 commit comments

Comments
 (0)