Skip to content

Commit

Permalink
Improves support for batching in SSLCertificate commands
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Hunt committed Jan 3, 2024
1 parent 670fcf1 commit 373d278
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 51 deletions.
2 changes: 1 addition & 1 deletion docs/Get-SSLCertificate.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Open an SSL connection to the given host and read the presented server certifica

### Parameter Set 1

- `[String]` **ComputerName** _A hostname or Url of the server to retreive the certificate._ Mandatory
- `[String]` **ComputerName** _A hostname or Url of the server to retreive the certificate._ Mandatory, ValueFromPipeline
- `[Int32]` **Port** _The port to connect to the remote server._
- `[String]` **OutSslStreamVariable** _Stores SslStream connetion details from the command in the specified variable._

Expand Down
7 changes: 7 additions & 0 deletions docs/Test-SSLCertificate.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ Thumbprint Subject EnhancedKeyUsageL
339CDD57CFD5B141169B615FF31428782D1DA639 CN=COMODO RSA Domai… {Server Authentication, Client Authentication}
AFE5D244A8D1194230FF479FE2F897BBCD7A8CB4 CN=COMODO RSA Certi…
```
### Example 3

Run multiple tests and accumulate any failures in the variable `$testFailures`.

```powershell
@('expired.badssl.com', 'google.com', 'https://self-signed.badssl.com' | Get-SSLCertificate | Test-SSLCertificate -ErrorVariable +testFailures
```

## Links

Expand Down
102 changes: 54 additions & 48 deletions src/public/Get-SSLCertificate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -62,80 +62,86 @@ function Get-SSLCertificate {

[CmdletBinding()]
param (
[Parameter(Mandatory, Position = 0)]
[Parameter(Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
[Alias('Address', 'Url')]
[string]$ComputerName,

[Parameter(Position = 1)]
[Parameter(Position = 1, ValueFromPipelineByPropertyName)]
[ValidateRange(1, 65535)]
[int]$Port = 443,

[Parameter()]
[Parameter(ValueFromPipelineByPropertyName)]
[string]
$OutSslStreamVariable

)

$uri = $null
process {

$uri = $null

if ([uri]::TryCreate($ComputerName, [System.UriKind]::RelativeOrAbsolute, [ref]$uri)) {
Write-Verbose "Converting Uri to host string"
if (![string]::IsNullOrEmpty($uri.Host)) {
$ComputerName = $uri.Host
if ([uri]::TryCreate($ComputerName, [System.UriKind]::RelativeOrAbsolute, [ref]$uri)) {
Write-Verbose "Converting Uri to host string"
if (![string]::IsNullOrEmpty($uri.Host)) {
$ComputerName = $uri.Host
if (!$PSBoundParameters.ContainsKey('Port') -and $null -ne $uri.Port) {
$Port = $uri.Port
}
}
}
}

Write-Verbose "ComputerName = $ComputerName"
Write-Verbose "ComputerName = $ComputerName"

$Certificate = $null
$TcpClient = New-Object -TypeName System.Net.Sockets.TcpClient
$Certificate = $null
$TcpClient = New-Object -TypeName System.Net.Sockets.TcpClient

try {
try {

$TcpClient.Connect($ComputerName, $Port)
$TcpStream = $TcpClient.GetStream()
$TcpClient.Connect($ComputerName, $Port)
$TcpStream = $TcpClient.GetStream()

$SslStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList @($TcpStream, $true, $ServerCertificateCustomValidation_AlwaysTrust)
try {
$SslStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList @($TcpStream, $true, $ServerCertificateCustomValidation_AlwaysTrust)
try {

$SslStream.AuthenticateAsClient($ComputerName)
$Certificate = $SslStream.RemoteCertificate

if ($PSBoundParameters.ContainsKey('OutSslStreamVariable')) {
$streamProperties = [PSCustomObject]@{
CipherAlgorithm = $SslStream.CipherAlgorithm
CipherStrength = $SslStream.CipherStrength
HashAlgorithm = $SslStream.HashAlgorithm
HashStrength = $SslStream.HashStrength
KeyExchangeAlgorithm = $SslStream.KeyExchangeAlgorithm
KeyExchangeStrength = $SslStream.KeyExchangeStrength
SslProtocol = $SslStream.SslProtocol
}
$SslStream.AuthenticateAsClient($ComputerName)
$Certificate = $SslStream.RemoteCertificate

Set-Variable -Name $OutSslStreamVariable -Value $streamProperties -Scope Global
}
if ($PSBoundParameters.ContainsKey('OutSslStreamVariable')) {
$streamProperties = [PSCustomObject]@{
CipherAlgorithm = $SslStream.CipherAlgorithm
CipherStrength = $SslStream.CipherStrength
HashAlgorithm = $SslStream.HashAlgorithm
HashStrength = $SslStream.HashStrength
KeyExchangeAlgorithm = $SslStream.KeyExchangeAlgorithm
KeyExchangeStrength = $SslStream.KeyExchangeStrength
SslProtocol = $SslStream.SslProtocol
}

Set-Variable -Name $OutSslStreamVariable -Value $streamProperties -Scope Global
}

"Cipher: {0} strength {1}" -f $SslStream.CipherAlgorithm, $SslStream.CipherStrength | Write-Verbose
"Hash: {0} strength {1}" -f $SslStream.HashAlgorithm, $SslStream.HashStrength | Write-Verbose
"Key exchange: {0} strength {1}" -f $SslStream.KeyExchangeAlgorithm, $SslStream.KeyExchangeStrength | Write-Verbose
"Protocol: {0}" -f $SslStream.SslProtocol | Write-Verbose
"Cipher: {0} strength {1}" -f $SslStream.CipherAlgorithm, $SslStream.CipherStrength | Write-Verbose
"Hash: {0} strength {1}" -f $SslStream.HashAlgorithm, $SslStream.HashStrength | Write-Verbose
"Key exchange: {0} strength {1}" -f $SslStream.KeyExchangeAlgorithm, $SslStream.KeyExchangeStrength | Write-Verbose
"Protocol: {0}" -f $SslStream.SslProtocol | Write-Verbose

} catch {
$_
} finally {
$SslStream.Dispose()
}
} catch {
$_
} finally {
$SslStream.Dispose()
$TcpClient.Dispose()
}
} catch {
$_
} finally {
$TcpClient.Dispose()
}

if ($null -ne $Certificate) {
if ($Certificate -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
$Certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $Certificate
}
if ($null -ne $Certificate) {
if ($Certificate -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
$Certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $Certificate
}

Write-Output $Certificate
$Certificate | Add-Member -MemberType NoteProperty -Name Host -Value $ComputerName
Write-Output $Certificate
}
}
}
6 changes: 5 additions & 1 deletion src/public/Test-SSLCertificate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ function Test-SSLCertificate {
AFE5D244A8D1194230FF479FE2F897BBCD7A8CB4 CN=COMODO RSA Certi…
Tests an invalid certificates and inspect the error in variable `$validation` for the certificate details.
.EXAMPLE
@('expired.badssl.com', 'google.com', 'https://self-signed.badssl.com' | Get-SSLCertificate | Test-SSLCertificate -ErrorVariable +testFailures
Run multiple tests and accumulate any failures in the variable `$testFailures`.
#>
[CmdletBinding(DefaultParameterSetName = 'Certificate')]
param (
Expand Down Expand Up @@ -78,7 +82,7 @@ function Test-SSLCertificate {
$buildResult = $Chain.Build($Certificate)

if (! $buildResult) {
$exception = [Exception]::new(("Certificate failed chain validation:{0}{1}" -f [System.Environment]::NewLine, ($Chain.ChainStatus.StatusInformation -join [System.Environment]::NewLine)))
$exception = [Exception]::new(("Certificate failed chain validation for '{0}'.{1}{2}" -f $Certificate.Host, [System.Environment]::NewLine, ($Chain.ChainStatus.StatusInformation -join [System.Environment]::NewLine)))
Write-Error -Exception $exception -Category SecurityError -ErrorId 100 -TargetObject $Chain
}

Expand Down
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json",
"version": "0.5.0",
"version": "0.5.1",
"cloudBuild": {
"buildNumber": {
"enabled": true
Expand Down

0 comments on commit 373d278

Please sign in to comment.