- 11 minutes to read

FAQ - IIS Binding Test Scripts

Automated PowerShell scripts for IIS Binding and SAN Monitoring validation testing.

What's on This Page:

Related Documentation:

Note

These scripts require PowerShell 7+ with Administrator privileges for IIS configuration access.

Warning

Never deploy test IIS sites to production environments. Always clean up after validation testing.

Batch IIS Functionality Testing Script

Create all test scenarios at once with this comprehensive testing suite:

# Nodinite IIS Certificate Binding Functionality Testing Suite
# Note: This script requires Windows PowerShell 5.1 due to WebAdministration module requirements.
# If running in PowerShell 7+, it will invoke Windows PowerShell as a subprocess.

$setupScript = {
    Write-Host "=== Nodinite IIS Certificate Binding Functionality Testing Suite ===" -ForegroundColor Magenta
    Write-Host "Creating comprehensive IIS binding test scenarios..." -ForegroundColor Cyan
    
    Import-Module WebAdministration -ErrorAction SilentlyContinue
    
    $testSites = @()
    $certificates = @()
    $setupErrors = @()
    
    try {
        Write-Host "`n Creating comprehensive IIS binding test scenarios" -ForegroundColor Blue
        
        # Helper function: Create IIS site with HTTPS binding using appcmd
        function New-TestIISSite {
            param(
                [string]$SiteName,
                [string]$PhysicalPath,
                [string]$Hostname,
                [int]$Port,
                [string]$CertThumbprint
            )
            
            try {
                # Create physical directory
                if (-not (Test-Path $PhysicalPath)) {
                    New-Item -ItemType Directory -Path $PhysicalPath -Force | Out-Null
                }
                "Test Site" | Out-File -FilePath "$PhysicalPath\index.html"
                
                # Remove existing site if present
                Remove-IISSite -Name $SiteName -Confirm:$false -ErrorAction SilentlyContinue
                
                # Create HTTP site first
                New-IISSite -Name $SiteName -PhysicalPath $PhysicalPath -BindingInformation "*:80:$Hostname" -Protocol http -ErrorAction Stop
                
                # Use appcmd to add HTTPS binding with certificate
                $appCmdPath = "C:\Windows\System32\inetsrv\appcmd.exe"
                if (Test-Path $appCmdPath) {
                    & $appCmdPath set site "$SiteName" /+bindings."[protocol='https',bindingInformation='*:$($Port):$Hostname']" 2>$null | Out-Null
                    & $appCmdPath set ssl site.name="$SiteName" /socket=$CertThumbprint 2>$null | Out-Null
                }
                
                return $true
            }
            catch {
                Write-Host "Error creating site: $_" -ForegroundColor Red
                return $false
            }
        }
        
        # Scenario 1: Healthy IIS Binding
        Write-Host "`n[Scenario 1/8] Creating healthy IIS binding with valid certificate..." -ForegroundColor Green
        try {
            $healthyCert = New-SelfSignedCertificate `
                -DnsName "www.testsite.local", "testsite.local" `
                -CertStoreLocation Cert:\LocalMachine\My `
                -NotAfter (Get-Date).AddYears(1) `
                -FriendlyName "TestSite Healthy Certificate" `
                -ErrorAction Stop
            
            $siteDir = "C:\inetpub\wwwroot\testsite"
            if (New-TestIISSite -SiteName "NodiniteTestSite" -PhysicalPath $siteDir -Hostname "www.testsite.local" -Port 443 -CertThumbprint $healthyCert.Thumbprint) {
                $certificates += @{ Name = "Healthy"; Thumbprint = $healthyCert.Thumbprint }
                $testSites += @{ Name = "NodiniteTestSite"; Cert = $healthyCert; Status = "Healthy" }
                Write-Host " Successfully created healthy binding site (Thumbprint: $($healthyCert.Thumbprint.Substring(0,8))...)" -ForegroundColor Green
            }
        }
        catch {
            $setupErrors += "Scenario 1 (Healthy Binding): $_"
            Write-Host " Failed to create healthy binding: $_" -ForegroundColor Red
        }
        
        # Scenario 2: Orphaned Binding (Missing Certificate)
        Write-Host "`n[Scenario 2/8] Creating orphaned binding (will delete certificate)..." -ForegroundColor Green
        try {
            $orphanedCert = New-SelfSignedCertificate `
                -DnsName "orphaned.testsite.local" `
                -CertStoreLocation Cert:\LocalMachine\My `
                -NotAfter (Get-Date).AddYears(1) `
                -FriendlyName "TestSite Orphaned Certificate" `
                -ErrorAction Stop
            
            $orphanDir = "C:\inetpub\wwwroot\orphaned"
            if (New-TestIISSite -SiteName "NodiniteOrphanedSite" -PhysicalPath $orphanDir -Hostname "orphaned.testsite.local" -Port 8443 -CertThumbprint $orphanedCert.Thumbprint) {
                # Delete certificate to create orphaned binding
                Remove-Item "Cert:\LocalMachine\My\$($orphanedCert.Thumbprint)" -Force -ErrorAction SilentlyContinue
                
                $certificates += @{ Name = "Orphaned"; Thumbprint = $orphanedCert.Thumbprint; Action = "Deleted" }
                $testSites += @{ Name = "NodiniteOrphanedSite"; Thumbprint = $orphanedCert.Thumbprint; Status = "Orphaned" }
                Write-Host " Successfully created orphaned binding (Thumbprint: $($orphanedCert.Thumbprint.Substring(0,8))... DELETED)" -ForegroundColor Green
            }
        }
        catch {
            $setupErrors += "Scenario 2 (Orphaned Binding): $_"
            Write-Host " Failed to create orphaned binding: $_" -ForegroundColor Red
        }
        
        # Scenario 3: Expiring Certificate Binding
        Write-Host "`n[Scenario 3/8] Creating binding with expiring certificate (expires in 1 day)..." -ForegroundColor Green
        try {
            $expiringCert = New-SelfSignedCertificate `
                -DnsName "expiring.testsite.local" `
                -CertStoreLocation Cert:\LocalMachine\My `
                -NotAfter (Get-Date).AddDays(1) `
                -FriendlyName "TestSite Expiring Certificate" `
                -ErrorAction Stop
            
            $expiringDir = "C:\inetpub\wwwroot\expiring"
            if (New-TestIISSite -SiteName "NodiniteExpiringSite" -PhysicalPath $expiringDir -Hostname "expiring.testsite.local" -Port 9443 -CertThumbprint $expiringCert.Thumbprint) {
                $certificates += @{ Name = "Expiring"; Thumbprint = $expiringCert.Thumbprint; ExpiresIn = "1 day" }
                $testSites += @{ Name = "NodiniteExpiringSite"; Cert = $expiringCert; Status = "Expiring" }
                Write-Host " Successfully created binding with expiring certificate (Expires: $(($expiringCert.NotAfter).ToString('yyyy-MM-dd')))" -ForegroundColor Green
            }
        }
        catch {
            $setupErrors += "Scenario 3 (Expiring Binding): $_"
            Write-Host " Failed to create expiring binding: $_" -ForegroundColor Red
        }
        
        # Scenario 4: Hostname Mismatch
        Write-Host "`n[Scenario 4/8] Creating binding with hostname mismatch..." -ForegroundColor Green
        try {
            $mismatchCert = New-SelfSignedCertificate `
                -DnsName "site-a.local" `
                -CertStoreLocation Cert:\LocalMachine\My `
                -NotAfter (Get-Date).AddYears(1) `
                -FriendlyName "TestSite Mismatch Certificate" `
                -ErrorAction Stop
            
            $mismatchDir = "C:\inetpub\wwwroot\mismatch"
            # Bind to different hostname but use certificate for site-a.local
            if (New-TestIISSite -SiteName "NodiniteMismatchSite" -PhysicalPath $mismatchDir -Hostname "site-b.local" -Port 10443 -CertThumbprint $mismatchCert.Thumbprint) {
                $certificates += @{ Name = "Mismatch"; Thumbprint = $mismatchCert.Thumbprint; Subject = "site-a.local"; BoundTo = "site-b.local" }
                $testSites += @{ Name = "NodiniteMismatchSite"; Cert = $mismatchCert; Status = "Mismatch" }
                Write-Host " Successfully created hostname mismatch binding (Cert: site-a.local, Binding: site-b.local)" -ForegroundColor Green
            }
        }
        catch {
            $setupErrors += "Scenario 4 (Hostname Mismatch): $_"
            Write-Host " Failed to create mismatch binding: $_" -ForegroundColor Red
        }
        
        # Scenario 5: Wildcard Certificate Binding
        Write-Host "`n[Scenario 5/8] Creating binding with wildcard certificate..." -ForegroundColor Green
        try {
            $wildcardCert = New-SelfSignedCertificate `
                -DnsName "*.example.local", "example.local" `
                -CertStoreLocation Cert:\LocalMachine\My `
                -NotAfter (Get-Date).AddYears(1) `
                -FriendlyName "TestSite Wildcard Certificate" `
                -ErrorAction Stop
            
            $wildcardDir = "C:\inetpub\wwwroot\wildcard"
            if (New-TestIISSite -SiteName "NodiniteWildcardSite" -PhysicalPath $wildcardDir -Hostname "www.example.local" -Port 11443 -CertThumbprint $wildcardCert.Thumbprint) {
                $certificates += @{ Name = "Wildcard"; Thumbprint = $wildcardCert.Thumbprint; Subject = "*.example.local" }
                $testSites += @{ Name = "NodiniteWildcardSite"; Cert = $wildcardCert; Status = "Wildcard" }
                Write-Host " Successfully created wildcard certificate binding (*.example.local bound to www.example.local)" -ForegroundColor Green
            }
        }
        catch {
            $setupErrors += "Scenario 5 (Wildcard Certificate): $_"
            Write-Host " Failed to create wildcard binding: $_" -ForegroundColor Red
        }
        
        # Scenario 6: IIS Not Installed
        # Note: This scenario cannot be tested in script form - it requires IIS to be uninstalled
        # Skipping automated test for Scenario 6 (manual validation required)
        Write-Host "`n[Scenario 6/8] Skipping 'IIS Not Installed' scenario (requires manual testing)" -ForegroundColor Yellow
        
        # Scenario 7: Multi-Level Wildcard Certificate (Security Risk)
        Write-Host "`n[Scenario 7/8] Creating binding with multi-level wildcard certificate..." -ForegroundColor Green
        try {
            $multiWildcardCert = New-SelfSignedCertificate `
                -DnsName "*.*.example.com", "example.com" `
                -CertStoreLocation Cert:\LocalMachine\My `
                -NotAfter (Get-Date).AddYears(1) `
                -FriendlyName "TestSite Multi-Level Wildcard Certificate" `
                -ErrorAction Stop
            
            $multiWildcardDir = "C:\inetpub\wwwroot\multilevelwildcard"
            if (New-TestIISSite -SiteName "NodiniteMultiLevelWildcardSite" -PhysicalPath $multiWildcardDir -Hostname "api.dev.example.com" -Port 13443 -CertThumbprint $multiWildcardCert.Thumbprint) {
                $certificates += @{ Name = "Multi-Level Wildcard"; Thumbprint = $multiWildcardCert.Thumbprint; Subject = "*.*.example.com" }
                $testSites += @{ Name = "NodiniteMultiLevelWildcardSite"; Cert = $multiWildcardCert; Status = "Multi-Level Wildcard" }
                Write-Host " Successfully created multi-level wildcard binding (*.*.example.com bound to api.dev.example.com)" -ForegroundColor Green
            }
        }
        catch {
            $setupErrors += "Scenario 7 (Multi-Level Wildcard): $_"
            Write-Host " Failed to create multi-level wildcard binding: $_" -ForegroundColor Red
        }
        
        # Scenario 8: Certificate with Excessive SANs
        Write-Host "`n[Scenario 8/8] Creating certificate with excessive SANs (120 entries)..." -ForegroundColor Green
        try {
            # Generate 120 SAN entries
            $sanList = @("example.com")
            for ($i = 1; $i -le 120; $i++) {
                $sanList += "subdomain$i.example.com"
            }
            
            $excessiveSANCert = New-SelfSignedCertificate `
                -DnsName $sanList `
                -CertStoreLocation Cert:\LocalMachine\My `
                -NotAfter (Get-Date).AddYears(1) `
                -FriendlyName "TestSite Excessive SANs Certificate" `
                -ErrorAction Stop
            
            $excessiveSANDir = "C:\inetpub\wwwroot\excessivesans"
            if (New-TestIISSite -SiteName "NodiniteExcessiveSANSite" -PhysicalPath $excessiveSANDir -Hostname "subdomain1.example.com" -Port 14443 -CertThumbprint $excessiveSANCert.Thumbprint) {
                $certificates += @{ Name = "Excessive SANs"; Thumbprint = $excessiveSANCert.Thumbprint; SANCount = $sanList.Count }
                $testSites += @{ Name = "NodiniteExcessiveSANSite"; Cert = $excessiveSANCert; Status = "Excessive SANs" }
                Write-Host " Successfully created certificate with $($sanList.Count) SANs (threshold: 100)" -ForegroundColor Green
            }
        }
        catch {
            $setupErrors += "Scenario 8 (Excessive SANs): $_"
            Write-Host " Failed to create excessive SANs binding: $_" -ForegroundColor Red
        }
    }
    catch {
        Write-Host " Unexpected error during test setup: $_" -ForegroundColor Red
    }
    
    # Summary Report
    Write-Host "`n" -ForegroundColor White
    Write-Host "=== Test Setup Summary ===" -ForegroundColor Cyan
    Write-Host " IIS Sites Created: $($testSites.Count)" -ForegroundColor Blue
    Write-Host " Certificates Created: $($certificates.Count)" -ForegroundColor Blue
    
    if ($testSites.Count -gt 0) {
        Write-Host "`nIIS Test Sites:" -ForegroundColor Green
        foreach ($site in $testSites) {
            Write-Host "  • $($site.Name) - Status: $($site.Status)" -ForegroundColor White
        }
    }
    
    if ($setupErrors.Count -gt 0) {
        Write-Host "`n Errors Encountered:" -ForegroundColor Yellow
        foreach ($setupError in $setupErrors) {
            Write-Host "  • $setupError" -ForegroundColor Yellow
        }
    }
    
    Write-Host "`n Configuration:" -ForegroundColor Blue
    Write-Host "  • Set MonitorIISCertificateBindings=true in Nodinite configuration" -ForegroundColor White
    Write-Host "  • Set IISBindingWarningDays=7 (or appropriate threshold)" -ForegroundColor White
    Write-Host "  • Restart Nodinite monitoring service" -ForegroundColor White
    Write-Host "  • Verify IIS binding resources appear in Monitor View" -ForegroundColor White
    
    Write-Host "`n Setup complete! IIS binding scenarios ready for monitoring validation." -ForegroundColor Green
}

# For PowerShell 7+, invoke Windows PowerShell 5.1
if ($PSVersionTable.PSVersion.Major -ge 7) {
    Write-Host "`nDetected PowerShell $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor). Invoking Windows PowerShell 5.1 for module compatibility..." -ForegroundColor Yellow
    & "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command $setupScript
} else {
    # Windows PowerShell 5.1 - run directly
    & $setupScript
}

Cleanup: Remove IIS Binding Test Scenarios

Remove all test IIS sites and certificates after validation:

# Cleanup Nodinite IIS Certificate Binding Test Scenarios
# Note: This script requires Windows PowerShell 5.1 due to WebAdministration module requirements.
# If running in PowerShell 7+, it will invoke Windows PowerShell as a subprocess.

$cleanupScript = {
    Import-Module WebAdministration -ErrorAction SilentlyContinue
    
    Write-Host "=== Cleanup: Nodinite IIS Binding Test Scenarios ===" -ForegroundColor Magenta
    Write-Host "Removing all test IIS sites and certificates..." -ForegroundColor Cyan
    
    $testSiteNames = @(
        "NodiniteTestSite",
        "NodiniteOrphanedSite",
        "NodiniteExpiringSite",
        "NodiniteMismatchSite",
        "NodiniteWildcardSite",
        "NodiniteMultiLevelWildcardSite",
        "NodiniteExcessiveSANSite"
    )
    
    $testCertFriendlyNames = @(
        "TestSite Healthy Certificate",
        "TestSite Orphaned Certificate",
        "TestSite Expiring Certificate",
        "TestSite Mismatch Certificate",
        "TestSite Wildcard Certificate",
        "TestSite Multi-Level Wildcard Certificate",
        "TestSite Excessive SANs Certificate"
    )
    
    $removedSites = 0
    $removedCerts = 0
    $cleanupErrors = @()
    
    # Remove IIS Sites
    Write-Host "`n Removing IIS test sites..." -ForegroundColor Blue
    foreach ($siteName in $testSiteNames) {
        try {
            Remove-IISSite -Name $siteName -Confirm:$false -ErrorAction SilentlyContinue
            Write-Host " Removed IIS site '$siteName'" -ForegroundColor Green
            $removedSites++
        }
        catch {
            $cleanupErrors += "Failed to remove site '$siteName': $_"
            Write-Host " Failed to remove site '$siteName': $_" -ForegroundColor Red
        }
    }

    # Remove Physical Directories
    Write-Host "`n Removing test site directories..." -ForegroundColor Blue
    $testDirs = @(
        "C:\inetpub\wwwroot\testsite",
        "C:\inetpub\wwwroot\orphaned",
        "C:\inetpub\wwwroot\expiring",
        "C:\inetpub\wwwroot\mismatch",
        "C:\inetpub\wwwroot\wildcard",
        "C:\inetpub\wwwroot\multilevelwildcard",
        "C:\inetpub\wwwroot\excessivesans"
    )

    foreach ($dir in $testDirs) {
        try {
            if (Test-Path $dir) {
                Remove-Item -Path $dir -Recurse -Force -ErrorAction Stop
                Write-Host " Removed directory '$dir'" -ForegroundColor Green
            }
        }
        catch {
            $cleanupErrors += "Failed to remove directory '$dir': $_"
            Write-Host " Failed to remove directory '$dir': $_" -ForegroundColor Yellow
        }
    }

    # Remove Certificates
    Write-Host "`n Removing test certificates..." -ForegroundColor Blue
    foreach ($friendlyName in $testCertFriendlyNames) {
        try {
            $certs = Get-ChildItem Cert:\LocalMachine\My | Where-Object { $_.FriendlyName -eq $friendlyName }
            foreach ($cert in $certs) {
                Remove-Item "Cert:\LocalMachine\My\$($cert.Thumbprint)" -Force -ErrorAction Stop
                Write-Host " Removed certificate '$friendlyName' (Thumbprint: $($cert.Thumbprint.Substring(0,8))...)" -ForegroundColor Green
                $removedCerts++
            }
        }
        catch {
            $cleanupErrors += "Failed to remove certificate '$friendlyName': $_"
            Write-Host " Failed to remove certificate '$friendlyName': $_" -ForegroundColor Yellow
        }
    }

    # Cleanup Summary
    Write-Host "`n=== Cleanup Summary ===" -ForegroundColor Cyan
    Write-Host " IIS Sites Removed: $removedSites" -ForegroundColor Green
    Write-Host " Certificates Removed: $removedCerts" -ForegroundColor Green

    if ($cleanupErrors.Count -gt 0) {
        Write-Host "`n Errors During Cleanup:" -ForegroundColor Yellow
        foreach ($cleanupError in $cleanupErrors) {
            Write-Host "  • $cleanupError" -ForegroundColor Yellow
        }
        Write-Host "`nNote: Some resources may have already been removed. Review above for any critical errors." -ForegroundColor Yellow
    }

    Write-Host "`n Cleanup complete! Test scenarios removed." -ForegroundColor Green
}

# For PowerShell 7+, invoke Windows PowerShell 5.1
if ($PSVersionTable.PSVersion.Major -ge 7) {
    Write-Host "Detected PowerShell $($PSVersionTable.PSVersion.Major).$($PSVersionTable.PSVersion.Minor). Invoking Windows PowerShell 5.1 for module compatibility..." -ForegroundColor Yellow
    & "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -Command $cleanupScript
} else {
    # Windows PowerShell 5.1 - run directly
    & $cleanupScript
}

Next Step