Friday, September 28, 2012

Managing Alternate Data Streams with Powershell 3.0

Something I've recently found out and that I think it's brilliant is the possibility under Powershell 3.0 to handle file forks natively, which is something I long expected to see implemented. Some of you maybe know already that the NTFS Master File Table (MFT) supports storing forks of files in its tree. These forks are better know under Windows (starting from NT4) as Alternate Data Streams (ADS).

Until now the only way to know if a file had one or more ADS was to recur to our friend the DIR command which, since Windows Vista, offered a /R parameter to display the existing ADS and their somewhat secret size.

Here's a sample output of DIR /R:

dir /r | find "DATA"
26 Introducing Windows Server 2008 R2.pdf:Zone.Identifier:$DATA
26 Parkdale.exe:Zone.Identifier:$DATA
26 setup.exe:Zone.Identifier:$DATA
26 Understanding Microsoft Virtualization Solutions.pdf:Zone.Identifier:$DATA

Piping the output of 'DIR /R' to the 'find' command allows the immediate listing of the files that have multiple data streams only and exclude all other 'normal' files.

As you can see in the example, many files usually have an ADS named 'Zone.Identifier' (whose size is 26 bytes). This particular fork stored withing the same filename tells you whether the file has been downloaded from the Net or not. A typical content is:

[ZoneTransfer]
ZoneId=3

with ZoneId values ranging (to my knowledge) from 0 to 4:

ZoneId=0: Local machine
ZoneId=1: Local intranet
ZoneId=2: Trusted sites
ZoneId=3: Internet
ZoneId=4: Restricted sites

If the ZoneId is equal to 3 or 4, when you will try to execute the file you will get a warning telling you "The publisher could not be verified. Are you sure you want to run this software?"...

Ok, now that we know how we can find the hidden ADS in our system, let's go back to our Powershell 3.0 command line to see in what ways it does help us in ADS management. Starting with this new version of Powershell, there is a way to find commands (using get-command) based on the parameters they accept (by adding the -parametername parameter). So let's run for instance:

gcm -ParameterName stream | select name

The returned list of cmdlets which support Alternate Data Streams is:

Add-Content
Clear-Content
Get-Content
Get-Item
Out-String
Remove-Item
Set-Content

For instance we can now retrieve the content of a fork the same way we did with

more < "Introducing Windows Server 2008 R2.pdf:Zone.Identifier"
or
more < "Introducing Windows Server 2008 R2.pdf:Zone.Identifier:$DATA"

by issuing

Get-Content "Introducing Windows Server 2008 R2.pdf" -stream Zone.Identifier
or
Get-Content "Introducing Windows Server 2008 R2.pdf" -stream Zone.Identifier$DATA

What's more, we can retrieve the properties of this ADS with Get-Item:

$ads = get-item '.\Introducing Windows Server 2008 R2.pdf' -Stream zone.identifier

The command

$ads | select filename,stream,length | fl 

will return

FileName : C:\folder\Introducing Windows Server 2008 R2.pdf
Stream   : Zone.Identifier
Length   : 26 

We can also quickly remove the fork (in this case no warning pop-up will come to disturb our inner peace!) with

Remove-Item .\file.txt -Stream  Zone.Identifier

This is a great step forward for Windows Powershell. Alternate Data Streams management has been left in the shade for almost a decade and today we can finally play with them like if they were standard user's files. 

Great, isn't it?

Wednesday, September 26, 2012

How to remotely modify Windows ACL using Powershell

I have been spending a few hours working on a permission configuration issue on remote Windows systems (NT4, 2000 and 2003). The aim of my script was to modify the existing permission on a file on remote systems, as well as setting the ownership for this same file. Obviously I decided to use the cmdlet that Powershell kindly offers (gcm -noun acl), but there are only two:
CommandType     Name
-----------     ----
Cmdlet          Get-Acl
Cmdlet          Set-Acl
At first sight I was sure that I was going to have problems with setting file ownership on a remote system because none of these two commands reference it. And I was right. Powershell doesn't allow to change file ownership on a remote file system (as explained here). I even tried to perform this operation with cacls and icacls, but I had no better luck and lot of errors (such as "no SID for trustee" and "Error Bad trustee name/SID no lookup").

As I do most of the times when I want to run something remotely and it doesn't work with native tools/cmdlets, I pulled from my magic hat the old good 'psexec.exe' in conjunction with 'filelacl.exe' (whose project has been recently abandoned by Microsoft, as you can see here, so hurry-up and store a copy of this program in safe place!).

My final script is a combination of pure Powershell cmdlets and freshly-mixed psexec and fileacl statements:
$remotehost = "test_host"
$username1 = "my_username"
$paswd = "my password"
$path = "\\$remotehost\c$\folder\file.txt"
$acl = Get-Acl $path
#Going to add my username with Full Control
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$username1","FullControl","Allow")
$acl.AddAccessRule($rule)
#Going to assing readandexecute ot Everyone group
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("everyone","readandexecute","Allow")
$acl.AddAccessRule($rule)
#Going to remove permissions for the local Administrator group
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("administrators","FullControl","Allow")
$acl.RemoveAccessRule($rule)
Set-Acl $path $acl
#Going to set the remote owner for this file
psexec -c -u $username1 -p $paswd \\$remotehost fileacl.exe "$path" /O "$username1"
#Let's check everything's been properly set
Get-Acl $path | Format-List
I know it doesn't look good but that's the best I could do to solve my issue. It works this way:
  • first of all I define a few variables, as the remote host name on which to work
  • I retrieve the current ACL of the remote file
  • I add two access rule: one for my username and one for the Everyone group
  • I also add another access rule to remove the permission for the local admin group
  • I apply these access rule with Set-Acl
  • I start a psexec session on the remote host and fire fileacl to set the ownership 
  • I dump the applied permissions with Get-Acl to check everything went well
Possible values for rights that you can assign under System.Security.AccessControl.FileSystemAccessRule are listed below. Just choose the one that applies to your situation:
  • AppendData
  • ChangePermissions
  • CreateDirectories
  • CreateFiles
  • Delete
  • DeleteSubdirectoriesAndFiles
  • ExecuteFile
  • FullControl
  • ListDirectory
  • Modify
  • Read
  • ReadAndExecute
  • ReadAttributes
  • ReadData
  • ReadExtendedAttributes
  • ReadPermissions
  • Synchronize
  • TakeOwnership
  • Traverse
  • Write
  • WriteAttributes
  • WriteData
  • WriteExtendedAttributes
I hope this simple script will be useful for those who, like me, didn't find a way to write file ownership on remote Master File Tables... be it under Windows NT, Windows 2000 or Windows 2003. Maybe the Scripting Guy can intervene and post a better solution!

Tuesday, September 25, 2012

PowerCLI: configuring vSwitches on vSphere5

Having just installed more than 30 vSphere 5 ESXi, I decided that I was not going to configure their vSwitches one by one, because I didn't like the idea that I could make a mistake in the configuration by entering all those settings manually.
 
Consumed by laziness, I immediately went on the Net to find the script that I was looking for and found this one: PowerCLI: Easy vSwitch & PortGroup Setup.

The aim of this script by Virtu-Al.net is to copy network settings from a source host to another host, which is more or less what I need if I first configure a host as a master from which to clone networking settings. The problem with this script is that it doesn't correspond to what I need for three reasons:
  • the first one is that it does not assign vmnics to the vSwitches,
  • the second one is that it does not activate vMotion on the Management Interface even though this setting is activated on the source host,
  • the third one is that it does not recursively clone settings in a one-to-many fashion.

Needless to say, I started jotting down my own script. It is structured in a way that for 32 hosts (using the Powershell Range construct x..y, which is very well explained here) I repeat the same task of:
  • enabling vMotion on the Management Network VMkernel port on vSwitch0
  • adding a secondary active NIC interface to vSwitch0, which will in the end rely on vmnic0 and vmnic2
  • creating a second vSwitch named vSwitch1 which relies on vmnic1 and vmnic3
  • creating three port groups with different VLAN IDs on vSwitch1
Connect-VIServer "your_vCenter" | Out-Null
1..32 | % {
$destination_host = Get-VMHost -Name "host$_.yourdomain.com"
$vswitch0 = "vSwitch0"
Write-Host "Configuring $vswitch0 Management Interface for vMotion and adding a second active NIC" -ForegroundColor blue
Write-Host "vSphere 5 installation already sets up vSwitch0 with a VM network and a Management Interface on the first NIC" -ForegroundColor gray
$destination_host |Get-VMHostNetworkAdapter |?{ $_.PortGroupName -match "Management Network"} | Set-VMHostNetworkAdapter  -VMotionEnabled:$true -Confirm:$false | Out-Null
$destination_host | Get-VirtualSwitch -Name $vswitch0 | Set-VirtualSwitch -Nic "vmnic0","vmnic2" -Confirm:$false | Out-Null
$vswitch1 = "vSwitch1"
Write-Host "Configuring $vswitch1 with two active adapters and adding three port groups with different VLANID" -ForegroundColor blue
$destination_host | New-VirtualSwitch -name $vswitch1 -Confirm:$false -nic "vmnic1","vmnic3" | Out-Null
$destination_host | Get-VirtualSwitch -Name $vswitch1 | New-VirtualPortGroup -Name "production_vlan" -Confirm:$false | Out-Null
$destination_host | Get-VirtualSwitch -Name $vswitch1 | New-VirtualPortGroup -Name "backup_vlan" -VLanId 8 -Confirm:$false | Out-Null
$destination_host | Get-VirtualSwitch -Name $vswitch1 | New-VirtualPortGroup -Name "production2_vlan" -VLanId 18 -Confirm:$false | Out-Null
Write-Host "Done configuring vSwitches on $destination_host"-ForegroundColor blue
}

As you can see, nothing very difficult here. I sue simple PowerCLI cmdlets which are very easy to understand. Just replace names and VLAN IDs to suit your needs and there you are. I hope this post helps someone. If you found it useful do not hesitate to comment, tweet or google+!!

Monday, September 24, 2012

PowerCLI: Add-VMHost deception

After using for two months a dozen of standalone ESXi 5 servers, and having the trial period just expired, I decided to join them to our vCenter infrastructure. Instead of using the manual procedure (right click on a cluster or folder, select 'Add host', enter the connection setting (hostname, user and password), assign a license, enable or disable lockdown mode and choose the location for this host's VM), I wanted to try the PowerCLI way.

So, I fired up a PowerGUI editor, and started checking the syntax for the 'Add-VMHost' cmdlet:

NAME
Add-VMHost

SYNOPSIS
Adds a host to be managed by a vSphere server.

SYNTAX
Add-VMHost [-Name]  [-Port ] [-Location]  [-Credential ] [-User ] [-Password ] [-Force] [-RunAsync] [-WhatIf] [-Confirm] []


DESCRIPTION
Adds a host to be managed by a vSphere server. The host is added to the datacenter or folder specified by the Location parameter. One of the User/Password and Credential parameters must be provided in order to authenticate with the host. If both are specified, the Credential parameter is used and the User and Password parameters are ignored.

To my great surprise there is no way of specifying a license to use... and this leads me to a lose-lose situation, because, being my ESXi expired, the cmdlet doesn't let me add these hosts to my vCenter and returns this error:

Add-VMHost : 9/24/2012 1:15:00 PM    Add-VMHost        The operation for the entity Folder-group-h106735 failed with the following message: "License not available to perform the operation."
+ CategoryInfo          : NotSpecified: (:) [Add-VMHost], NotEnoughLicenses
FullyQualifiedErrorId : Client20_TaskServiceImpl_CheckServerSideTaskUpdates_OperationFailed,VMware.VimAutomation.ViCore.Cmdlets.Commands.AddVMHost

Now I am uncomfortably stuck in this situation and my only way out is to add those ESXi hosts by hand using the vCenter interface, which I didn't want to use. Of course I checked this problem on the net and found many people talking about the use of Add-VMHost, but nobody talkin' of the discrepancies between the graphical interface and the behavior of the cmdlet... pretty stunning. Am I the first one to look for a way to assing a license to a host by means of this cmdlet?

I found a blog post on rtfm-ed.co.uk, but this guy shows us a way to license a host after having added it to vCenter. Which is not a solution for the problem I have.

I'll keep this post up-to-date if I ever find a way to solve this.

Tuesday, September 18, 2012

Problems and solutions for Windows 7 on a old P4

I have an old P4 running Windows 7 that I use to share some file from USB-attached disk drives and these days it happens that this box is periodically crashing and a BSOD is displayed. Due to the lack of time I am not willing to migrate these shares to another computer because a lot of configuration work would be necessary.

Thinking of a DIMM problem, I ran Memtest86+ from a USB disk (this is the best tool I've found so far for detecting RAM hardware errors, also because it has an auto-installer which does all the job of formatting a USB key, making it bootable and copying the memory diagnostic exe on it in one step) but, though I let it run for 3 days and made 16 passes, it didn't find any problem. I decided then to make an attempts with the new Windows Memory Diagnostic tool (which you can find in the 'Administrative Tools' menu) but it didn't detect any fault either.

So I gave up the idea of repairing the hardware and decided to implement a mechanism to auto-logon, then add a batch script to the 'Startup' folder which runs the sharing applications and lock the workstation straight after. So each time my workstation makes a BSOD all the applications I need are automagically restarted.

The first step is to enable auto-logon on Windows 7:
- run 'control userpasswords2'
- uncheck 'Users must enter a user name and password to use this computer'
- click OK
- an 'Automatically Log On' dialog box will appear
- enter the username you want to use for auto-logon and its password
- click OK

That's all. Auto-logon is now set.

The second step is to add a startup scripts which launches your applications then lock your Windows workstation. To do so:
- browse to %appdata%\Microsoft\Windows\Start Menu\Programs\Startup with Windows Explorer
- create a new batch file (.bat) in there
- add the names of your executables one per line this way:
    - start application1.exe
    - start application2.exe
    - start applicationn.exe
- at the end add this command to lock your workstation: 'rundll32.exe user32.dll, LockWorkStation'
- save your batch file

This way your computer will boot up and log on to Windows, then start your applications and lock itself. No action needed at all. At least in theory. In fact in my case my good old P4 didn't want to boot ans stayed stuck at detecting the attached USB drives. To solve this I went into the BIOS and disabled the USB Legacy Support. Disabling this option makes your BIOS not to try to initialize the USB disks on start-up, but leaves that task to Windows, which is kind of a USB-aware OS.

Three important notes now:

1) Configuring automatic login stores the user’s password in the registry (under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword) unencrypted which may represent a security weakness for critical systems.

2) Disabling USB Legacy Support will make your USB keyboard unavailable, so always have a PS/2 keyboard at hand.

3) Advanced users can tweak Windows 7 directly from the registry by modifying the ‘AutoAdminLogin’ value to ‘0′ to disable automatic login and ’1′ to enable it. The key is found in HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon.

I hope this little post will help somebody. I am just sharing my experience on the field... so do not hesitate to comment or post your questions!

Monday, September 17, 2012

Today's notes from the field...

Just a quick post to share what I have found today during my administration activities. First I have discovered that the debugging parameters nfs.lockdisable which sometimes I used to set to 1 has been removed starting from ESX 4.0 (as mentioned here).
nfs.lockdisable option as it was under ESX 3.5
The second discovery of the day is more or less a Powershell bug. When I use the test-connection cmdlet against some hosts it becomes pretty slow, even if I pass the IP address. Powershell sends out no more than 1 WMI ping each 10 seconds. I am still investigating this issue. My finding for the moment is that
  • it is no DNS issue,
  • it is not an authentication issue,
  • sometimes it works well with hosts in another domain and sometimes it does not,
  • sometimes it works with unix hosts, sometimes it does not
  • sometimes it fails with Windows hosts...
  • the issue stands the same under Powershell 2 and Powershell 3...
If any reader has the same problem or an idea on how to solve this second issue, please let me know! I am open for comments.


How to disable shell warnings in vSphere 5

This is a quick how-to that I regularly use (that's why I post it here) explaining how to disable the two warnings which appear on top of your ESXi Summary Page after you have enabled the ESXi shell and SSH connections.


Enabling SSH and the ESXi shell
vSphere alerts
Select the ESXi and go to the 'Configuration' tab. Once there, scroll down the page and select 'Advanced Settings' in the 'Software' menu. A pop-up windows will appear, where you have to select 'Uservars' then scroll down the list of setting to the very bottom and set 'UserVars.SuppressShellWarning' to 1.


How to set UserVars.SuppressShellWarning

That's all. I hope this helps.

Thursday, September 13, 2012

vSphere upgrade from 5.0 to 5.1

I am pretty interested in testing the new functionality of vMotion as it has been announced at VMworld a few days ago in San Francisco. This is how it is described on VMWare website:

"vSphere vMotion – Leverage the advantages of vMotion (zero-downtime migration) without the need for shared storage configurations. This new vMotion capability applies to the entire network."

Looks wonderful, isn't it? So i decided to upgrade some of my ESXi running on ProLiant BL460c G7 servers from vSphere 5.0.0-768111 to vSphere 5.1.0-799733 using the file 'VMware-ESXi-5.1.0-799733-HP-5.30.28.iso' which has just been released from VMWare for HP servers.

These are my screenshot of the upgrade:

Current version is ESXi 5.0.0-768111

Selecting the ISO for ESXi5.1

ISO loading

ISO loading...

Welcome screen

VMFS selection for upgrade

Here you can choose between a fresh install or an upgrade

Upgrade confirmation

ESXi succesfully upgraded to 5.1

Apparently everything went well, but it has not. My ESXi has been upgraded but it is no more recognised by my VirtualCenter instance, which is still sitting at 5.0. The error I get says: "A general system error occurred. Timed waiting for vpxa to start"...

Version mismatch
It definitively looks like I cannot manage ESXi 5.1 hosts from VirtualCenter 5.0. What a pity. I have to downgrade because I don't feel like passing to VirtualCenter 5.1 right now as we don't have any information about stability on this version. Has anyone of you already upgraded VirtualCenter to version 5.1? Please let me know how your upgrade went and if it is as stable as it should.

For completeness, here's a few useful links to 5.1 products:


Wednesday, September 12, 2012

vSphere Web Client stuck on loading

These days are full of odd findings. After discovering yesterday that Windows 7 and Windows 8 don't save the memory dump onto the disk if the available space is less than 25GB, I thought that I had reached my quota of bad news for this week. And I was wrong.

What I have discovered today is that, under vSphere 5, any Virtual Center user with limited privileges must belong to a generic read-only group at Virtual Center level to see the inventory through the Web Client. This has changed from version 4.1, where such an explicit permission needed not to be declared.

In fact, under vSphere 5, if a user with limited privileges logs into Virtual Center from the software client he will be able to see the inventory, but when passing from the Web Client the web interface (be it Internet Explorer or Firefox) will be stuck on 'Loading...' forever.

So, for the solution, just add a read-only permission for the problematic user/group at the root of the impacted Virtual Center. No need to force propagation, it will work straight away.

Tuesday, September 11, 2012

Missing memory dump under Windows 7 after BSOD

Windows 7 has sometimes a pretty strange behavior. I am trying to solve a recurrent KERNEL_MODE_EXCEPTION_NOT_HANDLED problem on one of my Windows 7 boxes and discovered that, though properly configured, there is no memory.dmp file under c:\windows. Pretty strange and shocking, right? Investigating the absence of this file after a BSOD, I found out that if the problematic box isn't on a domain, and has less than 25GB free space, then Windows 7 won't keep a crash dump file.

BSOD...
Luckily, a new registry value has been added that will override this odd behavior and always cause the crash dump file to be generated: set HKLM\System\CCS\Control\CrashControl\AlwaysKeepMemoryDump DWORD value to 1 and you will have a memory.dmp file under your Windows root folder (if there's enough disk space).

As a side note, if you are debugging a BSOD and you can't find this memory.dmp file, try to check under c:\windows\minidump: there you may find a short version of the missing memory dump. My suggestion is to use BlueScreenView to analyze them. This tool will in fact highlight the faulting driver straight away.

Bluescreenview screenshot
That's all for this technical note. Now I am trying to guess why someone at MS decided to implement this new behavior. I think it should probably be due to the fact that under Windows XP people had often been complaining about memory dumps filling their hard drives. So I may agree with MS about this choice. Also, as far I have understood, a memory dump is always kept in case the BSOD appears on a Windows Server version. And this is reassuring.

Windows 8 appears to behave the same (as stated here).
Related Posts Plugin for WordPress, Blogger...