diff --git a/New-SanCertificate.cmd b/New-SanCertificate.cmd new file mode 100644 index 0000000..254ce8b --- /dev/null +++ b/New-SanCertificate.cmd @@ -0,0 +1,4 @@ +@echo OFF +cd "%~dp0" +PowerShell.exe -ExecutionPolicy ByPass -File "%~dp0New-SanCertificate.ps1" +pause \ No newline at end of file diff --git a/New-SanCertificate.ps1 b/New-SanCertificate.ps1 new file mode 100644 index 0000000..53ebddd --- /dev/null +++ b/New-SanCertificate.ps1 @@ -0,0 +1,125 @@ +<# + +.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 IIS for the default 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 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()] + [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 "Default Web Site" -Protocol "https")) { + Write-Verbose "Creating IIS Binding on Default Web Site" + New-WebBinding -Name "Default Web Site" -IPAddress "*" -Port 443 -Protocol "https" + } + + # Assign to IIS Binding + (Get-WebBinding -Name "Default Web Site" -Port 443 -Protocol "https").AddSslCertificate($GeneratedCert.Thumbprint, "my") +} +else { + Write-Warning "IIS not installed so the binding was not configured`n" +} diff --git a/README.md b/README.md index 976e6b3..023d846 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,25 @@ Generates a self-signed certificate to be used by IIS for HTTPS communications - ## Requirements +- Must be running as an admin +- IIS must be installed for it to set the binding on the Default site + ## Variables -| Variable | Required | Default | Choices | Description | -| -------- | -------- | ------- | ------- | ----------- | -| | | | | | +| Variable | Required | Default | Choices | Description | +| ------------------ | -------- | ---------------------------- | ------- | ---------------------------------------------------------------------- | +| IpAddress | No | IPv4 addresses of the system | | IP Addresses to include in the Certificate | +| AdditionalDnsNames | No | | | Specifies additional DNS names that should be added to the certificate | +| Validity | No | 15 | | Defines the validity of the certificate in years | ## Example +```powershell +.\New-SanCertificate.ps1 +``` + ## License See LICENSE file for full license information. - -## Screenshots