Skip to content

Instantly share code, notes, and snippets.

@gillissm
Last active January 29, 2023 13:45
Show Gist options
  • Save gillissm/d67348b8c0b04772bf41fa9c8f00a0f3 to your computer and use it in GitHub Desktop.
Save gillissm/d67348b8c0b04772bf41fa9c8f00a0f3 to your computer and use it in GitHub Desktop.
**Add-SecureSiteBinding** script has been created to provide the ability to add one or more domains to an IIS website each tied to a self-signed certificate providing SSL capabilities. The script contains three parts which I'll review, the full script can be found in the [Add-SecureSiteBindings Gist](GIST URL).
#Requires -RunAsAdministrator
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true,
Position=0,
HelpMessage = "Name of the IIS Site the new URLs should be associated to")]
[ValidateNotNullOrEmpty()]
[string]
$SiteName,
[Parameter(Mandatory = $true,
Position=1,
HelpMessage = "Comma delimited list of all URLs to add to the site")]
[ValidateNotNullOrEmpty()]
[string[]]
$NewDnsNames,
[Parameter(Mandatory = $false,
Position=2,
HelpMessage = "Password to be used to export and import the certificate. Will be converted into a Secure String")]
[string]
$CertPassphrase = "Password12345",
[Parameter(Mandatory=$false,
Position=3,
HelpMessage="Port that the site bindings will be established on, defaults to 443.")]
[string]
$Port = "443"
)
<#
.SYNOPSIS
THIS IS DUPLICATED FROM THE SITECORE DOCKER TOOLS MODULE AVAILABLE FROM https://sitecore.myget.org/feed/sc-powershell/package/nuget/SitecoreDockerTools
Duplication was done to eliminate any
Adds a host entry to the system hosts file.
.DESCRIPTION
Adds a host entry with the specified Hostname and IPAddress to the system hosts file (if it does not already exist).
A backup of the current hosts file is taken before updating.
.PARAMETER Hostname
The hostname to use for the entry.
.PARAMETER IPAddress
The IP address to use for the entry. Default is 127.0.0.1.
.INPUTS
None. You cannot pipe objects to Add-HostsEntry.
.OUTPUTS
None. Add-HostsEntry does not generate any output.
.EXAMPLE
PS C:\> Add-HostsEntry 'my.host.name'
#>
function Add-HostsEntry
{
Param (
[Parameter(Mandatory = $true, Position = 0)]
[ValidateNotNullOrEmpty()]
[string]
$Hostname,
[string]
[ValidateNotNullOrEmpty()]
$IPAddress = "127.0.0.1",
[string]
$Path = (Join-Path -Path $env:windir -ChildPath "system32\drivers\etc\hosts")
)
if (-not (Test-Path $Path)) {
Write-Warning "No hosts file found, hosts have not been updated"
return
}
# Create backup
Copy-Item $Path "$Path.backup"
Write-Verbose "Created backup of hosts file to $Path.backup"
# Build regex match pattern
$pattern = '^' + [Regex]::Escape($IPAddress) + '\s+' + [Regex]::Escape($HostName) + '\s*$'
$hostsContent = @(Get-Content -Path $Path -Encoding UTF8)
# Check if exists
$existingEntries = $hostsContent -match $pattern
if ($existingEntries.Count -gt 0) {
Write-Verbose "Existing host entry found for $IPAddress with hostname '$HostName'"
return
}
# Add it
$hostsContent += "$IPAddress`t$HostName"
$hostsContent | Out-File -FilePath $Path -Encoding utf8
Write-Verbose "Host entry for $IPAddress with hostname '$HostName' has been added"
}
<#
.SYNOPSIS
Following logic is a modification to the examples demonstrating New-IISSiteBinding command
at https://docs.microsoft.com/en-us/powershell/module/iisadministration/new-iissitebinding?view=windowsserver2022-ps
Creates Self-Signed certifacte for all DNS/hostnames provided and then adds the appropriate binding to the named IIS web application
.PARAMETER NewDnsNames
REQUIRED, Comma delimited list of all URLs to add to the site
.PARAMETER SiteName
REQUIRED, Name of the IIS Site the new URLs should be associated to
.PARAMETER CertPassword
REQUIRED, Secure string of a password/phrase to secure the export and import of the self-signed certificate
.PARAMETER BindingPort
OPTIONAL, Default is 443. Port that the site bindings will be established on.
.INPUTS
None.
.OUTPUTS
None.
.EXAMPLE
PS C:\> Set-NewSiteBinding -NewDnsNames rainflytours.com,rainflyadbenture.com -SiteName rainflysites -CertPassword PassIsSecure
.EXAMPLE
PS C:\> Set-NewSiteBinding rainflytours.com,rainflyadbenture.com rainflysites PassIsSecure
.EXAMPLE
PS C:\> Set-NewSiteBinding rainflytours.com,rainflyadbenture.com rainflysites PassIsSecure -BindingPort 8080
#>
function Set-NewSiteBinding {
Param (
[Parameter(Mandatory = $true,
Position = 0,
HelpMessage = "Comma delimited list of all URLs to add to the site")]
[ValidateNotNullOrEmpty()]
[string[]]
$NewDnsNames,
[Parameter(Mandatory = $true,
Position = 1,
HelpMessage = "Name of the IIS Site the new URLs should be associated to")]
[ValidateNotNullOrEmpty()]
[string]
$SiteName,
[Parameter(Mandatory = $true,
Position = 2,
HelpMessage = "Password used to export and import the certificate")]
[ValidateNotNullOrEmpty()]
[SecureString]
$CertPassword,
[Parameter(Mandatory=$false,
HelpMessage = "Port that the site bindings will be established on, defaults to 443.")]
[string]
$BindingPort = "443"
)
Write-Host "Creating Self-Signed Certificate for: $NewDnsNames"
$storeLocation = "Cert:\LocalMachine\My"
$certificate = New-SelfSignedCertificate -DnsName $NewDnsNames -CertStoreLocation $storeLocation
$thumbPrint = $certificate.Thumbprint
$certificatePath = ("cert:\localmachine\my\" + $certificate.Thumbprint)
Export-PfxCertificate -FilePath "C:\temp\temp.pfx" -Cert $certificatePath -Password $CertPassword
Import-PfxCertificate -FilePath "C:\temp\temp.pfx" -CertStoreLocation "Cert:\LocalMachine\Root" -Password $securedString
foreach ($url in $NewDnsNames) {
$bindingInformation = "*:" + $BindingPort + ":" + $url
Write-Host "IIS Binding '$bindingInformation' to be added to $SiteName"
New-IISSiteBinding -Name $SiteName `
-BindingInformation $bindingInformation `
-CertificateThumbPrint $thumbPrint `
-CertStoreLocation $storeLocation `
-Protocol https `
-SslFlag "Sni" `
-Force
}
}
<#
.SYNOPSIS
Simple control method that makes the calls to created the certificates and bind them to IIS via Set-NewSiteBinding
Followed by a simple loop to add host file entries for all hostnames
Parameters for the file are used within this method.
#>
function Add-SecureSiteBindings {
$securedString = ConvertTo-SecureString -String $CertPassphrase -Force -AsPlainText
Set-NewSiteBinding -NewDnsNames $NewDnsNames -SiteName $SiteName -CertPassword $securedString -BindingPort $Port
$NewDnsNames | ForEach-Object{ Add-HostsEntry $_.Trim(); }
}
# Setup a log file to capture any messages at the location of the script
$logFilePath = Join-Path -path (Split-Path -Parent $MyInvocation.MyCommand.Path) -ChildPath "invoke-newsitebinding-$(Get-date -f 'yyyyMMddHHmmss').log";
Add-SecureSiteBindings *>&1 | Tee-Object $logFilePath
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment