DSCResources/MSFT_xCertificateImport/MSFT_xCertificateImport.psm1
#Requires -Version 4.0 <# .SYNOPSIS Validates the existence of a file at a specific path. .PARAMETER Path The location of the file. Supports any path that Test-Path supports. .PARAMETER Quiet Returns $false if the file does not exist. By default this function throws an exception if the file is missing. .EXAMPLE Validate-CertificatePath -Path '\\server\share\Certificates\mycert.cer' .EXAMPLE Validate-CertificatePath -Path 'C:\certs\my_missing.cer' -Quiet .EXAMPLE 'D:\CertRepo\a_cert.cer' | Validate-CertificatePath .EXAMPLE Get-ChildItem D:\CertRepo\*.cer | Validate-CertificatePath #> function Validate-CertificatePath { [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline )] [String[]] $Path , [Parameter()] [Switch] $Quiet ) Process { foreach($p in $Path) { if ($p | Test-Path -PathType Leaf) { $true } elseif ($Quiet) { $false } else { throw [System.ArgumentException]"File '$p' not found." } } } } <# .SYNOPSIS Validates whether a given certificate is valid based on the hash algoritms available on the system. .PARAMETER Thumbprint One or more thumbprints to validate. .PARAMETER Quiet Returns $false if the thumbprint is not valid. By default this function throws an exception if validation fails. .EXAMPLE Validate-Thumbprint fd94e3a5a7991cb6ed3cd5dd01045edf7e2284de .EXAMPLE Validate-Thumbprint fd94e3a5a7991cb6ed3cd5dd01045edf7e2284de,0000e3a5a7991cb6ed3cd5dd01045edf7e220000 -Quiet .EXAMPLE gci Cert:\LocalMachine -Recurse | ? { $_.Thumbprint } | select -exp Thumbprint | Validate-Thumbprint -Verbose #> function Validate-Thumbprint { [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline )] [ValidateNotNullOrEmpty()] [String[]] $Thumbprint , [Parameter()] [Switch] $Quiet ) Begin { $validHashes = [System.AppDomain]::CurrentDomain.GetAssemblies().GetTypes() | Where-Object -FilterScript { $_.BaseType.BaseType -eq [System.Security.Cryptography.HashAlgorithm] -and ($_.Name -cmatch 'Managed$' -or $_.Name -cmatch 'Provider$') } | ForEach-Object -Process { New-Object -TypeName PSObject -Property @{ Hash = $_.BaseType.Name BitSize = (New-Object $_).HashSize } | Add-Member -MemberType ScriptProperty -Name HexLength -Value { $this.BitSize / 4 } -PassThru } } Process { foreach($hash in $Thumbprint) { $isValid = $false foreach($algorithm in $validHashes) { if ($hash -cmatch "^[a-fA-F0-9]{$($algorithm.HexLength)}$") { Write-Verbose -Message "'$hash' is a valid $($algorithm.Hash) hash." $isValid = $true } } if ($Quiet -or $isValid) { $isValid } else { throw [System.ArgumentException]"'$hash' is not a valid hash." } } } } function Get-TargetResource { [CmdletBinding()] [OutputType([Hashtable])] param( [Parameter(Mandatory)] [ValidateScript( {$_ | Validate-Thumbprint} )] [String] $Thumbprint , [Parameter(Mandatory)] [ValidateScript( {$_ | Validate-CertificatePath} )] [String] $Path , [Parameter(Mandatory)] [ValidateSet('CurrentUser', 'LocalMachine')] [String] $Location = 'LocalMachine' , [Parameter(Mandatory)] [System.String] $Store = 'My', [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) $CertificateStore = 'Cert:' | Join-Path -ChildPath $Location | Join-Path -ChildPath $Store if ((Test-Path $CertificateStore) -eq $false) { throw [System.ArgumentException]"Certificate Store '$Store' not found." } $CheckEnsure = [Bool]( $CertificateStore | Get-ChildItem | Where-Object -FilterScript {$_.Thumbprint -ieq $Thumbprint} ) if ($CheckEnsure){$Ensure = 'Present'} else {$Ensure = 'Absent'} @{ Thumbprint = $Thumbprint Path = $Path Ensure = $Ensure } } function Test-TargetResource { [CmdletBinding()] [OutputType([Bool])] param( [Parameter(Mandatory)] [ValidateScript( {$_ | Validate-Thumbprint} )] [String] $Thumbprint , [Parameter(Mandatory)] [ValidateScript( {$_ | Validate-CertificatePath} )] [String] $Path , [Parameter(Mandatory)] [ValidateSet('CurrentUser', 'LocalMachine')] [String] $Location = 'LocalMachine' , [Parameter(Mandatory)] [System.String] $Store = 'My', [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) $result = @(Get-TargetResource @PSBoundParameters) if ($Ensure -ne $result.Ensure) { return $false } elseif ($Ensure -eq 'Present' -and ($result.Target -ne $Target)) { return $false } return $true } function Set-TargetResource { [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [ValidateScript( {$_ | Validate-Thumbprint} )] [String] $Thumbprint , [Parameter(Mandatory)] [ValidateScript( {$_ | Validate-CertificatePath} )] [String] $Path , [Parameter(Mandatory)] [ValidateSet('CurrentUser', 'LocalMachine')] [String] $Location = 'LocalMachine' , [Parameter(Mandatory)] [System.String] $Store = 'My', [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) $certPath = 'Cert:' | Join-Path -ChildPath $Location | Join-Path -ChildPath $Store if ($Ensure -ieq 'Present') { if ($PSCmdlet.ShouldProcess("Importing certificate '$Path' into '$certPath'")) { $param = @{ CertStoreLocation = $certPath FilePath = $Path Verbose = $VerbosePreference } Import-Certificate @param } } elseif ($Ensure -ieq 'Absent') { Get-ChildItem -Path $certPath | Where-Object {$_.Thumbprint -ieq $thumbprint} | Remove-Item -Force } } Export-ModuleMember -Function *-TargetResource |