How to export the Certificate details related to the particular IIS site using Powershell script - excel

I wrote a script where in it will export all the SSL certificate details from my machine to an Excel sheet, but I need to export the Certificates which are mapped to the particular site in IIS and then I need to export those details with Site name and the Certificate details to an Excel sheet.
Code
#Clearing the Console host in PS
Clear-Host
#Installing the Excel module to the Powershell
Install-Module -Name ImportExcel
#List of Servers
$computers = Get-Content "C:\TEMP\servers.txt"
#Number of days to look for expiring certificates
$threshold = 300
#Set deadline date
$deadline = (Get-Date).AddDays($threshold)
Invoke-Command -ComputerName $computers {
Get-ChildItem -Path 'Cert:\LocalMachine\My' -Recurse |
Select-Object -Property #{n='ServerName';e={$env:COMPUTERNAME}},Issuer, Subject, NotAfter,
##{Label = 'ServerName';Expression = {$env:COMPUTERNAME}}
#{Label='Expires In (Days)';Expression = {(New-TimeSpan -Start (Get-Date) -End $PSitem.NotAfter).Days}}
} | Export-Excel -Path C:\users\$env:username\documents\MultipleServer_Certificate_Expiry_Details.xlsx`

This is a very common thing, with many articles and samples all over the web on this IIS use case. This is what the web administration module is used for.
<#
Get all IIS bindings and SSL certificates
On a local or remote IIS PowerShell Session
#>
Import-Module -Name WebAdministration
Get-ChildItem -Path IIS:SSLBindings |
ForEach-Object -Process {
if ($_.Sites)
{
$certificate = Get-ChildItem -Path CERT:LocalMachine/My |
Where-Object -Property Thumbprint -EQ -Value $_.Thumbprint
[PsCustomObject]#{
Sites = $_.Sites.Value
CertificateFriendlyName = $certificate.FriendlyName
CertificateDnsNameList = $certificate.DnsNameList
CertificateNotAfter = $certificate.NotAfter
CertificateIssuer = $certificate.Issuer
}
}
}
Customize the above to fit your output needs.
Note if you happen to be on a legacy version of PowerShell:
[PsCustomObject]#{} will not work in PS 2.0 but you may replace it by New-Object -TypeName PSObject
Update
You've asked for a sample script to run on multiple servers. However, you already have the code in your post. Just put that Invoke-Command inside a ForEach loop and pass in a list of computers.
$Computers |
ForEach {
Invoke-Command -ComputerName $PSItem -ScriptBlock {
Get-ChildItem -Path 'Cert:\LocalMachine\My' -Recurse |
Select-Object -Property #{n='ServerName';e={$env:COMPUTERNAME}},Issuer, Subject, NotAfter,
#{Label='Expires In (Days)';Expression = {(New-TimeSpan -Start (Get-Date) -End $PSitem.NotAfter).Days}}
} | Export-Excel -Path "C:\users\$env:username\documents\MultipleServer_Certificate_Expiry_Details.xlsx"
}
Of course, you'll need to add in that sample for the Web Admin block to your cert data points

Related

Enable 32 bits to a list of existing IIS appools

Tried to find a list of appools in IIS starting with a common name "as" once found I would like to enable to only those 32bits to true
So far got this but it's not working, any given help will be very much appreaciated
import-module WebAdministration
$enable32bit="true"
$results = Get-IISAppPool | where {$_.Name -like "AS*"}
foreach ($item in $results) {
Set-ItemProperty IIS:\AppPools\$item -Name "enable32BitAppOnWin64" -Value $enable32bit
}
Possibly just this:
Set-ItemProperty IIS:\AppPools\AS* -name "enable32BitAppOnWin64" -Value "true"

Powershell If Statement not working - Posh-ACME

I am struggling to get the last if statement to work.
I have a blob storage account which contains the directories mentioned and a certificate.
I want to import that certificate to the keyvault.
When I run the pipeline (which contains the below script), it just runs to where I have put the Write-host 'everything..'
Can someone please assist why it won't work, I have tried to separate to 3 if statements, remove the if statement nothing has worked.
param (
[string] $CertificateNames,
[string] $KeyVaultResourceId
)
# Split certificate names by comma or semi-colon
$certificateName = $CertificateNames.Replace(',', ';') -split ';' | ForEach-Object -Process { $_.Trim() } | Select-Object -First 1
# For wildcard certificates, Posh-ACME replaces * with ! in the directory name
$certificateName = $certificateName.Replace('*', '!')
# Set working directory
$workingDirectory = Join-Path -Path "." -ChildPath "pa"
# Set Posh-ACME working directory
$env:POSHACME_HOME = $workingDirectory
Import-Module -Name Posh-ACME -Force
# Resolve the details of the certificate
$currentServerName = ((Get-PAServer).location) -split "/" | Where-Object -FilterScript { $_ } | Select-Object -Skip 1 -First 1
$currentAccountName = (Get-PAAccount).id
# Determine paths to resources
$orderDirectoryPath = Join-Path -Path $workingDirectory -ChildPath $currentServerName | Join-Path -ChildPath $currentAccountName | Join-Path -ChildPath $certificateName
$orderDataPath = Join-Path -Path $orderDirectoryPath -ChildPath "order.json"
$pfxFilePath = Join-Path -Path $orderDirectoryPath -ChildPath "fullchain.pfx"
Write-Host 'everything works up until here.. then breaks'
# If we have a order and certificate available
if ((Test-Path -Path $orderDirectoryPath) -and (Test-Path -Path $orderDataPath) -and (Test-Path -Path $pfxFilePath)) {
Write-Host 'check paths are ok'
$pfxPass = (Get-PAOrder $certificateName).PfxPass
# Load PFX
$certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $pfxFilePath, $pfxPass, 'EphemeralKeySet'
# Get the current certificate from key vault (if any)
$azureKeyVaultCertificateName = $certificateName.Replace(".", "-").Replace("!", "wildcard")
$keyVaultResource = Get-AzResource -ResourceId $KeyVaultResourceId
$azureKeyVaultCertificate = Get-AzKeyVaultCertificate -VaultName $keyVaultResource.Name -Name $azureKeyVaultCertificateName -ErrorAction SilentlyContinue
Write-Host 'check if certificate is in kv'
# If we have a different certificate, import it
If (-not $azureKeyVaultCertificate -or $azureKeyVaultCertificate.Thumbprint -ne $certificate.Thumbprint) {
Import-AzKeyVaultCertificate -VaultName $keyVaultResource.Name -Name $azureKeyVaultCertificateName -FilePath $pfxFilePath -Password (ConvertTo-SecureString -String $pfxPass -AsPlainText -Force) | Out-Null
}
Write-Host 'check if upload is success'
}
When the pipeline is run, it breaks and there is no errors:
see screenshot here
Resolved this, the issue was the file paths didn't exist so the if statement couldn't check against an invalid file path.
As there was no errors, this was a bit harder to find the reason, instead I removed the if statement and added Write-Host "test" to see where things were broken in the code.

Display Data on Two Columns Within Excel

I am trying to display data within an Excel document where Column A displays the server name and column B displays the .NET version. I'm running into an issue exporting to a .csv because it says that the file path does not exist. I would like some guidance on how I can resolve that issue and how I can display data on the two columns within Excel.
$Servers =
(
"test"
)
foreach ($Server in $Servers)
{
Invoke-Command -ComputerName $Server -ScriptBlock {
Write-Output "$(hostname)"
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | Get-ItemProperty -Name Version,Release -EA 0 | where { $_.PSChildName -match '^(?!S)\p{L}'} | select PSChildName, Version, Release | Select -ExpandProperty Version | Sort-Object Version | Export-Csv -Path C:\Users\User\Desktop\example.csv
}
The main issue is that you're using Export-Csv on the remote hosts since it is inside the Invoke-Command script block, and the likeable error is because the path you are using as export doesn't exist on those hosts.
It's also worth noting that Invoke-Command can run in parallel, -ComputerName as well as -Session can take an array, this removes the need for the foreach loop as well as it is much faster / efficient.
Invoke-Command -ComputerName $servers -ScriptBlock {
Write-Host "Working on $($env:COMPUTERNAME)..."
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse |
Get-ItemProperty -Name Version, Release -EA 0 |
ForEach-Object {
if($_.PSChildName -notmatch '^(?!S)\p{L}') {
return # skip this
}
[pscustomobject]#{
HostName = $env:COMPUTERNAME
Version = $_.Version
}
} | Sort-Object Version
} -HideComputerName | Select-Object * -ExcludeProperty RunspaceID |
Export-Csv -Path C:\Users\User\Desktop\example.csv -NoTypeInformation

Script to test RDP connection to Multiple Servers

I am New to scripting world.
I have a requirement to test RDP access to our Servers in two datacenter as a part of a Leased Line Migration. I have a little over 2000+ servers and I cannot manually test RDP connection to all of them. I was hoping if any of you can help me prepare a script where I give the IP addresses of all my servers in the script and it tests RDP connections to all those servers and gives me a result if the RDP connection is successful or not.
Thanks in advance
Ravi
Create a text file of the server names or read directly from ADDS.
Pass that computername in a pipeline to the Test-NetConnection cmdlet using the CommonTCPPort switch for the RDP protocol in a ForLoop.
# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-Content).Parameters
(Get-Command -Name Get-Content).Parameters.Keys
Get-help -Name Get-Content -Examples
Get-help -Name Get-Content -Full
Get-help -Name Get-Content -Online
(Get-Command -Name Get-ADComputer).Parameters
(Get-Command -Name Get-ADComputer).Parameters.Keys
Get-help -Name Get-ADComputer -Examples
Get-help -Name Get-ADComputer -Full
Get-help -Name Get-ADComputer -Online
(Get-Command -Name Test-NetConnection).Parameters
(Get-Command -Name Test-NetConnection).Parameters.Keys
Get-help -Name Test-NetConnection -Examples
Get-help -Name Test-NetConnection -Full
Get-help -Name Test-NetConnection -Online
About_loops
Youtube
Update
As per my comment, you should only really need something like this.
(Get-ADComputer).Name |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort RDP}
Or
Get-Content -Path 'D:\ServerNames.txt' |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort RDP}
Update
A follow-up to your Out-File comment that you put as an answer. Again, step back take the time to learn PowerShell (the built-in help files, Youtube, articles, books, blogs, etc...) to limit/avoid confusion, mistakes, bad coding habits, frustrations as well as possible serious harm to your computer or your environment when create, update, deletes may be a later use case.
So, your file use case is one of these:
$env:COMPUTERNAME |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort RDP}
<#
# Results
ComputerName : Labhost001
RemoteAddress : ...
RemotePort : 3389
InterfaceAlias : ...
SourceAddress : ...
PingSucceeded : True
PingReplyDetails (RTT) : ...
TcpTestSucceeded : False
#>
You should only need these ....
ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded
... that last property says whether the connection worked.
$env:COMPUTERNAME |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB}
<#
# Results
ComputerName : Labhost001
RemoteAddress : ...
RemotePort : 445
InterfaceAlias : ...
SourceAddress : ...
TcpTestSucceeded : True
#>
$env:COMPUTERNAME |
ForEach {
Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB |
Select-Object -Property ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded
}
<#
# Results
ComputerName RemotePort PingSucceeded TcpTestSucceeded
------------ ---------- ------------- ----------------
Labhost001 445 False True
#>
$env:COMPUTERNAME |
ForEach {
Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB |
Select-Object -Property ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded |
Out-File -FilePath 'D:\Temp\TNCResults.txt' -Append
}
Get-Content -Path 'D:\Temp\TNCResults.txt'
<#
# Results
ComputerName RemotePort PingSucceeded TcpTestSucceeded
------------ ---------- ------------- ----------------
Labhost001 445 False True
#>
$env:COMPUTERNAME |
ForEach {
Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB |
Select-Object -Property ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded |
Export-Csv -Path 'D:\Temp\TNCResults.csv' -NoTypeInformation -Append
}
Get-Content -Path 'D:\Temp\TNCResults.csv'
<#
# Results
"ComputerName","RemotePort","PingSucceeded","TcpTestSucceeded"
"Labhost001","445","False","True"
#>
Import-Csv -Path 'D:\Temp\TNCResults.csv'
<#
# Results
ComputerName RemotePort PingSucceeded TcpTestSucceeded
------------ ---------- ------------- ----------------
Labhost001 445 False True
#>
I just worked on this similar task today and got it working successfully.
You will need to create a text file contains the list of servers names or IPs.
In my case, I used two text files:
One file for Windows servers "rdp.txt"
The second file for Linux servers "ssh.txt"
Then in PowerShell run the following script:
Don't forget to update the files paths in lines (2 & 3) according to the directory you place the files in
#Read the text files contents
$RDPServers = Get-content 'C:\scripts\rdp.txt'
$SSHServers = Get-content 'C:\scripts\ssh.txt'
#Define two containers variables to hold the list of reachable and unreachable servers.
$LiveServer = #()
$DeadServer = #()
#Loop over the windows servers list to test each server connectivity
foreach($Server in $RDPServers){
#Test the connectivity to windows server and store the response "True" or "False" in $nettest Variable
$netest = Test-NetConnection -ComputerName $Server -Port 3389 | Select-Object -ExpandProperty TcpTestSucceeded
Write-Output "RDP $($Server) is : $($netest)"
if($netest -eq "True")
#Add to the $Lifeserers list
{ $LiveServer += "$Server"}
else
#Add to the $DeadServers list
{$DeadServer += "$Server" }
}
echo "..."
echo "..."
#Loop over the Linux servers list to test each server connectivity
foreach($Server in $SSHServers)
{
#Test the connectivity to Linux server and store the response "True" or "False" in $nettest Variable
$netest = Test-NetConnection -ComputerName $Server -Port 22 | Select-Object -ExpandProperty TcpTestSucceeded
Write-Output "SSH $($Server) is : $($netest)"
if($netest -eq "True") { $LiveServer += "$Server"}
else {$DeadServer += "$Server" }
}
echo "Test Completed."
Write-Host "Reachable Computer as below"
$LiveServer
Write-Host "Not Reachable Computer as below"
$DeadServer
Run the script and check the output.

Using Objects in Powershell to do command

What im trying to do is the following:
Im getting a list of all VM`s that have some set values such as being in use and NOT having Azure Benefits turned on.
What i have is that i made a tiny script to get all machines within an subscription and select on the basis mentioned above.
What i want to do with that output is do the command Update-azureVM in bulk.
Could someone help me with this ? do i need to export the values to an excel and use that sheet to do a bulk update-AzureVM
here is the code that i have setup at the moment:
$returnObj = #()
$VMs=Get-AzVm -status
foreach ($VM in $VMs)
{
$obj = New-Object psobject -Property #{
"VmSize" = $VM.HardwareProfile.VmSize;
"VmName" = $vm.Name;
"PowerState" = $vm.PowerState;
"License_Type" = $vm.LicenseType;
}
$returnObj += $obj | select VmSize, VmName, PowerState, License_Type
}
$returnObj |
Where-Object{$_.PowerState -ne "VM deallocated"} |
Where-Object{$_.License_Type -ne "Windows_Server"} |
Where-Object{$_.License_Type -ne "Windows_Client"} |
Export-Csv C:\temp\freek.csv
Thank you all in advance!

Resources