Wednesday, June 20, 2012

Server 2012 Install-WindowsFeature Net-Framework-Features fail. Use the source, Luke

Let go.

The force is strong on this one.

Trust your feelings.

I don’t know if you have noticed or not.  But if you attempt to install the .Net 3.5 on Server 2012 it always fails.

This seems to have been particularly troublesome to application installers that ‘just expect it to work’ and fail instead.    Then you end up here, desperately trying to figure out how to install .Net 3.5.

If you wan to see the error that these installers are tossing; simply open a PowerShell windows and attempt to install .Net 3.5 using install- (or add- ) Windows Feature:

image

A nice big fat failure.  But you think, this always worked before.  Server 2008 / R2 / SP1 this worked without a hitch or problem.  It was built-in. What gives?

The issue is in the detail of that error:  Use the “source” option to specify the location of the files…

Well, seems that the files are not there, at least for .Net 3.5 they are not installed to the local WinSxS source location when the OS is installed.  (Ever wondered how you can add features after install?  ‘Sources’)

Looking around a bit, you will eventually find it.  On the installation CD / ISO.  So that becomes your source path.  Insert the DVD or mount the ISO to your VM and use the following:

Add-WindowsFeature –name NET-Framework-Features –source D:\sources\sxs

The “D:” in my case is the drive letter of the CD drive of my VM.

image

Tuesday, June 19, 2012

Generating random passwords with PowerShell, rehash

In the recent password issue with LinkedIn.  The ArsTechnica report really makes it is evident that passwords alone are not enough.  DarkReading also has a good story on this.

Even passwords believed to be secure were hacked within hours or a day or two.  It is simply an issue of computing power.  Contrast that against what the human brain can memorize in regards to complex passwords. 

I was (and still am) a proponent of pass phrases as you could make a longer password and substitute characters and it was easier to remember.  But alas, it is just a password – and that must be recognized.

It is obvious that two-factor is the real way to go.  As Coding Horror elaborated on a while back, and I implemented after there was an attempt to hack my Facebook account (thank you for login alerts).  You know, it really isn’t that big of an inconvenience or problem.

But, I digress.

So, to blog a bit more about using PowerShell to do useful things – like generating a password string.

You can find all kinds of references to doing this.  Go search and pick your favorite:

http://letmebingthatforyou.com/?q=powershell%20generate%20random%20passwords

From that, I chose two.  I quick one liner, and a more complex script.

From PowerShell.com there are a few Generate Random Password Power Tips.  It is obviously a popular topic.

The first:

function Get-RandomPassword {
    param(
        $length = 10,
        $characters =

        'abcdefghkmnprstuvwxyzABCDEFGHKLMNPRSTUVWXYZ123456789!"§$%&/()=?*+#_'
    )
    # select random characters
    $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
    # output random pwd
    $private:ofs = ""
    [String]$characters[$random]
}

The second:

-join ([Char[]]'abcdefgABCDEFG0123456&%$' | Get-Random -count 20)

That one is pretty good if you just want to generate a password on the fly within a script.

The third:

function Get-RandomPassword {
    param(
        $length = 11,
        $characters = 'abcdefghkmnprstuvwxyzABCDEFGHKLMNPRSTUVWXYZ123456789!"§$%&/()=?*+#_'
    )
    # select random characters
    $random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
    # output random pwd
    $private:ofs = ""
    [String]$characters[$random]
}

function Randomize-Text {
    param(
        $text
    )
    $anzahl = $text.length -1
    $indizes = Get-Random -InputObject (0..$anzahl) -Count $anzahl
    $private:ofs = ''
    [String]$text[$indizes]
}

function Get-ComplexPassword {
    $password = Get-RandomPassword -length 6 -characters 'abcdefghiklmnprstuvwxyz'
    $password += Get-RandomPassword -length 2 -characters '#*+)'
    $password += Get-RandomPassword -length 2 -characters '123456789'
    $password += Get-RandomPassword -length 4 -characters 'ABCDEFGHKLMNPRSTUVWXYZ'
    Randomize-Text $password
}

This last one enforces password policy by guaranteeing a count of specific character types.  Why they left out ‘0’ I don’t know.  Also notice that the calls to Get-RandomPassword at the end constrains the special characters that are used / returned.  So if you have a web site that can’t handle special characters or it cannot handle specific ones you can constrain that here. 

I also found the blog of Erwin Wendland and his Create-RandomPassword Function for creating strong passwords.  This last one I would call a bit more like C#.

Tuesday, June 5, 2012

Synchronizing PowerShell script execution on multiple machines

I originally thought to call this “synchronizing watches” but since I am not changing system time I thought it might be misleading.  This post is all about synchronizing script execution on two different machines.

Some folks would use a central client and workflows (PowerShell v3) or PowerShell remoting to execute a script on remote machines at the same time.  Possibly even executing each one as a job so they happen at the same time. 

It also allows me to launch the script on server A and then move to the other side of the lab to launch its script and then begin the repro (or switch the monitor on the KVM).  I know that as long as they share a time service I can be confident in when the tracing began on the remote machine.

In my case I want to execute the script on each machine at the console.  My reasoning is that; the machines are not in the same domain making security messy, or I don’t want to modify firewall rules, or I am capturing network traffic and just don’t want the extra noise to filter through.

Here is my scenario: 

  • I have multiple servers (a large, distributed application)
  • Different things are happening on each server
  • I want to enable a network trace at the same time (to have nicely correlated logs)
  • The systems already have a common time source (the OS handles that after all)
  • I need to manually trigger the reproduction of the bug after the tracing starts, or I need to trigger some event prior to the tracing beginning
  • I only have two hands and two feet

Here is the synchronization snip at the beginning of my script:

Do {
    Start-Sleep ( 60 - (Get-Date -Format ss) )
    
    [string]$nowMinute = Get-Date -Format mm
} until ( $nowMinute[($nowMinute.Length - 1)] -eq "0" -or $nowMinute[($nowMinute.Length - 1)] -eq "5" )

The first thing that I do I describe as squaring up.  I invoke a Start-Sleep but I want to sleep until the end of the current minute, no longer.

Start-Sleep ( 60 - (Get-Date -Format ss) )

You could do this as two lines as well (or three if you like):

$secToZero = 60 - (Get-Date -Format ss)

Start-Sleep $secToZero

Then I get the current minute and evaluate it to the nearest 5 minute block.

I chose the 5 minute mark because it is easy to evaluate to (if the number ends in 0 or 5 it divides by 5).  I cast the returned integer to a string as well, so I can get that last digit.

[string]$nowMinute = Get-Date -Format mm

*Notice that if you use “MM” instead of “mm” you get the Month.

I do my math evaluation at the end of the Until.  Notice the –or between the 0 and 5 after the –eq.  That is important to force the evaluation against both numbers.

Here is where personal preference sets in.  I dreamed up three different ways to handle the evaluation in the Until block.

The first is a very literal evaluation of the second digit in the Seconds to see if it equals “0” or “5”.  the entire last line looks like this:

} until ( $nowMinute[($nowMinute.Length - 1)] -eq "0" -or $nowMinute[($nowMinute.Length - 1)] -eq "5" )

It is the ($nowMinute.Length –1) that puts us at position 1 ( position begins counting at 0) to perform the evaluation.  The position indicator for the array is the square brackets [].

Another way to handle this is through the PowerShell way to handle a Regular Expression (or a pattern match – a nice article on that is here.)

Based on that article I can keep my –or and simply indicate the second digit this way:

} until ( $nowMinute -match ".0" -or $nowMinute -match ".5" )

Or, I can do it more like a regular expression and state in a shorter line that the second digit can match either 0 or 5.  That looks like this:

} until ( $nowMinute -match ".[0,5]" )

The end result is all the same.  Much of the technique is all about personal preference.