Monday, June 11, 2012

Active Directory Password Expiration Email Notification

This is a PowerShell script that will send an email notification to Active Directory users when their password will expire in 14, 7, 3, 1, and Zero days. Administrators/helpdesk also get a daily report of passwords that are expired and the users who got an email reminder, a great heads up for your helpdesk.

The script generates a different message when there are zero days remaining (password is expired and must be changed today) and won't continue to notify users when there are less than zero days remaining. Negitive dedlines are used for some account options such as the passwords must be changed at next logon account flag, and you don't want to fill up a user's mailbox when they can't access their mail before changing their password anyway.

To setup the script, search for the "# CONFIG:" strings and edit the following line as documented, then set it up on a server as a daily scheduled task.

Active Directory Password Expiration Email Notification Script
Import-Module ActiveDirectory

$maxdays=(Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge.TotalDays
$summarybody="Name `t ExpireDate `t DaysToExpire `n"

(Get-ADUser -filter {(mail -like "*@domain.com") -and (Enabled -eq "True") -and (PasswordNeverExpires -eq "False")} -properties *) | Sort-Object pwdLastSet |
foreach-object {

    $lastset=Get-Date([System.DateTime]::FromFileTimeUtc($_.pwdLastSet))
    $expires=$lastset.AddDays($maxdays).ToShortDateString()
    $daystoexpire=[math]::round((New-TimeSpan -Start $(Get-Date) -End $expires).TotalDays)
    $samname=$_.samaccountname
    $firstname=$_.GivenName
    if (($daystoexpire -eq 14) -or ($daystoexpire -eq 7) -or ($daystoexpire -eq 3) -or ($daystoexpire -eq 1) -or ($daystoexpire -eq 0)) {
    #if ($daystoexpire -le 14) {
        $ThereAreExpiring=$true
        
         # CONFIG: Enter from email address.
        $emailFrom = "helpdesk@domain.com"
        # CONFIG: Replace domain domain.com with your email domain. Do not change $samname.
        $emailTo = "$samname@domain.com"
        if ($daystoexpire -eq 0) {
        # CONFIG: Enter text for subject and body of email notification for zero days remaining.
            $subject = "$firstname, your password has expried!"
            $body = "$firstname,
Your password has expired and you must change it immediately. No further email notifications will be sent.

Contact support at extension XXXX for assistance."
        }
        Else {
        # CONFIG: Enter text for subject and body of email notification for 14, 7, 3, and 1 days remaining. 
            $subject = "$firstname, your password expires in $daystoexpire day(s)!"
            $body = "$firstname,
Your password expires in $daystoexpire day(s).

If you are using a Windows computer, press Ctrl + Alt + Del the click Change password.

If you are using a Mac computer follow the instructions at http://sharepoint/Documentation to change your password.
"
        }
        # CONFIG: Enter your smtp server here.
        $smtpServer = "email.domain.com"
        $smtp = new-object Net.Mail.SmtpClient($smtpServer)
        $smtp.Send($emailFrom, $emailTo, $subject, $body)   
       
        $summarybody += "$samname `t $expires `t $daystoexpire `n"
    }
    elseif ($daystoexpire -lt 0) {
        $ThereAreExpiring=$true
        # Add a note to the report email, but don't notify user.
        $summarybody += "$samname `t $expires `t $daystoexpire `n"
    }
}
if ($ThereAreExpiring) {
    # CONFIG: From address for report to Helpdesk/IT Admin staff.
    $emailFrom = "helpdesk@domain.com"
    # CONFIG: Address to send report email to (for Helpdesk/IT Admin staff.
    $emailTo = "helpdesk@domain.com"
    # CONFIG: Subject for report email.
    $subject = "Expiring passwords"
    $body = $summarybody
    # CONFIG: SMTP Server.
    $smtpServer = "email.domain.com"
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $smtp.Send($emailFrom, $emailTo, $subject, $body)
}



Thursday, May 31, 2012

Active Directory Account Lockout Notifications using PowerShell

I've found it's often helpful to get an email notification when an Active Directory account is locked out. In a previous job we used Account Lockout Examiner from NetWrix for this functionality. A few years and a job or two later and I've found a way to do this with the Windows Task Scheduler and PowerShell. You also need to have a Windows Server 2008 Domain Controller. Your Active Directory domain does not need to be in 2008 Native Mode.

Before going on, I should mention that the following scripts were originally created by Joe0126 and shared in this post on the SpiceWorks Community site. I simply took what Joe0126 created and updated the output to meet my needs. The email notification will look like this:

Subject: Account Locked Out: ADDOMAIN\username
Email Body:
Account Name: ADDOMAIN\username
Workstation: ADCOMPUTERNAME
Time: 05/28/2012 17:45:43


In the case of an account lock event, the workstation will tell you what computer or server the account was locked out on. Usually this will be the user's workstation or one of your Exchange CAS servers. If the lockout happened on a computer that isn't joined to the domain workstation will be blank.

The account unlock notification is slightly different. The workstation will be the workstation AD Users and Computers is running on, and who is responsible for unlocking the account will be in the notification as well.

Subject: Account Unlocked: ADDOMAIN\username
Email Body:
Account Name: ADDOMAIN\username
Workstation: somecomputer.domain.com
Time: 05/29/2012 11:03:31

Unlocked By:
ADDOMAIN\someadmin


To start, grab the code for the scripts below. One will generate an email notification for an account lock event, the other will generate an email notification for an account unlock event. Update the script with the SMTP server and email addresses for your domain (update lines with domain.com) and save them to your Domain Controller.

On your domain controller, open Task Scheduler and create a new task (Not create basic task). Your trigger should be "On an Event." Select the Security Log and enter 4740 for the EventID. EventID 4740 is an Account Lock. For your action run your PowerShell Script. For the unlock notification, do the same for EventID 4767 and use the Unlock Notification Script.

Notifications won't be instantaneous as PowerShell's get-eventlog commandlet isn't very fast when it comes to finding events in the Windows log, but it has been fast enough for our environment. In most cases we get the account lockout notification before the user calls the helpdesk to report a problem.

Account Lock Notification Script:
$SMTPServer = "mail.example.com"
$MailFrom = "no-reply@example.com"
$MailTo = "account-lockout-notifications@example.com"

Import-Module activedirectory

$Event=Get-EventLog -LogName "Security" -InstanceId "4740" -Newest 1000

$User = $Event.ReplacementStrings[0]

$Computer = $Event.ReplacementStrings[1]

$Domain = $Event.ReplacementStrings[5]

$MailSubject= "Account Locked Out: " + $Domain + "\" + $User

$MailBody = "Account Name: " + $Domain + "\" + $User + "`r`n" + "Workstation: " + $Computer + "`r`n" + "Time: " + $Event.TimeGenerated + "`r`n"

$lockedAccounts = Search-ADAccount -LockedOut | Select -Property SamAccountName | Out-String

$MailBody = $MailBody + "`r`nThe following accounts are currently locked out:`r`n" +  $lockedAccounts

Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -SmtpServer $SMTPServer -Body $MailBody

Account Unlock Notification Script:
$SMTPServer = "mail.example.com"
$MailFrom = "no-reply@example.com"
$MailTo = "account-lockout-notifications@example.com"




Import-Module activedirectory

$Event=Get-EventLog -LogName "Security" -InstanceId "4767" -Newest 1000

$User = $Event.ReplacementStrings[0]


$Domain = $Event.ReplacementStrings[1]

$UnlockBy =  $Event.ReplacementStrings[4]


$UnlockByDomain = $Event.ReplacementStrings[5]

$Computer = $Event.MachineName

$MailSubject= "Account Unlocked: " + $Domain + "\" + $User

$MailBody = "Account Name: " + $Domain + "\" + $User + "`r`n" + "Workstation: " + $Computer + "`r`n" + "Time: " + $Event.TimeGenerated + "`r`n`r`n Unlocked By: " + $UnlockByDomain + "\" + $UnlockBy

Send-MailMessage -To $MailTo -From $MailFrom -Subject $MailSubject -SmtpServer $SMTPServer -Body $MailBody

For the extra lazy, unlock everyone:
Import-Module activedirectory
Search-ADAccount -LockedOut | Unlock-ADAccount

Update 1, 2012-06-18: I added the Unlock notification to all our Server 2008 R2 domain controllers. We were only getting notifications when an account was unlocked on the domain controller running the script. I don't think this is a similar issue with the lock notification script.

Update 2, 2014-12-29: Checked this post and found I've made a few more improvements since my last posting. Configuration for mail server is now at the top, and I added a line to get all locked accounts to the lock notification, just in case your IT Service Desk missed a few accounts. Also added PowerShell to unlock all locked accounts. Use with caution obviously. 


Thursday, March 1, 2012

Reeking of Fail: Flixter and UltraViolet

The goals of the UltraViolet Digital Rights Management system are admirable. The system aims to provide buy once, watch anywhere functionality. So far however, the system has been far from living up to this promise. Currently you can only view UltraViolet content on a Windows PC, Mac, iOS, or Android based mobile device. I can't find a single set top box that currently supports UltraViolet. Of the two UltraViolet titles that I've purchased, both are available on Amazon's Instant Streaming and iTunes, so Hollywood's own attempt at streaming video isn't even up to par with it's competition. Before even opening the box UltraViolet is off to a bad start.

Before going further, I would like to comment on my previous experience with digital copies provided with the purchase of a new Blu-Ray or DVD title. Most of them that I've found include a special digital copy disk an a redemption code. You put the special digital copy disk into your PC or Mac, and run the application on the disk. The application asks for your redemption code, and with the two-factor authentication of the special disk (something you have) and the redemption code (something you "know," also a one time password) you are given the coice of downloading your digital copy through iTunes or downloading a Windows Media File. (Again, this is from memory, there may have been other options.) The process was simple, strait forward, and the result was I got a digital copy to use on my iPhone, iPad, Apple TV, or play on my Mac or Windows PC. Downside, the digital copy was not a HD version (at least on iTunes) even if the digital copy came along with a Blu-Ray disc.

UltraViolet attempts to be similar, but without the special digital copy disc. With the rise in popularity of computers like the MacBook Air that don't have an optical drive eliminating the digital copy disk makes sense. The trend of computers without an optical drive is going strong. The UltraViolet card in the package directs you to a redemption URL. Currently Flixster is the only option. In order to redeem your UltraViolet movie, you first have to register a Flixter account. As you work your way through the redemption process you are prompted to log into or create your UltraViolet account. What? We need a second account?!? I feel your average consumer is going to find this confusing, though on the technical side it does make sense. If Flixter goes out of business, or if another company wants to create a service that competes with Flixer, the consumer can integrate the new service with their UltraViolet account and access their content through Flixter or the hypothetical new product. In practice, I found this frustrating. UltraViolet doesn't seem to offer an OpenID or similar Single Sign On technology, which would make much more sense than having separate accounts for Flixter and UltraViolet. Just sign into any UltraViolet compatible service with your UltraViolet account and get access to your content. It only makes sense with the prevalence of Facebook and Twitter which offer Single Sign On methods. To add to my frustration of having separate Flixter and UltraViolet accounts, the two websites have completely different password policies. Flixter accepted the nice secure password with mixed case letters, numbers, and special characters generated by LastPass, but UltraViolet would only accept letters and numbers. UltraViolet should dictate some policy and standards to their partners such as Flixter, and they should update their own authentication technology to allow for more secure passwords.

Once the accounts were created, the redemption process smoothed out somewhat. I entered my code for "Harry Potter and the Deathly Hallows Part 2", and was presented with the option to download an iTunes or Windows Media file, just like the old digital copy service. The link for the iTunes copy didn't work for me, and the page promptly disappeared and I have not been able to find it again. The only option to download is to install Adobe Air and the UltraViolet player, however the UltraViolet website then tells me that the title is unavailable to download until December 20th. No year is given, so I can only assume this means 2012. Again, "Harry Potter and the Deathly Hallows Part 2" is available to purchase and download in the iTunes store so I don't understand the download restriction in the UltraViolet system. When I redeemed my second UltraViolet title (Justice League: Doom) I haven't had similar quirks, though the download a copy option on the UltraViolet website again is not available until December 20th.

One side note on the UltraViolet website. If you think going to www.ultraviolet.com would bring you to the UltraViolet web site, you would be wrong. The actual website is www.uvvu.com. Again, I don't understand why a company delivering services over the internet would name their product without doing a simple whois check to see if the domain name is available, and if the domain is not available attempt to acquire the domain in question before going to market. This is yet another inexplicable failing for an industry that should have the resources to do this properly.

Once you have your accounts on Flixter.com and uvvu.com created, you would think entering your redemption code would be enough. Not so, first you have to search for or pick your UltraViolet title. Again I don't understand this. We have UPC codes on every product available in every retail store, so a redemption code should be enough to identify the title you have purchased as well as validate your purchase of the product, but it seems this is not the case for UltraViolet content.

So at this point, we have created a Flixter.com account, created a uvvu.com account, located our movie on the UltraViolet website, and now we're ready to enter our redemption code. Once you've gotten this far the process goes smoothly. If the code is valid, the title appears in your UltraViolet locker and you can stream the movie to your Mac or PC, or stream or download the title on your iOS or Android device. Currently there is no support for BlackBerry, WebOS, and other iOS and Android competitors. The exclusion of declining platforms such as BlackBerry and WebOS is understandable, but having no Windows Phone 7 option is concerning.

On to streaming. The UltraViolet website will direct you back to Flixter to stream your movie. When I was bounced back to Flixter's site, I was given the option to get a free movie to get your collection started! Well this was a nice bonus. The catch was you have to allow Flixter to post to your Facebook wall. I allowed this, but I set the post to be only visiable to me as at this point I can't find any reason at all to recommend Flixter and UltraViolet to my friends and family, and this choice was well justified. The site will not proceed bast the "Accept Gift" button in Google Chrome, and I could not redeem my free movie gift. I disabled Ghostery, AdBlock Plus, added the URL to allowed cookies, and still no luck. Turned out enabling 3rd party cookies in Chrome (not the default setting, I had disabled this earlier) fixed this. After that I was presented with the confusing option to allow Flixter to manage my UltraViolet account, and given the option to allow Warner Brothers access to my UltraViolet account for 1 year, 6 hours, or not at all. This apparently is to allow Flixter to show me UltraViolet content without having to log into my UltraViolet account. Finially the Single Sing On option! At this point I think I've entered my UltraViolet user name and password four or five times despite checking the "Remember Me" option on the uvvu.com website. At this point I would think the average consumer would have given up on the UltraViolet system, but I will continue on bravely. So Flixter has taken over my Facebook account, and I have successfully redeemed my free movie. In addition to "Harry Potter and the Deathly Hallows - Part 2" and "Justice League: Doom" I now have "He's Just Not That Into You" in my movie collection. Fabulous!

Did you note that I have not yet gotten to streaming my movie? I definitely have, and I'm rather annoyed.

So I click on "Justice League: Doom" and then Watch Now in the theory that an animated movie will highlight any quality issues with Flixter's delivery of the video stream. As the first frames of the movie play I make note of the SD icon in the lower right hand corner of the video player. So no HD stream. Expanding the video to full screen shows that it is highly compressed. At this point I could have downloaded the movie from iTunes (of note, the iTunes version of Justice League: Doom and Harry Potter are not averrable in HD.) Just for comparison I logged into Netflix and started playing "Thor & Loki: Blood Brothers." The Netflix stream started in just a few seconds compared to Flixter's 30 seconds of buffering, and the Nexflix player showed that it was indeed streaming a HD version of the content. A quick check of the other tittles in my Flixter collection. Harry Potter and "He's Just Not That Into You" both came up as SD streams, though the Flixter player did consider starting a HD stream of He's Just Not That Into You for a few seconds, just long enough of me to take note of the HD icon before it switched to SD. If I wanted to watch YouTube quality video on my laptop I'd go to YouTube, thanks but no thanks Flixter. By the way Flixter, YouTube offers me HD streaming video as well.

Not willing to put up with the lack of quality on my laptop, I'm going to give streaming to my iPhone a try. First step, install the Flixter iOS app on my iPhone. Log into Flixter on my iPhone. My UltraViolet movies are available for streaming. Curiously, I can log into Netflix and view my Netflix queue in the Flixter app. I haven't explored this, but worth noting is that the UltraViloet movies (and a good number of WB titles in general) are not available on Netflix Streaming. And is it really necessary to serve up iADs in your application Flixter? I am using your application to watch content that I have paid for!

Before the movie starts streaming, Flixter informs me that my phone is jailbroken and I'll have to install a clean version of iOS to use Flixter streaming. This is the first time I've run into an app using jailbreak detection. A quick install of xCon from the Cydia store gets rid of this annoyance, and my movie is streaming. The stream started much faster on iPhone than it did on my Mac, both my Mac and iPhone are on the same wifi network. The first time I started the stream it was badly pixelated. Like the emailed video you got from your 80-year old Grandma pixelated. I tried again about an hour later and the video quality was acceptable for an iPhone screen, it even looked better than what was displayed on my Mac.

One more thing to check, downloading the movie. On my Mac (and presumably on Windows) you have to first have Adobe Air installed, then you can install the Flixter Collections App. Personally I have yet to find a use for Adobe Air on either Mac or Windows, so I'm going to skip this. At this point I'm really not in the mood to download two more pieces of software that I didn't really want in the first place just to watch my movies. All I wanted was a digital copy of the movie that I can play via iTunes.

Back to the iPhone. The Flixter app will let you download a movie so you can watch it offline. A digital copy wouldn't be of much use if you couldn't watch it on your mobile device while traveling in a commercial airliner for example. Unfortunately, this is your only option for downloading the movie. Instead of giving you a file that will appear in the built in media player for iOS, the movie downloads into the Flixter app and you have to use the Flixter app to play your movies. While this is a limitation of iOS sandboxing more than anything, my feeling at this point is this is how Flixter would be forced to implement content downloading by the studios behind UltraViolet anyway. This sucks because it means you have to leave the Flixter app open on your iOS device while your content downloads, because Apple will only allow apps to download in the background for a few minutes or so. So you can't user your iOS device while your UltraViolet content downloads. If you purchased your content through the iTunes store on the other hand your content would download in the background and you could continue to use your iOS device. I suspect this limitation doesn't exist in Android devices as it's a limitation of the iOS platform, but I don't have one of those to confirm that. The file for "Justice League: Doom" weights in at 477 MB, so I'm obviously downloading a SD version of the content. Also the download is not going as quickly as I would expect for my Internet connection speed.

Overall my impression of the UltraViolet Digital Rights Management system are, well to say crap would be an insult to the perfection I flush down the toilet on a daily basis. The quality of the streams is low, the experience is poor, you are pestered by advertising on the Flixter web site and iOS application. All for content you paid for, and in my case, I paid for a Blu-Ray HD version of the content, but I can only access SD versions of the digital copy. I am not impressed. Flixter and UltraViolet aren't even worthy of my almost there tag. UltraViolet has a large gap to close before it can be considered competitive with it's competition.

Monday, February 13, 2012

Group Policy WMI Filter for Virtual Machines

I had a need to apply a Group Policy only to VMware virtual machines. One possible option was to filter on the vendor of the network adapter, which can be determined by looking at the MAC address. The public listing of company ID assignments can be found at IEEE OUI Public Listing and is updated daily. At the time of this writing, VMware has 00-05-69, 00-0C-29, 00-1C-14, and 00-50-65 as their company ID assignments.

This WMI filter should then pickup VMware Virtual Machines:
SELECT * FROM Win32_NetworkAdapter WHERE MACAddress LIKE "00:05:69%" or MACAddress LIKE "00:0C:29%" or MACAddress LIKE "00:50:65%"

Other Virtualization Vendors
Virtual Box: 08-00-27
Parallels: 00-1C-42

PSA: Do not name your Active Directory domain .local!

Please don't do this. The .local TLD is a reserved namespace for MDNS. MDNS is used extensivly by Apple in their Bonjour technology which is built into OS X, and typically finds it's way on to Windows computers via an iTunes installation. If there is ever the possiblity that Macs will be added to your network, do not use .local for your internal TLD. In fact, you really shouldn't be using any reserved namespace for your internal DNS. Trust me, you'll save yourself hours of potential headaches down the road when you don't do this. If you're stuck with this configuration, there are work arounds. None of them are great.

Workaround 1: How to make Mac OS X do dot-local lookups using both multicast and unicast queries
Workaround 2: Mac OSX 10.7 (Lion) Using .local Domain (Centrify DirectControl)

Wednesday, May 4, 2011

F-Secure Rescue CD

Malware is my most recent cause of headache. A specific antivirus product (looking at you SEP) has been completely worthless for preventing, detecting, and removing this stuff. Because I only have a few hours at client sites a full reinstall of Windows and applications, which would be the ideal solution, isn't an option.

Enter the F-Secure Rescue CD. A free removal tool, it has successfully detected and removed the Malware that other product didn't even detect. The F-Secure Rescue CD is a bootable Linux live CD that will boot the computer, download up to date malware detection patterns, and then scan the hard drive. Because it's booted into Linux and not Windows it's able to detect and remove malware that can go undetected while Windows is booted.

The downside is that the F-Secure Rescue CD will rename important Windows files that could prevent Windows from booting, resulting in a BSPD. If you do use this CD make sure you review the log file of files that are cleaned. In one instance it renamed C:\Windows\System32\Drivers\volsnap.sys to C:\Windows\System32\Drivers\volsnap.sys.virus. The volsnap.sys was infected with malware, but renaming the file also caused Windows to BSOD on boot, even when attempting to boot into Safe Mode. In most cases you can restore the file from your Windows install media using the recovery console, but you have to be well versed in the DOS command line to do so.

For example:
extract e:\i386\volsnap.sy_ C:\Windows\System32\Drivers\volsnap.sys.

Monday, December 6, 2010

MySQL Backup Script

This is my almost no configuration needed bash backup script for MySQL. The script first uses the mysql command line application to get a list of every database on your MySQL server, then loops through the list of databases and creates a separate dump file for each database.

You do need to create a ~/.my.cnf for the user the script will be running as.
  1. touch ~/.my.cnf
  2. chmod 600 ~/.my.cnf
The format for .my.cnf should be:

[client]
user = MySQL_User
password = MySQL_Password

Now the backup script. Configure the MYSQLUSER to match the MySQL user you will be backing up using (should match what you configured in .my.cnf.) Change the DIR variable to match where you want database dumps to be stored. Update the paths for MYSQL and MYSQLDUMP if needed. Then schedule the script to run as a daily cron job.
#!/bin/sh
MYSQLUSER=root
DIR=/srv/mysql-backup/dumps
MYSQL=/usr/bin/mysql
MYSQLDUMP=/usr/bin/mysqldump

# Day 1 is Monday.
DAY=`date +%u`

# Query MySQL for the list of databases in the MySQL Server.
# Create a seperate dump file for each database.
for DBNAME in $(${MYSQL} --user=${MYSQLUSER} -Bse 'show databases');
do
DUMPFILE=${DIR}/${DBNAME}/${DBNAME}_DAY${DAY}.sql
# Make the directory structure if needed.
/bin/mkdir -p ${DIR}/${DBNAME}
${MYSQLDUMP} --add-drop-table ${DBNAME} --user=${MYSQLUSER} > ${DUMPFILE}
# Remove last weeks backup if it exists.
if [ -e ${DUMPFILE}.bz2 ]
then
/bin/rm ${DUMPFILE}.bz2
fi
# Compress the dumpfile using bzip2.
/bin/bzip2 ${DUMPFILE}
done
# End Loop
This script will create a seven day rotation of MySQL dumps. (One dump for each day of the week.) The script alone isn't a complete backup solution. Use your backup solution of choice to backup the dump files to tape or other media. I'm using CrashPlan for all of my personal backup needs.