Click an Ad

If you find this blog helpful, please support me by clicking an ad!

Monday, February 17, 2014

Getting Your Email out of the Barracuda Message Archiver

We run a Barracuda Message Archiver 450. I really like the device, but we were looking at alternatives, and I needed a way to test possible solutions with real mail. The question that came to pass was, "How do we get our email out of the Barracuda?"

Basically, there is no out-of-the-box solution to this; Barracuda does not have a tool.

So, I wrote my own using Powershell. :)

I have to say that this code could stand to be cleaned up. I had to use some pretty circuitous methods to get it to work correctly.

Prior to running this:
1. You need to copy all of the files from the SMB share on the Barracuda Message Archiver somewhere else. I mapped this as U drive.
2. You need a working folder with gobs of space. I mapped this as my V drive.
3. Install 7zip

Basically, you have a bunch of .zip files. You extract everything out of these. The extracted files will have no extensions. What I got from support was that these files are either emails themselves, or are gzipped archives. I would use 7zip to try to decompress these files, and if the process returned an exit code of 2, I knew it wasn't a valid archive and would then append the .eml extension. If the file was a zip archive, the files unzipped would have the eml extension tacked onto the end.

I use a random number to create output folders to hold all of the many eml files. Some zips had upwards of 35,000 emails in them.

I KNOW I could have done a better job commenting this code. I'm almost embarassed to put it out here, but I really wished someone had given me some direction, so here it is. If you have the need for this script, you can create a copy of your archives and work through the code a chunk at a time to see what's going on, so that you don't put your production archives at risk. Remember that you can open .eml files with notepad. :)

I will use commented lines within the script for the remainder of this article.
The Script:

#Specify source and working folders, as well as report file variables
$Source = "U:\1"
$WorkingFolder = "V:\Extract"
$ReportFile = "C:\temp\MailArchReport.txt"
$ReportFileSpacer = "`r`n`r`n===========================================================================`r`n`r`n"

#Ask for starting file number and ending file number
[int]$StartingZip = Read-Host "Enter Number of First Zip File to Process"
[int]$EndingZip = Read-Host "Enter Number of Last Zip File to Process"

#Last chance to get out
$LastChanceAnswer = Read-Host "Are you sure you want to continue processing all files between $StartingZip.zip and $EndingZip.zip? (y or n)"
If ($LastChanceAnswer -ne "y"){
Break
} #End If

#Initialize the array to hold all expected zip file names
$ZipFileSet = @()

#Initialize Report File with the starting date and time
Get-Date | Add-Content $ReportFile

#Counter to populate the zip file names array
For ($i = $StartingZip; $i -le $EndingZip; $i++){
$StartipZipStr = "$i.zip"
$ZipFileSet = $ZipFileSet + $StartipZipStr
} #End For

#Add record for zip files processed to the report file
$ReportFileSpacer | Add-Content $ReportFile
"Files Processed:" | Add-Content $ReportFile
$ZipFileSet | %{Add-Content $ReportFile -Value $_}

#Go through the zip file names array and copy the files from the source to the working folder
Foreach ($file in $ZipFileSet){
copy-item "$Source\$file" -destination "$WorkingFolder"
} #End Foreach

#Create the first working folder
$WorkingFolderOneName = "$WorkingFolder\WorkingFolder1"
mkdir $WorkingFolderOneName | out-null

#Unzip all of the zip files in the array
Foreach ($file in $ZipFileSet){
$sourcefile = "$WorkingFolder\$file"
$targetfolder = "$WorkingFolderOneName"
$ZipCommandStringPartOne = 'C:\"Program Files"\7-zip\7z.exe'
$ZipCommandStringPartTwo = "x $sourcefile -o$targetfolder -r"
cmd.exe /C "$ZipCommandStringPartOne $ZipCommandStringPartTwo" | out-null
} #End Foreach

#Get a list of all files
$WeirdZipFiles = Get-ChildItem $TargetFolder -recurse | where {! $_.psiscontainer -and $_.fullname -notlike "*.???"} | select fullname, name, directory

#Add record for number of files
$ReportFileSpacer | Add-Content $ReportFile
"New zip files that don't have a zip extension:" | Add-Content $ReportFile
$WeirdZipFiles | measure-object | select count | %{$_.count | out-string} | Add-Content $ReportFile

#Initialize counters
$MovedCount = 0
$MovedRenamedCount = 0

#Create the folder for the emails
$RandomSeedForEMLFolder = Get-Random
$WorkingFolderTwoName = "$WorkingFolder\Emails_$RandomSeedForEMLFolder"
mkdir $WorkingFolderTwoName | out-null

#Each of those need to be unzipped.
Foreach ($file in $WeirdZipFiles){
$sourcefile = $File.Fullname
$targetfolder = $File.Directory.Fullname
$ZipCommandStringPartOne = 'C:\"Program Files"\7-zip\7z.exe'
$ZipCommandStringPartTwo = "x $sourcefile -o$targetfolder -r"
cmd.exe /C "$ZipCommandStringPartOne $ZipCommandStringPartTwo" | out-null
If ($LastExitCode -eq 2){ #If the file wasn't an archive, output the name.
$RandomSeed = Get-Random
$FileName = $File.Name
$FilePath = $File.directory.fullname
$OldFileFullname = ($FilePath + "\" + $FileName)
$FileNameAddition = "$RandomSeed.eml"
$NewFileName = ($FileName + $FileNameAddition)
$NewFileFullname = ($FilePath + "\" + $NewFileName)
Rename-Item $OldFileFullname -NewName $NewFileName
Move-Item $NewFileFullname $WorkingFolderTwoName
$MovedRenamedCount++
} #End If
If ($LastExitCode -eq 0){ #Otherwise, Rename, then move the raw eml file to working folder two
$FileNameSplit = $File.Name.split(".")
$ResultFileName = $FileNameSplit[0]
$FilePath = $File.directory.fullname
$OldFileFullname = ($FilePath + "\" + $ResultFileName)
$RandomSeed = Get-Random
$FileNameAddition = "$RandomSeed.eml"
$NewFileName = ($ResultFileName + $FileNameAddition)
$FilePath = $file.directory.fullname
$NewFileFullname = ($FilePath + "\" + $NewFileName)
Rename-Item $OldFileFullname -NewName $NewFileName
Move-Item $NewFileFullname $WorkingFolderTwoName
Remove-Item $SourceFile
$MovedCount++
} #End If
} #End Foreach

#Report Stuff
"`r`n Files that were renamed, then moved (.eml files): $MovedCount" | Add-Content $ReportFile
"`r`n Files that were extracted, then moved. $MovedCount" | Add-Content $ReportFile

#Remove working folder one
Remove-Item $WorkingFolderOneName -recurse -force

#Remove the zip files that were processed
Foreach ($file in $ZipFileSet){
$ZipFileSetPath = ($WorkingFolder + "\" + $file)
Remove-Item $ZipFileSetPath -recurse -force
} #End Foreach

#Add an ending timestamp to the report file
Get-Date | Add-Content $ReportFile

#Email the report file
Send-MailMessage `
-To me@contoso.com `
-From administrator@contoso.com `
-SMTPServer mail.contoso.com `
-Subject "Barracuda Zips Processed" `
-Body "See Attached Report" `
-Attachments $ReportFile

Remove-Item $ReportFile -force

Friday, February 14, 2014

Creating my Swiss-Army USB Thumbdrive

I've been messing around with security stuff lately, and finally got the motivation to create a bootable USB Thumbdrive.

I've wanted one for years, but never really got around to making one that fit all of my needs.

First, I used YUMI to make my drive bootable to Kali Linux, a security distribution of Linux that used to be called BackTrack.

Then, I put a ton of great utility apps onto the thumbdrive, and used this guide to create nice litle shortcuts for everything in the root folder.

The final product is a bootable Linux Distro, which also has all of my normal tools on it that are usable from within Windows.

Here's a screenshot of my root folder:

Maybe next time I'll go for something bigger, like this 1TB flash drive from Kingston!

Thursday, February 13, 2014

Sharepoint 2013 filling up my Domain Controller's Security Logs

I just bought and implemented Solarwinds' Syslog server. Good stuff. Now I just need to find the time to look at them! :P

In the process of looking through my domain controllers' security logs (just the failure audits) I was inundated with failures from my Sharepoint server. It made the rest of the logs unreadable, so my goal was set: I needed to fix the Sharepoint server and make it stop doing this!

Here's what the errors look like:

2014-01-22 14:46:13 Kernel.Critical dc02.contoso.com Jan 22 14:46:13 dc02.contoso.com MSWinEventLog 2 Security 12451 Wed Jan 22 14:46:13 2014 4769 Microsoft-Windows-Security-Auditing N/A Audit Failure dc02.contoso.com 14337 A Kerberos service ticket was requested.


Account Information: 
Account Name: spservice@contoso.com 
Account Domain: contoso.com 
Logon GUID: {00000000-0000-0000-0000-000000000000} 

Service Information: 
Service Name: spservice 
Service ID: S-1-0-0 

Network Information: 
Client Address: ::ffff:192.168.1.53 
Client Port: 57013 

Additional Information: 
Ticket Options: 0x40810000 
Ticket Encryption Type: 0xffffffff 
Failure Code: 0x1b 
Transited Services: -

It's happening on multiple "client ports":

56591

56594

56605

56607

56624

56643

etc.

Thankfully, I was able to track down a guide on configuring Sharepoint kerberos authentication. No, my logs are cleared up and I can see the data that I care about!

Tuesday, November 5, 2013

Checking for VMware Snapshots

So besides the standard way of simply looking at vCenter to see snapshots, there are a couple of other ways to accomplish this. The first way is manual, and uses RVTools, which is a GREAT tool for gathering lots of information about your VMware environment and its virtual machines. I run it every Monday just to make sure thing look healthy. Veeam's monitoring software, VeeamONE will also alert you when a snapshot is active for longer than a specified time, which can be altered by editing the alarm. VeeamONE is free, but if you want more features you have to go full version which is not free, of course.

I recommend both of these free tools to anyone who wants a health checkup or wants to create some quick documentation of their VMware Environment. These tools helped me immensely when I inherited mine, so that I could hit the ground with good information and a list of things to fix first.

I should not leave out vCheck, which a VERY full featured script offerend by Virtu-Al.net that can give you a LOT of good info. As a matter of fact, I created the script at the end of this entry from one of the subscripts of the vCheck project; the one that checks for snapshots.

I created this script to run at 6AM and let me know if there are any snapshots running before the start of the business day. Reasons for these snapshots can be a lot of things, but any of them bear looking into more closely. I could have a Veeam Backup that is stuck, like happened to me last week. I, or another admin, might have left a snapshot running (which merits a flogging!).

Also, you'll notice that the first thing it does is retrieve your credentials, which I created beforehand using the technique outlined in this post.

Without further ado, here's the script:

#Gets the credentials to facilitate connection to the Vcenter Server
$password = Get-Content c:\PSCred\mycred.txt | ConvertTo-SecureString
$credential = New-Object System.Management.Automation.PsCredential "TaskSchedUser@Contoso.com",$password

#Gets some other miscellaneous variables for use in the email alert
$smtpServer = "mailServer.contoso.com"
$MailFrom = "helpdesk@contoso.com"
$MailTo = "IT@contoso.com"
$VISRV = "vCenterServer"

#Add the snapin for PowerCLI (The VMware Powershell module)
add-pssnapin Vmware.VimAutomation.Core

#Connect to your vCenter Server, using the credentials we created to authenticate
connect-viserver -server vCenterServer.contoso.com -credential $credential

#Function that finds the user that created the snapshot, so you can flog them
function Find-User ($username){
if ($username -ne $null)
{
$usr = (($username.split("\"))[1])
$root = [ADSI]""
$filter = ("(&(objectCategory=user)(samAccountName=$Usr))")
$ds = new-object system.DirectoryServices.DirectorySearcher($root,$filter)
$ds.PageSize = 1000
$ds.FindOne()
}
}

#Function that gets snapshot info
function Get-SnapshotTree{
param($tree, $target)

$found = $null
foreach($elem in $tree){
if($elem.Snapshot.Value -eq $target.Value){
$found = $elem
continue
}
}
if($found -eq $null -and $elem.ChildSnapshotList -ne $null){
$found = Get-SnapshotTree $elem.ChildSnapshotList $target
}

return $found
}

#Function that gets more detailed snapshot info
function Get-SnapshotExtra ($snap){
$guestName = $snap.VM # The name of the guest

$tasknumber = 999 # Windowsize of the Task collector

$taskMgr = Get-View TaskManager

# Create hash table. Each entry is a create snapshot task
$report = @{}

$filter = New-Object VMware.Vim.TaskFilterSpec
$filter.Time = New-Object VMware.Vim.TaskFilterSpecByTime
$filter.Time.beginTime = (($snap.Created).AddSeconds(-5))
$filter.Time.timeType = "startedTime"

$collectionImpl = Get-View ($taskMgr.CreateCollectorForTasks($filter))

$dummy = $collectionImpl.RewindCollector
$collection = $collectionImpl.ReadNextTasks($tasknumber)
while($collection -ne $null){
$collection | where {$_.DescriptionId -eq "VirtualMachine.createSnapshot" -and $_.State -eq "success" -and $_.EntityName -eq $guestName} | %{
$row = New-Object PsObject
$row | Add-Member -MemberType NoteProperty -Name User -Value $_.Reason.UserName
$vm = Get-View $_.Entity
$snapshot = Get-SnapshotTree $vm.Snapshot.RootSnapshotList $_.Result
$key = $_.EntityName + "&" + ($snapshot.CreateTime.ToString())
$report[$key] = $row
}
$collection = $collectionImpl.ReadNextTasks($tasknumber)
}
$collectionImpl.DestroyCollector()

# Get the guest's snapshots and add the user
$snapshotsExtra = $snap | % {
$key = $_.vm.Name + "&" + ($_.Created.ToString())
if($report.ContainsKey($key)){
$_ | Add-Member -MemberType NoteProperty -Name Creator -Value $report[$key].User
}
$_
}
$snapshotsExtra
}

#Function to send mail. I normally just use a one-liner, but I'm reusing code, and this was here.
Function SnapMail ($Mailto, $snapshot)
{
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = $MailFrom
$msg.To.Add($Mailto)

$msg.Subject = "Snapshot Reminder"

$MailText = @"
There is a snapshot active on $($snapshot.VM) which was taken on $($snapshot.Created).

Name: $($snapshot.Name)

Description: $($snapshot.Description)
"@

$msg.Body = $MailText
$smtp.Send($msg)
}

#Cycles through any snapshots found, and send an email for each one
foreach ($snap in (Get-VM | Get-Snapshot)){
$SnapshotInfo = Get-SnapshotExtra $snap
SnapMail $mailto $SnapshotInfo
}

#Disconnect from the vCenter server
Disconnect-VIServer -Confirm:$false