Archive for the ‘Windows Server’ Category

Let’s presume we have some PowerShell script for editing DNS entry, and we need to run it as Scheduled Task under some service account .

Add service account “Log on As Batch Job” right by using GPO:

  • Click START and type Group Policy then click on Group Policy ManagementEither edit the existing GPO that contains existing USER RIGHTS ASSIGNMENT (likely Default Domain Policy) or right click and CREATE AND EDIT a new policy
  • Expand Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > User Rights Assignment node
  • Double click Log on as a batch job
  • Click the Add User or Group button and add your service account user

1.PNG

In case you still get “This Task Requires That The User Account Specified Has Log On As Batch Job Rights” warning in task scheduler, add user to Backup Operators group.

Then add user to DNSAdmins group.

If script needs to be executed from remote machine:

Enabling Remote Management

  • add service account to WinRMRemoteWMIUsers__ on the DNS Server/DC.
  • On the Windows desktop, right-click Windows PowerShell on the taskbar, and then click Run as Administrator.
  • On the Windows start screen, right-click Windows PowerShell, and then on the app bar, click Run as Administrator.
  • type the following, and then press Enter to enable all required firewall rule exceptions.

Configure-SMremoting.exe -enable

 

Open Computer Management: start > run > compmgmt.msc

Expand Services and Applications – right click WMI Control – Properties – Security tab – click Security

2.png

Add service account

In the applies to, choose “this namespace and subnamespace” and Click “Allow” for Execute Methods and Enable Account.

If script needs to be run remotely, click “Allow” also for Remote Enable

3.png

For remote access:

In WMI Control expand root – cimv2 – Security

cimv2.png

Add the group WinRMRemoteWMIUsers__ as the principal, then click ok.

In the applies to, choose “this namespace and subnamespace”

Add service account and Click “Allow” for Execute Methods, Enable Account and Enable Remote

Restart Windows Management Instrumentation service

Server 2016

CentOS 8 required Generation 2 VM,

Choose Generation 2 because legacy hardware, like the tulip NIC are no longer supported, gen 2 will avoid the use of legacy hardware emulation.

Specify Memory, Disk and VM name, after machine is create it will be turned off. Right click VM – Settings.. – Security Secoore Boot Enabled Select Microsoft UEFI Certificate Authority under Template

Start VM

Select “Edition” you want to install

VM will be installed

Server 2012 R2

Specify Generation 2, allocate memory and HDD space,don’t turn on VM. While VM is turned off, in VM properties select Firmware-Secure Boot, uncheck “Enable Secure Boot

Start VM

This script will check if user password expires in 1,3 or 7 days and if yes, it will send email to user

 

First, encrypt password and store it in file

$password = "somepass"
$secureStringPwd = $password | ConvertTo-SecureString -AsPlainText -Force
$secureStringText = $secureStringPwd | ConvertFrom-SecureString
Set-Content "C:\temp\ExportedPassword.txt" $secureStringText

 

$mailuser = "userc@example.com"

$pwdmail = Get-Content "C:\temp\ExportedPassword.txt"
$securemailPwd = $pwdmail | ConvertTo-SecureString

$EmailCreds = New-Object System.Management.Automation.PSCredential -ArgumentList $mailuser, $securemailPwd

$from = "user@xample.com"

# OU to search 

$path = "CN=Users,DC=example,DC=com"

$users = Get-ADUser -SearchBase $path -filter {Enabled -eq $True -and PasswordNeverExpires -eq $False -and PasswordLastSet -gt 0} `
-Properties "Name", "EmailAddress", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Name", "EmailAddress", `
@{Name = "PasswordExpiry"; Expression = {[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed").tolongdatestring() }}

# Days remaining until password expiration
$WarningDays = 1,3,7

# Get current day
$today = (Get-Date).ToLongDateString()
try {
foreach ($user in $users)
{
 foreach ($WarnDay in $WarningDays){
 if ($user.PasswordExpiry -eq (get-date).adddays($WarnDay).ToLongDateString()) 
 {
  # Calculate days beteween today and date when password will expire
  $ts = New-TimeSpan -Start $today -End $user.PasswordExpiry
  $days = $ts.Days
  $subject = "Password expiration notification - " + $user.Name
  $body = "Dear " + $user.name + ",`nYour Password will expire in " + $days + " days"
  Send-MailMessage -to $user.EmailAddress -from $from -Subject $subject -Body $body -BodyAsHtml -SmtpServer smtp.office365.com -UseSsl -Credential $EmailCreds -Port 587

 }}}}
catch {
$Error[0].Exception.Message
}
exit $LASTEXITCODE

This function will print registry value for specific key, in this case HPATH value

import _winreg

def getPath():
    # Open the key and return the handle object.
    hKey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
                          "COMODO")
    
    # Read the value.                      
    result = _winreg.QueryValueEx(hKey, "MachineId")
    # Close the handle object.
    result = result[0]
    return result
    _winreg.CloseKey(hKey)

Another solution:

def regkey_value(path, name="", start_key = None):
    if isinstance(path, str):
        path = path.split("\\")
    if start_key is None:
        start_key = getattr(_winreg, path[0])
        return regkey_value(path[1:], name, start_key)
    else:
        subkey = path.pop(0)
    with _winreg.OpenKey(start_key, subkey) as handle:
        assert handle
        if path:
            return regkey_value(path, name, handle)
        else:
            desc, i = None, 0
            while not desc or desc[0] != name:
                desc = _winreg.EnumValue(handle, i)
                i += 1
            return desc[1]


posread = regkey_value(r"HKEY_LOCAL_MACHINE\COMODO", "MachineId")

3rd way:

import _winreg

reg_connection = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)

key_value = _winreg.OpenKey(reg_connection, r"COMODO")

print _winreg.QueryValueEx(key_value, "MachineId")[0]

Reading registry keys from x64 versions of Windows using x86 Python installation:

import _winreg

def get_path(name):
    try:
        registry_key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\\COMODO', 0, (_winreg.KEY_WOW64_64KEY + _winreg.KEY_READ))
        value = _winreg.QueryValueEx(registry_key, "MachineId")[0]     
        return value
    except WindowsError:
        return None

Powershell script for AD replication monitoring:

<#
.SYNOPSIS
	Check AD Replication in a DC Server.
.DESCRIPTION
	Check AD Replication in a DC Server and returns Nagios output and code.
.PARAMETER Warning
	Number of failed replications for warning treshold.
	Default 1.
.PARAMETER Critical
	Number of failed replications for critical treshold.
	Default 5.
.OUTPUTS
    OK: AD replication successful.
    WARNING: Failed replications equal to Warning treshold.
    CRITICAL: Failed replications equal to Critical treshold.
.EXAMPLE
	.\Get-ADReplication.ps1 -Warning 5 -Critical 10
.NOTES 
	Author:	Juan Granados 
	Date:	December 2017
#>
Param(
		[Parameter(Mandatory=$false,Position=0)] 
		[ValidateNotNullOrEmpty()]
		[int]$Warning=1,
		[Parameter(Mandatory=$false,Position=1)] 
		[ValidateNotNullOrEmpty()]
		[int]$Critical=5
)
# Variables
$SyncErrors=0
$LASTEXITCODE = 0
$NagiosOutput = ""
$Syncs = 0

# Get AD Replication Status for this DC
$SyncResults = Get-WmiObject -Namespace root\MicrosoftActiveDirectory -Class MSAD_ReplNeighbor -ComputerName $env:COMPUTERNAME |
	select SourceDsaCN, NamingContextDN, LastSyncResult, NumConsecutiveSyncFailures, @{N="LastSyncAttempt"; E={$_.ConvertToDateTime($_.TimeOfLastSyncAttempt)}}, @{N="LastSyncSuccess"; E={$_.ConvertToDateTime($_.TimeOfLastSyncSuccess)}} 

# Process result
foreach ($SyncResult in $SyncResults)
{
	if ($SyncResult.LastSyncResult -gt 0){
		$NagiosOutput += "$($SyncResult.NumConsecutiveSyncFailures) failed sync with DC $($SyncResult.SourceDsaCN) on $($SyncResult.NamingContextDN) at $($SyncResult.LastSyncAttempt), last success sync at $($SyncResult.LastSyncSuccess)."
		$SyncErrors++
		if ($SyncErrors -eq $Warning){
			$LASTEXITCODE = 1
		}
		elseif ($SyncErrors -eq $Critical) {
			$LASTEXITCODE = 2
		}			
	}
	else{
		$Syncs++
	}
}
# Nagios Output
$NagiosOutput += " | Syncs=$($Syncs);;;; SyncErrors=$($SyncErrors);$Warning;$Critical;;"
if ($LASTEXITCODE -eq "2") {
	Write-Host "CRITICAL: Replication error: $($NagiosOutput)"
    #$host.SetShouldExit(2)
	 
} 
elseif ($LASTEXITCODE -eq "1") {
	Write-Host "WARNING: Replication error: $($NagiosOutput)"
    #$host.SetShouldExit(1)
	 
} 
elseif ($LASTEXITCODE -eq "0") {

	Write-Host "OK: replication is up and running.$($NagiosOutput)"
	#$host.SetShouldExit(0)
	 
}

exit $LASTEXITCODE

Install NSClient++ 0.4.1.73-x64 (if on Nagios 4.2.4 ), or  newest version on Windows server.

Edit C:\Program Files\NSClient++\nsclient.ini

; in flight - TODO
[/settings/default]

; Undocumented key
password = NAGIOS API

; Undocumented key
allowed hosts = 127.0.0.1, Nagios IP


; in flight - TODO
[/settings/NRPE/server]

; Undocumented key
verify mode = none

; Undocumented key
insecure = true

extended response = 1
allow arguments = true
allow nasty characters = true


allow nasty characters = true

; in flight - TODO
[/modules]

; Undocumented key
CheckExternalScripts = enabled

; Undocumented key
CheckHelpers = 1

; Undocumented key
CheckEventLog = 1

; Undocumented key
CheckNSCP = 1

; Undocumented key
CheckDisk = 1

; Undocumented key
CheckSystem = 1

; Undocumented key
NRPEServer = enabled
 

[/settings/external scripts]

allow arguments = true

[/settings/external scripts/scripts]


check_ad_replication = cmd /c echo scripts\check_ad_replication.ps1 -Warning 5 -Critical 10 | PowerShell.exe -Command -

Restart NSClient++ (x64) service:

Actions on Nagios server

Test it first:

/usr/lib64/nagios/plugins/check_nrpe -H DC IP -c check_ad_replication

OK: replication is up and running. |'Syncs'=10 'SyncErrors'=0;5;10

Add command, edit /etc/nagios/objects/commands.cfg

define command {
command_name check_ad_replication
command_line /usr/lib64/nagios/plugins/check_nrpe -H 192.168.98.21 -c check_ad_replication
}

Add this command as a service to Nagios host (Windows DC) /etc/nagios/conf.d/win_host.cfg

define service{
        use                             generic-service
        host_name                       dc.example.com
        service_description             Check Active Directory Replication
        check_command                   check_nrpe!check_ad_replication
        }

Go to Nagios portal and re-schedule the next check of the service (or wait until the next check)

And finally, check service status

Host_status.png

 

Today, i had to log in to Hyper-V host, bust forgot IP/Hostname, luckily i didn’t forget VM, so i logged it to it and searched registry.

Note: VM have Integration Services installed.

Under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters registry key which reveal Hyper-V hosts are:

  • HostName
  • PhysicalHostName
  • PhysicalHostNameFullyQualified

Command line:

reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters" /v "PhysicalHostNameFullyQualified"

Powershell:

Get-ItemPropertyValue 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters' -Name 'PhysicalHostNameFullyQualified'

This script will check if current IP is in specific range


Function IsIpAddressInRange {
param(
        [string] $ipAddress,
        [string] $fromAddress,
        [string] $toAddress
    )

    $ip = [system.net.ipaddress]::Parse($ipAddress).GetAddressBytes()
    [array]::Reverse($ip)
    $ip = [system.BitConverter]::ToUInt32($ip, 0)

    $from = [system.net.ipaddress]::Parse($fromAddress).GetAddressBytes()
    [array]::Reverse($from)
    $from = [system.BitConverter]::ToUInt32($from, 0)

    $to = [system.net.ipaddress]::Parse($toAddress).GetAddressBytes()
    [array]::Reverse($to)
    $to = [system.BitConverter]::ToUInt32($to, 0)

    $from -le $ip -and $ip -le $to
}


# get current IP and perform comparation
$ip1 = ((ipconfig | findstr [0-9].\.)[0]).Split()[-1]

if (IsIpAddressInRange $ip1 "192.168.0.10" "192.168.0.254")
{
Write-Host "in Corporate Network"
}
else
{
Write-Host "in private network"
}