├── .gitignore ├── Blog ├── Bash │ ├── .DS_Store │ ├── check-abuse.sh │ ├── citrix-cve-2019-19781.sh │ ├── find-top10.sh │ ├── mirrorwebsite.sh │ ├── pfx-utils.sh │ ├── random-password.sh │ ├── videos.txt │ ├── wifi-devices.sh │ └── youtube-download.sh ├── Batch │ ├── Win10-Update.bat │ ├── add-guest.bat │ ├── find-ca.bat │ ├── install-netframework-3.bat │ ├── mdconvert.bat │ ├── refresh-kerberostickets.bat │ ├── robocopy-clonesharefolder.bat │ └── save-details.bat ├── DevOps │ └── Vagrant │ │ └── Vagrantfile ├── PowerShell │ ├── Add-FileToBlobStorage.ps1 │ ├── Backup-AllKeyVault.ps1 │ ├── Check-CVE-2019-18935.ps1 │ ├── Check-Nic.ps1 │ ├── Clean-SophosTempFile.ps1 │ ├── Compare-AADUserSecurityGroupMembership.ps1 │ ├── Compare-Folder.ps1 │ ├── Compress-Folder.ps1 │ ├── Configure-IPGeoFencingIIS.ps1 │ ├── Create-NewLocalAdmin.ps1 │ ├── Decode-Base64ToFile.ps1 │ ├── Decode-SecureStringPassword.ps1 │ ├── Deployment │ │ ├── Deployment.ps1 │ │ ├── ReadMe.md │ │ ├── config │ │ │ └── DeploymentConfig.json │ │ └── lib │ │ │ ├── New-SubFolderWithDate.Test.ps1 │ │ │ └── New-SubFolderWithDate.ps1 │ ├── Disable-CrmTracing.ps1 │ ├── Disable-WindowsFirewall.ps1 │ ├── Enable-CrmTracing.ps1 │ ├── Enable-Rdp.ps1 │ ├── Enable-RemoteConnection.ps1 │ ├── Encode-FileToBase64.ps1 │ ├── Export-Drivers.ps1 │ ├── Find-AvailableIP.ps1 │ ├── Find-CriticalEventLog.ps1 │ ├── Find-StaleComputerObject.ps1 │ ├── Foreach-SerialAndParallel.ps1 │ ├── Get-ADReplicationReport.ps1 │ ├── Get-ADUsersReport.ps1 │ ├── Get-AVFileScan.ps1 │ ├── Get-FSMO.ps1 │ ├── Get-FilesWithMacros.ps1 │ ├── Get-LocalAdmin.ps1 │ ├── Get-LockedOutInfo.ps1 │ ├── Get-NtpStatusFromHost.ps1 │ ├── Get-PowerOption.ps1 │ ├── Get-RemoteRdpSession.ps1 │ ├── Get-Uptime.ps1 │ ├── Get-VMFootprintByEnv.ps1 │ ├── Get-VMFootprintOnASingleHost.ps1 │ ├── Get-YourScriptSigned.ps1 │ ├── Inspect-IISLogs.ps1 │ ├── Install-Chocolatey.ps1 │ ├── Install-DC.ps1 │ ├── Install-NagiosAgentRemotely.ps1 │ ├── Install-Pwsh.ps1 │ ├── Install-RSAT.ps1 │ ├── Install-WAC.ps1 │ ├── Monitor-AccountLockOut.ps1 │ ├── New-AADGuestUserInvite.ps1 │ ├── New-Checkpoint.ps1 │ ├── New-RDGfile.ps1 │ ├── New-RandomPassword.Tests.ps1 │ ├── New-RandomPassword.ps1 │ ├── New-ServiceAccount.ps1 │ ├── New-SshTunnel.ps1 │ ├── New-TextToSpeech.ps1 │ ├── New-Virus.ps1 │ ├── PingSweepAndReverseLookupExample.ps1 │ ├── PingSweepExample.ps1 │ ├── Proxy-Functions.ps1 │ ├── Refresh-Path.ps1 │ ├── Remove-OldBackup.ps1 │ ├── Restore-RecentChecktpoint.ps1 │ ├── ReverseLookupExample.ps1 │ ├── Search-ADUsersWithDuplicateFields.ps1 │ ├── Search-PcWithSophosFileToRemove.ps1 │ ├── Search-PhishingEmail.ps1 │ ├── Send-ADLockedOutEventToSlack.ps1 │ ├── Send-ADLockedOutEventToTeams.ps1 │ ├── Send-AdvancedLockedOutInfoToTeams.ps1 │ ├── Send-EmailWithSendGrid.ps1 │ ├── Send-Report.ps1 │ ├── Set-FirewallRuleToAllowPing.ps1 │ ├── Set-HighPerformance.ps1 │ ├── Set-SCVMMLastBackup.ps1 │ ├── Set-VBoxWorkaround.ps1 │ ├── Show-LockedUserPopUp.ps1 │ ├── Show-WiFiPassword.ps1 │ ├── Test-AccountLockOut.ps1 │ ├── Test-AdCredential.ps1 │ ├── Test-CurrenUserIsLocalAdmin.ps1 │ ├── Test-Job.ps1 │ ├── Trace-Crm.ps1 │ ├── Tune-Guitar.ps1 │ ├── Use-AzKeyVault.ps1 │ ├── Veeam-Notes.ps1 │ ├── Workaround-CVE-2020-1350.ps1 │ ├── check-defender.ps1 │ ├── check-vmstatus.ps1 │ ├── compress-log.ps1 │ ├── get-installedsoftware.ps1 │ ├── monitor-process.ps1 │ └── rdg.xml └── Python │ ├── combineapacheconfig.py │ ├── emailchecker.py │ ├── monitorconnection.py │ ├── sketchpaint.py │ └── urlfromsitemap.py ├── CODE_OF_CONDUCT.md ├── Media └── mini_logo.png └── README.MD /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/settings.json 2 | -------------------------------------------------------------------------------- /Blog/Bash/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaoloFrigo/scriptinglibrary/1c584b5339ef6547debc2755d479969376fe0a57/Blog/Bash/.DS_Store -------------------------------------------------------------------------------- /Blog/Bash/check-abuse.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | # SETTINGS 6 | NETWORK="" #123.3.2.1/24 7 | API_KEY="" #use you api key from abuseipdb.com 8 | DAYS=7 9 | 10 | if [[ $NETWORK == "" || $API_KEY == "" ]]; then 11 | echo "Please edit your NETWORK and API Settings"; 12 | exit 1 13 | fi 14 | # NOTES 15 | # If you want use this script as a custom Nagios Check copy it on 16 | # /usr/local/nagios/libexec/ and use the exit values that are commented out below 17 | 18 | AbuseIPCheck=$(curl -s -G https://api.abuseipdb.com/api/v2/check-block \ 19 | --data-urlencode "network=$NETWORK" \ 20 | -d maxAgeInDays=$DAYS \ 21 | -H "Key: $API_KEY" \ 22 | -H "Accept: application/json" |jq '.data.reportedAddress') 23 | 24 | if [ "$AbuseIPCheck" != [] ]; then 25 | echo "CRITICAL: $AbuseIPCheck"; 26 | #exit 2 #Comment out for Nagios 27 | else 28 | echo "OK"; 29 | #exit 0 #Comment out for Nagios 30 | fi 31 | -------------------------------------------------------------------------------- /Blog/Bash/citrix-cve-2019-19781.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Paolo Frigo, https://www.scriptinglibrary.com 3 | read -p "Please type the FQDN or IP of the Citrix server (ADC/NetscalerGateway/SD-WAN WANOP) you want to check: " TARGET;curl -vk –path-as-is https://$TARGET/vpn/../vpns/ 2>&1 | grep "You don’t have permission to access /vpns/" >/dev/null && echo "VULNERABLE: $TARGET" || echo "MITIGATED: $TARGET" -------------------------------------------------------------------------------- /Blog/Bash/find-top10.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Paolo Frigo, https://www.scriptinglibrary.com 3 | #THIS SCRIPT RETURNS THE TOP N IP IN THE IIS LOGS FOLDER 4 | TOP=10 5 | 6 | function find_top_ip () { 7 | IISLOG=$1 8 | echo "This is the TOP $TOP for the $IISLOG log file" 9 | echo "--------------------------------------" 10 | echo " HIT | IP" 11 | echo "--------------------------------------" 12 | cat $IISLOG | cut -d ' ' -f 9 | sort | uniq -c | sort -r | head -n $TOP 13 | echo "--------------------------------------" 14 | } 15 | 16 | for f in *.log; do find_top_ip $f; done -------------------------------------------------------------------------------- /Blog/Bash/mirrorwebsite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | # This script creates a local copy of a website using WGET 5 | 6 | read -p 'URL: ' URL 7 | wget --verbose --debug --adjust-extension --backup-converted --base=$URL --no-http-keep-alive --no-parent --mirror $URL 8 | -------------------------------------------------------------------------------- /Blog/Bash/pfx-utils.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # THIS SCRIPT EXTRACT A CERTIFICATE AND PRIVATE KEY FROM PFX FILE 4 | # Paolo Frigo, https://www.scriptinglibrary.com 5 | 6 | read -p "Certificate name (e.g. MyCert.pfx):" PfxCert 7 | CertName=${PfxCert/.pfx/} 8 | 9 | #Export the private key 10 | openssl pkcs12 -in $PfxCert -nocerts -out key.pem -nodes 11 | 12 | #Export the certificate 13 | openssl pkcs12 -in $PfxCert -nokeys -out $CertName.pem 14 | 15 | #Remove the passphrase from the private key 16 | openssl rsa -in key.pem -out $CertName.key 17 | 18 | #Create a Zip file 19 | zip $CertName.zip $CertName.pem key.pem $CertName.key $PfxCert 20 | 21 | echo "$CertName.pem, key.pem and $CertName.key generated from $PfxCert" 22 | echo "All files added to a zip archive $CertName.zip" 23 | -------------------------------------------------------------------------------- /Blog/Bash/random-password.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | # credit for URANDOM: https://gist.github.com/earthgecko/3089509 5 | 6 | # This scripts generates a strong password of 32 characters 7 | 8 | # using PwGen 9 | #pwgen -sBy 32 1 10 | 11 | # using Openssl 12 | openssl rand -base64 32 13 | 14 | # using URandom 15 | #cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-32} | head -n 1 16 | # use this for URandom on MacOS 17 | #cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1 18 | # this with more symbols 19 | #cat /dev/urandom | LC_CTYPE=C tr -dc "a-zA-Z0-9!@#$%^&*()_+?><~\`;'" | fold -w 32 | head -n 1 20 | -------------------------------------------------------------------------------- /Blog/Bash/videos.txt: -------------------------------------------------------------------------------- 1 | https://www.youtube.com/watch?v=eKbA8wPbH20 2 | https://www.youtube.com/watch?v=l1DIFfHvcqo -------------------------------------------------------------------------------- /Blog/Bash/wifi-devices.sh: -------------------------------------------------------------------------------- 1 | ​#!/bin/bash 2 | 3 | # 4 | # This scripts uses and requires NMAP, creates a report with all hosts connected to the SUBNET 5 | # 6 | # author: Paolo Frigo https://www.scriptinglibrary.com 7 | 8 | # CONFIGURE ACCORDING TO YOUR NEEDS 9 | REPORT_FILENAME="scan-$(date +%Y-%m-%d).txt" 10 | WIFI_SUBNET="10.0.0" 11 | 12 | nmap -sL $WIFI_SUBNET.* | grep -v "^Nmap scan report for $WIFI_SUBNET" | sed -e 's/Nmap scan report for //g'| tee $REPORT_FILENAME 13 | echo "--- $REPORT_FILENAME has been created! ---" 14 | ​ 15 | -------------------------------------------------------------------------------- /Blog/Bash/youtube-download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #author: Paolo Frigo, https://www.scriptinglibrary.com 3 | video_list="videos.txt" 4 | total=$(wc -l $video_list | awk '{ print $1 }') 5 | counter=0 6 | help="Please, install it: 7 | 'sudo apt-get install youtube-dl' or 8 | 'brew install youtube-dl' 9 | for more info: https://github.com/rg3/youtube-dl" 10 | 11 | if command -v youtube-dl >/dev/null 2>&1 ; then 12 | echo "$(date) Download Started..." 13 | else 14 | echo "youtube-dl not found. $help" 15 | exit 16 | fi 17 | 18 | for video in $(cat $video_list); do 19 | counter=$(($counter + 1)) 20 | echo "[$counter/$total]: " $video 21 | youtube-dl -f 22 -o '%(title)s.%(ext)s' $video 22 | done 23 | 24 | echo "$(date) Download Finished!" 25 | -------------------------------------------------------------------------------- /Blog/Batch/Win10-Update.bat: -------------------------------------------------------------------------------- 1 | Rem Paolo Frigo, https://scriptinglibrary.com 2 | 3 | Rem This script launch the unattended in-place upgrade for Windows 10 4 | Rem for attended mode use Microsoft Update Assistant https://www.microsoft.com/en-au/software-download/windows10 5 | 6 | Rem Copy the content of the iso Windows 10 20H2 iso on a SMB Share 7 | net use W: \\Nas\Media\Windows-20H2 8 | W: 9 | 10 | setup.exe /migchoice upgrade /showoobe none /eula accept /DynamicUpdate NoDrivers /Telemetry Disable /quiet -------------------------------------------------------------------------------- /Blog/Batch/add-guest.bat: -------------------------------------------------------------------------------- 1 | Rem Paolo Frigo, https://scriptinglibrary.com 2 | Rem This scripts add a local guest account to the system 3 | 4 | Rem Replace myguest with the guest username and MYSECRET with a password 5 | net user myguest MYSECRET /add /expires:never -------------------------------------------------------------------------------- /Blog/Batch/find-ca.bat: -------------------------------------------------------------------------------- 1 | Rem Paolo Frigo, https://scriptinglibrary.com 2 | 3 | Rem Determine the CA name and server name in your AD domain. 4 | 5 | certutil -config - -ping 6 | 7 | -------------------------------------------------------------------------------- /Blog/Batch/install-netframework-3.bat: -------------------------------------------------------------------------------- 1 | Rem Paolo Frigo, https://scriptinglibrary.com 2 | Rem This script installs .Net Framework 3 from a SMB share 3 | 4 | dism.exe /Online /Enable-Feature /FeatureName:NetFX3 /All /Source:\\NAS\WIN-ISO\Sources\sxs -------------------------------------------------------------------------------- /Blog/Batch/mdconvert.bat: -------------------------------------------------------------------------------- 1 | :: MD CONVERT 2 | :: ------------------------ 3 | :: Converts all MarkDowns files passed as arguments into different 4 | :: formats and saves them into a separate folder. 5 | :: 6 | :: AUTHOR: Paolo Frigo https://www.scriptinglibrary.com 7 | :: 8 | :: REQUIREMENTS: 9 | :: pandoc (https://pandoc.org/) 10 | :: miktex for pdf conversion form LaTeX (https://miktex.org/) 11 | set list=docx html rst odt rtf epub pdf 12 | 13 | for %%x in (%*) do ( 14 | mkdir output 15 | mkdir output\\%%~nx 16 | for %%e in (%list%) do ( 17 | mkdir output\\_%%e 18 | pandoc %%x -o output/_%%e/%%~nx.%%e 19 | pandoc %%x -o output/%%~nx/%%~nx.%%e 20 | ) 21 | :: Keep a copy of the MarkDown File. 22 | mkdir output\\_md 23 | copy %%x output\_md\ 24 | copy %%x output\%%~nx\ 25 | ) 26 | -------------------------------------------------------------------------------- /Blog/Batch/refresh-kerberostickets.bat: -------------------------------------------------------------------------------- 1 | rem Paolo Frigo, https://scriptinglibrary.com 2 | rem Refresh kerberos tickets without requiring logoff or reboot 3 | 4 | rem To check the result before and after you can use either of these two options: 5 | rem gpresult /r 6 | rem whoami /groups 7 | 8 | rem klist.exe tool is refreshing the kerberos tickets (From Win 7 / Windows Server 2003) 9 | klist -li 0:0x3e7 purge -------------------------------------------------------------------------------- /Blog/Batch/robocopy-clonesharefolder.bat: -------------------------------------------------------------------------------- 1 | Rem Paolo Frigo, https://scriptinglibrary.com 2 | 3 | Rem The original author of this snippet is CRAIG SCHELLENBERG 4 | Rem https://www.sikich.com/insight/how-to-perform-file-server-migrations-using-robocopy-part-1/ 5 | 6 | Rem REPLACE 7 | Rem , AND LOGNAME_%date:~-10,2%"-"%date:~7,2%"-"%date:~-4,4%.txt 8 | 9 | robocopy /e /b /copyall /PURGE /r:5 /w:5 /MT:64 /tee /log+: /v 10 | 11 | -------------------------------------------------------------------------------- /Blog/Batch/save-details.bat: -------------------------------------------------------------------------------- 1 | REM Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | REM THIS SCRIPTS REDIRECTS SYSTEMINFO AND IPCONFIG OUTPUT TO A FILE 4 | 5 | SET /p DESC="Enter a suffix, e.g. PRE-UPGRADE: " 6 | SET OUTPUTFILE="D:\%COMPUTERNAME%-%DESC%.TXT 7 | 8 | systeminfo > %OUTPUTFILE% 9 | ipconfig /all >> %OUTPUTFILE% 10 | 11 | echo "%OUTPUTFILE% file written" -------------------------------------------------------------------------------- /Blog/DevOps/Vagrant/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | 9 | ## 10 | ## Paolo Frigo, https://www.scriptinglibrary.com 11 | ## Vagrant configuration to spin up a lab environment 12 | 13 | 14 | Vagrant.configure("2") do |config| 15 | 16 | ## LINUX VMS 17 | 18 | config.vm.define "lab-ubuntu01" do |ubuntu01| 19 | ubuntu01.vm.box = "generic/ubuntu1804" 20 | ubuntu01.vm.hostname = "lab-ubuntu01" 21 | ubuntu01.vm.network "private_network", ip: "172.16.1.10" 22 | ubuntu01.vm.provider "hyperv" do |hv| 23 | hv.memory = 1024 24 | end 25 | end 26 | 27 | config.vm.define "lab-centos01" do |centos01| 28 | centos01.vm.box = "generic/centos7" 29 | centos01.vm.hostname = "lab-centos01" 30 | centos01.vm.network "private_network", ip: "172.16.1.11" 31 | centos01.vm.provider "hyperv" do |hv| 32 | hv.memory = 1024 33 | end 34 | end 35 | 36 | ## WINDOWS VMS 37 | 38 | config.vm.define "lab-win01" do |win01| 39 | win01.vm.box = "mwrock/Windows2016" 40 | win01.vm.hostname = "lab-windows01" 41 | win01.vm.communicator = "winrm" 42 | win01.winrm.username = "vagrant" 43 | win01.winrm.password = "vagrant" 44 | win01.vm.network "private_network", ip: "172.16.1.22" 45 | win01.vm.provider "hyperv" do |hv| 46 | hv.memory = 2048 47 | end 48 | end 49 | 50 | config.vm.define "lab-win02" do |win02| 51 | win02.vm.box = "mwrock/Windows2012R2" 52 | win02.vm.hostname = "lab-windows02" 53 | win02.vm.communicator = "winrm" 54 | win02.winrm.username = "vagrant" 55 | win02.winrm.password = "vagrant" 56 | win02.vm.network "private_network", ip: "172.16.1.23" 57 | win02.vm.provider "hyperv" do |hv| 58 | hv.memory = 2048 59 | end 60 | end 61 | 62 | end 63 | -------------------------------------------------------------------------------- /Blog/PowerShell/Add-FileToBlobStorage.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://scriptinglibrary.com 2 | 3 | <# 4 | .SYNOPSIS 5 | Add a file to a blob storage 6 | 7 | .DESCRIPTION 8 | This function leverages the Azure Rest API to upload a file into a blob storage using a SAS token. 9 | 10 | .PARAMETER file 11 | Absolute path of the file to upload 12 | 13 | .PARAMETER connectionstring 14 | Uri and SAS token 15 | 16 | .EXAMPLE 17 | Add-FileToBlogStorage -file "FULL_PATH" -connectionstring "BLOBSTORAGE_URI_WITH_SAS_TOKEN" 18 | 19 | #> 20 | function Add-FileToBlobStorage{ 21 | Param( 22 | [Parameter(Mandatory=$true)] 23 | [ValidateScript({Test-Path $_ })] 24 | [string] 25 | $file, 26 | [Parameter(Mandatory=$true)] 27 | [ValidateScript({$_ -match "https\:\/\/(.)*\.blob.core.windows.net\/(.)*\?(.)*"})] 28 | [string] 29 | $connectionstring 30 | ) 31 | $HashArguments = @{ 32 | uri = $connectionstring.replace("?","/$($(get-item $file).name)?") 33 | method = "Put" 34 | InFile = $file 35 | headers = @{"x-ms-blob-type" = "BlockBlob"} 36 | 37 | } 38 | Invoke-RestMethod @HashArguments 39 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Backup-AllKeyVault.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://scriptinglibrary.com 2 | 3 | Function Backup-MyKeyVault { 4 | <# 5 | .SYNOPSIS 6 | Backup Azure Key Vault keys, certs and secrets 7 | 8 | .DESCRIPTION 9 | This funciton creates a ZIP archive containing all keys, secrets and certificates stored in your Azure Key Vault. 10 | 11 | .PARAMETER VaultName 12 | thi parameter is required to specify which Vault Name you want to backup 13 | 14 | .EXAMPLE 15 | Backup-MyKeyVault -KeyVault "mykeyvaultname1", "mykeyvaultname2" 16 | 17 | Specify one or more Azure Key Voults to backup 18 | 19 | .EXAMPLE 20 | get-azkeyvault | Backup-MyKeyVault 21 | Oneliner to enumerate all Azure Key Vault and create individual archive for each one. 22 | #> 23 | 24 | [CmdletBinding()] 25 | param ( 26 | [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName =$true)] 27 | [string[]] 28 | $VaultName 29 | ) 30 | process { 31 | foreach ($MyVaultName in $VaultName) { 32 | 33 | if (($(Get-AzKeyVaultKey $MyVaultName).count + $(Get-AzKeyVaultSecret $MyVaultName).count ) -gt 0) 34 | { 35 | #Creates temporary folders 36 | New-Item -ItemType Directory "$($MyVaultName)" | Out-Null 37 | Set-Location $MyVaultName 38 | New-Item -ItemType Directory -name "Certs" | Out-Null 39 | New-Item -ItemType Directory -name "Secrets" | Out-Null 40 | New-Item -ItemType Directory -name "Keys" | Out-Null 41 | 42 | #Stats counters 43 | $CertCounter=0 44 | $KeyCounter=0 45 | $SecretCounter=0 46 | 47 | Foreach ($item in $(Get-AzKeyVaultSecret -VaultName $MyVaultName)){ 48 | if ($item.ContentType -eq "application/x-pkcs12"){ 49 | $cert = Get-AzureKeyVaultCertificate -VaultName $MyVaultName -Name "$(($item).name)" 50 | Backup-AzureKeyVaultCertificate -Certificate $cert -OutputFile "Certs\\$(($item).name).blob" -Force | Out-Null 51 | $CertCounter+=1 52 | } 53 | else{ 54 | Backup-AzureKeyVaultSecret -VaultName $MyVaultName -Name $($item).name -OutputFile "Secrets\\$(($item).name).blob" | Out-Null 55 | $SecretCounter+=1 56 | } 57 | } 58 | Foreach ($keyitem in $(Get-AzKeyVaultKey -VaultName $MyVaultName)){ 59 | try{ 60 | Backup-AzKeyVaultKey -VaultName $MyVaultName -Name $($keyitem.name) -Output "Keys\\$($keyitem.name).blob" -ErrorAction SilentlyContinue |Out-Null 61 | $KeyCounter+=1 62 | } 63 | catch { 64 | Write-Error "$($keyitem.name) was not exported" 65 | } 66 | } 67 | Set-Location .. 68 | $datetime = Get-Date -format "yyyyMMdd-hhmmss" 69 | $Filename = "$($MyVaultName)-$($datetime).zip" 70 | 71 | Compress-Archive -Path "$($MyVaultName)/*" -DestinationPath "$Filename" 72 | Remove-Item -Recurse -Force $MyVaultName 73 | Write-output "EXPORTED from `"$MyVaultName`" to `"$Filename`": `n $KeyCounter keys `n $CertCounter certificates `n $SecretCounter secrets " 74 | } 75 | else{ 76 | Write-Output "NO ACTION for $($MyVaultName): `nThere are no Keys,Certificates or Secrets to backup!" 77 | } 78 | } 79 | } 80 | 81 | } 82 | 83 | #Backup all Azure Key Vaults 84 | get-azkeyvault | Backup-MyKeyVault 85 | -------------------------------------------------------------------------------- /Blog/PowerShell/Check-CVE-2019-18935.ps1: -------------------------------------------------------------------------------- 1 | # Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | # This scripts search IIS logs and Windows EventLog for 4 | # Indicators of compromise (IOC) described in CVE-2019-18935 5 | 6 | # https://nvd.nist.gov/vuln/detail/CVE-2019-18935 7 | # https://www.telerik.com/support/kb/aspnet-ajax/details/allows-javascriptserializer-deserialization 8 | 9 | 10 | $IISLogFolder = "D:\Logs\" 11 | 12 | Write-Output "ANALISING IIS LOGS [$IISLogFolder] FOR CVE-2019-18935 EXPLOITATION ATTEMPTS." 13 | 14 | $results = Get-ChildItem $IISLogFolder -Filter "*log" | 15 | ForEach-Object {get-content $_.FullName } | 16 | Select-String ".*POST \/Telerik\.Web\.UI\.WebResource\.axd.*500.*" -AllMatches 17 | 18 | Write-Output ">> $($results.count) results found matching the pattern." 19 | 20 | 21 | if ($results.count -gt 0){ 22 | $results | ForEach-Object {Write-Output $_} 23 | } 24 | 25 | #https://www.cyber.gov.au/acsc/view-all-content/advisories/advisory-2020-004-remote-code-execution-vulnerability-being-actively-exploited-vulnerable-versions-telerik-ui-sophisticated-actors 26 | Write-Output "ANALYSING WINDOWS EVENT LOG ENTRIES FOR MORE INDICATORS OF SUCCESSFUL EXPLOITATION" 27 | $EventLogEntries = Get-EventLog -LogName Application -InstanceId 1309 -ErrorAction Ignore #-ComputerName YourIISserver #In case this script does not run locally on the webserver 28 | 29 | if ($EventLogEntries){ 30 | $EventLogEntries | Write-Output $_ 31 | } 32 | else { 33 | Write-Output "No results found in the Windows EventLog." 34 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Check-Nic.ps1: -------------------------------------------------------------------------------- 1 | #Nagios/NSCP Network Interface Card Load Check 2 | #Author: Paolo Frigo, https://www.scriptinglibrary.com 3 | $NETWORK_CARD ="microsoft hyper-v network adapter*" 4 | 5 | $WARNING = 29 6 | $CRITICAL = 49 7 | 8 | $TransferRate = ((get-counter).countersamples | where-object {$_.instancename -like "$NETWORK_CARD"} | select-object -exp CookedValue )*8 9 | 10 | $NetworkUtilisation = [math]::round($TransferRate/1000000000*100,2) 11 | 12 | if ($NetworkUtilisation -gt $CRITICAL){ 13 | Write-Output "CRITICAL: $($NetworkUtilisation) % Network utilisation, $($TransferRate.ToString('N0')) b/s" 14 | exit 2 15 | } 16 | if ($NetworkUtilisation -gt $WARNING){ 17 | Write-Output "WARNING: $($NetworkUtilisation) % Network utilisation, $($TransferRate.ToString('N0')) b/s" 18 | exit 1 19 | } 20 | Write-Output "OK: $($NetworkUtilisation) % Network utilisation, $($TransferRate.ToString('N0')) b/s" 21 | exit 0 22 | 23 | -------------------------------------------------------------------------------- /Blog/PowerShell/Clean-SophosTempFile.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | # Removes temporary files from Sophos Temp folder 4 | 5 | $SophosTempDir = "C:\Windows\Temp\" #"C:\ProgramData\Sophos\Sophos Anti-Virus\Temp\" 6 | 7 | if (test-path $SophosTempDir){ 8 | $SophosTempFiles= Get-childitem "$($SophosTempDir)*`$`$`$" 9 | if ($SophosTempFiles){ 10 | try { 11 | $SophosTempFiles | Remove-Item -Force 12 | Write-OutPut "$($($SophosTempFiles).count) files removed from $SophosTempDir" 13 | } 14 | catch{ 15 | Write-Error "Clean-up operation failed." 16 | exit 1 17 | } 18 | } 19 | } 20 | else { 21 | Write-Error "The Sophos directory doesn't exist $SophosTempDir" 22 | } 23 | exit 0 -------------------------------------------------------------------------------- /Blog/PowerShell/Compare-AADUserSecurityGroupMembership.ps1: -------------------------------------------------------------------------------- 1 | 2 | # Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | # CONNECT TO AZURE CLOUD SHELL HTTPS://SHELL.AZURE.COM 5 | 6 | # CONENCT TO AZURE AD 7 | connect-azuread 8 | 9 | # CHECK THE DETAILS OF YOUR AAD TENANT 10 | # Get-AzureADTenantDetail -All $true 11 | 12 | # GET THE AAD SECURITY GROUPS OF YOUR USERS 13 | # Replace the 2 UserPrincipalName of your e.g. john.doe@contoso.com 14 | $USERS = "UPN_OF_USER_A", "UPN_OF_USER_B" 15 | 16 | foreach ($User in $Users){ 17 | Get-AzureADUser -ObjectId $user 18 | Get-AzureADUser -ObjectId $User | Get-AzureADUserMembership | Select-Object -ExpandProperty displayname 19 | } 20 | 21 | 22 | # OR USE THIS ONELINER TO COMPARE THE SECURITY GROUPS OF 2 AAD USERS 23 | Compare-object $(Get-AzureADUser -ObjectId "UPN_OF_USER_A" | Get-AzureADUserMembership | Select-Object -exp displayname) $(Get-AzureADUser -ObjectId "UPN_OF_USER_B"| Get-AzureADUserMembership | Select-Object -exp displayname) 24 | -------------------------------------------------------------------------------- /Blog/PowerShell/Compare-Folder.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://scriptinglibrary.com 2 | 3 | <# 4 | .SYNOPSIS 5 | Compare the contents of two folders based on file hashes. 6 | 7 | .DESCRIPTION 8 | This script calculates SHA256 hashes for all files in two specified folders 9 | (and their subdirectories) and compares them. It outputs any differences 10 | in file content or structure. 11 | 12 | .PARAMETER Folder1 13 | The absolute path to the first folder to compare. 14 | 15 | .PARAMETER Folder2 16 | The absolute path to the second folder to compare. 17 | 18 | .EXAMPLE 19 | Compare-Folders.ps1 -Folder1 "C:\Path\To\Folder1" -Folder2 "C:\Path\To\Folder2" 20 | 21 | This compares the contents of "Folder1" and "Folder2" and outputs any differences. 22 | 23 | .NOTES 24 | Author: Paolo Frigo 25 | #> 26 | 27 | param ( 28 | [Parameter(Mandatory)] 29 | [string]$Folder1, 30 | 31 | [Parameter(Mandatory)] 32 | [string]$Folder2 33 | ) 34 | 35 | 36 | function Get-RelativePath { 37 | param ( 38 | [string]$FullPath, 39 | [string]$BasePath 40 | ) 41 | return $FullPath.Substring($BasePath.Length).TrimStart('\') 42 | } 43 | 44 | 45 | $folder1Hashes = Get-ChildItem -Path $Folder1 -File -Recurse | 46 | ForEach-Object { 47 | [PSCustomObject]@{ 48 | RelativePath = $_.FullName.Substring((Resolve-Path $Folder1).Path.Length + 1) 49 | Hash = (Get-FileHash $_.FullName).Hash 50 | } 51 | } 52 | 53 | 54 | $folder2Hashes = Get-ChildItem -Path $Folder2 -File -Recurse | 55 | ForEach-Object { 56 | [PSCustomObject]@{ 57 | RelativePath = $_.FullName.Substring((Resolve-Path $Folder2).Path.Length + 1) 58 | Hash = (Get-FileHash $_.FullName).Hash 59 | } 60 | } 61 | 62 | 63 | $differences = Compare-Object -ReferenceObject $folder1Hashes -DifferenceObject $folder2Hashes -Property RelativePath, Hash -PassThru 64 | 65 | if ($differences) { 66 | Write-Host "Differences found:" 67 | $differences | Format-Table -Property RelativePath, Hash, SideIndicator 68 | Write-Host "`nExplanation of SideIndicator:" 69 | Write-Host "'<= ' means the file exists only in Folder1." 70 | Write-Host "'=> ' means the file exists only in Folder2." 71 | Write-Host "' ' means the file exists in both folders but has different content." 72 | } else { 73 | Write-Host "The folders are identical (both file content and structure)." 74 | } 75 | -------------------------------------------------------------------------------- /Blog/PowerShell/Compress-Folder.ps1: -------------------------------------------------------------------------------- 1 | function Compress-Folder { 2 | <# 3 | .SYNOPSIS 4 | Compress a folder and remove the directory if needed. 5 | 6 | .DESCRIPTION 7 | This function is a wrapper of Compress-Archive for PowerShell versions greater or equal to 5 or 8 | if not it leverages ZipFile class from .NET Framework to achieve the same result providing backward 9 | compatibility. If RemoveDirWhenFinished parameter is set to $True the target directory will be 10 | removed after compression. 11 | 12 | .PARAMETER FolderName 13 | FolderName parameter is required to specify which folder you want to compress 14 | 15 | .PARAMETER RemoveDirWhenFinished 16 | RemoveDirWhenFinished parameter is optional, if the compression task succeeded and the parameter 17 | is set to $True the "FolderName" target directory will be removed. 18 | 19 | .EXAMPLE 20 | Compress-Folder -FolderName "/Users/paolofrigo/Documents/tmp_folder_01" 21 | 22 | Creates an archive named "tmp_folder_01.zip" on the parent path. 23 | 24 | .EXAMPLE 25 | Compress-Folder -FolderName "D:\Logs\temp01" -RemoveDirWhenFinished $True 26 | 27 | Creates an archive named "temp01.zip" and it removes the folder when finished. 28 | 29 | .NOTES 30 | Author: Paolo Frigo https://www.scriptinglibrary.com 31 | 32 | #> 33 | [CmdletBinding()] # Add cmdlet features. 34 | Param ( 35 | [Parameter(Mandatory = $True)] 36 | [string]$FolderName, 37 | [Parameter(Mandatory = $False)] 38 | [bool]$RemoveDirWhenFinished 39 | ) 40 | Begin { 41 | $PSVersion = $PSVersionTable.PSVersion.Major 42 | $FolderNameFullPath = (Resolve-Path $FolderName).Path 43 | $DestinationFullPath = "$FolderNameFullPath.zip" 44 | $Destination = "$Foldername.zip" 45 | } 46 | Process { 47 | if (Test-Path -path $FolderNameFullPath) { 48 | If (Test-path $DestinationFullPath) { 49 | Remove-Item $DestinationFullPath #-confirm 50 | } 51 | try { 52 | if (($PSVersion -ge 5) -and (Get-ChildItem -path $FolderNameFullPath).count -gt 0) { 53 | Compress-Archive -Path $FolderNameFullPath -DestinationPath $DestinationFullPath -Force -CompressionLevel Optimal 54 | } 55 | else { 56 | Add-Type -assembly "system.io.compression.filesystem" 57 | [io.compression.zipfile]::CreateFromDirectory($FolderNameFullPath, $DestinationFullPath) 58 | } 59 | Write-Verbose "Archive Created: $Destination" 60 | if ((test-path -path $DestinationFullPath) -and $RemoveDirWhenFinished -eq $True) { 61 | Remove-Item -Recurse -path $FolderNameFullPath 62 | Write-Verbose "$FolderName removed." 63 | } 64 | } 65 | catch { 66 | Write-Error "Compression failed for $FolderName" 67 | } 68 | } 69 | else { 70 | Write-Error "Path not valid $FolderNameFullPath" 71 | } 72 | } 73 | End { 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Blog/PowerShell/Configure-IPGeoFencingIIS.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Add bulk IP filtering to IIS Website 4 | 5 | Based on Aaron Guilmette solution: 6 | https://www.undocumented-features.com/2018/02/08/implementing-geo-filtering-with-iis/ 7 | 8 | PLEASE NOTE: 9 | I recommend using the -OnlyExportIPSecurityXML otherwise for thousands of subnets this process 10 | can take several hours. 11 | In IIS you’ll also need to update or verify the allow/deny policy of the site (IIS | Sites | | IP Address and Domain Restrictions | Edit Feature Settings and review the value for “Access for unspecified clients”) to DENY 12 | 13 | #> 14 | 15 | param ( 16 | $Logfile = (Get-Date -Format yyyy-mm-dd-hh-mm) + "_" + $($MyInvocation.MyCommand) + "_.txt", 17 | [switch]$OnlyExportIPSecurityXML, 18 | $Output = "IPSecurityXML.txt", 19 | $Site = "Default Web Site", 20 | $Source) 21 | 22 | #### Begin Function declaration 23 | 24 | function Write-Log([string[]]$Message, [string]$LogFile = $Script:LogFile, [switch]$ConsoleOutput, [ValidateSet("SUCCESS", "INFO", "WARN", "ERROR", "DEBUG")][string]$LogLevel) 25 | { 26 | $Message = $Message + $Input 27 | If (!$LogLevel) { $LogLevel = "INFO" } 28 | switch ($LogLevel) 29 | { 30 | SUCCESS { $Color = "Green" } 31 | INFO { $Color = "White" } 32 | WARN { $Color = "Yellow" } 33 | ERROR { $Color = "Red" } 34 | DEBUG { $Color = "Gray" } 35 | } 36 | if ($null -ne $Message -and $Message.Length -gt 0) 37 | { 38 | $TimeStamp = [System.DateTime]::Now.ToString("yyyy-MM-dd HH:mm:ss") 39 | if ($null -ne $LogFile -and $LogFile -ne [System.String]::Empty) 40 | { 41 | Out-File -Append -FilePath $LogFile -InputObject "[$TimeStamp] $Message" 42 | } 43 | if ($ConsoleOutput -eq $true) 44 | { 45 | Write-Host "[$TimeStamp] [$LogLevel] :: $Message" -ForegroundColor $Color 46 | } 47 | } 48 | } 49 | 50 | Function cidr 51 | { 52 | [CmdLetBinding()] 53 | Param ( 54 | [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] 55 | [Alias("Length")] 56 | [ValidateRange(0, 32)] 57 | $MaskLength 58 | ) 59 | Process 60 | { 61 | Return LongToDotted ([Convert]::ToUInt32($(("1" * $MaskLength).PadRight(32, "0")), 2)) 62 | } 63 | } 64 | 65 | Function LongToDotted 66 | { 67 | [CmdLetBinding()] 68 | Param ( 69 | [Parameter(Mandatory = $True, Position = 0, ValueFromPipeline = $True)] 70 | [String]$IPAddress 71 | ) 72 | Process 73 | { 74 | Switch -RegEx ($IPAddress) 75 | { 76 | "([01]{8}\.){3}[01]{8}" { 77 | Return [String]::Join('.', $($IPAddress.Split('.') | ForEach-Object { [Convert]::ToUInt32($_, 2) })) 78 | } 79 | "\d" { 80 | $IPAddress = [UInt32]$IPAddress 81 | $DottedIP = $(For ($i = 3; $i -gt -1; $i--) 82 | { 83 | $Remainder = $IPAddress % [Math]::Pow(256, $i) 84 | ($IPAddress - $Remainder) / [Math]::Pow(256, $i) 85 | $IPAddress = $Remainder 86 | }) 87 | Return [String]::Join('.', $DottedIP) 88 | } 89 | default 90 | { 91 | 92 | } 93 | } 94 | } 95 | } 96 | 97 | ### End Function Declaration 98 | 99 | # New-Alias appcmd.exe -Value $env:windir\System32\inetsrv\appcmd.exe 100 | 101 | # Check if Elevated 102 | $wid = [system.security.principal.windowsidentity]::GetCurrent() 103 | $prp = New-Object System.Security.Principal.WindowsPrincipal($wid) 104 | $adm = [System.Security.Principal.WindowsBuiltInRole]::Administrator 105 | if ($prp.IsInRole($adm)) 106 | { 107 | Write-Log -LogFile $Logfile -LogLevel SUCCESS -ConsoleOutput -Message "Elevated PowerShell session detected. Continuing." 108 | } 109 | else 110 | { 111 | Write-Log -LogFile $Logfile -LogLevel ERROR -ConsoleOutput -Message "This application/script must be run in an elevated PowerShell window. Please launch an elevated session and try again." 112 | Break 113 | } 114 | 115 | $IPs = Get-Content $Source 116 | $count = $IPs.Count 117 | $i = 1 118 | 119 | # OnlyExportXML 120 | If ($OnlyExportIPSecurityXML) 121 | { 122 | foreach ($IP in $IPs) 123 | { 124 | If ($IP -match "/") 125 | { 126 | $CIDR = $IP.Split("/")[1] 127 | $IPAddr = $IP.Split("/")[0] 128 | $Mask = cidr $cidr 129 | $Content = "" 130 | $Content | Out-File -Append $Output 131 | Write-Log -LogFile $Logfile -LogLevel INFO -Message "Network $IP processed." 132 | } 133 | Else 134 | { 135 | $Content = "" 136 | $Content | Out-File -Append $Output 137 | Write-Log -LogFile $Logfile -LogLevel INFO -Message "Address $IP processed." 138 | } 139 | } 140 | Write-Log -LogFile $Logfile -LogLevel SUCCESS -ConsoleOutput -Message "This XML output can be inserted under the node in the `$Windir\System32\Inetsrv\Config\applicationHost.config file for the appropriate web site." 141 | Write-Log -LogFile $Logfile -LogLevel SUCCESS -ConsoleOutput -Message "Path:" 142 | Write-Log -LogFile $Logfile -LogLevel SUCCESS -ConsoleOutput -Message "location path=Web Site Name/system.WebServer/Security/ipSecurity" 143 | Write-Log -LogFile $Logfile -LogLevel SUCCESS -ConsoleOutput -Message "" 144 | Write-Log -LogFile $Logfile -LogLevel SUCCESS -ConsoleOutput -Message "After inserting XML output into applicationHost.config file, restart IIS." 145 | } 146 | 147 | # Add Source IPs 148 | If (!$OnlyExportIPSecurityXML) 149 | { 150 | # Allow localhost 151 | add-webconfiguration /system.webServer/security/ipSecurity -location $Site -value @{ ipAddress = "localhost"; allowed = "true" } -pspath IIS:\ 152 | 153 | foreach ($IP in $IPs) 154 | { 155 | Write-Host "Processing [$i / $count] :: $IP" 156 | try 157 | { 158 | If ($IP -match "/") 159 | { 160 | $CIDR = $IP.Split("/")[1] 161 | $IPAddr = $IP.Split("/")[0] 162 | $Mask = cidr $cidr 163 | #appcmd.exe set config "$Site" -section:system.webServer/security/ipSecurity /+"[ipAddress='$($IPAddr)',subnetmask='$($Mask)',allowed='True']" /commit:apphost 164 | 165 | add-webconfiguration /system.webServer/security/ipSecurity -location $Site -value @{ ipAddress = $IPAddr; subnetMask = $Mask; allowed = "true" } -pspath IIS:\ -ErrorAction stop 166 | Write-Log -LogFile $Logfile -LogLevel INFO -Message "Network $IP processed." 167 | } 168 | Else 169 | { 170 | #appcmd.exe set config $Site -section:system.webServer/security/ipSecurity /+"[ipAddress='$($IP)',allowed='True']" /commit:apphost 171 | 172 | add-webconfiguration /system.webServer/security/ipSecurity -location $Site -value @{ ipAddress = $IP; allowed = "true" } -pspath IIS:\ -erroraction stop 173 | Write-Log -LogFile $Logfile -LogLevel INFO -Message "Address $IP processed." 174 | } 175 | } 176 | catch 177 | { 178 | $Exception = $_.Exception 179 | $ErrorMessage = $_.Exception.Message 180 | Write-Log -Message "Error processing $IP" -LogFile $Logfile -LogLevel ERROR -ConsoleOutput 181 | Write-Log -Message $ErrorMessage -LogFile $Logfile -LogLevel ERROR 182 | } 183 | finally 184 | { 185 | $i++ 186 | } 187 | } 188 | 189 | Try 190 | { 191 | Set-WebConfigurationProperty -Filter /system.webserver.ipsecurity -name allowUnlisted -value $false -Location $Site 192 | Write-Log -LogFile $Logfile -Message "Updated web configuration property to deny unlisted IP addresses to site $($Site)." 193 | } 194 | Catch 195 | { 196 | $ErrorMessage = $_.Exception.Message 197 | $FailedItem = $_.Exception.ItemName 198 | Write-Log -Message $ErrorMessage -LogFile $Logfile -LogLevel ERROR -ConsoleOutput 199 | Write-Log -Message $FailedItem -LogFile $Logfile -LogLevel ERROR -ConsoleOutput 200 | } 201 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Create-NewLocalAdmin.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | #requires -runasadministrator 3 | 4 | function Create-NewLocalAdmin { 5 | [CmdletBinding()] 6 | param ( 7 | [string] $NewLocalAdmin, 8 | [securestring] $Password 9 | ) 10 | begin { 11 | } 12 | process { 13 | New-LocalUser "$NewLocalAdmin" -Password $Password -FullName "$NewLocalAdmin" -Description "Temporary local admin" 14 | Write-Verbose "$NewLocalAdmin local user crated" 15 | Add-LocalGroupMember -Group "Administrators" -Member "$NewLocalAdmin" 16 | Write-Verbose "$NewLocalAdmin added to the local administrator group" 17 | } 18 | end { 19 | } 20 | } 21 | $NewLocalAdmin = Read-Host "New local admin username:" 22 | $Password = Read-Host -AsSecureString "Create a password for $NewLocalAdmin" 23 | Create-NewLocalAdmin -NewLocalAdmin $NewLocalAdmin -Password $Password -Verbose 24 | -------------------------------------------------------------------------------- /Blog/PowerShell/Decode-Base64ToFile.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | #This helper function will dencode a base64 string into a file 4 | function Decode-Base64ToFile{ 5 | [CmdletBinding()] 6 | param ( 7 | [Parameter(Mandatory=$True)] 8 | [string] 9 | $outputfile, 10 | [Parameter(Mandatory=$True)] 11 | [string] 12 | $base64string 13 | ) 14 | [System.IO.File]::WriteAllText($outputfile, [System.Text.Encoding]::Utf8.GetString([System.Convert]::FromBase64String($base64string))) 15 | Write-Output "$($outputfile) created" 16 | } 17 | 18 | #[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes([System.IO.File]::ReadAllText("hello.txt"))) 19 | 20 | #Hello, World! 21 | $base64 = "SGVsbG8sIFdvbHJkIQ0K" 22 | $outputfile = "hello.txt" 23 | 24 | Decode-Base64ToFile -outputfile $outputfile -base64string $base64 25 | -------------------------------------------------------------------------------- /Blog/PowerShell/Decode-SecureStringPassword.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .Synopsis 3 | Tries to decode a SecureString and returns its clear text value 4 | .DESCRIPTION 5 | Tries to decode a SecureString from a PSCredential Object and returns its clear text value 6 | .EXAMPLE 7 | get-credential | Decode-SecureStringPassword 8 | .EXAMPLE 9 | get-credential | dssp 10 | .EXAMPLE 11 | Decode-SecureStringPassword -password SecureString 12 | 13 | .Notes 14 | Author: Paolo Frigo https://www.scriptinglibrary.com 15 | 16 | #> 17 | function Decode-SecureStringPassword { 18 | [CmdletBinding()] 19 | [Alias('dssp')] 20 | [OutputType([string])] 21 | Param 22 | ( 23 | [Parameter(Mandatory = $true, 24 | ValueFromPipelineByPropertyName = $true, 25 | Position = 0) ] 26 | [SecureString] $password 27 | ) 28 | Begin { 29 | } 30 | Process { 31 | return [System.Runtime.InteropServices.Marshal]::PtrToStringUni([System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($password)) 32 | } 33 | End { 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Blog/PowerShell/Deployment/Deployment.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | . .\lib\New-SubFolderWithDate.ps1 3 | 4 | $ConfigFile = "config\DeploymentConfig.json" 5 | 6 | if ($(Test-Path $ConfigFile) -eq $false){ 7 | throw "Missing config file: $($ConfigFile)" 8 | } 9 | 10 | $config = Get-Content $ConfigFile | ConvertFrom-Json 11 | 12 | Write-Output "[$($config.environment.type)] $($config.project.name) - Version: $($config.info.version)" 13 | 14 | if ($config.environment.type -eq "TEST"){ 15 | New-SubFolderWithDate -prefix $config.environment.type -verbose 16 | } 17 | 18 | foreach ($artefact in $config.artefacts){ 19 | try{ 20 | Invoke-WebRequest -uri $artefact.uri -UseBasicParsing -out "lib\$($artefact.filename)" -TimeoutSec 30 21 | Write-Output "Artefact Downloaded : $($artefact.description)" 22 | } 23 | catch { 24 | throw "Artifact Download Error" 25 | } 26 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Deployment/ReadMe.md: -------------------------------------------------------------------------------- 1 | # Deployment Example 2 | The aim of this deployment project is summarize in a single example some tips and suggestions published on https://www.scriptinglibrary.com 3 | 4 | This deployment script shows some of the benefits of _decoupling settings from the script itself_, in fact all the settings are stored in a single JSON file in the config folder. 5 | 6 | Scripts can be _signed_ and _executed with even the most restrictive execution policies_, if we need to re-use script in different environments (PROD, TEST) or add/remove artefacts we can modify the JSON File without altering a single line of the script. 7 | 8 | _Splitting_ the deployment file and importing all other sections with _dot-sourcing_ makes the script easier to read and to maintain. 9 | 10 | Using _Pester_ and writing some _Unit and Integration tests_ for TEST environment task of creating a subfolder offers the opportunity of checking the _code coverage of 100%_ of our source code. 11 | ~~~~ 12 | PS D:\Paolo\Git\Blog\PowerShell\Deployment\lib> Invoke-Pester .\New-SubFolderWithDate.Test.ps1 -CodeCoverage .\New-SubFo 13 | lderWithDate.ps1 14 | 15 | 16 | Describing New-SubFolderWithDate Unit-Tests 17 | [+] Should throw an error when the folder already exists 1.95s 18 | [+] Should throw an error when fails to create a folder 485ms 19 | Describing New-SubFolderWithDate Integration-Tests 20 | [+] Should create the folder 331ms 21 | Tests completed in 2.77s 22 | Passed: 3 Failed: 0 Skipped: 0 Pending: 0 Inconclusive: 0 23 | 24 | Code coverage report: 25 | Covered 100,00% of 7 analyzed commands in 1 file. 26 | ~~~~ 27 | In brief, this deployment script should prompt the Environment, Project and version that will be deployed and the status of the artifact download in this case from a git repository (without using posh-git). 28 | 29 | Output : 30 | ~~~~ 31 | PS D:\Paolo\Git\Blog\PowerShell\Deployment> .\Deployment.ps1 32 | [PROD] MyPlayground - Version: 1.0.0 33 | Artefact Downloaded : Proxy Functions, Latest Release 34 | Artefact Downloaded : Set-HighPerformance, Latest Release 35 | ~~~~ -------------------------------------------------------------------------------- /Blog/PowerShell/Deployment/config/DeploymentConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "Version": "1.0.0", 4 | "Date" : "04/04/2018" 5 | }, 6 | "project": { 7 | "name": "MyPlayground" 8 | }, 9 | "environment": { 10 | "type": "PROD" 11 | }, 12 | "artefacts":[ 13 | { 14 | "uri" :"https://raw.githubusercontent.com/PaoloFrigo/scriptinglibrary/master/Blog/PowerShell/Proxy-Functions.ps1", 15 | "filename": "Proxy-Functions.ps1", 16 | "description": "Proxy Functions, Latest Release" 17 | }, 18 | { 19 | "uri": "https://raw.githubusercontent.com/PaoloFrigo/scriptinglibrary/master/Blog/PowerShell/Set-HighPerformance.ps1", 20 | "filename": "Set-HighPerformance.ps1", 21 | "description": "Set-HighPerformance, Latest Release" 22 | } 23 | 24 | ] 25 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Deployment/lib/New-SubFolderWithDate.Test.ps1: -------------------------------------------------------------------------------- 1 | . .\New-SubfolderWithDate 2 | 3 | Describe "New-SubFolderWithDate Unit-Tests" -tags "unit-tests" { 4 | 5 | it "Should throw an error when the folder already exists" { 6 | Mock "Test-Path" { 7 | return $true 8 | } 9 | Mock "New-Item" {} 10 | {New-SubfolderWithDate -prefix "A"} | Should throw "Folder already exists" 11 | } 12 | it "Should throw an error when fails to create a folder" { 13 | Mock "Test-Path" { 14 | return $false 15 | } 16 | Mock "New-Item" {throw "any error"} 17 | {New-SubfolderWithDate -prefix "A"} | Should throw "Folder not created" 18 | } 19 | } 20 | Describe "New-SubFolderWithDate Integration-Tests" -tags "integration-tests" { 21 | it "Should create the folder" { 22 | $prefix = "ABCDEF123" 23 | $FolderName = "$prefix-$(Get-Date -Format "yyyyMMdd")" 24 | if ($(Test-Path $FolderName) -eq $false){ 25 | New-SubfolderWithDate -prefix $prefix 26 | Test-Path $FolderName 27 | Remove-Item $FolderName 28 | } 29 | else{ 30 | Write-Output "Example folder already exists change prefix ABCDEF123" 31 | } 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Deployment/lib/New-SubFolderWithDate.ps1: -------------------------------------------------------------------------------- 1 | function New-SubFolderWithDate { 2 | [cmdletbinding(SupportsShouldProcess = $true)] 3 | param( 4 | [parameter(Position = 1, 5 | Mandatory = $true, 6 | ValueFromPipeline = $true)] 7 | [string]$Prefix 8 | ) 9 | $FolderName = "$Prefix-$(Get-Date -Format "yyyyMMdd")" 10 | if (Test-Path $FolderName){ 11 | throw "Folder already exists" 12 | } 13 | try { 14 | New-Item -ItemType Directory -Name $FolderName 15 | Write-Verbose "Folder Created Successfully: $FolderName" 16 | } 17 | catch { 18 | throw "Folder not created" 19 | } 20 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Disable-CrmTracing.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | #https://support.microsoft.com/en-au/help/907490/how-to-enable-tracing-in-microsoft-dynamics-crm 3 | 4 | Add-PSSnapin Microsoft.Crm.PowerShell 5 | 6 | $setting = Get-CrmSetting TraceSettings 7 | $setting.Enabled = $False 8 | 9 | Set-CrmSetting $setting 10 | Get-CrmSetting TraceSettings 11 | 12 | Write-OutPut "The Crm Tracing is now DISABLED" 13 | pause -------------------------------------------------------------------------------- /Blog/PowerShell/Disable-WindowsFirewall.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | # Paolo Frigo, https://www.scriptinglibrary.com 3 | # 4 | # This script will disable the windows firewall for all profiles PUBLIC, DOMAIN, PRIVATE 5 | # 6 | Set-NetFirewallProfile -profile Public,domain,private -enabled false 7 | # To check the FIREWALL PROFILE STATUS use 8 | # Get-NetFirewallProfile | select-object name, enabled -------------------------------------------------------------------------------- /Blog/PowerShell/Enable-CrmTracing.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | #https://support.microsoft.com/en-au/help/907490/how-to-enable-tracing-in-microsoft-dynamics-crm 3 | 4 | Add-PSSnapin Microsoft.Crm.PowerShell 5 | 6 | $setting = Get-CrmSetting TraceSettings 7 | $setting.Enabled = $True 8 | $setting.Directory = "D:\crmtrace\logs\" 9 | 10 | Set-CrmSetting $setting 11 | Get-CrmSetting TraceSettings 12 | 13 | Write-Output "The Crm Tracing is now ENABLED and the tracing logs will be available on this directory $($setting.Directory)" 14 | pause -------------------------------------------------------------------------------- /Blog/PowerShell/Enable-Rdp.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | <# 4 | $Target = "Workstation1" # 5 | # Open a remote powershell session 6 | Enter-PSSession -Credential $(get-credential -Message "Auth") -ComputerName $Target 7 | # Enable Remote Desktop 8 | (Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices).SetAllowTsConnections(1,1) | Out-Null 9 | (Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0) | Out-Null 10 | Get-NetFirewallRule -DisplayName "Remote Desktop*" | Set-NetFirewallRule -enabled true 11 | Exit-PSSession 12 | #> 13 | 14 | <# 15 | .SYNOPSIS 16 | Enable RDP connections on the remote PC 17 | 18 | .DESCRIPTION 19 | Enable RD Connection Services and Firewall Rules that will permit RDP connections to a remote PC. 20 | 21 | .PARAMETER ComputerName 22 | Specify your target computer using a FQDN or IP 23 | 24 | .EXAMPLE 25 | C:\PS>Enable-RemoteDesktopOnTarget -computername "172.16.0.5" -verbose 26 | VERBOSE: There are 2 IPs Available on network 172.16.0.* 27 | 172.16.0.9 28 | 172.16.0.10 29 | 30 | .NOTES 31 | Author: Paolo Frigo, https://www.scriptinglibrary.com 32 | #> 33 | function Enable-RemoteDesktopOnTarget{ 34 | [CmdletBinding()] 35 | Param( 36 | # Parameter help description 37 | [Parameter(Mandatory=$true, ValueFromPipeline=$true)] 38 | [string] 39 | $ComputerName 40 | ) 41 | Begin{ 42 | } 43 | Process{ 44 | Invoke-Command -ComputerName $ComputerName -ScriptBlock { 45 | # Enable Remote Desktop 46 | (Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices).SetAllowTsConnections(1,1) | Out-Null 47 | (Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0) | Out-Null 48 | Write-Verbose -Message "$(get-date -Format [dd/MM/yyyy_hh:mm]) - Remote Desktop Services enabled on $ComputerName" 49 | Get-NetFirewallRule -DisplayName "Remote Desktop*" | Set-NetFirewallRule -enabled true 50 | Write-Verbose -Message "$(get-date -Format [dd/MM/yyyy_hh:mm]) - Firewall Rule enabled for RDP Connections on $ComputerName" 51 | } 52 | } 53 | End{ 54 | } 55 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Enable-RemoteConnection.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | # This script enables remote desktop connection on the target host, add a firewall rule to the winodws host based firewall and 4 | # tests if the standard RDP port is open. 5 | 6 | # If you want to provide local admin credentials 7 | # $cred = Get-Credential 8 | 9 | Param ( 10 | [Parameter( Mandatory=$true, 11 | ValueFromPipeline = $true, 12 | ValueFromPipelineByPropertyName = $true)] 13 | $ComputerName 14 | ) 15 | 16 | 17 | #Tests if the target host is reachable 18 | if (test-connection -computername $ComputerName -quiet -count 1){ 19 | } 20 | else { 21 | Throw "$computername is not reachable" 22 | } 23 | 24 | #Tests PSRemoting is enabled on the target host 25 | if (test-wsman -computername $ComputerName){ 26 | #Enables The remote desktop connections 27 | invoke-command -computername $ComputerName -scriptblock {Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server'-name "fDenyTSConnections" -Value 0} #-credential $cred 28 | #Adds a firewall rule 29 | invoke-command -computername $ComputerName -scriptblock {Enable-NetFirewallRule -DisplayGroup "Remote Desktop"} #-credential $cred 30 | if ((test-netconnection -computername $ComputerName -port 3389).TcpTestSucceeded -eq $True){ 31 | Write-Output "Remote connection ENABLED, Firewall rule ADDED and RDP port OPEN on $ComputerName" 32 | } 33 | else{ 34 | Write-Warning "The RDP port on $ComputerName is BLOCKED" 35 | } 36 | } 37 | else { 38 | Throw "$ComputerName hasn't got PS Remoting Enabled" 39 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Encode-FileToBase64.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | #This helper function will encode a file into a Base64 string 4 | function Encode-FileToBase64{ 5 | [CmdletBinding()] 6 | param ( 7 | [Parameter(Mandatory=$True)] 8 | [string] 9 | $filename 10 | ) 11 | if (Test-Path "$filename"){ 12 | $content = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes([System.IO.File]::ReadAllText("$fileName"))) 13 | return $filename, $content 14 | } 15 | throw "File not found $fileName" 16 | } 17 | 18 | #Example 19 | get-childitem | export-csv example.csv 20 | Encode-FileToBase64 example.csv 21 | 22 | -------------------------------------------------------------------------------- /Blog/PowerShell/Export-Drivers.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | 3 | # Paolo Frigo, https://scriptinglibrary.com 4 | 5 | # More details on: 6 | # https://docs.microsoft.com/en-us/powershell/module/dism/export-windowsdriver?view=windowsserver2019-ps#examples 7 | 8 | $DestinationFolder="D:\Drivers\" 9 | 10 | if (Test-Path -Path $DestinationFolder){ 11 | Export-WindowsDriver -Online -Destination $DestinationFolder 12 | } 13 | else { 14 | Write-Error "Invalid Path: $DestinationFolder" 15 | } 16 | 17 | -------------------------------------------------------------------------------- /Blog/PowerShell/Find-AvailableIP.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Get available IPs on the network 4 | 5 | .DESCRIPTION 6 | Get a list of all IPs on the network which don't respond to ICPM protocol. 7 | 8 | .PARAMETER Network 9 | Specify your network using a '*' symbol, for example 10.0.0.* 10 | 11 | .EXAMPLE 12 | C:\PS>Find-AvailableIP -Network"172.16.0.*" -verbose 13 | VERBOSE: There are 2 IPs Available on network 172.16.0.* 14 | 172.16.0.9 15 | 172.16.0.10 16 | 17 | .EXAMPLE 18 | C:\PS> "172.16.0.*" | Find-AvailableIP 19 | 172.16.0.9 20 | 172.16.0.10 21 | 22 | .EXAMPLE 23 | C:\PS> "10.0.0.*", "10.0.1.*" | Find-AvailableIP -Verbose 24 | VERBOSE: There are 2 IPs Available on network 10.0.0.* 25 | 10.0.0.2 26 | 10.0.0.5 27 | VERBOSE: There are 3 IPs Available on network 10.0.1.* 28 | 10.10.1.2 29 | 10.10.1.3 30 | 10.10.1.5 31 | .NOTES 32 | Author: Paolo Frigo, https://www.scriptinglibrary.com 33 | #> 34 | 35 | function Find-AvailableIP { 36 | [CmdletBinding()] 37 | [OutputType([string])] 38 | 39 | param( 40 | #check if the IP Address belong to a private class A,B or C 41 | [parameter(ValueFromPipeline, Mandatory = $true)] 42 | [ValidateScript( {$_ -match "^(10\.|172\.16\.|192\.168\.|)[0-9.]*(\*$)"})] 43 | [string] 44 | $Network 45 | ) 46 | 47 | Begin { 48 | } 49 | Process { 50 | $counter = 0 51 | $Results = @() 52 | $IPs = 1 .. 254 53 | foreach ($IP in $IPs) { 54 | $counter += 1 55 | $IpAddress = $Network.Replace("*", $IP) 56 | Write-Progress -activity "Testing subnet $Network" -status "$IpAddress" -PercentComplete (($counter / ($IPs.Length)) * 100) 57 | if ( (Test-Connection -computername "$IpAddress" -quiet -count 1 ) -eq $False) { 58 | $Results += $IpAddress 59 | } 60 | } 61 | Write-Verbose "There are $($Results.Length) IPs available on network $Network" 62 | Write-OutPut $Results 63 | } 64 | End { 65 | } 66 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Find-CriticalEventLog.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | #requires -runasadministrator 3 | 4 | # This script will iterate through the list af all computers and search for a specific error in the Event Log 5 | 6 | $ComputerList = "PC1", "PC2", "PC3" # OR get-adcomputer -searchbase YOUR_WORKSTATION_OU -filter * | select-object -exp name 7 | $ResultLimit = 5 8 | $LogName = "System" 9 | $ErrorId = 41 # Kernel-Power error (ID 41) - The system has rebooted without cleanly shutting down first. 10 | $ErrorDesc = "Critical Reboot" 11 | 12 | $ComputerList | ForEach-Object { if (Test-Connection $_ -quiet -count 1){write-host "$ErrorDesc for $_ "; Get-EventLog -ComputerName $_ -LogName $LogName -InstanceId $ErrorId -newest $ResultLimit}} 13 | 14 | -------------------------------------------------------------------------------- /Blog/PowerShell/Find-StaleComputerObject.ps1: -------------------------------------------------------------------------------- 1 | #requires -module ActiveDirectory 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | # This scripts creates a repot of all the Computer Objects in AD, 6 | # without limiting the result to a specific OU, that are not logged-in 7 | # since N days ago. 8 | 9 | $NumberOfDays = 200 10 | $ReportName = "StaleObjReport.csv" 11 | 12 | #Saves the report on the same dir of this script 13 | $ReportNamePath = "$PSScriptRoot\\$ReportName" 14 | $InactivityPeriod = (Get-Date).Adddays(-($NumberOfDays)) 15 | 16 | $StaleObjectSearch = @{ 17 | Filter = {LastLogonTimeStamp -lt $InactivityPeriod} 18 | Properties = "Name", "OperatingSystem", "SamAccountName", "DistinguishedName" 19 | } 20 | 21 | Get-ADComputer @StaleObjectSearch | Export-Csv -NoTypeInformation -Path $ReportNamePath -------------------------------------------------------------------------------- /Blog/PowerShell/Foreach-SerialAndParallel.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Version 7 2 | 3 | # THIS SCRIPT COMPARES SERIAL AND PARALLEL EXECUTION OF A FOREACH LOOP 4 | # Paolo Frigo, https://www.scriptinglibrary.com 5 | 6 | Write-Output "Serial Execution of 10 tasks of 1 seconds" 7 | Measure-Command -expression {1..10 | foreach-object {Start-Sleep -seconds 1}} 8 | 9 | Write-Output "Parallel Execution of 10 tasks of 1 seconds " 10 | Measure-Command -expression {1..10 | foreach-object -parallel {Start-Sleep -seconds 1}} 11 | 12 | #Setting Throttlelimit to 10 instead 5 (default value) 13 | #Interesting blog article from Paul Higinbotham : https://devblogs.microsoft.com/powershell/powershell-foreach-object-parallel-feature/ 14 | Write-Output "Parallel Execution (throttlelimit = 10 ) of 10 tasks of 1 seconds" 15 | Measure-Command -expression {1..10 | foreach-object -parallel {Start-Sleep -seconds 1} -throttlelimit 10} 16 | -------------------------------------------------------------------------------- /Blog/PowerShell/Get-ADReplicationReport.ps1: -------------------------------------------------------------------------------- 1 | #requires -module ActiveDirectory 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | # Generates a Report for the AD replication status and AD DC Diagnosis 6 | 7 | $DATE = get-date -Format "yyyy-MM-dd" 8 | $REPORT_PATH = "ADSyncReport-$DATE.txt" 9 | 10 | <# 11 | 12 | Write-Output "Summarize the replication status and view overall health" 13 | repadmin /replsummary > $REPORT_PATH 14 | 15 | Write-Output "Show replication partner and status" 16 | repadmin /showrepl >> $REPORT_PATH 17 | 18 | Write-Output "Show only Replication Errors" 19 | repadmin /showrepl /errorsonly >> $REPORT_PATH 20 | 21 | Write-Output "Show replication Queue" 22 | Repadmin /Queue >> $REPORT_PATH 23 | 24 | Write-Output "How to Force Active Directory Replication" 25 | repadmin /syncall >> $REPORT_PATH 26 | repadmin /syncall /aed >> $REPORT_PATH 27 | 28 | Write-Output "Find the last time your DC were backup" 29 | Repadmin /showbackup * >> $REPORT_PATH 30 | 31 | Write-Output "Displays calls that have not yet been answered" 32 | repadmin /showoutcalls * >> $REPORT_PATH 33 | 34 | Write-Output "List the Topology information" 35 | repadmin /bridgeheads * /verbose >> $REPORT_PATH 36 | 37 | Write-Output "Inter Site Topology Generator Report" 38 | repadmin /istg * /verbose >> $REPORT_PATH 39 | #> 40 | 41 | <# 42 | 43 | REPADMIN /KCC > $REPORT_PATH 44 | REPADMIN /REHOST >> $REPORT_PATH 45 | REPADMIN /REPLICATE >> $REPORT_PATH 46 | #> 47 | 48 | REPADMIN /REPLSUM >> $REPORT_PATH 49 | REPADMIN /SHOWREPL >> $REPORT_PATH 50 | REPADMIN /SHOWREPS >> $REPORT_PATH 51 | REPADMIN /SHOWUTDVEC >> $REPORT_PATH 52 | REPADMIN /SYNCALL >> $REPORT_PATH 53 | 54 | foreach ($DC in (Get-ADDomain).ReplicaDirectoryServers){ 55 | dcdiag /s:$DC /v >> $REPORT_PATH 56 | } 57 | 58 | Write-Output "Report generated: $REPORT_PATH" 59 | 60 | <# 61 | Write-Output "Sending the generated report via email to the ops team." 62 | Send-MailMessage -From "SENDER" ` 63 | -to "RECIPIENT" ` 64 | -Attachments $REPORT_PATH ` 65 | -Subject "AD replication and ADDC Diagnosis report" ` 66 | -Body "Please review the report attached" ` 67 | -smtp "MAILSERVER" 68 | #> -------------------------------------------------------------------------------- /Blog/PowerShell/Get-ADUsersReport.ps1: -------------------------------------------------------------------------------- 1 | #requires -module ActiveDirectory 2 | 3 | # This scripts generates a generic report on user access and status in a csv format 4 | 5 | #Paolo Frigo, https://www.scriptinglibrary.com 6 | 7 | #SETTINGS 8 | $Domain = "YOUR_DOMAIN" 9 | $BaseOU = "OU" 10 | $CSVReport = "UsersReport.csv" 11 | 12 | #https://docs.microsoft.com/en-us/archive/blogs/askds/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works 13 | $PrimaryDC = Get-ADDomainController -Discover -Domain $domain -Service "PrimaryDC" 14 | $MaxPswAge = (Get-ADDefaultDomainPasswordPolicy).MaxPAsswordAge.Days 15 | 16 | Get-aduser -filter * -SearchBase $BaseOU -properties * -server $PrimaryDC | Select-Object name, samaccountname, emailaddress,enabled,created, passwordLastSet, @{Name="Password Expires"; Expression={($.passwordLastSet).addDays($MaxPswAge)}}, passwordexpired, lastlogondate, @{Name="Account Expires"; Expression={[DateTime]::FromFileTime($_.accountexpires)}} |Export-Csv -Path $CSVReport -NoTypeInformation 17 | Write-Output "CSV Report Generated: $CSVReport" -------------------------------------------------------------------------------- /Blog/PowerShell/Get-AVFileScan.ps1: -------------------------------------------------------------------------------- 1 | #requires -module defender 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | <# 6 | .Synopsis 7 | Wrapper function of the Microsoft Defender on demand scanner feature 8 | .DESCRIPTION 9 | Wrapper function of the Microsoft Defender on demand scanner feature with a built-in check for AV signature update. 10 | .PARAMETER file 11 | Full path of the file to scan with the AV 12 | .EXAMPLE 13 | Get-AVFileScan -file "FULL_PATH_OF_YOUR_FILE" 14 | .EXAMPLE 15 | Get-AVFileScan -file "FULL_PATH_OF_YOUR_FILE" -verbose 16 | #> 17 | function Get-AVFileScan 18 | { 19 | [CmdletBinding()] 20 | [Alias()] 21 | [OutputType([int])] 22 | Param 23 | ( 24 | [Parameter(Mandatory=$true, 25 | ValueFromPipelineByPropertyName=$true, 26 | Position=0)] 27 | [ValidateScript({Test-Path $_ })] 28 | [string] 29 | $file 30 | ) 31 | 32 | Begin 33 | { 34 | if ((Get-MpComputerStatus).AntivirusSignatureLastUpdated -lt $(Get-Date).adddays(-2)) { 35 | Write-Warning "Your AV definitions are older than 2 days. Launching the Signature Update." 36 | Update-MpSignature -Verbose 37 | } 38 | } 39 | Process 40 | { 41 | $DefenderFolder = (Get-ChildItem "C:\ProgramData\Microsoft\Windows Defender\Platform\" | Sort-Object -Descending | Select-Object -First 1).fullname 42 | $Defender = "$defenderFolder\MpCmdRun.exe" 43 | $output = & $Defender -scan -scantype 3 -file (get-item $file).FullName 44 | $output | ForEach-Object {Write-Verbose $_} 45 | 46 | return $output[-1] -notmatch "no threats" 47 | } 48 | End 49 | { 50 | } 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /Blog/PowerShell/Get-FSMO.ps1: -------------------------------------------------------------------------------- 1 | # From Scripting Guys Blog 2 | # https://blogs.technet.microsoft.com/heyscriptingguy/2014/11/28/powertip-use-powershell-to-get-list-of-fsmo-role-holders/ 3 | Get-ADDomain | Select-Object InfrastructureMaster, RIDMaster, PDCEmulator 4 | Get-ADForest | Select-Object DomainNamingMaster, SchemaMaster 5 | Get-ADDomainController -Filter * | 6 | Select-Object Name, Domain, Forest, OperationMasterRoles | 7 | Where-Object {$_.OperationMasterRoles} | 8 | Format-Table -AutoSize -------------------------------------------------------------------------------- /Blog/PowerShell/Get-FilesWithMacros.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | <# 4 | .Synopsis 5 | Get all office documents with Macros 6 | .DESCRIPTION 7 | Get all office documents with Macros 8 | .EXAMPLE 9 | Get a list of all documents with macros saved on a specific folder (in case SHARED FOLDER needs 10 | to be mapped in advance) and format the result as a table. 11 | 12 | PS D:\> Get-FilesWithMacros "d:\" | ft 13 | 14 | Directory Name LastWriteTime LastAccessTime Length 15 | --------- ---- ------------- -------------- ------ 16 | D:\ New Microsoft Excel Worksheet.xlsm 18/01/2018 6:45:27 PM 18/01/2018 6:45:27 PM 6164 17 | D:\ New Microsoft Word Document.docm 18/01/2018 6:45:33 PM 18/01/2018 6:45:33 PM 0 18 | 19 | .EXAMPLE 20 | How to create a Report in CSV Format with all macro documents 21 | 22 | gfwm "d:\" | Export-CSV "Report_D_drive_macros.csv" 23 | 24 | .NOTES 25 | Author Paolo Frigo https://www.scriptinglibrary.com 26 | #> 27 | function Get-FilesWithMacros { 28 | [CmdletBinding()] 29 | [Alias('gfwm')] 30 | [OutputType([string])] 31 | Param 32 | ( 33 | # Folder Name 34 | [Parameter(Mandatory = $true, 35 | ValueFromPipelineByPropertyName = $true, 36 | Position = 0)] 37 | $folder 38 | 39 | ) 40 | Begin 41 | { 42 | } 43 | Process 44 | { 45 | #List of all Office Documents Extensions with Macros enabled 46 | $macro_extensions = ".docm", ".dotm", ".xlsm",".xlm", ".xltm", ".xla", ".pptm", ".potm", ".ppsm", ".sldm" 47 | get-childitem -Path $folder -Recurse -ErrorAction SilentlyContinue| Where-Object { $macro_extensions -contains $_.Extension} | Select-Object Directory, Name, LastWriteTime, LastAccessTime, Length 48 | } 49 | End 50 | { 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Blog/PowerShell/Get-LocalAdmin.ps1: -------------------------------------------------------------------------------- 1 | function Get-LocalAdmin { 2 | 3 | <# 4 | 5 | .Synopsis 6 | Get Local admin list 7 | .Description 8 | Get Local admin list 9 | 10 | .Example 11 | Get-LocalAdmin -Computername myworkstation.contoso.com 12 | 13 | This shows the NTP Status of the localhost, this will be the result: 14 | 15 | Retrieving Local Admin list for myworkstation.contoso.com 16 | MYWORKSTATION\Administrator 17 | CONTOSO\Domain Admins 18 | 19 | .Example 20 | get-adcomputer -searchbase ‘OU=workstations,dc=contoso,dc=com’ -filter * -property * | select name | Get-LocalAdmin 21 | 22 | Get Local admin list for all the workstation in AD. 23 | 24 | .Notes 25 | Author: Paolo Frigo https://www.scriptinglibrary.com 26 | 27 | #> 28 | param ( 29 | 30 | [Parameter(Mandatory = $true, 31 | ValueFromPipeline = $true, 32 | ValueFromPipelineByPropertyName = $true, 33 | Position = 0)] 34 | [Alias('Name')] 35 | 36 | [string[]]$ComputerName 37 | ) 38 | Process { 39 | 40 | Write-Warning "Retrieving Local Admin list for $ComputerName" 41 | 42 | try { 43 | If (!(Test-Connection -ComputerName $computerName -Count 1 -Quiet)) { 44 | Write-Output "$computerName is offline." 45 | #Continue # Move to next computer 46 | } 47 | else { 48 | $admins = Get-WmiObject win32_groupuser –computer $ComputerName 49 | $admins = $admins |Where-Object {$_.groupcomponent –like '*"Administrators"'} 50 | $admins | ForEach-Object { 51 | $_.partcomponent –match “.+Domain\=(.+)\,Name\=(.+)$” > $nul 52 | $matches[1].trim('"') + “\” + $matches[2].trim('"') } 53 | } 54 | 55 | } 56 | catch { 57 | Write-Output "Can't gather information from $ComputerName" 58 | Write-Output $Error[0].Exception; 59 | } 60 | finally { 61 | 62 | } 63 | 64 | } 65 | } 66 | 67 | 68 | #Example with desktop, but you can use Laptops or VMs or Servers as OU 69 | get-adcomputer -searchbase ‘OU=workstations,dc=contoso,dc=com’ -filter 70 | -------------------------------------------------------------------------------- /Blog/PowerShell/Get-LockedOutInfo.ps1: -------------------------------------------------------------------------------- 1 | #Requires -module ActiveDirectory 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | function Get-LockedOutInfo 6 | { 7 | [CmdletBinding()] 8 | [Alias()] 9 | [OutputType([Hashtable])] 10 | Param 11 | ( 12 | # Param1 help description 13 | [Parameter(Mandatory=$true, 14 | ValueFromPipelineByPropertyName=$true, 15 | Position=0)] 16 | $username, 17 | 18 | [Parameter(Mandatory=$false, 19 | ValueFromPipelineByPropertyName=$true, 20 | Position=1)] 21 | $justPDC 22 | 23 | 24 | ) 25 | 26 | Begin 27 | { 28 | } 29 | Process 30 | { 31 | 32 | $DClist = (Get-ADDomainController -Filter * ) 33 | 34 | if ($justPDC){ 35 | $DClist = $DClist | Where-Object { $_.OperationMasterRoles -contains "PDCEmulator" } 36 | } 37 | $results = (@()) 38 | foreach ($addc in ($DClist| Select-Object -ExpandProperty hostname)){ 39 | 40 | if (Test-Connection -Quiet -count 1 -ComputerName $addc){ 41 | $LockoutEvents = Get-WinEvent -ComputerName $addc -FilterHashtable @{Logname="Security";ID=4740} -ErrorAction SilentlyContinue 42 | if ($LockoutEvents){ 43 | $time = $LockoutEvents[0].TimeCreated 44 | $details = $LockoutEvents[0].message 45 | if ($details -match $username -and $details -match "Caller Computer Name:\s([a-zA-Z\-0-9]*)"){ 46 | $results +=( @{ 47 | 'Username' = $username; 48 | 'callerid' = $Matches[1]; 49 | 'Time' = $time; 50 | 'DC'="$addc" 51 | }) 52 | 53 | } 54 | } 55 | } 56 | else { 57 | Write-Warning "$addc not reachable" 58 | } 59 | } 60 | return $results 61 | } 62 | End 63 | { 64 | } 65 | } 66 | 67 | 68 | 69 | #Example 70 | #Get-LockedOutInfo -username $username -justPDC $true -------------------------------------------------------------------------------- /Blog/PowerShell/Get-NtpStatusFromHost.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | # 3 | # Paolo Frigo, www.scriptinglibrary.com 4 | # 5 | function Get-NTPStatusFromHost { 6 | <# 7 | 8 | .Synopsis 9 | Get NTP status from a host 10 | .Description 11 | Get the Network Time Protocol (NTP) status from a host. It's a simple a W32tm Wrapper. 12 | 13 | .Example 14 | Get-NTPStatusFromHost -Computername localhost 15 | 16 | This shows the NTP Status of the localhost, this will be the result: 17 | 18 | NTP STATUS FOR localhost 19 | Leap Indicator: 0(no warning) 20 | Stratum: 7 (secondary reference - syncd by (S)NTP) 21 | Precision: -6 (15.625ms per tick) 22 | Root Delay: 0.0079510s 23 | Root Dispersion: 0.3620458s 24 | ReferenceId: 0xC0A86302 (source IP: 192.168.0.2) 25 | Last Successful Sync Time: 23/05/2017 10:43:37 PM 26 | Source: dc1.contoso.com 27 | Poll Interval: 15 (32768s) 28 | 29 | .Example 30 | get-adcomputer -searchbase ‘OU=workstations,dc=contoso,dc=com’ -filter * -property * | select name | Get-NTPStatusFromHost 31 | 32 | This shows the NTP Status for all the workstation in AD. 33 | 34 | .Notes 35 | Author: Paolo Frigo - https://www.scriptinglibrary.com 36 | 37 | #> 38 | Param( 39 | [Parameter(Mandatory = $true, 40 | ValueFromPipeline = $true, 41 | ValueFromPipelineByPropertyName = $true, 42 | Position = 0)] 43 | [Alias('Name')] 44 | 45 | [string[]]$ComputerName 46 | ) 47 | Process { 48 | write-output "NTP STATUS FOR $ComputerName" 49 | w32tm /query /computer:$ComputerName /status 50 | } 51 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Get-PowerOption.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | 3 | function Get-PowerOption{ 4 | <# 5 | .Synopsis 6 | Get the power option of a host. 7 | 8 | .Description 9 | Get the power option of a host. 10 | 11 | .Example 12 | PS C:\Windows\system32> Get-PowerOption box1 13 | 14 | WARNING: *** Starting WinRM service on box1 15 | 16 | Existing Power Schemes (* Active) 17 | ----------------------------------- 18 | Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced) 19 | Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance) * 20 | Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a (Power saver) 21 | Power Scheme GUID: db310065-829b-4671-9647-2261c00e86ef (High Performance (ConfigMgr)) 22 | WARNING: *** Stopping WinRM service on box1 23 | .Example 24 | get-adcomputer -searchbase ‘OU=Computers,dc=contoso,dc=com’ -filter * -property * | select-object name | Get-PowerOption 25 | 26 | Get-PowerOption for all the workstations in AD. 27 | 28 | .Notes 29 | Author: Paolo Frigo - https://www.scriptinglibrary.com 30 | #> 31 | Param( 32 | [Parameter(Mandatory=$true, 33 | ValueFromPipeline=$true, 34 | ValueFromPipelineByPropertyName=$true, 35 | Position=0)] 36 | [Alias('name')] 37 | 38 | [string[]]$ComputerName 39 | ) 40 | process{ 41 | $winRmNotRunning =(Get-Service -ComputerName $ComputerName winrm).Status -eq "Stopped" 42 | if ($winRmNotRunning -eq "True"){ 43 | Get-Service -ComputerName $ComputerName winrm | Start-Service 44 | Write-Warning "*** Starting WinRM service on $ComputerName" 45 | } 46 | $RemoteSession = New-PSSession -ComputerName $ComputerName 47 | invoke-command -Session $RemoteSession -ScriptBlock { powercfg /l } 48 | Get-Service -ComputerName $ComputerName winrm | Stop-Service 49 | Write-Warning "*** Stopping WinRM service on $ComputerName" 50 | Remove-PSSession -Session $RemoteSession 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Blog/PowerShell/Get-RemoteRdpSession.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | # 5 | ##RdpSessionTable will contain all your results 6 | function New-RdpSessionTable() { 7 | $RDPSessionTable = New-Object System.Data.DataTable("RDPSessions") 8 | "COMPUTERNAME", "USERNAME", "ID", "STATE" | ForEach-Object { 9 | $Col = New-Object System.Data.DataColumn $_ 10 | $RDPSessionTable.Columns.Add($Col) 11 | } 12 | return , $RDPSessionTable 13 | } 14 | ## 15 | function Get-RemoteRdpSession { 16 | <# 17 | .SYNOPSIS 18 | This function is a simple wrapper of query session / qwinsta and returs a DataTable Objects 19 | 20 | .DESCRIPTION 21 | This function is a simple wrapper of query session / qwinsta and returs a DataTable Objects 22 | 23 | .PARAMETER ComputerName 24 | ComputerName parameter is required to specify a list of computers to query 25 | 26 | .PARAMETER State 27 | State parameter is optional and can be set to "ACTIVE" or "DISC". If not 28 | used both ACTIVE and DISC connections will be returned. 29 | 30 | .EXAMPLE 31 | Get-RemoteRdpSession -computername $(Get-AdComputer -filter * | select-object -exp name ) 32 | 33 | .EXAMPLE 34 | Get-RemoteRdpSession -computername "server1", "server2" -state DISC 35 | 36 | .NOTES 37 | Author: Paolo Frigo https://www.scriptinglibrary.com 38 | #> 39 | 40 | [CmdletBinding()] 41 | 42 | [OutputType([int])] 43 | Param 44 | ( 45 | [Parameter(Mandatory = $true, 46 | ValueFromPipelineByPropertyName = $true, 47 | Position = 0)] 48 | [string[]] 49 | $computername, 50 | 51 | [Parameter(Mandatory = $false, Position = 1 )] 52 | [ValidateSet("Active", "Disc")] 53 | [string] 54 | $state 55 | ) 56 | Begin { 57 | $tab = New-RdpSessionTable 58 | $counter = 1 59 | $total = $computername.Length 60 | } 61 | Process { 62 | foreach ($hostname in $computername) { 63 | Write-Progress -Activity "Get-RemoteRdpSession" -Status "Querying RDP Session on $hostname" -PercentComplete (($counter / $total) * 100) 64 | if (Test-Connection -ComputerName $hostname -Quiet -Count 1){ 65 | $result = query session /server:$hostname 66 | $rows = $result -split "`n" 67 | foreach ($row in $rows) { 68 | if ($state) { 69 | $regex = $state 70 | } 71 | else { 72 | $regex = "Disc|Active" 73 | } 74 | 75 | if ($row -NotMatch "services|console" -and $row -match $regex) { 76 | $session = $($row -Replace ' {2,}', ',').split(',') 77 | $newRow = $tab.NewRow() 78 | $newRow["COMPUTERNAME"] = $hostname 79 | $newRow["USERNAME"] = $session[1] 80 | $newRow["ID"] = $session[2] 81 | $newRow["STATE"] = $session[3] 82 | $tab.Rows.Add($newRow) 83 | } 84 | } 85 | } 86 | $counter += 1 87 | } 88 | } 89 | End { 90 | return $tab 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Blog/PowerShell/Get-Uptime.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Paolo Frigo, www.scriptinglibrary.com 3 | # 4 | Get-CimInstance -ClassName win32_operatingsystem | Select-Object -ExpandProperty LastBootUpTime -------------------------------------------------------------------------------- /Blog/PowerShell/Get-VMFootprintByEnv.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | #requires -modules ActiveDirectory 3 | 4 | # 5 | # Paolo Frigo, https://www.scriptinglibrary.com 6 | # This script will sum all VM Footprints according to your naming convention filter PROD/TEST/DEV used. 7 | # 8 | # VMNODES will list all hyper-v hosts 9 | 10 | 11 | $Filter = "prod" # prod, test or dev 12 | $VMNODES = "VMNode-01", "VMNode-02", "VMNode-03" #get-adcomputer -filter {name -like "My_Naming_Convention"} | Select-object -expandproperty name 13 | $Result = 0 14 | 15 | foreach ($VMHost in $VMNODES) { 16 | if (Test-Connection $VMHost -Quiet -Count 1) { 17 | $VM = get-vm -computername $VMHost | Where-Object {$_.name -match "$Filter"} 18 | $Disks = $VM | Get-VMHardDiskDrive | Select-object -expandproperty path 19 | $total_size = Invoke-Command -ComputerName $VMHost -ScriptBlock { 20 | param($Disks) 21 | $total = 0 22 | #write-host $disks 23 | foreach ($disk in $disks) { 24 | $size = [math]::round((get-item -Path $disk | select-object -ExpandProperty length)/1GB,2) 25 | write-host "Disk: $disk `t Size $size GB" 26 | $total += $size 27 | } 28 | return $total 29 | } -ArgumentList (,$Disks) 30 | $Result += $total_size 31 | } 32 | else { 33 | raise "$VMHost is not reachable" 34 | } 35 | } 36 | 37 | Write-Output "$Filter VM footprint is $Result GB".ToUpper() -------------------------------------------------------------------------------- /Blog/PowerShell/Get-VMFootprintOnASingleHost.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | # 4 | # Paolo Frigo, https://www.scriptinglibrary.com 5 | # This script will get the size of all VHDX files of all VMs hosted on your Hyper-V 6 | # 7 | # notes - Please have a look to get-vmfootprintbyenv.ps1 in case you want to run this 8 | # script against multiple hyper-v hosts 9 | 10 | function Get-VMFootprint ($VM){ 11 | $total_size = 0 12 | foreach ($disk in ($VM | Get-VMHardDiskDrive | Select-object -expandproperty path) ){ 13 | $total_size += Get-Item $disk | Select-Object -ExpandProperty Length 14 | } 15 | Return [math]::round($total_size/1GB,2) 16 | } 17 | 18 | $counter = 0 19 | $vm_counter = 0 20 | $total = 0 21 | 22 | foreach ($VMHost in $ALL_HSD_VM_NODES){ 23 | $counter += 1 24 | foreach ($VM in (get-vm -computername $VMHost)){ 25 | $vm_counter += 1 26 | Write-Progress -Status "Get Footprint of $($VM.Name)" -Activity "Retrieve information from $($VmHost)" -PercentComplete $($counter/$NumNodes*100) 27 | $VmSize = $(Get-VMFootprint($VM)) 28 | Write-Verbose "$($VM.Name) - $VmSize GB" 29 | $total += $VmSize 30 | } 31 | } 32 | 33 | Write-Output "$vm_counter VMs Footprint: $total GB " 34 | -------------------------------------------------------------------------------- /Blog/PowerShell/Get-YourScriptSigned.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasdministrator 2 | 3 | #Paolo, scriptinglibrary.com 4 | 5 | #Get-Help about_signing #Official doc 6 | 7 | $MySigningCertificate = New-SelfSignedCertificate -subject "Paolo's Signing Certificate" -Type CodeSigning -CertStoreLocation "cert:\LocalMachine\My" 8 | 9 | #Export our pfx and use a strong password to protect it 10 | #Never store a password in your script! 11 | $MyStrongPassword = ConvertTo-SecureString -String "SuperSecret!" -Force -AsPlainText 12 | $PathWhereToSaveIt = "D:\MyNewSigningCertificate.pfx" 13 | $MySigningCertificate | Export-PfxCertificate -FilePath $PathWhereToSaveIt -password $MyStrongPassword 14 | 15 | 16 | #How to import it 17 | #Personal 18 | Import-PfxCertificate -FilePath $PathWhereToSaveIt -CertStoreLocation "cert:\LocalMachine\My" -Password $MyStrongPassword 19 | #TrustedPublisher 20 | Import-PfxCertificate -FilePath $PathWhereToSaveIt -CertStoreLocation "cert:\LocalMachine\Root" -Password $MyStrongPassword 21 | #Root 22 | Import-PfxCertificate -FilePath $PathWhereToSaveIt -CertStoreLocation "cert:\LocalMachine\TrustedPublisher" -Password $MyStrongPassword 23 | 24 | #List Certificate 25 | Get-ChildItem "Cert:\LocalMachine\My\" -CodeSigningCert 26 | # My Signing Cert 27 | $MyCert = (Get-ChildItem "Cert:\LocalMachine\My\" -CodeSigningCert)[0] 28 | #List all the details 29 | Get-ChildItem Cert:\LocalMachine\My\ -CodeSigningCert | Select-Object * 30 | 31 | $TestDir = "D:\TestFolder" 32 | #Create new directory 33 | New-Item -ItemType "Directory" -Path $TestDir 34 | #Create few scripts and sign them 35 | 1..5| ForEach-Object {Set-Content -path "$testdir\ExampleScript$_.ps1" -Value "Get-ChildItem"} 36 | #List Contet 37 | Get-ChildItem $TestDir 38 | 39 | #Signing multiple scripts at once 40 | $MyCertFromPfx = Get-PfxCertificate -FilePath $PathWhereToSaveIt #Will Be Prompted for the password 41 | #Sign all files 42 | Get-ChildItem $TestDir | Set-AuthenticodeSignature -certificate $MyCertFromPfx -IncludeChain "All" 43 | #Check all files 44 | Get-ChildItem $TestDir| Get-AuthenticodeSignature -------------------------------------------------------------------------------- /Blog/PowerShell/Inspect-IISLogs.ps1: -------------------------------------------------------------------------------- 1 | #requires -module ActiveDirectory 2 | 3 | <# 4 | PF, https://www.scriptinglibrary.com 5 | 6 | .SYNOPSIS 7 | This script inspect the most recent log file and prints a list of internal and external ip with usernames 8 | 9 | .DESCRIPTION 10 | This script inspect the most recent log file and prints a list of internal and external ip with usernames 11 | 12 | .EXAMPLE 13 | .\Inspect-IISLogs.ps1 14 | 15 | .EXAMPLE 16 | Run an infinite loop in a separate powershell window and update every 1minute 17 | 18 | while($true){clear; .\Inspect-IISLogs.ps1 ; (get-date).datetime ; sleep -Seconds 60;} 19 | #> 20 | 21 | #SETTINGS 22 | $LogFolder="D:\Logs\W3SVC1" 23 | $MostRecentLogFile = (Get-ChildItem $LogFolder)[-1].FullName 24 | $allLines= Get-Content $MostRecentLogFile 25 | $IPStats=@{} 26 | $PrivateNtwk="10.0" 27 | 28 | Function Parse-LogEntry{ 29 | [CmdletBinding()] 30 | param ( 31 | [Parameter(Mandatory=$true)] 32 | [string] 33 | $line 34 | ) 35 | 36 | if ($line){ 37 | $fields=$line.Split(" ") 38 | $user=$fields[7] 39 | $ip=$fields[8] 40 | #$browser=$fields[9] 41 | #$date=$fields[0] 42 | #$time=$fields[1] 43 | #$code=$fields[11] 44 | if (($ip -notmatch "::1") -and ($ip -notmatch "127.0.0.1" ) ){ 45 | return "$ip", "$user" #, $code, $browser, $date, $time 46 | } 47 | } 48 | } 49 | Function Generate-Stats{ 50 | [CmdletBinding()] 51 | param ( 52 | [Parameter(Mandatory=$true)] 53 | [string] 54 | $ip, 55 | [Parameter(Mandatory=$true)] 56 | [string] 57 | $user 58 | ) 59 | 60 | if ($user -like "-" -or $ip -like "cs-username") 61 | { 62 | return 63 | } 64 | #Convert user SID with fullname, upn or samaaccount 65 | if ($user -match "S-1-5"){ 66 | $user = get-aduser -filter{sid -like $user} |Select-Object -exp name #userpricipalname #samaccountname 67 | } 68 | if ($IPStats["$ip"]){ 69 | if ([array]$IPStats["$ip"] -notcontains $user ){ 70 | $IPStats["$ip"] = $IPStats["$ip"] , "$user" 71 | } 72 | else { 73 | return 74 | } 75 | } 76 | else{ 77 | $IPStats["$ip"] = $user 78 | } 79 | } 80 | Foreach ($Line in $AllLines){ 81 | $parsedline = Parse-LogEntry($line) 82 | if ($parsedline){ 83 | Generate-Stats -ip $parsedline[0] -user $parsedline[1] 84 | } 85 | } 86 | 87 | Write-Output "`nINTERNAL IPs`n------------------------" 88 | $IPStats.GetEnumerator() | Where-Object {$_.name -match "$PrivateNtwk"} | sort-object -Property name 89 | Write-Output "`nEXTERNAL IPs`n------------------------" 90 | $IPStats.GetEnumerator() | Where-Object {$_.name -notmatch "$PrivateNtwk"} | sort-object -Property name 91 | -------------------------------------------------------------------------------- /Blog/PowerShell/Install-Chocolatey.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | #https://chocolatey.org/docs/installation 6 | Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) -------------------------------------------------------------------------------- /Blog/PowerShell/Install-DC.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | # Create a AD DC with Powershell (mainly for lab env) 4 | # ---------------------------------------------------- 5 | # Install the role, import the module, create a forest 6 | # add this server as a Primary Domain Controller 7 | 8 | install-windowsfeature AD-Domain-Services 9 | Import-Module ADDSDeployment 10 | Install-ADDSForest -------------------------------------------------------------------------------- /Blog/PowerShell/Install-NagiosAgentRemotely.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | Paolo Frigo, https://scriptinglibrary.com 3 | 4 | .Synopsis 5 | Install remotely the NSCP++ agent for Nagios 6 | .DESCRIPTION 7 | This script allow you to install remotely the NSCP++ agent for Nagios to a target windows computer (server/workstation). 8 | Included in the installation process is also the deployment of a custom configuration file and the custom powershell scripts for whitebox monitoring. 9 | .EXAMPLE 10 | install-nagiosagentremotely 11 | #> 12 | 13 | 14 | $MsiInstaller = "NSCP-0.4.1.73-x64.msi" #Or a newer version 15 | $port = "12489" 16 | $NAS = "\\YOUR_UNC_PATH\Nagios\" #Installation folder 17 | 18 | function Install-NSCP 19 | { 20 | [CmdletBinding()] 21 | [Alias()] 22 | [OutputType([int])] 23 | Param 24 | ( 25 | [Parameter(Mandatory=$true, 26 | ValueFromPipelineByPropertyName=$true, 27 | Position=0)] 28 | $target 29 | ) 30 | 31 | Begin 32 | { 33 | if ((Test-NetConnection -computername $Target -Port $port).TcpTestSucceeded -eq $true){ 34 | Write-Warning "NSCP++ is already running on $Target" 35 | exit 36 | } 37 | 38 | } 39 | Process 40 | { 41 | $OldPath = (Get-Location).path 42 | Set-Location $NAS 43 | 44 | Write-Information "`n-Copying the installer on the windows temp folder" 45 | Copy-Item -path ".\$MsiInstaller" -Destination \\$Target\C$\windows\Temp\ 46 | 47 | Write-Information "-Installing the app" 48 | #IMPORTANT: Pay attention that the installer is hard-coded in the following scriptblock 49 | invoke-command -ComputerName $Target -ScriptBlock {Start-Process "msiexec" -ArgumentList '/qn /i c:\windows\temp\NSCP-0.4.1.73-x64.msi INSTALLLOCATION="C:\Program Files\NSClient++" CONFIGURATION_TYPE=registry://HKEY_LOCAL_MACHINE/software/NSClient++ ADDDEFAULT=ALL REMOVE=PythonScript' -wait -NoNewWindow} 50 | 51 | Write-Information "-Stopping the service" 52 | invoke-command -ComputerName $Target -ScriptBlock { Stop-Service nscp } 53 | 54 | Write-Information "-Making a Backup copy of the Nagios Client" 55 | Move-Item -path "\\$Target\c$\Program Files\NSClient++\nsclient.ini" -Destination "\\$Target\c$\Program Files\NSClient++\nsclient.ini.dist" -Force 56 | 57 | Write-Information "-Copying the new nsclient.ini file" 58 | Copy-Item -path ".\nsclient.ini" -Destination "\\$Target\c$\Program Files\NSClient++\" 59 | 60 | Write-Information "-Copying New Custom Powershell scripts" 61 | Copy-Item -path ".\*.ps1" -Destination "\\$Target\c$\Program Files\NSClient++\scripts" 62 | 63 | Write-Information "-Restarting the service" 64 | invoke-command -ComputerName $Target -ScriptBlock { Start-Service nscp } 65 | 66 | Set-Location $oldpath 67 | 68 | start-sleep -Seconds 5 69 | Write-Output "-Checking it the port on the target server for the NSCP server is:" 70 | if ((Test-NetConnection -computername $Target -Port $port).TcpTestSucceeded -eq $true){ 71 | Write-Output "-OPEN - NSCP++ is working as expected on $Target `n`nInstallation completed successfully." 72 | } 73 | else { 74 | Write-Warning "-CLOSED - Port $port on $Target is closed NSCP is not running, not installed correctly or a firewall rule maybe is blocking it" 75 | } 76 | } 77 | End 78 | { 79 | } 80 | } 81 | 82 | Install-NSCP -------------------------------------------------------------------------------- /Blog/PowerShell/Install-Pwsh.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | #Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | # DOWNLOAD AND INSTALL THE LATEST VERSION OF POWERSHELL 5 | # BY USING THE MSI INSTALLER IN UNATTENDED/QUIET MODE. 6 | 7 | Invoke-Expression "& { $(Invoke-RestMethod https://aka.ms/install-powershell.ps1) } -UseMSI -quiet" 8 | -------------------------------------------------------------------------------- /Blog/PowerShell/Install-RSAT.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | # Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | # Install the tools on a domain joined machine on a PrivilegedAccessVM (Win 10) 5 | Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online -------------------------------------------------------------------------------- /Blog/PowerShell/Install-WAC.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | #WINDOWS ADMIN CENTER DOCs 6 | #https://docs.microsoft.com/en-us/windows-server/manage/windows-admin-center/deploy/install 7 | 8 | $WAC_Online = "http://aka.ms/WACDownload" 9 | $WAC_Installer = "C:\windows\Temp\wac.msi" 10 | $Port = 443 11 | 12 | # Leave it blank if you want to generate a Self-Signed Certificate. 13 | $CertificateThumbprint = "" 14 | $IsAdminCenterInstalled = [bool] (Get-WmiObject -class win32_product | Where-Object {$_.Name -eq "Windows Admin Center"}) 15 | 16 | If ($IsAdminCenterInstalled){ 17 | $ReInstall = Read-Host "Admin Center is already installed. Do you want to re-install/upgrade it? [Y/N]" 18 | If ( ("N","n") -contains $ReInstall){ 19 | Write-Warning "Ok, No further action is required." 20 | Exit 0 21 | } 22 | } 23 | $ProgressPreference = 'SilentlyContinue' 24 | Invoke-WebRequest -Uri $WAC_Online -OutFile $WAC_Installer 25 | #if CertificateThumbprint is defined and installed on the system will be used during the installation 26 | if ([bool](get-childitem cert: -recurse | where-object {$_.thumbprint -eq $CertificateThumbprint})){ 27 | msiexec /i $WAC_Installer /qn SME_PORT=$Port SME_THUMBPRINT=$CertificateThumbprint SSL_CERTIFICATE_OPTION=installed 28 | } 29 | else{ 30 | msiexec /i $WAC_Installer /qn SME_PORT=$Port SSL_CERTIFICATE_OPTION=generate 31 | } 32 | 33 | #Post Installation Checks 34 | do { 35 | if ((Get-Service ServerManagementGateway).status -ne "Running"){ 36 | Write-Output "Starting Windows Admin Center (ServerManagementGateway) Service" 37 | Start-Service ServerManagementGateway 38 | } 39 | Start-sleep -Seconds 5 40 | } until ((Test-NetConnection -ComputerName "localhost" -port $Port).TcpTestSucceeded) 41 | 42 | Write-Output "Installation completed and Windows Admin Center is running as expected." -------------------------------------------------------------------------------- /Blog/PowerShell/Monitor-AccountLockOut.ps1: -------------------------------------------------------------------------------- 1 | #requires -module BurntToast,ActiveDirectory 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | $SleepTime = 60 #seconds 6 | do { 7 | if (Search-ADAccount -LockedOut) { 8 | foreach ($user in (Search-ADAccount -LockedOut)) { 9 | New-Burnttoastnotification -text "Locked-Out User Notification", "$($($user).name) is now Locked-Out" 10 | } 11 | } 12 | start-sleep -Seconds $SleepTime 13 | } 14 | while ($True) 15 | 16 | 17 | <# 18 | # If you want a limited number of test you can use a foreach loop instead of a do-while 19 | # 20 | ForEach ($i in (1..100)){ 21 | if (Search-ADAccount -LockedOut) { 22 | foreach ($user in (Search-ADAccount -LockedOut)) { 23 | New-Burnttoastnotification -text "Locked-Out User Notification", "$($($user).name) is now Locked-Out" 24 | } 25 | } 26 | start-sleep -Seconds $SleepTime 27 | } 28 | #> 29 | 30 | # A better approach can be simple schedule this job and run it any minute. 31 | -------------------------------------------------------------------------------- /Blog/PowerShell/New-AADGuestUserInvite.ps1: -------------------------------------------------------------------------------- 1 | #requires -module azuread 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | # THIS SCRIPT REQUIRES A CSV FILE WITH A LIST OF GUEST USERS AND IT WILL SEND AN INVITATION 6 | # EMAIL WITH A CUSTOMISED MESSAGE BODY. 7 | 8 | # I've modified the script that I found in the Microsoft Learn pages (docs.microsoft.com) 9 | # https://docs.microsoft.com/en-us/learn/modules/create-users-and-groups-in-azure-active-directory/2-user-accounts-azure-ad 10 | 11 | # SETTINGS 12 | $GuestUserCSVlist = "D:\bulkinvite\invitations.csv" 13 | $CustomMessage = "Hello. You are invited to the Contoso organization." 14 | 15 | 16 | 17 | #Connect to your Azure AD tenant 18 | Connect-AzureAD 19 | 20 | #Load the list of guest users to invite 21 | $invitations = import-csv $GuestUserCSVlist 22 | 23 | #Change the message 24 | $messageInfo = New-Object Microsoft.Open.MSGraph.Model.InvitedUserMessageInfo 25 | $messageInfo.customizedMessageBody = $CustomMessage 26 | 27 | foreach ($email in $invitations) 28 | {New-AzureADMSInvitation ` 29 | -InvitedUserEmailAddress $email.InvitedUserEmailAddress ` 30 | -InvitedUserDisplayName $email.Name ` 31 | -InviteRedirectUrl https://myapps.microsoft.com ` 32 | -InvitedUserMessageInfo $messageInfo ` 33 | -SendInvitationMessage $true 34 | } -------------------------------------------------------------------------------- /Blog/PowerShell/New-Checkpoint.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | #requires -runasadministrator 4 | 5 | # Paolo Frigo, https://www.scriptinglibrary.com 6 | 7 | $prefix = "lab-centos*" 8 | 9 | Write-Output "This script will create a checkpoint immediately for all $prefix VMs" 10 | get-vm $prefix | checkpoint-vm 11 | Write-Output "Activity completed" -------------------------------------------------------------------------------- /Blog/PowerShell/New-RDGfile.ps1: -------------------------------------------------------------------------------- 1 | #requires -module activedirectory 2 | 3 | # This script requires a rdg.xml template and generates an rdg file for 4 | # RDMan - Remote Desktop Connection Manager 5 | 6 | #Paolo Frigo, https://www.scriptinglibrary.com 7 | 8 | #$ComputerListFromAD = get-adcomputer -Filter * -Properties * 9 | 10 | #Generating a list of fake servers from server1 to server100 instead of querying AD 11 | $ComputerListFromAD = 1..100 | ForEach-Object {write-output "Server$_"} 12 | 13 | $RDGTemplate = $PSScriptRoot + "\"+ "rdg.xml" 14 | $RDGFileOutPut = $PSScriptRoot + "\" +"scriptinglibrary.rdg" 15 | 16 | [XML] $template = Get-Content $RDGTemplate 17 | 18 | $template.RDCMan.file.group 19 | 20 | foreach ($pc in $ComputerListFromAD) { 21 | $s = $template.CreateNode("element", "server","") 22 | $p = $template.CreateNode("element", "properties","") 23 | $n = $template.CreateNode("element", "name","") 24 | $n.set_InnerXML($pc) 25 | $template.RDCMan.file.group.AppendChild($s).AppendChild($p).AppendChild($n) 26 | } 27 | 28 | $template.save($RDGFileOutPut) 29 | Write-Output "RDG File generated: $RDGFileOutPut" -------------------------------------------------------------------------------- /Blog/PowerShell/New-RandomPassword.Tests.ps1: -------------------------------------------------------------------------------- 1 | # Paolo Frigo, 2018 2 | # https://www.scriptinglibrary.com 3 | 4 | . .\New-RandomPassword.ps1 5 | 6 | Describe "New-RandomPassword" -Tags "Unit Tests" { 7 | it "Should generate a String" { 8 | (New-RandomPassword).GetType().Name | Should BeExactly "String" 9 | } 10 | 11 | #Pick a password Length between 0 and 7 and 33 and 100 characters 12 | $n = 0..1 + 33..100 13 | foreach ($length in $n){ 14 | it "Should throw an exeption if the password Length ($length) is out of the accepted range (8-32)" { 15 | {New-RandomPassword -Length 5} | Should throw 16 | } 17 | } 18 | #Pick a password Length between 8 and 32 characters 19 | $n = 8..32 20 | foreach ($length in $n){ 21 | It "Should generate a password $length character long" { 22 | (New-RandomPassword($length)).length | Should BeExactly "$length" 23 | } 24 | } 25 | #Test/Generate 300 passwords 26 | foreach ($attempt in (1..300)){ 27 | It "Should generate a password complex enough for AD ($attempt/300 attempt)"{ 28 | $n = 8..32 | Get-Random 29 | $RegEx = "(?=^.{8,32}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*" 30 | (New-RandomPassword($n)) -match $RegEx 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Blog/PowerShell/New-RandomPassword.ps1: -------------------------------------------------------------------------------- 1 | # Paolo Frigo, 2018 2 | # https://www.scriptinglibrary.com 3 | 4 | Function New-RandomPassword{ 5 | Param( 6 | [ValidateRange(8, 32)] 7 | [int] $Length = 16 8 | ) 9 | $AsciiCharsList = @() 10 | foreach ($a in (33..126)){ 11 | $AsciiCharsList += , [char][byte]$a 12 | } 13 | #RegEx for checking general AD Complex passwords 14 | $RegEx = "(?=^.{8,32}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*" 15 | 16 | do { 17 | $Password = "" 18 | $loops = 1..$Length 19 | Foreach ($loop in $loops) { 20 | $Password += $AsciiCharsList | Get-Random 21 | } 22 | } 23 | until ($Password -match $RegEx ) 24 | return $Password 25 | } 26 | 27 | # Generate passwords similar to pwgen" 28 | for ($i = 0; $i -lt (12); $i++) { 29 | $line = "" 30 | for ($j = 0; $j -lt (5); $j++) { 31 | $line += "$(New-RandomPassword(10)) " 32 | } 33 | Write-Output $line 34 | } 35 | # This example just print a random password 36 | # Write-Output "Generate Random Password: $(New-RandomPassword(10))" 37 | -------------------------------------------------------------------------------- /Blog/PowerShell/New-ServiceAccount.ps1: -------------------------------------------------------------------------------- 1 | #requires -module ActiveDirectory 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | $CSVFILEPATH = "D:\Scripts\service_accounts.csv" 6 | $DEST_OU="OU=Service Accounts,DC=lab,DC=local" 7 | 8 | 9 | function New-ServiceAccount { 10 | Param 11 | ( 12 | [Parameter(Mandatory=$true)] 13 | [string] 14 | $samaccountname, 15 | [Parameter(Mandatory=$true)] 16 | [string] 17 | $description, 18 | [Parameter(Mandatory=$true)] 19 | [String] 20 | $password, 21 | [Parameter(Mandatory=$true)] 22 | [string] 23 | $destou 24 | ) 25 | $psw = convertto-securestring "$password" -asplaintext -force 26 | New-ADUser -Path $destou -Name "$samaccountname" -AccountPassword $psw -Enabled $true -AllowReversiblePasswordEncryption $false -CannotChangePassword $true -PasswordNeverExpires $true 27 | Write-Output "$samaccountname service account created in $destou" 28 | } 29 | 30 | 31 | if ((Test-path ($CSVFILEPATH)) -eq $false){ 32 | throw "CSV FILE $CSVFILEPATH not found!" 33 | } 34 | Foreach ($sa in $(import-csv -Path $CSVFILEPATH)){ 35 | New-ServiceAccount -samaccountname $sa.samaccountname -description $sa.description -password $sa.password -destou $DEST_OU 36 | } 37 | -------------------------------------------------------------------------------- /Blog/PowerShell/New-SshTunnel.ps1: -------------------------------------------------------------------------------- 1 | # Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | # This scripts creates connect a local port to a remote port via an SSH tunnel 4 | 5 | # SCENARIO: POOR-MAN'S VPN 6 | # 7 | # HOST1 on NETWORKA wants to connect to HOST2 on NETWORKB, 8 | # HOST2 is not exposed to the internet and there are not port-forwarding configured 9 | # if there is an internet facing ssh server let's call it JUMPBOX available in 10 | # the networkB that box can be used to tunnel the connection. 11 | 12 | # SETTINGS 13 | # ----------------------------------------------------------------------------------- 14 | #Local port 15 | $LocalPort = "12345" # HOST1 can be on 10.1.2.4/24 NETWORKA 16 | 17 | #Target box 18 | $TargetBox = "192.168.1.94" # HOST2 19 | $TargetPort = "3389" # RDP 20 | 21 | #SSH Server #JUMPBOX 22 | $Username = "PaoloF" 23 | $MyLinuxBox = "mylinuxbox.fqdn-or-Public-IP" 24 | $RemotePortForSSH = "22" 25 | 26 | 27 | # DEPENDENCY CHECK 28 | # ----------------------------------------------------------------------------------- 29 | # This script requires PLINK, if is not present will be downloaded 30 | 31 | try{ 32 | $plinktest = Invoke-expression "plink.exe" 33 | } 34 | catch{ 35 | Write-Warning "PLINK DEPENDENCY IS MISSING. Downloading the latest version of PLINK.." 36 | Invoke-WebRequest "https://the.earth.li/~sgtatham/putty/latest/w64/plink.exe" -o "plink.exe" 37 | If(Test-Path "plink.exe"){ 38 | Write-Output "Download completed!" 39 | } 40 | } 41 | 42 | Write-Output "CREATING THE SSH TUNNEL USING PORT-FW" 43 | invoke-expression "plink.exe -P $($RemotePortForSSH) -L $($LocalPort):$($TargetBox):$($TargetPort) $($Username)@$($MyLinuxBox)" -------------------------------------------------------------------------------- /Blog/PowerShell/New-TextToSpeech.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | # This is just an simple Text To Speech Example 4 | 5 | Add-Type –AssemblyName System.Speech 6 | $SpeechSynthesizer = New-Object –TypeName System.Speech.Synthesis.SpeechSynthesizer 7 | #$SpeechSynthesizer.SelectVoice("Microsoft Zira Desktop") 8 | $SpeechSynthesizer.Speak($Text) 9 | 10 | # To List of installed voices 11 | #Foreach ($voice in $SpeechSynthesizer.GetInstalledVoices()){ 12 | # $Voice.VoiceInfo | Select-Object Gender, Name, Culture, Description 13 | #} 14 | -------------------------------------------------------------------------------- /Blog/PowerShell/New-Virus.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://scriptinglibrary.com 2 | 3 | # This script creates a COM file containing a Virus for testing AV soultions 4 | 5 | #https://en.wikipedia.org/wiki/EICAR_test_file 6 | set-content "X5O!P%@AP[4`\PZX54(P^)7CC)7}`$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!`$H+H*" -path "eicar.com" -------------------------------------------------------------------------------- /Blog/PowerShell/PingSweepAndReverseLookupExample.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, ScriptingLibrary.com 2 | #Ping sweep and reverse lookup together 3 | (1..254) | ForEach-Object {$ip="10.0.40.$_"; Write-output "$IP $(test-connection -computername "$ip" -quiet -count 1) $( Resolve-DnsName $ip -ErrorAction Ignore |Select-Object -exp NameHost ) "} 4 | -------------------------------------------------------------------------------- /Blog/PowerShell/PingSweepExample.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, scriptinglibrary.com 2 | #Ping Sweep 3 | (1..254) | ForEach-Object {$ip="10.0.40.$_"; Write-output "$IP $(test-connection -computername "$ip" -quiet -count 1)"} -------------------------------------------------------------------------------- /Blog/PowerShell/Proxy-Functions.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | <# 4 | .Synopsis 5 | Modify proxy settings for the current user. 6 | 7 | .DESCRIPTION 8 | Modify proxy settings for the current user modifying the windows registry. 9 | 10 | .EXAMPLE 11 | Get the proxy settings for the current user 12 | 13 | PS D:\> get-proxy 14 | ProxyServer ProxyEnable 15 | ----------- ----------- 16 | 0 17 | 18 | .EXAMPLE 19 | Set the proxy server for the current user. Test the address and if the TCP Port is open before applying the settings. 20 | proxy squid.server.com 3128 # or set-proxy -server "yourproxy.server.com" -port 3128 21 | 22 | .EXAMPLE 23 | Remove the current proxy settings for the user. 24 | 25 | .NOTES 26 | Author Paolo Frigo https://www.scriptinglibrary.com 27 | #> 28 | 29 | function Get-Proxy (){ 30 | Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' | Select-Object ProxyServer, ProxyEnable 31 | } 32 | 33 | function Set-Proxy { 34 | [CmdletBinding()] 35 | [Alias('proxy')] 36 | [OutputType([string])] 37 | Param 38 | ( 39 | # server address 40 | [Parameter(Mandatory = $true, 41 | ValueFromPipelineByPropertyName = $true, 42 | Position = 0)] 43 | $server, 44 | # port number 45 | [Parameter(Mandatory = $true, 46 | ValueFromPipelineByPropertyName = $true, 47 | Position = 1)] 48 | $port 49 | ) 50 | #Test if the TCP Port on the server is open before applying the settings 51 | If ((Test-NetConnection -ComputerName $server -Port $port).TcpTestSucceeded) { 52 | Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyServer -Value "$($server):$($port)" 53 | Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyEnable -Value 1 54 | Get-Proxy #Show the configuration 55 | } 56 | Else { 57 | Write-Error -Message "The proxy address is not valid: $($server):$($port)" 58 | } 59 | } 60 | 61 | function Remove-Proxy (){ 62 | Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyServer -Value "" 63 | Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -name ProxyEnable -Value 0 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Blog/PowerShell/Refresh-Path.ps1: -------------------------------------------------------------------------------- 1 | # PF, https://scriptinlibrary.com 2 | 3 | # https://stackoverflow.com/questions/17794507/powershell-reload-the-path-in-powershell 4 | function Refresh-PathEnv { 5 | $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") 6 | Write-Output "Environment Variable Refreshed" 7 | } 8 | -------------------------------------------------------------------------------- /Blog/PowerShell/Remove-OldBackup.ps1: -------------------------------------------------------------------------------- 1 | #PF,2019 https://www.scriptinglibrary.com 2 | 3 | <# 4 | 5 | .Synopsis 6 | This function Remove-OldBackup will retain the latest N copy on a database from a specified folder 7 | 8 | .Description 9 | This function Remove-OldBackup will retain the latest N copy on a database from a specified folder 10 | 11 | 12 | .Example 13 | Remove-OldBackup -Folder $Folder -Database $Database -KeepLast $KeepLast 14 | Remove from $Folder all $Database like files and keep the most recent number ($keeplast) of files 15 | 16 | .Notes 17 | Remember to use the dot-surcing notation to import this function before calling the Remove-OldBackup cmd-let. 18 | Please add a -Confirm if needed 19 | Author: Paolo Frigo, https://www.scriptinglibrary.com 20 | 21 | 22 | #> 23 | function Remove-OldBackup{ 24 | [CmdletBinding()] 25 | param ( 26 | [Parameter(Mandatory=$true)] 27 | [ValidateScript({Test-Path $_})] 28 | [string] $Folder, 29 | [Parameter(Mandatory=$true)] 30 | [String] $Database, 31 | [Parameter(Mandatory=$true)] 32 | [int] $KeepLast 33 | ) 34 | $ExcludeFiles = Get-ChildItem -Path $Folder | Where-Object {$_.Name -like $Database} |Sort-Object -Property CreationTime | Select-Object -last $KeepLast -ExpandProperty Name 35 | Get-ChildItem -Path $Folder -Exclude ($ExcludeFiles) | Where-Object {$_.Name -like $Database} | Remove-Item #-confirm 36 | } 37 | 38 | # SETTINGS 39 | #$Folder = "D:\temp\Backup\" #backup folder 40 | #$Database = "db*bak" #database name 41 | #$KeepLast = 2 #retain just last 2 copies 42 | #example 43 | #Remove-OldBackup -Folder $Folder -Database $Database -KeepLast $KeepLast -------------------------------------------------------------------------------- /Blog/PowerShell/Restore-RecentChecktpoint.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | $prefix = "lab-centos*" 6 | 7 | 8 | Write-Output "This script will restore the most recent checkpoint for all $prefix VMs without asking for confirmation" 9 | Get-VM $prefix | Foreach-Object { $_ | Get-VMSnapshot | Sort CreationTime | Select -Last 1 | Restore-VMSnapshot -Confirm:$false } 10 | Write-Output "Activity completed" -------------------------------------------------------------------------------- /Blog/PowerShell/ReverseLookupExample.ps1: -------------------------------------------------------------------------------- 1 |  2 | #Paolo Frigo, ScriptingLibrary.com 3 | #Reverse Lookup 4 | (1..254) | ForEach-Object {$ip="10.0.40.$_"; Write-output "$IP $( Resolve-DnsName $ip -ErrorAction Ignore |Select-Object -exp NameHost ) "} -------------------------------------------------------------------------------- /Blog/PowerShell/Search-ADUsersWithDuplicateFields.ps1: -------------------------------------------------------------------------------- 1 | #Requires -Module ActiveDirectory 2 | #Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | # THIS SCRIPT CAN BE USE TO SEARCH FOR AD USERS WITH THE SAME EMAIL ADDRESS, EMPLOYEEID, ETC... 5 | 6 | $OU="OU=External,OU=Staff,DC=contoso,DC=com" #Limit the scope to your OU 7 | $DuplicateField = "mail" #choose what is the duplicate field you are searching 8 | 9 | Get-ADUser -SearchBase $OU -properties $DuplicateField -filter * | Group-Object $DuplicateField | Where-Object {$_.count -gt 1} -------------------------------------------------------------------------------- /Blog/PowerShell/Search-PcWithSophosFileToRemove.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | #requires -module ActiveDirectory 3 | 4 | # Paolo Frigo, https://www.scriptinglibrary.com 5 | 6 | # Find Workstations with temporary files from Sophos To Remove 7 | 8 | # SETTINGS 9 | $WS = "*" #Replace with your pattern 10 | $OU = "OU=Laptop, DC=Contoso, DC=com" #Replace with your domain OU 11 | #----- 12 | 13 | $ComputerList = get-adcomputer -Filter {Name -like $WS} -SearchBase $OU | Select-Object -ExpandProperty name 14 | $Total = $ComputerList.Count 15 | $Counter = 1 16 | foreach ($PC in $ComputerList) { 17 | if (Test-Connection -ComputerName $PC -quiet -count 1){ 18 | write-progress -Activity "Searching on $PC" -PercentComplete $(($Counter/$total)*100) 19 | $SophosTempFiles = Get-ChildItem "\\$($PC)\c$\ProgramData\Sophos\Sophos Anti-Virus\Temp\*`$`$`$" 20 | if ($SophosTempFiles){ 21 | Write-Output "$PC has $($SophosTempFiles.count) temp files to remove." 22 | } 23 | } 24 | $Counter += 1 25 | } 26 | 27 | Write-Output "$Total Workstations were scanned successfully" -------------------------------------------------------------------------------- /Blog/PowerShell/Search-PhishingEmail.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | #doc 4 | #https://docs.microsoft.com/en-us/powershell/module/exchange/mailboxes/search-mailbox?view=exchange-ps 5 | 6 | 7 | $admin = "paolofrigo" 8 | $query = "from:attacker@domain.com" #", subject:, content:" #"KEYWORD OR KEYWORD" 9 | 10 | 11 | 12 | #load the Exchange management shell SnapIn 13 | Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn; 14 | 15 | #Check if your user is a member of these groups 16 | #Get-RoleGroupMember "Discovery Management" 17 | #Get-RoleGroupMember "Organization Management" 18 | 19 | Get-Mailbox -ResultSize unlimited | Search-Mailbox -SearchQuery "$query" -TargetMailbox $admin -TargetFolder "SearchAndDeleteLog" -LogOnly -LogLevel Full 20 | 21 | 22 | #Searh Mailbox is being deprecated consider to user New-ComplianceSearch 23 | #https://docs.microsoft.com/en-us/powershell/module/exchange/policy-and-compliance-content-search/new-compliancesearch?view=exchange-ps 24 | 25 | #https://www.scriptinglibrary.com/languages/powershell/removing-a-phishing-email-from-all-exchange-mailboxes-with-powershell// -------------------------------------------------------------------------------- /Blog/PowerShell/Send-ADLockedOutEventToSlack.ps1: -------------------------------------------------------------------------------- 1 | #requires -module ActiveDirectory 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | # The execution of this is scheduled to run every 5 minutes on ServerX 6 | 7 | # The goal of this script to notify to SLACK Channel: "#GENERAL" channel 8 | # every single lockout-event in the local AD domain. 9 | 10 | # Webhooks Channel 11 | $SlackChannelUri = "https://hooks.slack.com/services/ETC..ETC.." 12 | $ChannelName = "#general" 13 | 14 | $BodyTemplate = @" 15 | { 16 | "channel": "CHANNELNAME", 17 | "username": "ActiveDirectory Bot", 18 | "text": "*DOMAIN_USERNAME* account is currently locked out. \nTime: DATETIME.", 19 | "icon_emoji":":ghost:" 20 | } 21 | "@ 22 | 23 | 24 | if (Search-ADAccount -LockedOut){ 25 | foreach ($user in (Search-ADAccount -LockedOut)){ 26 | $body = $BodyTemplate.Replace("DOMAIN_USERNAME","$user").Replace("DATETIME",$(Get-Date)).Replace("CHANNELNAME","$ChannelName") 27 | Invoke-RestMethod -uri $SlackChannelUri -Method Post -body $bodytemplate -ContentType 'application/json' 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Blog/PowerShell/Send-ADLockedOutEventToTeams.ps1: -------------------------------------------------------------------------------- 1 | #requires -module ActiveDirectory 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | # The execution of this is scheduled to run every 5 minutes on ServerX 6 | 7 | # The goal of this script to notify to Teams Channel: "Test Area for Webhooks" channel 8 | # every single lockout-event in the local AD domain. 9 | 10 | #Test Webhooks Channel 11 | $TeamsChannelUri = "https://outlook.office.com/webhook/THE_REST_OF_THE_URI_HAS_BEEN_REMOVED" 12 | 13 | $BodyTemplate = @" 14 | { 15 | "@type": "MessageCard", 16 | "@context": "https://schema.org/extensions", 17 | "summary": "ADUserLockOut-Notification", 18 | "themeColor": "D778D7", 19 | "title": "Active Directory: Account Locked-Out Event", 20 | "sections": [ 21 | { 22 | 23 | "facts": [ 24 | { 25 | "name": "Username:", 26 | "value": "DOMAIN_USERNAME" 27 | }, 28 | { 29 | "name": "Time:", 30 | "value": "DATETIME" 31 | } 32 | ], 33 | "text": "An AD account is currently being locked out for 15 minutes" 34 | } 35 | ] 36 | } 37 | "@ 38 | 39 | 40 | if (Search-ADAccount -LockedOut){ 41 | foreach ($user in (Search-ADAccount -LockedOut)){ 42 | $body = $BodyTemplate.Replace("DOMAIN_USERNAME","$user").Replace("DATETIME",$(Get-Date)) 43 | Invoke-RestMethod -uri $TeamsChannelUri -Method Post -body $body -ContentType 'application/json' 44 | } 45 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Send-AdvancedLockedOutInfoToTeams.ps1: -------------------------------------------------------------------------------- 1 | #requires -module activedirectory 2 | 3 | . .\Get-LockedOutInfo.ps1 4 | 5 | # Paolo Frigo, https://www.scriptinglibrary.com 6 | 7 | #Webhooks channel 8 | $TeamsChannelUri = "PASTE_YOUR_TEAMS_URL" 9 | 10 | $BodyTemplate = @" 11 | { 12 | "@type": "MessageCard", 13 | "@context": "https://schema.org/extensions", 14 | "summary": "ADUserLockOut-Notification", 15 | "themeColor": "D778D7", 16 | "title": "Active Directory: FULLNAME Account Locked-Out", 17 | "sections": [ 18 | { 19 | 20 | "facts": [ 21 | { 22 | "name": "Username:", 23 | "value": "DOMAIN_USERNAME" 24 | }, 25 | { 26 | "name": "From Server/ Computer:", 27 | "value": "CALLERID" 28 | }, 29 | { 30 | "name": "LockoutTime Time:", 31 | "value": "LOCKOUTTIME" 32 | }, 33 | { 34 | "name": "Notification Time:", 35 | "value": "DATETIME" 36 | }, 37 | { 38 | "name": "Domain Controller:", 39 | "value": "DC" 40 | }, 41 | ], 42 | "text": "An AD account is currently being locked out for 15 minutes" 43 | } 44 | ] 45 | } 46 | "@ 47 | 48 | if (Search-ADAccount -LockedOut){ 49 | foreach ($user in (Search-ADAccount -LockedOut)){ 50 | $Event = get-lockedoutInfo -username $($user.samaccountname) -justPdc $false 51 | $body = $BodyTemplate.Replace("DOMAIN_USERNAME",$($user.samaccountname)).Replace("FULLNAME",$user.name).Replace("DATETIME",$(Get-Date)).Replace("CALLERID", $Event.callerid).Replace("DC", $Event.DC).Replace("LOCKOUTTIME", $Event.Time) 52 | Invoke-RestMethod -uri $TeamsChannelUri -Method Post -body $body -ContentType 'application/json' 53 | } 54 | } 55 | exit 0 56 | -------------------------------------------------------------------------------- /Blog/PowerShell/Send-EmailWithSendGrid.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | 4 | <# 5 | .Synopsis 6 | This function sends an email using SendGrid APIs 7 | 8 | .DESCRIPTION 9 | This function sends an email using SendGrid REST API. 10 | 11 | .EXAMPLE 12 | Send-EMailWithSendGrid -from "email@domain" -to "email@domain" -ApiKey "MY_SENDGRID_API_KEY" -Body "Test 1..2..3!" -Subject "Sendgrid Test" 13 | 14 | .NOTES 15 | Author Paolo Frigo, https://www.scriptinglibrary.com 16 | #> 17 | function Send-EmailWithSendGrid { 18 | Param 19 | ( 20 | [Parameter(Mandatory=$true)] 21 | [string] $From, 22 | 23 | [Parameter(Mandatory=$true)] 24 | [String] $To, 25 | 26 | [Parameter(Mandatory=$false)] 27 | [String] $Cc, 28 | 29 | [Parameter(Mandatory=$false)] 30 | [String] $Bcc, 31 | 32 | [Parameter(Mandatory=$true)] 33 | [string] $ApiKey, 34 | 35 | [Parameter(Mandatory=$true)] 36 | [string] $Subject, 37 | 38 | [Parameter(Mandatory=$true)] 39 | [string] $Body 40 | 41 | ) 42 | 43 | $headers = @{} 44 | $headers.Add("Authorization","Bearer $apiKey") 45 | $headers.Add("Content-Type", "application/json") 46 | 47 | $jsonRequest = [ordered]@{ 48 | personalizations= @( 49 | @{ 50 | to = @(@{email = "$To"} 51 | ) 52 | subject = "$SubJect" } 53 | ) 54 | from = @{email = "$From"} 55 | content = @( @{ type = "text/plain" 56 | value = "$Body" }) 57 | } | ConvertTo-Json -Depth 10 58 | 59 | Invoke-RestMethod -Uri "https://api.sendgrid.com/v3/mail/send" -Method Post -Headers $headers -Body $jsonRequest 60 | 61 | } 62 | 63 | # $From = "email@address" 64 | # $To = "email@address" 65 | # $APIKEY = "MY_API_KEY" 66 | # $Subject = "TEST" 67 | # $Body ="SENDGRID 123" 68 | 69 | # Send-EMailWithSendGrid -from $from -to $to -ApiKey $APIKEY -Body $Body -Subject $Subject -------------------------------------------------------------------------------- /Blog/PowerShell/Send-Report.ps1: -------------------------------------------------------------------------------- 1 | ​#Requires -RunAsAdministrator 2 | #Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | # SETTINGS EMAIL REPORT 5 | $MailRecipient = "Recipient Name " 6 | $MailSender = "Sender Name " 7 | $MailServer = "mail.server.com" 8 | $TargetServers = (Get-ADComputer -Filter * | Where-Object {$_.name -like "server-*" }).Name 9 | 10 | $ServerList = @{} 11 | #CHECK SERVER REBOOT TIME 12 | foreach ($Server in $TargetServers ) { 13 | Try { 14 | $BootUpTime = (Get-CimInstance -ClassName win32_operatingsystem -ComputerName "$Server" ).LastBootUpTime 15 | } 16 | Catch { 17 | $BootUpTime = "N/A" 18 | } 19 | $ServerList.Add($Server, $BootUpTime) 20 | } 21 | #GENERATE EMAIL REPORT 22 | Send-MailMessage -To "$MailRecipient" -From "$MailSender" -Subject "Reboot time of target servers" -Body "$($ServerList|Out-String)" -SmtpServer "$MailServer" 23 | exit 0 -------------------------------------------------------------------------------- /Blog/PowerShell/Set-FirewallRuleToAllowPing.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | # Paolo Frigo, https://www.scriptinglibrary.com 4 | # This oneliner adds an inbound rule for allowing Ping (ICMP protocol on IPv4) 5 | 6 | New-NetFirewallRule –DisplayName “Allow Ping / ICMP” –Protocol ICMPv4 -------------------------------------------------------------------------------- /Blog/PowerShell/Set-HighPerformance.ps1: -------------------------------------------------------------------------------- 1 | #Requires -RunAsAdministrator 2 | function Set-HighPerformance 3 | { 4 | <# 5 | .Synopsis 6 | Set the power option of a host to High performance. 7 | 8 | .Description 9 | Set the power option of a host to High performance. 10 | 11 | .Example 12 | PS C:\Windows\system32> Set-HighPerformance box1 13 | 14 | WARNING: *** Starting WinRM service on box1 15 | 16 | Existing Power Schemes (* Active) 17 | ----------------------------------- 18 | Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced) * 19 | Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance) 20 | Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a (Power saver) 21 | Power Scheme GUID: db310065-829b-4671-9647-2261c00e86ef (High Performance (ConfigMgr)) 22 | Set High performance power option on box1 23 | 24 | Existing Power Schemes (* Active) 25 | ----------------------------------- 26 | Power Scheme GUID: 381b4222-f694-41f0-9685-ff5bb260df2e (Balanced) 27 | Power Scheme GUID: 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c (High performance) * 28 | Power Scheme GUID: a1841308-3541-4fab-bc81-f71556f20b4a (Power saver) 29 | Power Scheme GUID: db310065-829b-4671-9647-2261c00e86ef (High Performance (ConfigMgr)) 30 | WARNING: *** Stopping WinRM service on box1 31 | 32 | .Example 33 | get-adcomputer -searchbase ‘OU=Computers,dc=contoso,dc=com’ -filter * -property * | select-object name | Set-HighPerformance 34 | 35 | Set-HighPerformance for all the workstations in AD. 36 | 37 | .Notes 38 | Author: Paolo Frigo - https://www.scriptinglibrary.com 39 | #> 40 | Param( 41 | [Parameter(Mandatory=$true, 42 | ValueFromPipeline=$true, 43 | ValueFromPipelineByPropertyName=$true, 44 | Position=0)] 45 | [Alias('name')] 46 | 47 | [string[]]$ComputerName 48 | ) 49 | Process 50 | { 51 | $winRmNotRunning =(Get-Service -ComputerName $ComputerName winrm).Status -eq "Stopped" 52 | if ($winRmNotRunning -eq "True"){ 53 | Get-Service -ComputerName $ComputerName winrm | Start-Service 54 | Write-Warning "*** Starting WinRM service on $ComputerName" 55 | } 56 | $RemoteSession = New-PSSession -ComputerName $ComputerName 57 | #$poweroption = invoke-command -ComputerName $ComputerName -ScriptBlock {powercfg -l} 58 | #$hp_guid = $poweroption | %{if($_.contains("High performance")) {$_.split()[3]}} 59 | invoke-command -Session $RemoteSession -ScriptBlock { powercfg /l } 60 | invoke-command -Session $RemoteSession -ScriptBlock { powercfg /s "8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c"} 61 | Write-Output "Set High performance power option on $ComputerName" 62 | invoke-command -Session $RemoteSession -ScriptBlock { powercfg /l } 63 | 64 | Get-Service -ComputerName $ComputerName winrm | Stop-Service 65 | Write-Warning "*** Stopping WinRM service on $ComputerName" 66 | 67 | Remove-PSSession -Session $RemoteSession 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Set-SCVMMLastBackup.ps1: -------------------------------------------------------------------------------- 1 | Import-Module -Name "virtualmachinemanager" 2 | #Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | # SETTINGS 5 | $BackupRepository = "\\YOUR\REPOSITORY\" 6 | $VMList = Get-SCVirtualMachine -VMMServer "scvmm.fqdn" 7 | 8 | function Split-VEEAMBackupFile($VMBackupFileName){ 9 | if ($VMBackupFileName.Substring($VMBackupFileName.length-9,1) -eq "_"){ 10 | $VeeamDateSize = 27 11 | } 12 | else{ 13 | $VeeamDateSize = 22 14 | } 15 | $VMNAme = $VMBackupFileName.Substring(0,$VMBackupFileName.Length-$VeeamDateSize) 16 | $DateString = $VMBackupFileName.Substring($VMNAme.Length+1, 10) 17 | $TimeString = "$($VMBackupFileName.Substring($VMNAme.Length+12,2)):$($VMBackupFileName.Substring($VMNAme.Length+14,2)):$($VMBackupFileName.Substring($VMNAme.Length+16,2))" 18 | $Datetime = "$DateString $Timestring" | Get-Date 19 | return $VMNAme,$Datetime 20 | } 21 | function Set-LastBackupProperty 22 | { 23 | param( 24 | [Parameter(Mandatory=$true, Position=0)] 25 | [string] $VMName, 26 | [Parameter(Mandatory=$true, Position=1)] 27 | [string] $LastBackupTime 28 | ) 29 | $VM = $VMList | Where-Object {$_.Name -match "$VMName"} #Get-SCVirtualMachine -Name "$VMName" 30 | $CustomProp = Get-SCCustomProperty -Name "LastBackup" 31 | $VM | Set-SCCustomPropertyValue -CustomProperty $CustomProp -Value "$LastBackupTime" 32 | } 33 | $BackupFiles = Get-ChildItem $BackupRepository |Sort-Object Name -Descending | Where-Object {$_.Name -like "*.vbk" -and $_.Length -gt 22MB}| Select-Object -exp name 34 | $VeeamFullBackup = @{} 35 | foreach ($VMBackupFileName in $BackupFiles){ 36 | $BackupRecord = Split-VEEAMBackupFile($VMBackupFileName) 37 | try{ 38 | $VeeamFullBackup.add($BackupRecord[0],$BackupRecord[1]) 39 | } 40 | catch{ 41 | #Write-warning "The Backup for $($BackupRecord[0]) has already a more recent backup than the one taken at $($BackupRecord[1]) " 42 | } 43 | } 44 | foreach ($vmname in $VeeamFullBackup.Keys){ 45 | $Datetime = $VeeamFullBackup["$vmname"].ToString("dd/MM/yyyy hh:mm") 46 | #Write-Output "Setting for $vmname the LastBackup custom Property to $Datetime" 47 | Set-LastBackupProperty -VMNAme "$vmname" -LastBackupTime "$Datetime" 48 | } 49 | exit 0 -------------------------------------------------------------------------------- /Blog/PowerShell/Set-VBoxWorkaround.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Paolo Frigo, www.scriptinglibrary.com 3 | # 4 | get-service vbox* | stop-service 5 | Set-Date -Date (Get-Date).AddDays(-60) 6 | get-service -Exclude vbox* | Where-Object {$_.status -eq "stopped" -and $_.StartType -eq "automatic"} | start-service 7 | get-service vbox* | start-service -------------------------------------------------------------------------------- /Blog/PowerShell/Show-LockedUserPopUp.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Paolo Frigo, www.scriptinglibrary.com 3 | # 4 | $header="".ToUpper() 5 | $footer=" This message will close automatically in $TimeOut seconds.".ToUpper() 6 | $NameList = "" 7 | $TimeOut = 15 #seconds 8 | 9 | $LockedOutUsersList = Search-ADAccount -LockedOut | Where-Object {$_.enabled -eq $true} 10 | 11 | if ($LockedOutUsersList.Length -gt 0){ 12 | foreach ($AdUser in $LockedOutUsersList){ 13 | $NameList += "$AdUser, " 14 | } 15 | $wshell = New-Object -ComObject Wscript.Shell 16 | $wshell.Popup($header+$NameList+$footer,$TimeOut,"AD USERS LOCKED OUT",0) 17 | } 18 | exit 0 -------------------------------------------------------------------------------- /Blog/PowerShell/Show-WiFiPassword.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://scriptinglibrary.com 2 | 3 | # This script print all WiFi setting stored in the your system 4 | # SSID : passphrase 5 | 6 | # .Notes 7 | # This script is a wrapper of this 2 netsh commands 8 | # netsh.exe wlan show profiles #Shows all your wifi 9 | # netsh.exe wlan show profiles name="$SSID" key=clear #Shows the passphrase stored for SSID wifi network in the Key Content value. 10 | 11 | $wifi = $(netsh.exe wlan show profiles) 12 | 13 | if ($wifi -match "There is no wireless interface on the system."){ 14 | Write-Output $wifi 15 | exit 16 | } 17 | 18 | $ListOfSSID = ($wifi | Select-string -pattern "\w*All User Profile.*: (.*)" -allmatches).Matches | ForEach-Object {$_.Groups[1].Value} 19 | $NumberOfWifi = $ListOfSSID.count 20 | Write-Warning "[$(Get-Date)] I've found $NumberOfWifi Wi-Fi Connection settings stored in your system $($env:computername) : " 21 | foreach ($SSID in $ListOfSSID){ 22 | try { 23 | $passphrase = ($(netsh.exe wlan show profiles name=`"$SSID`" key=clear) | 24 | Select-String -pattern ".*Key Content.*:(.*)" -allmatches).Matches | 25 | ForEach-Object {$_.Groups[1].Value} 26 | } 27 | catch { 28 | $passphrase = "N/A" 29 | } 30 | Write-Output "$SSID : $passphrase" 31 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Test-AccountLockOut.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, scriptinglibrary.com 2 | #requires -runasadministrator 3 | #requires -module ActiveDirectory 4 | 5 | #how to test ad account lockout policies 6 | 7 | #create a test user 8 | New-aduser -name "test-user" 9 | 10 | #let's check the user created 11 | Get-ADUser test-user 12 | 13 | <# 14 | DistinguishedName : CN=test-user,CN=Users,DC=contoso,DC=com 15 | Enabled : False 16 | GivenName : 17 | Name : test-user 18 | ObjectClass : user 19 | ObjectGUID : 8353f6f5-2a3d-4096-a021-a430e3f257cc 20 | SamAccountName : test-user 21 | SID : S-1-5-21-3655427247-682778731-3851803015-1103 22 | Surname : 23 | UserPrincipalName : 24 | #> 25 | 26 | #Reset the password for this user: 27 | Get-ADUser test-user | Set-ADAccountPassword 28 | <# 29 | Please enter the current password for 'CN=test-user,CN=Users,DC=contoso,DC=com' 30 | Password: 31 | Please enter the desired password for 'CN=test-user,CN=Users,DC=contoso,DC=com' 32 | Password: ********* 33 | Repeat Password: ********* 34 | #> 35 | 36 | #Let's enable our test account 37 | Get-ADUser test-user | Enable-ADAccount 38 | 39 | #let's check the AD default domain password policies 40 | Get-ADDefaultDomainPasswordPolicy 41 | 42 | <# 43 | ComplexityEnabled : True 44 | DistinguishedName : DC=contoso,DC=com 45 | LockoutDuration : 00:30:00 46 | LockoutObservationWindow : 00:30:00 47 | LockoutThreshold : 5 48 | MaxPasswordAge : 42.00:00:00 49 | MinPasswordAge : 1.00:00:00 50 | MinPasswordLength : 7 51 | objectClass : {domainDNS} 52 | objectGuid : dfc165e9-bbf7-46a3-82c8-6eecac1e2496 53 | PasswordHistoryCount : 24 54 | ReversibleEncryptionEnabled : False 55 | #> 56 | 57 | #let's double check our user before staring to test 58 | Get-ADUser test-user -properties LockedOut, LastBadPasswordAttempt 59 | <# 60 | DistinguishedName : CN=test-user,CN=Users,DC=contoso,DC=com 61 | Enabled : True 62 | GivenName : 63 | LastBadPasswordAttempt : 1/11/2018 11:37:45 PM 64 | LockedOut : False 65 | Name : test-user 66 | ObjectClass : user 67 | ObjectGUID : 8353f6f5-2a3d-4096-a021-a430e3f257cc 68 | SamAccountName : test-user 69 | SID : S-1-5-21-3655427247-682778731-3851803015-1103 70 | Surname : 71 | UserPrincipalName : 72 | #> 73 | 74 | #Let's make 5 wrong authentication attempts to lockout the test user 75 | (1..5)| ForEach-Object{runas /user:contoso\test-user cmd} 76 | <# 77 | Enter the password for contoso\test-user: 78 | Attempting to start cmd as user "contoso\test-user" ... 79 | RUNAS ERROR: Unable to run - cmd 80 | 1326: The user name or password is incorrect. 81 | Enter the password for contoso\test-user: 82 | Attempting to start cmd as user "contoso\test-user" ... 83 | RUNAS ERROR: Unable to run - cmd 84 | 1326: The user name or password is incorrect. 85 | Enter the password for contoso\test-user: 86 | Attempting to start cmd as user "contoso\test-user" ... 87 | RUNAS ERROR: Unable to run - cmd 88 | 1909: The referenced account is currently locked out and may not be logged on to. 89 | Enter the password for contoso\test-user: 90 | Attempting to start cmd as user "contoso\test-user" ... 91 | RUNAS ERROR: Unable to run - cmd 92 | 1909: The referenced account is currently locked out and may not be logged on to. 93 | Enter the password for contoso\test-user: 94 | Attempting to start cmd as user "contoso\test-user" ... 95 | RUNAS ERROR: Unable to run - cmd 96 | 1909: The referenced account is currently locked out and may not be logged on to. 97 | #> 98 | 99 | 100 | #let's check our user 101 | Get-ADUser test-user -properties LockedOut, LastBadPasswordAttempt 102 | 103 | <# 104 | DistinguishedName : CN=test-user,CN=Users,DC=contoso,DC=com 105 | Enabled : True 106 | GivenName : 107 | LastBadPasswordAttempt : 1/11/2018 11:59:00 PM 108 | LockedOut : True 109 | Name : test-user 110 | ObjectClass : user 111 | ObjectGUID : 8353f6f5-2a3d-4096-a021-a430e3f257cc 112 | SamAccountName : test-user 113 | SID : S-1-5-21-3655427247-682778731-3851803015-1103 114 | Surname : 115 | UserPrincipalName : 116 | #> 117 | 118 | #search for locked out accounts 119 | Search-ADAccount -LockedOut 120 | <# 121 | AccountExpirationDate : 122 | DistinguishedName : CN=test-user,CN=Users,DC=contoso,DC=com 123 | Enabled : True 124 | LastLogonDate : 125 | LockedOut : True 126 | Name : test-user 127 | ObjectClass : user 128 | ObjectGUID : 8353f6f5-2a3d-4096-a021-a430e3f257cc 129 | PasswordExpired : False 130 | PasswordNeverExpires : False 131 | SamAccountName : test-user 132 | SID : S-1-5-21-3655427247-682778731-3851803015-1103 133 | UserPrincipalName : 134 | #> 135 | 136 | 137 | #investigate on specific user 138 | Get-ADUser -Filter {DisplayName -like "John D*"} -Properties PasswordExpired, PasswordLastSet, EmailADdress,BadLogonCount,lastbadpasswordattempt, Lastlogondate, LockedOut, LockoutTime 139 | 140 | 141 | Get-EventLog -LogName Security -ComputerName $(Get-ADDomainController).hostname -InstanceId 4740 -newest 5 142 | <# 143 | Index Time EntryType Source InstanceID Message 144 | ----- ---- --------- ------ ---------- ------- 145 | 13236 Nov 01 23:59 SuccessA... Microsoft-Windows... 4740 A user account was locked out.... 146 | #> 147 | 148 | 149 | #Let's search for the caller ID 150 | Get-EventLog -LogName Security -ComputerName $(Get-ADDomainController).hostname -InstanceId 4740 -newest 1 | Select-Object -exp Message 151 | <# 152 | A user account was locked out. 153 | 154 | Subject: 155 | Security ID: S-1-5-18 156 | Account Name: MYDC$ 157 | Account Domain: CONTOSO 158 | Logon ID: 0x3e7 159 | 160 | Account That Was Locked Out: 161 | Security ID: S-1-5-21-3655427247-682778731-3851803015-1103 162 | Account Name: test-user 163 | 164 | Additional Information: 165 | Caller Computer Name: MYDC 166 | #> 167 | 168 | #Let's close this test by disabling the test-account 169 | Disable-ADAccount test-user -------------------------------------------------------------------------------- /Blog/PowerShell/Test-AdCredential.ps1: -------------------------------------------------------------------------------- 1 | # 2 | # Paolo Frigo, www.scriptinglibrary.com 3 | # 4 | 5 | function Test-ADCredential([SecureString] $cred) { 6 | try { 7 | start-process 'cmd' -Credential $cred 8 | $auth_success = [bool](Get-Process 'cmd' -IncludeUserName | Select-Object id, username, processname ) 9 | if ($auth_success -eq $true) { 10 | Get-Process 'cmd' -IncludeUserName | Where-Object {$_.username -eq "$($cred.Username)" } | Stop-Process -Force 11 | Write-OutPut "Autentication succedeed for $($cred.Username)" 12 | } 13 | } 14 | catch { 15 | Write-Error "Authentication Failed for $($cred.Username)" 16 | } 17 | } 18 | Test-ADCredential($(Get-Credential)) -------------------------------------------------------------------------------- /Blog/PowerShell/Test-CurrenUserIsLocalAdmin.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | function Test-CurrentUserIsLocalAdmin(){ 3 | Return [bool] ([Security.Principal.WindowsIdentity]::GetCurrent().Groups | where-object { $_.value -like "S-1-5-32-544"}) 4 | } -------------------------------------------------------------------------------- /Blog/PowerShell/Test-Job.ps1: -------------------------------------------------------------------------------- 1 | # THIS SCRIPT TEST PARALLEL EXECUTION USING JOBS 2 | # Paolo Frigo, https://www.scriptinglibrary.com 3 | 4 | $ServerList = "www.google.com", "www.bing.com", "www.yahoo.com" 5 | 6 | #CLEAR THE JOB LIST 7 | Get-Job | Remove-Job 8 | 9 | #START A LIST OF JOBS 10 | $ServerList | Foreach-object {Start-job -name "$_" -scriptblock {param ($Target) Test-connection -computername $Target -count 1} -argumentlist $_} 11 | 12 | # Note that Job States are: RUNNING, COMPLETED, FAILED 13 | # WAITS FOR ALL JOBS TO COMPLETE UP TO THE TIMEOUT LIMIT 14 | # PREVENTING THE SCRIPT TO RUN FOREVER 15 | $Timeout = 60 #seconds 16 | $Counter = 0 17 | do{Start-sleep -seconds 1; $Counter+=1} while( (Get-Job).state -contains "Running" -and $Timeout -gt $counter) 18 | 19 | #GET ALL THE RESULTS WITH KEEP (WITHOUT DELETING THEM) 20 | $ServerList | Foreach-object {Receive-Job -name $_ -keep} 21 | 22 | #CLEAR THE JOB LIST 23 | Get-Job | Remove-Job #this step is not required if KEEP flag is removed. -------------------------------------------------------------------------------- /Blog/PowerShell/Trace-Crm.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | #This script need to run on the CRM Server 3 | #https://support.microsoft.com/en-au/help/907490/how-to-enable-tracing-in-microsoft-dynamics-crm 4 | 5 | #Add-PSSnapin Microsoft.Crm.PowerShell 6 | Param ( 7 | [Parameter(Mandatory=$true)] 8 | [ValidateSet("ON","OFF")] 9 | $Status 10 | ) 11 | 12 | #SETTINGS 13 | $TraceLogDirectory = "D:\crmtracelogs\" 14 | 15 | if (Test-Path $TraceLogDirectory){ 16 | Throw "This file path for Trace Logs is NOT valid `"$TraceLogDirectory`"" 17 | } 18 | 19 | $setting = Get-CrmSetting TraceSettings 20 | if ($Status -eq "ON"){ 21 | $setting.Directory = $TraceLogDirectory 22 | $setting.Enabled = $True 23 | } 24 | else { 25 | $setting.Enabled = $False 26 | } 27 | 28 | Set-CrmSetting $setting 29 | #Get-CrmSetting TraceSettings #Prints out the Settings 30 | Write-Output "The Crm Tracing is now $Status and the tracing logs will be available on this directory $($setting.Directory)" -------------------------------------------------------------------------------- /Blog/PowerShell/Tune-Guitar.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | $StringFrequencyList = 82, 110, 146, 196, 246, 329 # E,A,D,G,B,E 4 | $Duration = 4000 # milliseconds 5 | 6 | $StringFrequencyList | Foreach-Object {[console]::beep($_,$Duration)} -------------------------------------------------------------------------------- /Blog/PowerShell/Use-AzKeyVault.ps1: -------------------------------------------------------------------------------- 1 | #requires -module Az 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | #Connect to your Azure account 6 | Connect-AzAccount 7 | 8 | #List all available Vaults 9 | Get-AzKeyVault 10 | #In case of multiple Vaults Use Tags or Name to filter the right one. 11 | 12 | # Get the Access Policies/Network Rules etc for your Vault 13 | # e.g. azkeyvscriptinglibXXXXX 14 | Get-AzKeyVault azkeyvscriptinglibXXXXX 15 | 16 | # Add a secret to the Vault 17 | $MySecret = Get-Credential 18 | Set-AzKeyVaultSecret -VaultName azkeyvscriptinglibXXXXX -name $Mysecret.username -SecretValue $Mysecret.password 19 | 20 | # Retrieve a secret from the Vault in a SecureString Format 21 | (Get-AzKeyVaultSecret -VaultName azkeyvscriptinglibXXXXX -Name $Mysecret.username).SecretValue 22 | # Retrieve a secret from the Vault into a Plain Text Format 23 | (Get-AzKeyVaultSecret -VaultName azkeyvscriptinglibXXXXX -Name $Mysecret.username).SecretValueText 24 | 25 | #Disconnect-AzAccount or Logout-AzAccount -------------------------------------------------------------------------------- /Blog/PowerShell/Veeam-Notes.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | #add the veeam snapin 6 | Add-PSSnapin VeeamPSSnapIn 7 | 8 | #check all the availabe cmdlets 9 | Get-Command -module veeampssnapin 10 | 11 | #connect to a veeam backup server 12 | Connect-VBRServer 13 | 14 | #get the details user, server, port of the opened connections 15 | Get-VBRServerSession 16 | 17 | #get a list of all Servers MS HYPER-V and or VMWare-vSphere 18 | Get-VBRServer 19 | 20 | #Find the VM on WMWARE 21 | Find-VBRViEntity 22 | 23 | #Find the VM on Hyper-V 24 | Find-VBRHvEntity 25 | 26 | #Get the VBR Credentials 27 | Get-VBRCredentials 28 | 29 | #Let's use this example 30 | 31 | $hyperv_node = "hyper-lab.contoso.com" # or a list of nodes 32 | $vm_name = "testd-web01" 33 | $vm=Find-VBRHvEntity -server $hyperv_node -name $vm_name 34 | $nas="\\nas.contoso.com\Archive" 35 | $vmm_cred = Get-VBRCredentials | Where-Object {$_.description -like "scvmm"} 36 | $email_notify_to= "me@contoso.com" 37 | $email_notify_from = "veeam-bkp@contoso.com" 38 | $mailserver = "mail.contoso.com" 39 | $smtpport=587 40 | $emailsubject = "VM Full backup - VEEAMZIP Weekly report" 41 | 42 | Find-VBRHvEntity -server $hyperv_node -name $vm_name 43 | 44 | #Or list the all the VMs 45 | Get-VBRServer -Name $hyperv_node | Find-VBRHvEntity 46 | 47 | #Compress with VeeamZip 48 | Start-VBRZip -Folder $nas -Entity $vm -Compression 4 -DisableQuiesce -AutoDelete In2Weeks -NetworkCredentials $vmm_cred -RunAsync 49 | 50 | #These week Backups 51 | $BACKUP_SUMMARY = Get-ChildItem $nas | Select-Object NAME, LastWriteTime, @{N='SizeInGB';E={[math]::Round($_.length / 1GB,2)}} | Where-Object {$_.LASTWRITETIME -gt $(Get-Date).ADDdAYS(-7) } | ConvertTo-Html 52 | 53 | #Send an email 54 | Send-MailMessage -subject $emailsubject -BodyAsHtml "$BACKUP_SUMMARY" -From $email_notify_from -to $email_notify_to -SmtpServer $mailserver -port $smtpport 55 | 56 | -------------------------------------------------------------------------------- /Blog/PowerShell/Workaround-CVE-2020-1350.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | #requires -Version 5.1 3 | 4 | # Paolo Frigo, https://www.scriptinglibrary.com 5 | 6 | # https://nvd.nist.gov/vuln/detail/CVE-2020-1350 7 | # https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350 8 | 9 | $RegBackupFile = "c:\windows\temp\DNS-CVE-2020-1350.reg" 10 | 11 | #Conditions for applying the workaround DNS Role installed, DNS Server running 12 | $DNSServerInstalled = [bool] (Get-WindowsFeature | Where-Object {($_.name -like "DNS") -and ($_.InstallState -eq "Installed")}) 13 | $DNSServerRunning = (Get-Service DNS -ErrorAction Ignore).Status -eq "Running" 14 | 15 | function Check-Workaround(){ 16 | try { 17 | if (Get-ItemPropertyValue -path "HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\" -Name TcpReceivePacketSize){ 18 | return $True # Workaround already applied 19 | } 20 | } 21 | catch { 22 | Return $False #No workaround applied 23 | } 24 | } 25 | 26 | function Apply-Workaround(){ 27 | if ($DNSServerInstalled -and $DNSServerRunning -and $($(Check-Workaround) -eq $false)){ 28 | Write-Verbose "DNS SERVER service is Installed and Running, Workaround not found in the registry" 29 | 30 | Write-Output "Starting to Backup of the Registry ( $RegBackupFile ) before applying the workaround" 31 | reg export "HKLM\SYSTEM\CurrentControlSet\Services\DNS\Parameters\" $RegBackupFile 32 | 33 | New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\" -Name TcpReceivePacketSize -PropertyType DWORD -Value 0xFF00 34 | Restart-Service DNS -verbose -Confirm 35 | Write-Output "Workaround applied." 36 | 37 | } 38 | } 39 | 40 | function Remove-Workaround(){ 41 | if ($DNSServerInstalled -and $DNSServerRunning -and $($(Check-Workaround) -eq $true)){ 42 | Write-Verbose "DNS SERVER service is Installed and Running, Workaround found in the registry" 43 | Remove-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\DNS\Parameters\" -Name TcpReceivePacketSize -Confirm 44 | Restart-Service DNS -verbose -Confirm 45 | Write-Output "Workaround removed." 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Blog/PowerShell/check-defender.ps1: -------------------------------------------------------------------------------- 1 | #Paolo Frigo, https://scriptinglibrary.com 2 | 3 | #This is a simple powershell script to monitor MS Defender for Endpoints and it can be used with Nagios Core / Nagios XI 4 | 5 | $DefenderRunninigAndRealTimesOn = $(Get-Service Windefend).Status -eq "Running" -and $(Get-MpComputerStatus).RealTimeProtectionEnabled 6 | $ExitStatus = 0 7 | $Message = "OK" 8 | if ($DefenderRunninigAndRealTimesOn -eq $False){ 9 | $Message = "CRITICAL - Microsoft Defender is not running or the real-time protection was disabled" 10 | $ExitStatus = 2 11 | } 12 | if ([bool] (Get-MpThreatDetection) -eq $True){ 13 | $Message = "CRITICAL - Microsoft Defender has detected some threats recently" 14 | $ExitStatus = 2 15 | } 16 | if ([bool]((Get-MpComputerStatus).AntivirusSignatureLastUpdated -lt (Get-date).AddDays(-7)) -eq $True) { 17 | $Message = "CRITICAL - Microsoft Defender AV Definitions are older than a week" 18 | $ExitStatus = 2 19 | } 20 | Write-Output $Message 21 | exit $ExitStatus -------------------------------------------------------------------------------- /Blog/PowerShell/check-vmstatus.ps1: -------------------------------------------------------------------------------- 1 | #requires -module hyper-v 2 | 3 | #Paolo Frigo, https://www.scriptinglibrary.com 4 | 5 | foreach ($i in $(Get-VM)){ 6 | if ($i.status -ne "Operating normally"){ 7 | Write-Output "$i.name - $i.staus" 8 | exit 2 9 | } 10 | } 11 | Write-Output "All VMs are Operating normally" 12 | exit 0 -------------------------------------------------------------------------------- /Blog/PowerShell/compress-log.ps1: -------------------------------------------------------------------------------- 1 | #requires -runasadministrator 2 | 3 | # Paolo Frigo https://www.scriptinglibrary.compress 4 | 5 | # List of Log Folders 6 | $Logs = "D:\Logs\W3SVC6", "D:\Logs\W3SVC5", "D:\Logs\W3SVC4", "D:\Logs\W3SVC3", "D:\Logs\W3SVC2" 7 | 8 | 9 | $oldpath = $pwd 10 | 11 | function compress-log { 12 | [CmdletBinding()] 13 | param ( 14 | [Parameter(Mandatory)] 15 | [string] 16 | $LogDir 17 | ) 18 | 19 | 20 | Set-Location $LogDir 21 | $Logs = $(Get-ChildItem *log) 22 | 23 | 24 | $counter = 1 25 | foreach ($log in $Logs){ 26 | Write-Progress -Activity "Activity: Compressing $log" -Status "Compressing $log" -PercentComplete "$($counter/($logs.count)*100)" 27 | 28 | 29 | $Compress=@{ 30 | Path = "$log" 31 | DestinationPath= "$log.zip" 32 | CompressionLevel = "Fastest" 33 | } 34 | Compress-Archive @Compress 35 | if (Test-Path $Compress.DestinationPath){ 36 | Remove-Item $log 37 | } 38 | $counter = $counter + 1 39 | } 40 | } 41 | 42 | 43 | foreach ($LogFolder in $Logs){ 44 | if (Test-Path $LogFolder){ 45 | Write-Output "STARTING TO COMPRESS LOGS IN $LogFolder" 46 | compress-log -LogDir $LogFolder 47 | } 48 | } 49 | Set-Location $oldpath -------------------------------------------------------------------------------- /Blog/PowerShell/get-installedsoftware.ps1: -------------------------------------------------------------------------------- 1 |  2 | # I'm not the author of the function Get-InstalledSoftware 3 | # More info on: 4 | # https://github.com/RamblingCookieMonster/PowerShell/blob/master/Get-InstalledSoftware.ps1 5 | 6 | # I'm just using sharing this implementation on scriptinglibary.com 7 | 8 | function Get-InstalledSoftware { 9 | <# 10 | .SYNOPSIS 11 | Pull software details from registry on one or more computers 12 | 13 | .DESCRIPTION 14 | Pull software details from registry on one or more computers. Details: 15 | -This avoids the performance impact and potential danger of using the WMI Win32_Product class 16 | -The computer name, display name, publisher, version, uninstall string and install date are included in the results 17 | -Remote registry must be enabled on the computer(s) you query 18 | -This command must run with privileges to query the registry of the remote system(s) 19 | -Running this in a 32 bit PowerShell session on a 64 bit computer will limit your results to 32 bit software and result in double entries in the results 20 | 21 | .PARAMETER ComputerName 22 | One or more computers to pull software list from. 23 | 24 | .PARAMETER DisplayName 25 | If specified, return only software with DisplayNames that match this parameter (uses -match operator) 26 | 27 | .PARAMETER Publisher 28 | If specified, return only software with Publishers that match this parameter (uses -match operator) 29 | 30 | .EXAMPLE 31 | #Pull all software from c-is-ts-91, c-is-ts-92, format in a table 32 | Get-InstalledSoftware c-is-ts-91, c-is-ts-92 | Format-Table -AutoSize 33 | 34 | .EXAMPLE 35 | #pull software with publisher matching microsoft and displayname matching lync from c-is-ts-91 36 | "c-is-ts-91" | Get-InstalledSoftware -DisplayName lync -Publisher microsoft | Format-Table -AutoSize 37 | 38 | .LINK 39 | http://gallery.technet.microsoft.com/scriptcenter/Get-InstalledSoftware-Get-5607a465 40 | 41 | .FUNCTIONALITY 42 | Computers 43 | #> 44 | param ( 45 | [Parameter( 46 | Position = 0, 47 | ValueFromPipeline=$true, 48 | ValueFromPipelineByPropertyName=$true, 49 | ValueFromRemainingArguments=$false 50 | )] 51 | [ValidateNotNullOrEmpty()] 52 | [Alias('CN','__SERVER','Server','Computer')] 53 | [string[]]$ComputerName = $env:computername, 54 | 55 | [string]$DisplayName = $null, 56 | 57 | [string]$Publisher = $null 58 | ) 59 | 60 | Begin 61 | { 62 | 63 | #define uninstall keys to cover 32 and 64 bit operating systems. 64 | #This will yeild only 32 bit software and double entries on 64 bit systems running 32 bit PowerShell 65 | $UninstallKeys = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", 66 | "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall" 67 | 68 | } 69 | 70 | Process 71 | { 72 | 73 | #Loop through each provided computer. Provide a label for error handling to continue with the next computer. 74 | :computerLoop foreach($computer in $computername) 75 | { 76 | 77 | Try 78 | { 79 | #Attempt to connect to the localmachine hive of the specified computer 80 | $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$computer) 81 | } 82 | Catch 83 | { 84 | #Skip to the next computer if we can't talk to this one 85 | Write-Error "Error: Could not open LocalMachine hive on $computer`: $_" 86 | Write-Verbose "Check Connectivity, permissions, and Remote Registry service for '$computer'" 87 | Continue 88 | } 89 | 90 | #Loop through the 32 bit and 64 bit registry keys 91 | foreach($uninstallKey in $UninstallKeys) 92 | { 93 | 94 | Try 95 | { 96 | #Open the Uninstall key 97 | $regkey = $null 98 | $regkey = $reg.OpenSubKey($UninstallKey) 99 | 100 | #If the reg key exists... 101 | if($regkey) 102 | { 103 | 104 | #Retrieve an array of strings containing all the subkey names 105 | $subkeys = $regkey.GetSubKeyNames() 106 | 107 | #Open each Subkey and use GetValue Method to return the required values for each 108 | foreach($key in $subkeys) 109 | { 110 | 111 | #Build the full path to the key for this software 112 | $thisKey = $UninstallKey+"\\"+$key 113 | 114 | #Open the subkey for this software 115 | $thisSubKey = $null 116 | $thisSubKey=$reg.OpenSubKey($thisKey) 117 | 118 | #If the subkey exists 119 | if($thisSubKey){ 120 | try 121 | { 122 | 123 | #Get the display name. If this is not empty we know there is information to show 124 | $dispName = $thisSubKey.GetValue("DisplayName") 125 | 126 | #Get the publisher name ahead of time to allow filtering using Publisher parameter 127 | $pubName = $thisSubKey.GetValue("Publisher") 128 | 129 | #Collect subset of values from the key if there is a displayname 130 | #Filter by displayname and publisher if specified 131 | if( $dispName -and 132 | (-not $DisplayName -or $dispName -match $DisplayName ) -and 133 | (-not $Publisher -or $pubName -match $Publisher ) 134 | ) 135 | { 136 | 137 | #Display the output object, compatible with PowerShell 2 138 | New-Object PSObject -Property @{ 139 | ComputerName = $computer 140 | DisplayName = $dispname 141 | Publisher = $pubName 142 | Version = $thisSubKey.GetValue("DisplayVersion") 143 | UninstallString = $thisSubKey.GetValue("UninstallString") 144 | InstallDate = $thisSubKey.GetValue("InstallDate") 145 | } | select ComputerName, DisplayName, Publisher, Version, UninstallString, InstallDate 146 | } 147 | } 148 | Catch 149 | { 150 | #Error with one specific subkey, continue to the next 151 | Write-Error "Unknown error: $_" 152 | Continue 153 | } 154 | } 155 | } 156 | } 157 | } 158 | Catch 159 | { 160 | 161 | #Write verbose output if we couldn't open the uninstall key 162 | Write-Verbose "Could not open key '$uninstallkey' on computer '$computer': $_" 163 | 164 | #If we see an access denied message, let the user know and provide details, continue to the next computer 165 | if($_ -match "Requested registry access is not allowed"){ 166 | Write-Error "Registry access to $computer denied. Check your permissions. Details: $_" 167 | continue computerLoop 168 | } 169 | 170 | } 171 | } 172 | } 173 | } 174 | } 175 | 176 | 177 | #Create a CSV report with all the installed software 178 | $ReportFileName = "InstalledSoftware-$($env:COMPUTERNAME)-$(Get-Date -Format "yyyyMMdd").csv" #Read-Host -Prompt "Report Name (e.g. mypc.csv)" 179 | Get-InstalledSoftware | Export-csv $ReportFileName -NoTypeInformation -------------------------------------------------------------------------------- /Blog/PowerShell/monitor-process.ps1: -------------------------------------------------------------------------------- 1 | # Paolo Frigo, https://www.scriptinglibrary.com 2 | 3 | # This script will monitor the chosen processes and output the selected informations onto a csv file. 4 | 5 | $ProcessName = "*" 6 | $LogFile = $PSScriptRoot+"\MyCustomLogs.csv" 7 | 8 | 9 | #Creates the file if it doesn't exists adding the header for the CSV 10 | if ((Test-Path $LogFile) -eq $False){ 11 | Set-Content -Value "Date, ProcessName, ID, CPU, Mem, TotalRAM" -Path $LogFile 12 | } 13 | 14 | $datetime = Get-Date -Format "dd/M/yyyy hh:mm:ss" 15 | $total_mem=(systeminfo | Select-String 'Total Physical Memory:').ToString().Split(':')[1].Replace(" ", "") 16 | $processes=get-process $ProcessName| Select-Object PM, CPU, Name, Id #Selected fields for the processes 17 | 18 | foreach ($proc in $processes){ 19 | Add-Content -Value "$($datetime), $($proc.Name), $($proc.ID), $($proc.CPU), $([math]::Round($proc.PM/(1024*1024),2))MB, $($total_mem)" -Path $LogFile 20 | } 21 | exit 0 -------------------------------------------------------------------------------- /Blog/PowerShell/rdg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | True 7 | ScriptingLibrary 8 | 9 | 10 | 11 | True 12 | Servers 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Blog/Python/combineapacheconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ This script combines your APACHE httpd.conf with all included files\ 3 | into one and redirects it to the standard output. """ 4 | __author__ = "ben", "PAOLO FRIGO | www.scriptinglibrary.com" 5 | 6 | import os 7 | import os.path 8 | import logging 9 | import fnmatch 10 | import re 11 | import argparse 12 | 13 | def ProcessMultipleFiles(inputfiles): 14 | """ Process an expression with /* with all the files included on that directory """ 15 | if inputfiles.endswith("/"): 16 | inputfiles = inputfiles + "*" 17 | content = "" 18 | localfolder = os.path.dirname(inputfiles) 19 | basenamepattern = os.path.basename(inputfiles) 20 | for root, dirs, files in os.walk(localfolder): 21 | for filename in fnmatch.filter(files, basenamepattern): 22 | content += ProcessInput(os.path.join(root, filename)) 23 | return content 24 | 25 | 26 | def RemoveExcessiveLinebreak(lineofcontent): 27 | """ Remove Excessive Linebreaks form the line of content passed as argument """ 28 | length = len(lineofcontent) 29 | lineofcontent = lineofcontent.replace( 30 | os.linesep + os.linesep + os.linesep, os.linesep + os.linesep 31 | ) 32 | newlength = len(lineofcontent) 33 | if newlength < length: 34 | lineofcontent = RemoveExcessiveLinebreak(lineofcontent) 35 | return lineofcontent 36 | 37 | 38 | def ProcessInput(inputfile): 39 | """ This function accepts an input path for the httpd conf file, searchs 40 | for 'include' and replaces it with the matchin content of the included 41 | file, add starts and end comments and removes all other comments or 42 | spaces. """ 43 | content = "" 44 | if logging.root.isEnabledFor(logging.DEBUG): 45 | content = "# Start of " + inputfile + os.linesep 46 | with open(inputfile, "r") as infile: 47 | for line in infile: 48 | stripline = line.strip(" \t") 49 | if stripline.startswith("#"): 50 | continue 51 | # search for serverroot 52 | searchroot = re.search(r"serverroot\s+(\S+)", stripline, re.I) 53 | if searchroot: 54 | serverroot = searchroot.group(1).strip('"') 55 | logging.info("serverroot: " + serverroot) 56 | if stripline.lower().startswith("include"): 57 | match = stripline.split() 58 | if len(match) == 2: 59 | includefiles = match[1] 60 | includefiles = includefiles.strip('"') 61 | if not includefiles.startswith("/"): 62 | includefiles = os.path.join(serverroot, includefiles) 63 | content += ProcessMultipleFiles(includefiles) + os.linesep 64 | else: 65 | content += line 66 | else: 67 | content += line 68 | content = RemoveExcessiveLinebreak(content) 69 | if logging.root.isEnabledFor(logging.DEBUG): 70 | content += "# End of " + inputfile + os.linesep + os.linesep 71 | return content 72 | 73 | 74 | if __name__ == "__main__": 75 | logging.basicConfig( 76 | level=logging.DEBUG, format="[%(asctime)s][%(levelname)s]:%(message)s" 77 | ) 78 | PARSER = argparse.ArgumentParser( 79 | description="""DESCRIPTION: This script combines your APACHE httpd.conf with 80 | all included files into one and redirects it to the standard output.""", 81 | usage="./combineapacheconfig.py /etc/httpd/conf/httpd.conf \ 82 | ./combineapacheconfig.py -h ", 83 | epilog="""Author :Ben, Paolo Frigo""", 84 | ) 85 | PARSER.add_argument( 86 | "apacheconf", 87 | default="/etc/httpd/conf/httpd.conf", 88 | help="SPECIFY YOUR HTTPD/APACHE CONF FILE PATH. \ 89 | i.e. /etc/httpd/conf/httpd.conf", 90 | ) 91 | USERSARGS = PARSER.parse_args() 92 | try: 93 | serverroot = os.path.dirname(USERSARGS.apacheconf) 94 | content = ProcessInput(USERSARGS.apacheconf) 95 | except Exception as e: 96 | logging.error("Failed to process " + USERSARGS.apacheconf, exc_info=True) 97 | exit(1) 98 | print(content) 99 | -------------------------------------------------------------------------------- /Blog/Python/emailchecker.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | """ This script checks if an email address exists on a mailserver. """ 3 | 4 | __author__ = "PAOLO FRIGO | https://www.scriptinglibrary.com" 5 | 6 | import logging 7 | import argparse 8 | from smtplib import SMTP 9 | 10 | MAILSERVER = "your.mailserver.com" 11 | PORT = 25 12 | DEBUG_MODE = False 13 | RFC_LINK = r"https://goo.gl/9hYJQg" 14 | 15 | if __name__ == "__main__": 16 | 17 | PARSER = argparse.ArgumentParser( 18 | description="""DESCRIPTION: This script checks if an email address 19 | exists on a mailserver. """, 20 | usage="\n./emailchecker.py email@address \ 21 | \n./emailchecker.py -h \t\tfor help", 22 | epilog="""Author : Paolo Frigo""", 23 | ) 24 | 25 | PARSER.add_argument("emailaddress", help="email_address") 26 | PARSER.add_argument( 27 | "--mailserver", required=False, default=MAILSERVER, help="mailserver address" 28 | ) 29 | PARSER.add_argument( 30 | "--port", required=False, default=PORT, type=int, help="port number" 31 | ) 32 | USERSARGS = PARSER.parse_args() 33 | 34 | logging.basicConfig( 35 | level=logging.DEBUG if DEBUG_MODE else logging.ERROR, 36 | format="[%(asctime)s][%(levelname)s]: %(message)s", 37 | ) 38 | logging.info("Email checker script started") 39 | 40 | try: 41 | with SMTP(host=USERSARGS.mailserver, port=USERSARGS.port) as smtp: 42 | logging.info( 43 | "Connecting to {}:{}".format(USERSARGS.mailserver, USERSARGS.port) 44 | ) 45 | result = smtp.verify(USERSARGS.emailaddress) 46 | print("SMTP CODE: {} \nMESSAGE: {}".format(*result)) 47 | logging.info("RFC1893, SMTP CODES: {}".format(RFC_LINK)) 48 | logging.info("Connection closed ") 49 | except: 50 | logging.error( 51 | "Failed to connect to {}:{}".format(USERSARGS.mailserver, USERSARGS.port) 52 | ) 53 | -------------------------------------------------------------------------------- /Blog/Python/monitorconnection.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | #Paolo Frigo, https://scriptinglibrary.com 4 | 5 | import speedtest #pip3 install speedtest-cli 6 | import os 7 | from datetime import datetime 8 | 9 | logfile = "speedtest.log" 10 | 11 | isp = speedtest.Speedtest() 12 | srv = isp.get_best_server() 13 | downstream = "{0:,.2f} Mb".format(float(isp.download()/10**6)) 14 | upstream = "{0:,.2f} Mb".format(float(isp.upload()/10**6)) 15 | latency = "{0:,.0f} ms".format(float(srv['latency'])) 16 | update = datetime.strftime(datetime.now(),'%d/%m/%y %I:%M%p') 17 | 18 | with open(logfile, 'a+') as file: 19 | file.write(F"{update},{downstream},{upstream},{latency}\n") 20 | print (f"{logfile} updated") -------------------------------------------------------------------------------- /Blog/Python/sketchpaint.py: -------------------------------------------------------------------------------- 1 | # This was written in 2006 and released as a micro open-source project for education purpose in 2009. 2 | # It's one of my first python pet project 3 | # All variable and function names are in Italian. 4 | 5 | #SketchPynt -v 0.1, Paolo Frigo 6 | import Tkinter, tkColorChooser, string, tkMessageBox, cPickle, tkFileDialog 7 | 8 | VERSIONE="SketchPynt! v0.1" 9 | AUTORE="SketchPynt!\n[PF] Paolo Frigo" 10 | #DEFAULT, Impostazioni predefinite 11 | COLORE="#000000" #Colore della matita 12 | SFONDO="#FFFFFF" #Colore di sfondo e della gomma 13 | SIZE=[500,500] #Dimensione Area di Disegno 14 | MATITA=6 #Dimensione della matita 15 | GOMMA=20 #Dimensione della gomma 16 | 17 | def clean(): 18 | canvas.delete('all') 19 | initCanvas() 20 | def infoPro(): 21 | tkMessageBox.showinfo(title=VERSIONE, message=AUTORE) 22 | def initCanvas(): 23 | Lavagna=canvas.create_rectangle(5, 5, SIZE[0]-5, SIZE[0]-5, fill=SFONDO, outline=COLORE ) 24 | canvas.config(cursor='crosshair') 25 | canvas.tag_bind(Lavagna,'', onCanvasMov1) 26 | canvas.tag_bind(Lavagna,'', onCanvasMov2) 27 | canvas.tag_bind(Lavagna,'', impostaColore) 28 | def impostaColore( event): 29 | coloreNuovo=tkColorChooser.askcolor() 30 | global COLORE 31 | COLORE=coloreNuovo[1] 32 | def onCanvasMov1(event): 33 | canvas.create_oval(event.x-(MATITA/2), event.y-(MATITA/2), event.x+(MATITA/2), event.y+(MATITA/2), fill=COLORE, outline=COLORE) 34 | def onCanvasMov2(event): 35 | canvas.create_rectangle(event.x-(GOMMA/2), event.y-(GOMMA/2), event.x+(GOMMA/2), event.y+(GOMMA/2), fill=SFONDO, outline=SFONDO) 36 | def stampa(): 37 | file_da_salvare=tkFileDialog.asksaveasfilename(title='Esporta Disegno', filetypes=[ ('File PostScript!','*.ps')]) 38 | canvas.postscript(file=file_da_salvare) 39 | finestra=Tkinter.Tk() 40 | finestra.title(VERSIONE) 41 | canvas=Tkinter.Canvas(bg='white', width=SIZE[0], height=SIZE[1]) 42 | canvas.pack(side=Tkinter.BOTTOM) 43 | initCanvas() 44 | menu=Tkinter.Menu(finestra) 45 | finestra.config(menu=menu) 46 | filemenu=Tkinter.Menu(menu) 47 | menu.add_cascade(label="File", menu=filemenu) 48 | filemenu.add_command(label="Nuovo", command=clean) 49 | filemenu.add_command(label="Stampa", command=stampa) 50 | filemenu.add_command(label="Esci",command=finestra.quit) 51 | aboutmenu = Tkinter.Menu(menu) 52 | menu.add_cascade(label="?", menu=aboutmenu) 53 | aboutmenu.add_command(label="Info", command=infoPro) 54 | finestra.mainloop() 55 | -------------------------------------------------------------------------------- /Blog/Python/urlfromsitemap.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import argparse, logging 3 | import xml.etree.ElementTree as ET 4 | 5 | #Paolo Frigo, https://www.scriptinglibrary.com 6 | 7 | parser = argparse.ArgumentParser( 8 | description='THIS SCRIPTS PRINTS ALL URLs IN THE SITEMAP.XML FILE', 9 | usage="./urlfromsitemap.py sitemap.xml ", epilog='Author: Paolo Frigo') 10 | 11 | parser.add_argument('sitemap', default='sitemap.xml', help='sitemap.xml') 12 | args = parser.parse_args() 13 | 14 | try: 15 | tree = ET.parse(args.sitemap) 16 | root = tree.getroot() 17 | 18 | for child in root: 19 | print (child[0].text) 20 | 21 | except: 22 | logging.error("Failed to process " + args.sitemap, exc_info=True) 23 | exit(1) -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at paolo@scriptinglibrary.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /Media/mini_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaoloFrigo/scriptinglibrary/1c584b5339ef6547debc2755d479969376fe0a57/Media/mini_logo.png -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | 2 | This repository is a collection of scripts published on [SCRIPTING LIBRARY](http://www.scriptinglibrary.com) and created by Paolo Frigo. 3 | 4 | ![scriptinglibrary logo](Media/mini_logo.png) 5 | 6 | ## SCRIPTING LIBRARY 7 | Scripting Library is a collection of scripts and experiences shared by IT Pros, Developers, DevOps and Geeks across Linux and Windows OS with BaSH, PowerShell and Python from all over the world. 8 | 9 | ## LANGUAGES 10 | * Powershell 11 | * Python 12 | * BaSH 13 | * NodeJS 14 | 15 | ## LICENSE 16 | 17 | This work is licensed under a Creative Commons Attribution 4.0 International License. 18 | 19 | ## SHOW YOUR SUPPORT 20 | Don't forget to give a ⭐️ if you found this repository useful! 21 | 22 | 23 | ## DISCLAIMER 24 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | 32 | --------------------------------------------------------------------------------