Created
April 1, 2022 01:35
-
-
Save jborean93/573695261ca50fb0142fa3f4a1a24fcd to your computer and use it in GitHub Desktop.
Create pwsh wrapper for netsh.exe http add|delete|show sslcert
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Flags()] enum CertCheckMode { | |
VerifyClientCertRevocation = 0x00000000 | |
VerifyRevocationUsingCacheOnly = 0x00000002 | |
DefaultRevocationFreshnessTimeIsEnabled = 0x00000004 | |
NoUsageCheck = 0x00010000 | |
} | |
[Flags()] enum SslFlags { | |
None = 0x00000000 | |
UseDsMapper = 0x00000001 | |
NegotiateClientCert = 0x00000002 | |
NoRawFilter = 0x00000004 | |
Reject = 0x00000008 | |
DisableHTTP2 = 0x00000010 | |
DisableQUIC = 0x00000020 | |
DisableTLS13 = 0x00000040 | |
DisableOCSAPStapling = 0x00000080 | |
EnableTokenBinding = 0x00000100 | |
LogExtendedEvents = 0x00000200 | |
DisableLegacyTls = 0x00000400 | |
EnableSessionTicket = 0x00000800 | |
DisableTLS12 = 0x00001000 | |
EnableClientCorrelation = 0x00002000 | |
} | |
Function Add-HttpSslCert { | |
<# | |
.SYNOPSIS | |
Add SSL cert binding. | |
.DESCRIPTION | |
Add SSL cert binding for an IP address, hostname, or central certificate store binding. | |
.PARAMETER IPPort | |
The IP and port to add the binding for, this is in the form 'ipaddr:port'. | |
.PARAMETER HostPort | |
The hostname and port (for SNI) to add the binding for, this is in the form 'name:port' | |
.PARAMETER CCS | |
The Central Certificate Store binding port to add the binding for. | |
.PARAMETER ScopedCCS | |
A scoped Central Certificate Store binding port to add the binding for, this is in the form 'name:port' | |
.PARAMETER CertificateThumbprint | |
The certificate thumbprint to set for the binding. | |
This is not used if adding a CCS or ScopedCCS binding. | |
.PARAMETER AppId | |
A unique application identifier for the owning application. | |
.PARAMETER CertStoreName | |
Store name in the local machine context that contains the certificate. | |
If undefined then it will default to 'My' for a HostPort binding. | |
.PARAMETER EnableDSMapper | |
Turn on DS mappers. | |
.PARAMETER ClientCertNegotiation | |
Turns on negotiation of a certificate. | |
.PARAMETER Reject | |
Reject any new matching connections. | |
.PARAMETER DisableHttp2 | |
Disables HTTP2. | |
.PARAMETER DisableQuic | |
Disables QUIC. | |
.PARAMETER DisableLegacyTls | |
Disable legacy TLS protocol versions. | |
.PARAMETER DisableTls12 | |
Disable TLSv1.2. | |
.PARAMETER DisableTls13 | |
Disable TLSv1.3. | |
.PARAMETER DisableOcspStapling | |
Disable OCSP stapling. | |
.PARAMETER EnableTokenBinding | |
Enable token binding. | |
.PARAMETER LogExtendedEvents | |
Enable additional debug event logs. | |
.PARAMETER EnableSessionTicket | |
Enable TLS session resumption. | |
.EXAMPLE | |
$cert = Get-Item WSMan:\LocalMachine\My | Where-Object Subject -eq $subj | |
Add-HttpSslCert -IPPort 0.0.0.0:443 -AppId ([Guid]::NewGuid()) -CertificateThumbprint $cert.Thumbprint | |
.NOTES | |
This cmdlet is a simple wrapper around 'netsh.exe http add sslcert ...'. | |
Some options are only available on newer versions of Windows. | |
#> | |
[CmdletBinding(DefaultParameterSetName = "IPPort", SupportsShouldProcess)] | |
param ( | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "IPPort")] | |
[string] | |
$IPPort, | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "HostPort")] | |
[string] | |
$HostPort, | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "CCS")] | |
[string] | |
$CCS, | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "ScopedCCS")] | |
[string] | |
$ScopedCCS, | |
[Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = "IPPort")] | |
[Parameter(Mandatory, ValueFromPipelineByPropertyName, ParameterSetName = "HostPort")] | |
[string] | |
$CertificateThumbprint, | |
[Parameter(Mandatory, ValueFromPipelineByPropertyName)] | |
[guid] | |
$AppId, | |
[Parameter(ParameterSetName = "IPPort")] | |
[Parameter(Mandatory, ParameterSetName = "HostPort")] | |
[string] | |
$CertStoreName, | |
[switch] | |
$EnableDSMapper, | |
[switch] | |
$ClientCertNegotiation, | |
[switch] | |
$Reject, | |
[switch] | |
$DisableHttp2, | |
[switch] | |
$DisableQuic, | |
[switch] | |
$DisableLegacyTls, | |
[switch] | |
$DisableTls12, | |
[switch] | |
$DisableTls13, | |
[switch] | |
$DisableOcspStapling, | |
[switch] | |
$EnableTokenBinding, | |
[switch] | |
$LogExtendedEvents, | |
[switch] | |
$EnableSessionTicket | |
) | |
process { | |
$key = if ($PSCmdlet.ParameterSetName -eq "IPPort") { | |
"ipport=$IPPort" | |
} | |
elseif ($PSCmdlet.PagingParameters -eq "HostPort") { | |
"hostnameport=$HostPort" | |
} | |
elseif ($PSCmdlet.ParameterSetName -eq "CCS") { | |
"ccs=$CCS" | |
} | |
else { | |
"scopedccs=$ScopedCCS" | |
} | |
$arguments = @( | |
"http" | |
"add" | |
"sslcert" | |
$key | |
"appid={$AppId}" | |
if ($CertificateThumbprint) { "certhash=$CertificateThumbprint" } | |
if ($CertStoreName) { "certstorename=$CertStoreName" } | |
if ($EnableDSMapper) { "dsmapperusage=enabled" } | |
if ($ClientCertNegotiation) { "clientcertnegotiation=enabled" } | |
if ($Reject) { "reject=enable" } | |
if ($DisableHttp2) { "disablehttp2=enable" } | |
if ($DisableQuic) { "disablequic=enable" } | |
if ($DisableLegacyTls) { "disablelegacytls=enable" } | |
if ($DisableTls12) { "disabletls12=enable" } | |
if ($DisableTls13) { "disabletls13=enable" } | |
if ($DisableOcspStapling) { "disableocpsstapling=enable" } | |
if ($EnableTokenBinding) { "enabletokenbinding=enable" } | |
if ($LogExtendedEvents) { "logextendedevents=enable" } | |
if ($EnableSessionTicket) { "enablesessionticket=enable" } | |
) | |
if ($PSCmdlet.ShouldProcess($key, "netsh.exe {0}" -f ($arguments -join " "))) { | |
$out = netsh.exe @arguments | |
if ($LASTEXITCODE) { | |
$err = [System.Management.Automation.ErrorRecord]::new( | |
[Exception]::new($out), | |
"netsh.http.add.sslcert", | |
[System.Management.Automation.ErrorCategory]::InvalidOperation, | |
$null) | |
$PSCmdlet.WriteError($err) | |
} | |
} | |
} | |
} | |
Function Get-HttpSslCert { | |
<# | |
.SYNOPSIS | |
Get HTTP sslcert binding info | |
.DESCRIPTION | |
Gets HTTP ssl binding information. | |
.PARAMETER IPPort | |
The IP and port of the binding to get the info for, this is in the form 'ipaddr:port'. | |
.PARAMETER HostPort | |
The hostname and port (SNI) of the binding to get the info for, this is in the form 'name:port'. | |
.PARAMETER CCS | |
The Central Certificate Store binding defined port to get the info for. | |
.PARAMETER ScopedCCS | |
The Central Certificate Store binding name and port to get the info for, this is in the form 'name:port' | |
.EXAMPLE Get all sslcert bindings | |
Get-HttpSslCert | |
.EXAMPLE Get sslcert binding for specific one | |
Get-HttpSslCert -IPPort 0.0.0.0:443 | |
.NOTES | |
This cmdlet is a simple wrapper around 'netsh.exe http show sslcert ...'. | |
It uses functionality in netsh recently added in Server 2022 and Windows 11. | |
#> | |
[CmdletBinding(DefaultParameterSetName = "IPPort")] | |
param ( | |
[Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "IPPort")] | |
[AllowEmptyCollection()] | |
[string[]] | |
$IPPort = @(), | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "HostPort")] | |
[AllowEmptyCollection()] | |
[string[]] | |
$HostPort = @(), | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "CCS")] | |
[AllowEmptyCollection()] | |
[string[]] | |
$CCS = @(), | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "ScopedCCS")] | |
[AllowEmptyCollection()] | |
[string[]] | |
$ScopedCCS = @() | |
) | |
process { | |
[string[]]$values = if ($PSCmdlet.ParameterSetName -eq "IPPort") { | |
$IPPort | ForEach-Object { 'ipport={0}' -f $_ } | |
} | |
elseif ($PSCmdlet.ParameterSetName -eq "HostPort") { | |
$HostPort | ForEach-Object { 'hostnameport={0}' -f $_ } | |
} | |
elseif ($PSCmdlet.ParameterSetName -eq "CCS") { | |
$CCS | ForEach-Object { 'ccs={0}' -f $_ } | |
} | |
else { | |
$ScopedCCS | ForEach-Object { 'scopedccs={0}' -f $_ } | |
} | |
$values = if (-not $values) { , @(, @()) } else { $values } | |
foreach ($id in $values) { | |
$arguments = @( | |
"http" | |
"show" | |
"sslcert" | |
$id | |
"json=enable" | |
) | |
$PSCmdlet.WriteVerbose("Running netsh.exe {0}" -f ($arguments -join " ")) | |
$rawOut = &netsh.exe @arguments | |
try { | |
$raw = $rawOut | ConvertFrom-Json | |
} | |
catch { | |
$err = [System.Management.Automation.ErrorRecord]::new( | |
[Exception]::new("netsh failure: $rawOut"), | |
"netsh.http.show.sslcert", | |
[System.Management.Automation.ErrorCategory]::InvalidArgument, | |
$null) | |
$PSCmdlet.WriteError($err) | |
continue | |
} | |
$raw | Select-Object -ExpandProperty SslCertificateBindings | ForEach-Object -Process { | |
$certHashBytes = [System.Convert]::FromBase64String($_.SslHash) | |
[PSCustomObject]@{ | |
PSTypeName = 'Netsh.SslCert' | |
IPPort = $_.IpPort | |
ConfigType = $_.ConfigType | |
Host = $_.Host | |
AppId = [Guid]::new($_.GuidString) | |
CertificateThumbprint = [System.BitConverter]::ToString($certHashBytes).Replace("-", "") | |
SslCertStoreName = $_.SslCertStoreName | |
DefaultCertCheckMode = [CertCheckMode]$_.DefaultCertCheckMode | |
DefaultRevocationFreshnessTime = $_.DefaultRevocationFreshnessTime | |
DefaultRevocationUrlRetrievalTimeout = $_.DefaultRevocationUrlRetrievalTimeout | |
DefaultSslCtlIdentifier = $_.DefaultSslCtlIdentifier | |
DefaultSslCtlStoreName = $_.DefaultSslCtlStoreName | |
DefaultFlags = [SslFlags]$_.DefaultFlags | |
} | |
} | |
} | |
} | |
} | |
Function Remove-HttpSslCert { | |
<# | |
.SYNOPSIS | |
Remove HTTP sslcert binding | |
.DESCRIPTION | |
Removes a HTTP ssl binding configuration for the ip/host/ccs key set. | |
.PARAMETER IPPort | |
The IP and port of the binding to remove, this is in the form 'ipaddr:port'. | |
.PARAMETER HostPort | |
The hostname and port (SNI) of the binding to remove, this is in the form 'name:port'. | |
.PARAMETER CCS | |
The Central Certificate Store binding defined port to remove. | |
.PARAMETER ScopedCCS | |
The Central Certificate Store binding name and port to remove, this is in the form 'name:port' | |
.EXAMPLE | |
Remove-HttpSslCert -IPPort 0.0.0.0:443 | |
.NOTES | |
This cmdlet is a simple wrapper around 'netsh.exe http delete sslcert ...'. | |
#> | |
[CmdletBinding(DefaultParameterSetName = "IPPort", SupportsShouldProcess)] | |
param ( | |
[Parameter(Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "IPPort")] | |
[string[]] | |
$IPPort, | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "HostPort")] | |
[string[]] | |
$HostPort, | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "CCS")] | |
[string[]] | |
$CCS, | |
[Parameter(Position = 0, ValueFromPipelineByPropertyName, ParameterSetName = "ScopedCCS")] | |
[string[]] | |
$ScopedCCS | |
) | |
process { | |
[string[]]$values = if ($PSCmdlet.ParameterSetName -eq "IPPort") { | |
$IPPort | ForEach-Object { 'ipport={0}' -f $_ } | |
} | |
elseif ($PSCmdlet.ParameterSetName -eq "HostPort") { | |
$HostPort | ForEach-Object { 'hostnameport={0}' -f $_ } | |
} | |
elseif ($PSCmdlet.ParameterSetName -eq "CCS") { | |
$CCS | ForEach-Object { 'ccs={0}' -f $_ } | |
} | |
else { | |
$ScopedCCS | ForEach-Object { 'scopedccs={0}' -f $_ } | |
} | |
foreach ($id in $values) { | |
$arguments = @( | |
"http" | |
"delete" | |
"sslcert" | |
$id | |
) | |
if ($PSCmdlet.ShouldProcess($id, "netsh.exe {0}" -f ($arguments -join " "))) { | |
$out = &netsh.exe @arguments | |
if ($LASTEXITCODE) { | |
$err = [System.Management.Automation.ErrorRecord]::new( | |
[Exception]::new($out), | |
"netsh.http.delete.sslcert", | |
[System.Management.Automation.ErrorCategory]::InvalidOperation, | |
$null) | |
$PSCmdlet.WriteError($err) | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment