<# .SYNOPSIS Generates a self-signed certificate to be used by IIS for HTTPS communications .DESCRIPTION Generates a SAN self-signed certificate to be used by IIS for HTTPS communications. The certificate will be automatically trusted by the local machine and assigned to the HTTPS binding of the defined IIS site. The certificate by default will include the following items in the SAN for the cert: Hostname Short hostname limited to 15 characters localhost All IPv4 addresses .PARAMETER IpAddress IP Addresses to include in the Certificate. If not provided, the script will gather IPv4 addresses .PARAMETER AdditionalDnsNames Specifies additional DNS names that should be added to the certificate .PARAMETER SiteName Site name of the IIS site that should have the HTTPS binding configured. Defaults to Default Web Site .PARAMETER Validity Defines the validity of the certificate in years. Defaults to 15 years .NOTES Version: 1.0 Author: Tyler Hale Creation Date: 2022.07.15 #> [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [ValidateScript({foreach ($IP in $_) {[ipaddress]$IP}})] [string[]] $IpAddress = ((Get-NetIPAddress -AddressFamily IPv4 -Type Unicast -AddressState Preferred).IPAddress), [Parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [string[]] $AdditionalDnsNames, [Parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [string] $SiteName = "Default Web Site", [Parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [int] $Validity = 15 ) ############################################### [Script Settings] ################################################ $Hostname = $Env:COMPUTERNAME $CertParameters = @{ "Subject" = $Hostname "NotAfter" = (Get-Date).AddYears($Validity) "KeyExportPolicy" = "NonExportable" "KeySpec" = "KeyExchange" "KeyUsage" = "DigitalSignature","KeyEncipherment" "CertStoreLocation" = "cert:\LocalMachine\My" } ############################################# [Internal Processing] ############################################## # Stop if not running as an admin If (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Error "Not running as an admin. Please relaunch running as an admin." pause exit } # Account for incompatibility for hostnames longer than 15 characters if ($Hostname.Length -gt 15) { Write-Verbose "Applying fixes for hostname length" $ShortHostname = $Hostname.Substring(0,15) $HostString = "127.0.0.1 $ShortHostname" } # Setup SAN text extension for the cert request $TextExtension = "2.5.29.17={text}DNS=$Hostname&DNS=localhost" # Add Compatibility hostname if defined to SAN if ($null -ne $ShortHostname) {$TextExtension += "&DNS=$ShortHostname"} # Add custom DNS names to SAN if ($null -ne $DnsName) {foreach ($Name in $DnsName) {$TextExtension += "&DNS=$Name"}} # Add IP Addresses to SAN foreach ($Ip in $IpAddress) {$TextExtension += "&IPAddress=$Ip"} if ($IpAddress -notcontains "127.0.0.1") {$TextExtension += "&IPAddress=127.0.0.1"} # Add final text extension to cert request $CertParameters['TextExtension'] = @($TextExtension) ################################################## [Execution] ################################################### # Add hosts entry for short hostname if needed if ($null,'' -ne $ShortHostname) { if ((Get-Content "C:\Windows\System32\drivers\etc\hosts") -notcontains $HostString) { Write-Verbose "Adding hosts entry" Add-Content -Path "C:\Windows\System32\drivers\etc\hosts" -Value $HostString } } # Generate certificate $GeneratedCert = New-SelfSignedCertificate @CertParameters # Export certificate $ExportedCert = $GeneratedCert | Export-Certificate -FilePath "$(Get-Item .\ | Select-Object -ExpandProperty FullName)\$Hostname`_$(Get-Date -Format yyyy-MM-dd_HH.mm.ss).cer" Write-Host "Certificate exported to $($ExportedCert.FullName)`nYou will need to import the cert to the Local Machine - Trusted Root Certificate Authority on external clients that need to connect to this machine`n" # Add certificate to trusted root CA Import-Certificate -CertStoreLocation cert:\LocalMachine\Root -FilePath $ExportedCert.FullName | Out-Null if (Get-Command -Name "Get-WebBinding" -ErrorAction SilentlyContinue) { # Setup https binding if it is not configured if ($null -eq (Get-WebBinding -Name $SiteName -Protocol "https")) { Write-Verbose "Creating IIS Binding on Default Web Site" New-WebBinding -Name $SiteName -IPAddress "*" -Port 443 -Protocol "https" } # Assign to IIS Binding (Get-WebBinding -Name $SiteName -Port 443 -Protocol "https").AddSslCertificate($GeneratedCert.Thumbprint, "my") } else { Write-Warning "IIS not installed so the binding was not configured`n" }