Thursday, May 29, 2014

Change Local Account Password CmdLet

There are lots of ways to change the password on local machine accounts. I used this as a sample project as I was exploring all the features of CmdLets. At first glance, this code is overkill for the task at hand. It is a good example of how to implement -WhatIf, -Confirm, and -Force. I have another post that shows just the 2 lines of code needed to change the local account password.


#AccountManagement is used for Varifying password changes
Add-Type -AssemblyName System.DirectoryServices.AccountManagement

function Set-AccountPassword
{
<#
.Synopsis
   Sets the password for a local machine account
.DESCRIPTION
   It will set a password on a remote machine for the specified account with the specified password
.EXAMPLE
   Set-AccountPassword -ComputerName localhost -AccountName Administrator -Password BatteryStapleHorse
.EXAMPLE
    Set-AccountPassword -Password BatteryStapleHorse -SkipVerify -Force
#>
    [CmdletBinding(DefaultParameterSetName='Default', 
                  SupportsShouldProcess, 
                  PositionalBinding=$false,
                  HelpUri = 'http://www.microsoft.com/',
                  ConfirmImpact='Medium')]
    Param
    (
        # ComputerName help description
        [Parameter(Mandatory=$false, 
                   ValueFromPipeline=$true,
                   ValueFromPipelineByPropertyName=$true, 
                   Position=0)]
        [string]$ComputerName = "$env:computername",

        # AccountName help description
        [Parameter(Position=1)]
        [string]
        $AccountName = 'Administrator',

        # Password help description
        [Parameter(Position=2,
                    Mandatory=$true,
                    ParameterSetName="Default")]
        [ValidateLength(15,139)]
        [String]
        $Password,

        [Parameter()]
        [switch]$SkipVerify,

        [Parameter()]
        [switch]$Force
    )


    Begin
    {
     
    }   
    Process
    {
        Write-Verbose "Testing connection to $ComputerName before we try and change the password"
        if(Test-Connection $ComputerName -Count 1){
            Write-Verbose "$ComputerName is online"

            #Example of support for -WhatIf
            #Also used with -Confirm and ConfirmImpact options
            if ($pscmdlet.ShouldProcess("$ComputerName\$AccountName", "SetPassword"))
            {
                #Example of support for -Force, this will prompt every time unless the -force param is used
                if($Force -or $pscmdlet.ShouldContinue("Change the password for this account: $ComputerName\$AccountName","Setting Password")){
                    Write-Verbose "Using ADSI for connection to WinNT://$ComputerName/$AccountName"
                    $admin = [adsi]("WinNT://$ComputerName/$AccountName, user")

                    Write-Verbose "Invoking SetPassword on $ComputerName"
                    $admin.psbase.invoke("SetPassword", $Password)
                
                    # This will verify that the password was changed to $Password
                    # Skip Verify is an optional param
                    if(!$SkipVerify){
                        Write-Verbose "Verifing that the password changed correctly"
                        
                        $obj = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('machine',"$ComputerName")
                        if($obj.ValidateCredentials("$AccountName","$Password")){
                            Write-Verbose "Verified!"
                        }else{
                            Write-Error "Failed to verify password change"
                        }
                    }else{
                        Write-Verbose "SkipVerify=True skipping verify check"
                    } #SkipVerify
                } #ShouldContinue
            } #ShouldProcess
        } #Test-Connection
    } #Process
    End
    {
    }
}

Wednesday, May 28, 2014

Simple DSC Example

One thing I am doing to get more practice with Desired State Configuration is to create configurations for existing servers. I am grabbing the easiest things to script and working out from there. Here one I quickly put together for our terminal server boxes.


$ConfigData = @{
    AllNodes = @(
        @{
            NodeName = "*"
        },
        @{
            NodeName = "ProdServer1";
            
            Database = "database";
            DatabaseServer = "DBServer"
        },
        @{
            NodeName = "ProdServer2";
            
            Database = "database"
            DatabaseServer = "DBServer"
        },
        @{
            NodeName = "QAServer1";
            
            Database = "QAdatabase"
            DatabaseServer = "DBServer"
        }
    )
}


Configuration TerminalServer
{
   node $allnodes.NodeName {
        WindowsFeature Backup {
            Name = "Windows-Server-Backup";
       }
   }

   node $allnodes.NodeName
   {
   
   

       WindowsFeature DesktopExperience {
        Name = "Desktop-Experience";
        IncludeAllSubFeature = "True";
       } 

       WindowsFeature RDS {
        Name = "RDS-RD-Server";
        IncludeAllSubFeature = "True";
       }         
   
       
       Registry ProductdDatabase{
        Key = "HKLM:\SOFTWARE\company\product";
        ValueName = 'InitialCatalog';
        ValueData = $node.Database
       }

       Registry ProductDatabaseServer{
        Key = "HKLM:\SOFTWARE\company\product";
        ValueName = 'DataSource';
        ValueData = $node.DatabaseServer
       }

   }
} 

TerminalServer -ConfigurationData $ConfigData

Start-DscConfiguration -Wait -Verbose -Path .\TerminalServer

Tuesday, May 27, 2014

Enable-PrintHistory

I recently wrote a script that parses windows events to report on printing by user or by printer. To make that happen, it was important that a special log gets enabled. I was able to create a small script to do that for me.

$EventLog = Get-WinEvent -ListLog Microsoft-Windows-PrintService/Operational 
$EventLog | 
   %{$_.IsEnabled = $true; 
      $_.MaximumSizeInBytes=50MB;
      $_.LogMode = "AutoBackup"
      $_.SaveChanges()} 

One thing you will notice is that I call SaveChanges() after I see all the values. None of the settings will be saved if you don't do that. It is one of those details that could easily be missed if you were not looking for it.

I polished it up a bit as a CmdLet: Enable-PrintHistory

Wednesday, May 21, 2014

How do I track pages printed?

We had a 3rd party service managing our printers for a while. It didn't work out in the long run but they gave us these nice reports showing us how many pages each printer printed in the previous quarter. I found that information very valuable thought and kind of missed it.

After a little digging, I came up with a way to track that information without having to walk to every printer. To be honest, I had a lot of ideas but I eventually found a Windows event log that that gave me everything I needed. The event log is called Microsoft-Windows-PrintService/Operational. You first need to enable the log but it collects a lot of good details. 

$log = Get-WinEvent -FilterHashTable @{ "LogName"= "Microsoft-Windows-PrintService/Operational";"ID"="307"}

Once we pull all of the events, it they will be easy enough to parse with RegEx. Through this together quite quickly but it gets the job done. I have only tested this message format on Server 2012R2.

 *RegEx excluded from the post because I can't get it to render correctly in blogger without a lot of rework. See script at the end.

Once I parse out the values I need, I package it back into an object. From there you can do whatever you need to do with it.

$log | ?{$_.message -match $MessageRegEx} | 
    %{ New-Object PSObject -property @{"Document"=$Matches.Document;
       "UserName"=$Matches.Username;
       "IP"=$Matches.IP;
       "ComputerName"=$Matches.Computer;
       "Pages"=$Matches.Pages;
       "TimeStamp"= $_.TimeCreated;
       "Printer" = $Matches.Printer;
       "PrintHost" = $_.MachineName
    }}

Then write that out to a CSV file when you are done. If you take a look at the values that I can parse out of it, I get a lot more information that I expected. Not only can you get page counts per printer, you can track printed page counts back to individual users. I pull this dataset into Excel and transform it into a pivot table for easy reporting.

After I clean this up a bit, here is my resulting CmdLet: Get-PrintHistory

Monday, May 19, 2014

Why Powershell Desired State Configuration?

I am a huge fan of Powershell. I use it where I can to manage my infrastructure and workstations. Powershell remoting is such a wonderful thing. I start to think about my infrastructure as nodes or objects in code. As someone that shifted into IT from development, this becomes a very powerful tool. 

I craft and test my commands on test workstations. I then take those commands and order all of my nodes in AD to go take care of it. I see a job spin off for every one at almost the same time. And I know they are doing exactly what I am telling them to do. It just gives you that feeling of power. It is even better when you can see and hear it happening.

Our largest dental clinic has 50 chars in it. Each cubicle has dividers between them, 2 people could stand up in opposite corners of this large room and they could see each other. There is a central control station that faculty use where I love to issue remote commands. When I send something like Wake On Lan to all the clinics, I can hear every machine in there click on at almost the same time. I can hear the fans spin up and I can see the monitor glow cast a blue shine across the room. There is nothing like seeing your code interact with the real world like that.

This is the perfect fix it now type of remote scripting. This is great for when I want to refresh group policy for flush DNS on every node. I target my Active Directory nodes and say go take care of this. But not every script is a fix it now type of script.

Because I blindly target nodes when I do this, some slip through the cracks. Maybe WOL was miss configured, bios has a low battery warning, the mobile user is out of the office, or it is a spare machine sitting on a shelf. I am left with several machines for whatever reason missed the script. I don't care so much when I flush dns on everything but what about enabling bitlocker? That just has to get taken care of. So I have to decide how to handle this going forward. GPO, SCCM, scheduled task on some random box, or I run this script again when I think about it. 

Personally, I make that call case by case and use whatever I think is best for the change. I have to consider newly deployed machines, returning machines, and how likely those settings will drift. And this is where Desired State Config starts to enter the picture. We have to remember it is just another tool like GPO or SCCM, but it does have a lot to offer.
DSC lets you declare how a system should look, and it will take care of it for you. You once again get to say "make it so" and the system takes action. Not only does this set configurations on nodes, it makes sure they stay configured. With a pull server in place, they never miss a command. You set it and forget it. 

I am just getting started with DSC and I love the idea. Still not sure it is the best match for my current environment, but I think it is important we take notice of it. I felt Powershell was overlooked by a lot of people for the longest time. Step back and see how important Powershell has become already. And when they Jeffery Snover says the reason they created Powershell was so that they could create Desired State Config, you know this is something you should pay attention to.

I don't think we will see this for workstation management yet, it is only a matter of time before we see tools like SCCM switch over to use DSC.

Sunday, May 18, 2014

My Notes from TechED 2014

I just got back from TechED 2014. One thing I really love about TechED is that all the sessions are presented by the people that work very closely with the products they are talking about. Often time you can gain a lot of insight just by the way they talk about things. Every sessions has 1 or 2 real gems.

As I review my notes, here are some of the key takeaways for myself. Things I didn't realize before or things I need to pay more attention to going forward. These are my notes and they are a little cryptic at times.

Azure now offers Redis cache
SQL 3014 offers %3000 performance increase for some workloads
API management is new Azure feature
Antimalware now part of azure
Office 365 encryption with each file having its own key
Site recovery now support replica directly to Azure
Managed apps are on IOS/Android
Azure Remote App
Cortana runs in the cloud is and is context aware
Xamarin offers .Net support for IOS/Android with Visual Studio 2013
HDInsight is Microsoft's implementation of Hadoop
PowerBI.com is like PowerView but in Azure with a powerful natural language search
Oslo and the Office Graph
One source of the truth
vNext Intune managed apps gives more control over data. Can block copy paste to other apps
Win-B310 TWC: Bullet proofing your network security - Download PPT and check blog for online sessions
defaultpassword.com
exploit-db
Security Compliance Manager: http://technet.microsoft.com/en-us/library/cc677002.aspx
    Can compare you settings vs best practice. Can also import GPO and compare it.
Microsoft Attack Surface Analyzer: http://www.microsoft.com/en-us/download/details.aspx?id=24487
    Run it before and after you install an application and it shows you how it changes the system attack surface
ITIL V3 DCIM-B224 - Watch this session again
   Start IT Steering Committee
   What service do we offer and how do we measure it
Desired State Config
  Scale * Complexity =  Exceeds Skill
New-CimSession - is this the replacement for New-PSSession, Investigate more
When hacked, do a memory dump before you shut it down. Then do a disk dump.
   Lot of important stuff in ram, like possible encryption keys or memory resident tools
Whatever runs is in memory and the rest of the OS is just a bunch of files
The prefetch can identify recent programs that were ran
This is turned off by default on SSD drives, turn it back on
X2works pf64.exe can analyse prefetch files
RPD History shows recent connections
Bitmap cache can show pieces of the last sessions screen
mstsc /public
Recommended to centeralize logs
Nvidia K2 or K5000 for VDI
Use change logon /drain
Local accounts have the same name, the fact that they have the same SID is not important
If 2 accounts have the same password, they have the same hash.
You can deny access to computer from network with group policy
New local group for local accounts that can be used in GPO to deny access
NT AUTHORITY\Local account
Run LSASS as protected process, it requires dlls to be digitally signed
mstsc /restrictedadmin
You can create silos in Active Directory
Monad Manifesto http://www.jsnover.com/Docs/MonadManifesto.pdf
DSC will be the primary administrative interface for Microsoft
released in October and Stack Overflow is using it in production
You can push or pull, use pull over https
DSC uses WSMAN
VMM can inject .mof files already
Must import non more modules in config files
connect.microsoft.com - where to provide feedback
Don't let existing habits dictate how you use this
DSC for Linux
Become a pull admin - Things are changing fast enough that you have to pull the info yourself to keep up
Focus on servers
One version of the truth
Virus Total integration with sysinternals
Uploading suspicious files can tip off attackers that you are on to them
clip command takes standard input to the clip board
AccessChk new options -h file/print shares -l detailed list -f filter out things
procmon can export to XML
there are scripts on blog to identify changed items and then copy those files/reg keys to a folder
if you run xcopy from a 32 bit cmd, then it will put things into the 32 bit locations automatically
You can use scheduled tasks to bypass UAC prompts
PsExec now encrypts on the wire
PsPing can to UDP testing, timed tests, and created firewall exceptions
darkreading.com
winflip for windows 8 embedded thin clinets
Storage spaces limit to 80 disks per pool and 4 pools per SOFS cluster
disk x columns = write speed
When trying to max iops, consider latency
Performance paper in PPT from Wed Tiered Storage Spaces Best Practices
use MPIO, use SMB multichannel
4xSSD + 20x7.2rpm drives = 700 VDI users
Force dedup after deploy then run tiering
There is a script to validate all the drive you need to run before you set up spaces
Monitor health, latency, tier usage
Server Performance Monitor (SPA) tool can configure alerts
xJEA
Get-PSSSessionConfiguration shows several default configurations
uses local account. 127 character password that changes daily
Get-Command will show you what you can run
DevOps - If you cannot measure it, you cannot improve it
Campfire, look at it
Automated SCCM Deployment that uses a variable.xml file for all the settings
   will download everything, take care of dependencies, and fire up VMs if needed
jp64 from TZworks can read the NTFS Journal changes
in IIS, application pool settings can dump passwords in plain text
Same issue with services
Sysinternals Process Manager uses purple for packed files
Search strings for HTTP
Change the default refresh rate when hunting malware
Add verified signature column
Add VirusTotal column
Autoruns can scan offline systems
ProcMon - filter category write, then proc tree view to include subtree
Azure Express Route - 1-2 ms delay, with 10GB pipe

That is more of a mess then I expected. I may revisit this list later and clean it up with more details as I work with these things.