Popular Posts

Monday, August 31, 2020

Extending a disk on a window system using PowerShell and PowerCLI

Identify the correct disk to extend on OS

param(

[string]$drivename #ex: C or D
$percentage = 1.1

)

try{

$moddrivename = $drivename + ":"

$extendnumber = [math]::Round(((Get-WmiObject -Class Win32_LogicalDisk | where DeviceID -like $moddrivename | select -ExpandProperty Size) /1TB)*$percentage)

if ($extendnumber -ge 2) {

return "2TBDisk"

}

$searchstring = '\\' +$env:computername+ '\root\cimv2:Win32_LogicalDisk.DeviceID="' +$drivename+ ':"'

$disknumberlong = Get-WmiObject -Class Win32_LogicalDiskToPartition | where Dependent -Like $searchstring | select -ExpandProperty Antecedent

$disknumberlong -match 'Disk #(\d+)' | out-null

$disknumber = $matches[0].split('#')[1]

return $disknumber

} catch {

throw

}




Extending VM disk

param(

[String]$serverfqdn,
[String]$disknumber, #passed from the previous script
[double]$percentage=1.1 #percentage at which the disk should be extended by

)

Get-Module -Name VMware* -ListAvailable | Import-Module #call PowerCLI module


$vcusername = ''
$vcpassword = ''

$hostname = $serverfqdn.split(".")[0]

if ($hostname -like 'some naming convention') {

$vcservers = @("vc1","vc2")

foreach ($vc in $vcservers) {

Connect-VIServer -Server $vc -User $vcusername -Password $vcpassword

if ($vm = Get-VM $hostname) {

$correctvc = $vc
break

}

else {

Disconnect-VIServer -Server $vc -Confirm:$false
continue

}

}

} elseif ($hostname -like 'some naming convention 2') {

$vcservers = @("vc3","vc4")

foreach ($vc in $vcservers) {

Connect-VIServer -Server $vc -User $vcusername -Password $vcpassword

if ($vm = Get-VM $hostname) {

$correctvc = $vc
break

}

else {

Disconnect-VIServer -Server $vc -Confirm:$false
continue

}

}

}

#we assume most disks are using the first controller
$SCSI = '0:'+$disknumber

#heres the tricky part, pass each disk on the VM to get-scsicontroller which returns it's respective busnumber and unit number. Then get the disk name by filtering the result using the $SCSI variable.
$diskname = Get-VM $hostname | Get-HardDisk | Select @{N='VM';E={$_.Parent.Name}},Name,@{N='Node';E={'{0}:{1}' -f ((Get-ScsiController -HardDisk $_).ExtensionData.BusNumber),$_.ExtensionData.UnitNumber}} | where Node-like $SCSI | select Name -ExpandProperty Name

$disksize = Get-HardDisk -VM $hostname | where {$_.Name -eq $diskname} | select -ExpandProperty CapacityGB

$newdisksize = $disksize*$percentage

Write-Host $newdisksize

Get-HardDisk -VM $hostname | where {$_.Name -eq $diskname} | Set-HardDisk -CapacityGB $newdisksize -confirm:$false

Disconnect-VIServer -Server $correctvc -Confirm:$false



Extending disk on OS

param(

[string]$drivename,
[double]$percentage=0.1

)


try{

"RESCAN" | diskpart

$moddrivename = $drivename + ":"

$extendnumber = [math]::Round(((Get-WmiObject -Class Win32_LogicalDisk | where DeviceID -like $moddrivename | select -ExpandProperty Size) /1MB)*$percentage)
write-host $extendnumber

$searchstring = '\\' +$env:computername+ '\root\cimv2:Win32_LogicalDisk.DeviceID="' +$drivename+ ':"'

$disknumberlong = Get-WmiObject -Class Win32_LogicalDiskToPartition | where Dependent -Like $searchstring | select -ExpandProperty Antecedent

$disknumberlong -match 'Disk #(\d)'

$disknumber = $matches[0].split('#')[1]

$string1 = "select disk " + $disknumber
$string2 = "select volume " + $drivename
$string3 = "extend size=" + $extendnumber

$commands = @(
$string1,
$string2,
$string3
)

$commands | diskpart

Write-Host "Disk extension on OS layer completed"
exit 0

} catch {

Write-Host "Disk extension on OS layer failed"
exit -1

}

Thursday, August 20, 2020

Common SSL/TLS vulnerability fixes

SSL/TLS Diffie-Hellman Modulus <= 1024 Bits (Logjam)

Configure the following registry and restart the server


[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\KeyExchangeAlgorithms\Diffie-Hellman]

"ServerMinKeyBitLength"=dword:00000800




Transport Layer Security (TLS) Protocol CRIME Vulnerability - Splunkd port 8089


Change allowSslCompression = true to false and restart splunkforwarder service


C:\Program Files\SplunkUniversalForwarder\etc\system\default>more server.conf | findstr allowSslCompression

allowSslCompression = false




SSL/TLS Diffie-Hellman Modulus <= 1024 Bits (Logjam)


Add the following line in sshd_config and restart sshd service


# Ciphers and keying

Ciphers chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com

 

Thursday, August 13, 2020

Shutdown and Startup VMs using PowerCLI

Shutdown

param (
[Parameter(Mandatory=$true)]
$serverslistfile
)
function writetolog([string] $txt) {
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
Add-content $logfile -value $Stamp':'$txt
}
$vCenter = 'vcentername'
$logfile = 'C:\Windows\Temp\DR_ShutdownVMs.log'
$serverslist = Get-Content $serverslistfile
Write-host "############################## ABC company DR activity - Shutdown VMs ##############################"
writetolog("############################## ABC company DR activity - Shutdown VMs ##############################")
Write-Host "vCenter server selected : "$vCenter
writetolog("vCenter server selected : " + $vCenter)
Write-Host "Servers list selected : "
writetolog("Servers list selected : ")
$serverslist | ForEach-Object { Write-Host $_ ; writetolog($_) }
$Confirm = Read-Host "Please type 'ok' to confirm selection is correct"
if($Confirm -eq 'ok') {
writetolog("Proceed: OK by $env:UserName")
try{
Connect-VIServer $vCenter
Write-Host "Successfully connected to $vCenter vCenter"
writetolog("Successfully connected to $vCenter vCenter")
} catch {
Write-Host "Cannot connect to $vCenter vCenter, Exiting Program"
writetolog("Cannot connect to $vCenter vCenter, Exiting Program")
exit -1
}
$serverslist | foreach-object {
if((Get-VM $_ | select -ExpandProperty PowerState) -eq "PoweredOn") {
try {
shutdown-vmguest $_ -Confirm:$false | Out-Null
Write-Host $_ "Shutdown-ed"
writetolog($_ + " Shutdown-ed")
} catch{
Write-host $_ "Error"
writetolog($_ + " Error Shutting down")
}
} else {
Write-host $_ "Already Powered Down"
writetolog($_ + " Already Powered Down")
}
}
Disconnect-VIServer $vCenter -Confirm:$false
Write-Host "Successfully disconnected from $vCenter vCenter"
writetolog("Successfully disconnected from $vCenter vCenter")
} else {
exit
}




Startup


param (
[Parameter(Mandatory=$true)]
$serverslistfile
)
function writetolog([string] $txt) {
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
Add-content $logfile -value $Stamp':'$txt
}
$vCenter = 'vcentername'
$logfile = 'C:\Windows\Temp\DR_PowerOnVMs.log'
$serverslist = Get-Content $serverslistfile
Write-host "############################## ABC company R activity - Power On VMs ##############################"
writetolog("############################## ABC company DR activity - Power On VMs ##############################")
Write-Host "vCenter server selected : "$vCenter
writetolog("vCenter server selected : " + $vCenter)
Write-Host "Servers list selected : "
writetolog("Servers list selected : ")
$serverslist | ForEach-Object { Write-Host $_ ; writetolog($_) }
$Confirm = Read-Host "Please type 'ok' to confirm selection is correct"
if($Confirm -eq 'ok') {
writetolog("Proceed: OK by $env:UserName")
try{
Connect-VIServer $vCenter
Write-Host "Successfully connected to $vCenter vCenter"
writetolog("Successfully connected to $vCenter vCenter")
} catch {
Write-Host "Cannot connect to $vCenter vCenter, Exiting Program"
writetolog("Cannot connect to $vCenter vCenter, Exiting Program")
exit -1
}
$serverslist | foreach-object {
if((Get-VM $_ | select -ExpandProperty PowerState) -eq "PoweredOff") {
try {
Start-VM $_ -Confirm:$false | out-null
Write-Host $_ "Powered On"
writetolog($_ + " Powered On")
} catch{
Write-host $_ "Error"
writetolog($_ + " Error Powering On")
}
} else {
Write-host $_ "Already Powered On"
writetolog($_ + " Already Powered On")
}
}
Disconnect-VIServer $vCenter -Confirm:$false
Write-Host "Successfully disconnected from $vCenter vCenter"
writetolog("Successfully disconnected from $vCenter vCenter")
} else {
exit
}

Get and Set DNS search order using PowerShell

Get DNS

Scenario: I was asked to generate a list of servers that were still using our old DNS servers. This script was included in an SCCM DCM baseline to generate the report.

try{
$isComplaint = $true
$Interface = Get-WMIObject Win32_NetworkAdapterConfiguration | where{$_.IPEnabled -eq “True” -and $_.IPAddress -like "10.*"} -ErrorAction Stop
Foreach($NIC in $Interface) {
$IPs = $NIC.DNSServerSearchOrder
Foreach($IP in $IPs) {
if(($IP -eq 'your.old.DNS.ip') -or ($IP -eq 'your.old.DNS.ip2')) {
$isComplaint = $false
return "Non-Compliant"
}
}
}
if ($isComplaint -eq $true) {
return "Compliant"
}
}
catch{
return "Error"
}




Set DNS

Scenario: Configure new DNS server in DNS search order for those servers still using old DNS server. For this, we created a SCCM task sequence consisting of following script and deployed to a collection of computers. The DNS server list was passed through a TS variable "DNSservers". If you are only intrested about the PowerShell portion, then pass the DNS server list in the following format $DNSServers = “198.168.1.10",”198.168.1.2". The reason why we didnt directly ran the script on all servers was because there were a mixture of domain and workgroup servers that needed this change. We were able to run the script all servers using SCCM without bothering about the connection/authentication challenges.

$logfile = 'C:\Windows\Temp\SetDNS.log'
function writetolog([string] $txt) {
$Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
Add-content $logfile -value $Stamp':'$txt
}
try{
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$DNSServers = $tsenv.Value("DNSservers")
write-host "Retrieved DNS servers list successfully"
writetolog("Retrieved DNS servers list successfully : " + $DNSServers)
$DNSServers = $DNSServers -split ','
}
catch{
write-host "Cannot retrieve DNS servers list"
writetolog("Retrieved DNS servers list successfully")
exit -1
}
#$DNSServers = “198.168.1.10",”198.168.1.2"
try{
$Interface = Get-WMIObject Win32_NetworkAdapterConfiguration | where{$_.IPEnabled -eq “True” -and $_.IPAddress -like "10.*"} -ErrorAction Stop
write-host "Connected to WMI succesfully and interfaces retrieved"
writetolog("Connected to WMI succesfully and interfaces retrieved")
Foreach($NIC in $Interface) {
try{
$NIC.SetDNSServerSearchOrder($DNSServers)
write-host "DNS servers configured successfully"
writetolog("DNS servers configured successfully")
exit 0
}
catch{
write-host "Cannot set DNS servers"
writetolog("Cannot set DNS servers")
exit -1
}
}
}
catch{
write-host "Cannot connect to WMI"
writetolog("Cannot connect to WMI")
return -1
}


 







Export list of all hosts in Ansible Tower Inventory using PowerShell

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$serversarray = @()
$cred = Get-Credential

$capture = Invoke-RestMethod -Uri "https://towerhostURL/api/v2/hosts/" -Method Get -Credential $cred
$count = $capture.results.Count
for ($i = 0; $i -lt $count; $i++) {
$servername = $capture.results[$i].name
$group = $capture.results[$i].summary_fields.groups.results[0].name
$server = New-Object System.Object
$server | Add-Member -MemberType NoteProperty -Name ServerName -Value $servername
$server | Add-Member -MemberType NoteProperty -Name Group -Value $group
$serversarray += $server
}
while ($capture.next -ne $null) {
Write-Host $capture.next
$link = $capture.next
$capture = Invoke-RestMethod -Uri "https://towerhostURL$link" -Method Get -Credential $cred
$count = $capture.results.Count
for ($i = 0; $i -lt $count; $i++) {
$servername = $capture.results[$i].name
$group = $capture.results[$i].summary_fields.groups.results[0].name
$server = New-Object System.Object
$server | Add-Member -MemberType NoteProperty -Name ServerName -Value $servername
$server | Add-Member -MemberType NoteProperty -Name Group -Value $group
$serversarray += $server
}
}
$serversarray | Export-Csv -NoTypeInformation .\Ansiblehostslist.csv
$serversarray.Clear()

Get network interfaces of all VMs in an Azure subscription using PowerShell

$subs = Get-AzureRmSubscription

$array = @()
foreach ($sub in $subs)
{
Set-AzureRmContext -SubscriptionId $sub.Id | Out-Null
$rmVMs = Get-AzureRmVM
Write-Output "Subscription $($sub.Id) VMs: $($rmVMs.Count)"
foreach ($vm in $rmVMs) {
Write-Host $vm.Name
$nicCount = $vm.NetworkProfile.NetworkInterfaces.count
write-host $nicCount
for ($i = 0; $i -lt $nicCount; $i++) {
$networkInterfaceID = $vm.NetworkProfile.NetworkInterfaces[$i].Id
$networkInterfaceResourceGroupName = $networkInterfaceID.Split('/')[4]
$networkInterfaceName = $networkInterfaceID.Split('/')[-1]
Write-Host $networkInterfaceName
$networkInterface = Get-AzureRmNetworkInterface -ResourceGroupName $networkInterfaceResourceGroupName -Name $networkInterfaceName
$PrivateIP = $networkInterface | Get-AzureRmNetworkInterfaceIpConfig | Select -ExpandProperty PrivateIPAddress | Out-String
Write-Host $PrivateIP
$server = New-Object System.Object
$server | Add-Member -MemberType NoteProperty -Name VM -Value $vm.Name
$server | Add-Member -MemberType NoteProperty -Name NIC -Value $networkInterfaceName
$server | Add-Member -MemberType NoteProperty -Name PrivateIP -Value $PrivateIP
if($networkInterface.IpConfigurations.PublicIpAddress -ne $null) {
$publicIPinterface = $networkInterface.IpConfigurations.PublicIpAddress[0].Id
$publicIPinterfaceName = $publicIPinterface.Split('/')[-1]
$PublicIP = Get-AzureRmPublicIpAddress -ResourceGroupName $networkInterfaceResourceGroupName -Name $publicIPinterfaceName | select -ExpandProperty IpAddress | Out-String
}
$server | Add-Member -MemberType NoteProperty -Name PublicIP -Value $PublicIP
$array += $server
}
}
}
$array | Export-Csv -NoTypeInformation .\azurermVMip.csv
$array.Clear()

Check missing updates on a SCCM client using PowerShell

write-host "Checking compliance on" $env:computername

#identify the assignments on this host
$UpdateAssignment = Get-WmiObject -Query "Select * from CCM_AssignmentCompliance" -Namespace root\ccm\SoftwareUpdates\DeploymentAgent -ErrorAction SilentlyContinue

#for each assignment, show the assignment ID
if($UpdateAssignment){
$UpdateAssignment | ForEach-Object{
Write-Host "Deployments"
Write-Host $_.AssignmentId
}
#within each assignment, get updates that are yet to be installed
$TargetedUpdates = Get-WmiObject -Query "Select * from CCM_TargetedUpdateEX1 where UpdateState = 0" -Namespace root\ccm\SoftwareUpdates\DeploymentAgent -ErrorAction Stop
if($TargetedUpdates){
$iMissing=0
$TargetedUpdates | ForEach-Object {
$iMissing++
}
write-host -BackgroundColor Red "Number of Missing Updates: $iMissing"
write-host $iMissing
}
else {
Write-Host -BackgroundColor Green -ForegroundColor Black "No Missing Software Updates Found"
}
}
else{

write-host -BackgroundColor Red "No Deployments Assigned"
}



write-host "Checking full compliance on" $env:computername

#this method will identify missing updates on this host regardless of the assignments
$allupdates = Get-WmiObject -Query "select * from CCM_UpdateStatus where Status='missing'" -Namespace root\ccm\SoftwareUpdates\UpdatesStore

$allupdates | ForEach-object{
write-host $_.Article
write-host $_.Title
write-host $_.Status
write-host ""
}

Wednesday, August 12, 2020

Manage SCCM using PowerShell

Remove member from SCCM collection

param(

[Parameter(Mandatory=$true)]

[String]$serverslistfile,

[Parameter(Mandatory=$true)]

[String]$collectionName,

[String]$smsServer = 'SCCMDPservername',

[String]$smsNamespace = 'root\sms\site_NAME'

)

$serverslist = Get-Content $serverslistfile

function remove-fromCollection {

$collection = Get-WmiObject -ComputerName $smsServer -Query "select * from SMS_Collection where Name LIKE '$collectionName'" -Namespace $smsNamespace #-Credential $Cred

$collection.get()

$serverslist.Split(",") | foreach {

$serverName = $_.split(".")[0]

Write-Host $serverName

$rule = $collection.CollectionRules | where {$_.RuleName -eq "$serverName"}

$collection.DeleteMemberShipRule($rule)

}

}

remove-fromCollection




Delete computer from SCCM

param(
[String]$serverslistfile,
[String]$smsServer = ‘SCCMDPservername’,
[String]$smsNamespace = 'root\sms\site_NAME'
)
$serverslist = Get-Content $serverslistfile

function delete-device {
$serverslist | foreach {

$serverName = $_.split(".")[0]

$resource = Get-WmiObject -ComputerName $smsServer -Query "select * from SMS_R_SYSTEM where Name LIKE '$serverName'" -Namespace $smsNamespace

write-host "Deleting $serverName"

$resource.delete()
}
}

delete-device


Monday, August 10, 2020

Change user password, enable account using Ansible

- name: Change password
hosts: all
gather_facts: no
remote_user: root
tasks:
- user:
name: username1
password: "{{ 'password' | password_hash('sha512') }}"
- user:
name: username2
password: "{{ 'password' | password_hash('sha512') }}"
- name: Enable account and set expiry
hosts: all
gather_facts: no
remote_user: root
tasks:
- name: change expiry date
user:
name: user1
expires: time in epochtime
- name: change expiry date 1
user:
name: user2
expires: time in epochtime

Friday, August 7, 2020

Collect hardware metrics from physical Windows Servers

Background

It is often needed to monitor your server infrastructure in terms of performance metrics. Virtual servers could be monitored through hypervisor management software such as VMware vSphere and Microsoft Hyper-V. However, monitoring physical servers for hardware metrics in the absense of a monitoring solution could be a challenge.


Script/Commands

The following commands can be incorporated in your script to retrieve hardware metrics

$cpuUsage = [math]::Round((Get-Counter -ComputerName $server '\Processor(_Total)\% Processor Time' | 
select CounterSamples -ExpandProperty CounterSamples | select CookedValue -ExpandProperty CookedValue),0)

$os = Get-WmiObject -ComputerName $server win32_OperatingSystem

$memUsage = [math]::Round(100-(($os.FreePhysicalMemory/$os.TotalVisibleMemorySize)*100),0)

$freemem = [math]::Round($os.FreePhysicalMemory/1048576,0)

$memsize = [math]::Round($os.TotalVisibleMemorySize/1048576,0)

#Drive type 3 refers to local disk
Get-WmiObject -ComputerName $server win32_logicaldisk -Filter DriveType='3' | foreach {

$diskname = $_.DeviceID
$size = [math]::Round($_.Size/1GB,0)
$freesize = [math]::Round($_.FreeSpace/1GB,0)
$diskfree = [math]::Round(($freesize / $size)*100,0) #As a percentage

}