Tuesday, October 14, 2014

Everyday Powershell - Part 29 - Add-SMTPAlias

It's funny. When you think about how many clicks you need to go through to add an SMTP alias to an Exchange mailbox... There's a lot of clicks! Or you could just use this function and be done in 5 seconds.

function Add-SMTPAlias{
    <# Add-SMTPAlias
    .SYNOPSIS Adds smtp alias to a given mailbox

    .DESCRIPTION

    .PARAMETER alias
    Users Alias

    .PARAMETER
    newsmtpaddress desired email alias

    .EXAMPLE
    Add-IPToSMTPRelay -alias someuser -newsmtpaddress someusersotheremail@someserver.com 
    #>

    [CmdletBinding()]
    param (
        [Parameter(mandatory=$true,ValueFromPipeline=$true)]
        $alias,
        [Parameter(mandatory=$true,ValueFromPipeline=$true)]
        [mailaddress]$newsmtpaddress
    )
    process{
        $emailaddresses = (get-mailbox $alias).emailaddresses
        $emailaddresses += $newsmtpaddress.ToString()
        try{
            Set-Mailbox $alias -EmailAddresses $emailaddresses -ErrorAction stop
        }
        catch{
            write-warning ("Problem setting email address " + $_)
        }
    }
}

5 minutes or 5 seconds, the choice is yours GUI fans. Maybe it's time to give in to the power of the shell?

Wednesday, September 10, 2014

Everyday Powershell - Part 28 - Add-IPToSMTPRelay

Here's one that came up when we'd provisioned a new powershell integration server and couldn't send email from it!

Turns out our email server's weren't allowing it relay. So we needed to add it's IP to the RemoteIPRanges parameter and as Paul Cunningham  points out this can be tricky.

function Add-IPToSMTPRelay{
    <#
    Add-IPToSMTPRelay
    .SYNOPSIS
    Adds an IP address to the allow anonymous SMTP relay Receive connector on TMAIL

    .DESCRIPTION
    You will need to know your receive connectors name... use get-recieveconnector We only use one so it's been hard coded into the funtion, this could be parameterised if you need
    
    .PARAMETER
    IP IP Address to add to allowed anonymous SMTP relay 

    .EXAMPLE
    Add-IPToSMTPRelay 192.168.1.1
    #>

    [CmdletBinding()]
    param (
        [Parameter(mandatory=$true,ValueFromPipeline=$true)]
        [ipaddress]$ip
    )
    process{
        $remoteipranges = (Get-ReceiveConnector "smtp relays").remoteipranges
        $remoteipranges += ($ip).ToString()
        Set-ReceiveConnector "smtp relays" -RemoteIPRanges $remoteipranges
    }
}

You may be saying... "WOAH WOAH WOAH this looks different to your usual posts! What's all this function param process stuff?"

Well as you can see we wrapped up the powershell in a Function. The Comment block at the top is the help. The Param block defines any parameters in this case we've just got $IP. The process block is what actually happens and would be what we'd normally post.

This allows us to embed the function in a module and then stick the module in our powershell profile so it's always available!

This is far better than digging around in a scripts folder we'll dig into setting up a module in the next few weeks.

Friday, September 5, 2014

Everyday Powershell - Part 27 - Uploading files to a FTP server

Full credit to Goyuix for his awesome example on StackOverflow which I am shamlessly ripping off for this Post!

$logpath = "C:\SomePath"
$ftpserver = "ftp://someFTP.com//"
$user = "User"
$password = "Password"
$ftppath = "Somefolder"
$todayslogs = Get-ChildItem $logpath | where {$_.CreationTime -gt ((get-date).AddDays(-1))}

foreach($log in $todayslogs){
    $uploadpath = $ftpserver + $ftppath + "/" + $log.Name 
    # create the FtpWebRequest and configure it
    $ftp = [System.Net.FtpWebRequest]::Create($uploadpath)
    $ftp = [System.Net.FtpWebRequest]$ftp
    $ftp.Method = [System.Net.WebRequestMethods+Ftp]::UploadFile
    $ftp.Credentials = new-object System.Net.NetworkCredential($user,$password)
    $ftp.UseBinary = $true
    $ftp.UsePassive = $true
    # read in the file to upload as a byte array
    $content = [System.IO.File]::ReadAllBytes($log.FullName)
    $ftp.ContentLength = $content.Length
    # get the request stream, and write the bytes into it
    $rs = $ftp.GetRequestStream()
    $rs.Write($content, 0, $content.Length)
    # be sure to clean up after ourselves
    $rs.Close()
    $rs.Dispose()
}

This one was written to automate the upload of some logs. It happens every day so that's why we just (get-date).addays(-1) but that where on get-childitem can be anything you like.

One thing to note is the hardcoded password. You may not want to do this, depends on your security requirements. You can save the credentials in another file as a secure.string if you like. There's probably a post coming about that.

Tuesday, July 29, 2014

Everyday Powershell - Part 26 - Check Server last boot time

Here's a quickie that was useful this week.
$servers = Get-ADComputer -filter {OperatingSystem -like "*Server*"}
$report = @()
foreach ($server in $servers){
    $temp = "" | Select Name, Lastboot
    $temp.name = $server.dnshostname
    if(test-connection $temp.name -Count 1 -quiet){
        $temp.lastboot = [datetime]::ParseExact(((Get-wmiobject -ComputerName $temp.name Win32_operatingSystem).lastbootuptime).Substring(0,12), "yyyyMMddHHmm", $null)
    }
    else{
        $temp.lastboot = $null
    }
    $report += $temp
}
$report | sort name

Original inspiration was from here;

You see the great thing with powershell is once you know how to do something on one server you can do it on many servers relatively easily. To support some of our older fleet we had to change that query from CIM to WMI and meant some trickery with the Datetime but that’s all pretty simple stuff.

This could be combined with the server shutdown comments script from part 11 to get the reason for the last reboot too!

Monday, July 28, 2014

Run Need For Speed Rivals at 60FPS

So I watched the Need for Speed movie on the weekend... Despite being pretty bad it did impart a longing to drive exotic cars through scenic landscapes.

So I grabbed the latest game in the franchise; Need for Speed Rivals. It was a PS4 Launch title and runs on the Frostbite engine that powers battlefield games. So it should be a really good bunch of eye candy running nice and smooth on the new(ish) rig!

So after loading it up and sitting through an eternity of tutorial videos I got into the game... What's this? It's bloody capped at 30FPS!!!

This is an atrocity in the modern age of gaming! Capping performance of a PC title to run at a lower frame rate to, presumably, maintain compatibility with the console versions.

Luckily before returning the game I did a quick Google and found that the arbitrary limit on the frame rate could be be changed with two command line arguments...

-GameTime.MaxSimFps 60 -GameTime.ForceSimRate 60

MaxSimFps tells the game to run at 60 FPS but everything runs twice as fast if you don't set ForceSimRate to 60 as well.

Game runs exactly as I expected when run with those parameters and I'm now doing what I wanted, blasting past gorgeous scenery in insanely overpowered status symbols...

However it is of great concern that a big studio would release a AAA title on PC with the frame-rate limited like that. A key benefit of PC high end gaming is high resolutions with high frame rates.

When a big publisher decides that the PC market should be stuck on the same frame-rates as their console users, it should be ringing alarm bells for performance enthusiasts everywhere.

Friday, July 25, 2014

Everyday Powershell - Part 25 - Monitor for CryptoWall

So the bastards got us! Yup we got Cryptowalled!

We caught the infection before it did too much damage, isolated the PC, configured the firewall to block the IPs it was trying to get to and restored the pwnd files from backup. Business as usual really.

But what do we do to monitor for this in the future?

Whacked this together quickly;
$protectedpaths = "\\server1\someshare", "\\server2\someother"
$filename = "-Canary-.txt"
$foldername = "\-----AAA--TOP-----\"
$canarystring = "If this can be read everything is ok"
$logpath = "C:\scripts\cryptolockercanary.txt"
$recipients = "someadmin@mail.com"
$smtpserver = "somemailserver"

$report = @()

foreach ($path in $protectedpaths){
    $temp = "" | select Time, Path, EncryptedStatus
    $pathwithfolder =  $path + $foldername
    $canarypath =  $pathwithfolder + $filename
    $temp.time = get-date
    $temp.path = $pathwithfolder
    if (test-path $canarypath){
        $test = Get-content $canarypath
        if ($test -eq $canarystring){
            $temp.EncryptedStatus = $false
        }
        else{
            $temp.EncryptedStatus = $true
            Send-MailMessage -to $recipients -From 
some@email.com  -Subject ("CryptoLockerCanary Has been changed! " + $temp.time) -BodyAsHtml ($temp | convertto-html | Out-String) -SmtpServer $smtpserver
        }
    }
    else{
        mkdir $pathwithfolder
        out-file $canarypath -InputObject $canarystring
        Set-ItemProperty -Path $canarypath -Name attributes -Value ((Get-ItemProperty $canarypath).attributes -BXOR ([io.fileattributes]::Hidden))
        if (test-path $canarypath){
            Send-MailMessage -to $recipients -From 
some@email.com  -Subject ("CryptoLockerCanary file is not present - creating new one " + $temp.time) -BodyAsHtml ($temp | convertto-html | Out-String) -SmtpServer $smtpserver
        }
        else{
            Send-MailMessage -to $recipients -From some@email.com -Subject ("CryptoLockerCanary file is not present and COULD NOT CREATE new one - Recomend investigation " + $temp.time) -BodyAsHtml ($temp | convertto-html | Out-String) -SmtpServer $smtpserver
        }
    }
    $report += $temp
}
$report | export-csv -Path $logpath -Append -NoTypeInformation
$report

It'll take any folders defined in $protectedpaths and stick a "canary" file in there. If it sees a change to the canary file it'll send out emails to $recipients.

This is scheduled to run every five minutes so this way we'll get alerted really quickly if it get's through again.

Tuesday, July 8, 2014

Game Design brings out my evil side

Mwuhahahahahahaha!
Believe it or not... This is a Racing Game.
Island-Test6 a smooshing together of unity, world machine and some custom car scripts has allowed me to indulge in much deviousness.

What is the fine line between fun challenge and pure frustration? Well I don't know, but I'm trying my damnedest to find out!