Hyper-V and Azman for delegated VM access (using PowerShell!)

There’s an excellent article about delegating Hyper-V permissions using Azman (Authorization Manager) which has recently proven invaluable for me. We’ve been using VMM for a while, but the only real use case we have is to impose a simple segregation between our “production” development systems and our test systems (to avoid testers accidentally powering off the CI server, for example).

VMM is really overkill for this, and after upgrading to VMM 2012 I found that it no longer even managed to set permissions properly. (All our users hate the VMM self-service portal and want to use the Hyper-V MMC anyway…)

One part of the process detailed in that article which I wanted to improve on was the VBS scripts used to set the Scope for VMs. The permission model relies on assigning VMs to scopes (and then assigning users to those scopes with particular permissions profiles). The latter can be done with the Azman UI (or, I am sure, via scripting of some kind via WMI). The former can only be done via scripting. Since I do most of my Hyper-V management using PowerShell I wanted a simple solution to keep it all in one place.

https://github.com/tbentropy/vmscope

So I wrote a simple PowerShell module with two methods, Get-VMScope and Set-VMScope. Get-VMScope lists the scope for the given VM (either pass a string with the name or a wildcard pattern, or pipe in an object with either a “VMName” or “ElementName” property – e.g. you can pipe in the VM objects which are returned by the psHyperV module. Set-VMScope takes a (single) VMName/ElementName and you set the Scope using the -Scope parameter.

No documentation (yet), but it’s fairly self-explanatory!

One issue I found while migrating from VMM 2012 to using this was that snapshots contain a scope property which will override the global one whenever the machine is reverted. This can be overcome by re-snapshotting, or manually editing the snapshot XML file, or running a script/task to set the scope whenever the machines are reverted automatically. This problem will gradually go away as the machines get rebuilt of course.

PXE configuration

(This is just a random braindump, no real structure!) Directory structure:


RemoteInstall/ - Base folder, shared using TFTP, HTTP and SMB
Boot/ - No reason for this subfolder (hang over from using WDS initially)
abortpxe.0 - Permits exit from PXE process via menu
abortpxe.com
boot.gpxe - Initial boot file for gPXE, see below
chain.c32
gpxe-1.0.1-gpxe.kpxe - Initial file used to boot gPXE
gpxe-1.0.1-undionly.kpxe - Same, but using UNDI only (I found this doesn't work with a lot of older NICs)
ifcpu.c32 - CPU feature detection, use for menus
ifcpu64.c32 - CPU feature detection, use for menus
LiteTouchPE_x64.iso
LiteTouchPE_x86.iso - Images produced using MDT, and then booted using memdisk - see notes
memdisk - Used to boot from an ISO image
poweroff.com - Turn off machine
pxechain.com
pxelinux.0 - This is loaded by gPXE to provide the menus
pxelinux.com
vesamenu.c32 - Provides menu system
Linux/ - Place to put Linux files (and things like memtest)
pxelinux.cfg/ - Configuration for pxelinux
default - Default menu loaded for all clients
graphics.conf - Configuration for menu graphics
linux.menu
logo.jpg
tools.menu

DHCP configuration: I’m using the Windows DHCP server. You need to configure some server options at the root of your scope:


Option Name Value Class
066 Boot Server Host Name None
067 Bootfile Name http:///reminst/Boot/boot.gpxe gPXE
067 Bootfile Name Boot\gpxe-1.0.1-gpxe.kpxe None

You’ll need to create a custom class called gPXE to specify one of the options inside. Right-click on “IPv4” under your DHCP server -> “User Classes” -> Add Name: gPXE Description: gPXE Clients ASCII: gPXE Other than that set up DHCP as normal. You don’t need to configure option 60. More details on chainbooting gPXE can be found here. boot.gpxe:


#!gpxe
chain http:///reminst/Boot/pxelinux.0

This is simple, but can be made much more complex (see gPXE command line reference). MDT notes: Generating the MDT images is fairly straightforward, though obviously you need to configure MDT first (outside the scope of this article). The .iso MDT produces contains a WIM image, boot.sdi and bootmgr etc. This can be used to boot windows PE, which then triggers OS deployment. One little thing to mention here is that for this process to work you need to disable the “Press any key to boot from CD/DVD” option which comes up. This is done by removing the bootfix.bin file from the generated ISO. Delete it from: C:\Program Files\Windows AIK\Tools\PETools\x86\boot\ C:\Program Files\Windows AIK\Tools\PETools\amd64\boot\ And MDT won’t copy it into the ISOs it generates. Menu entries for MDT:


LABEL wds
MENU LABEL ^Windows Deployment Services (x86)
LINUX http:///reminst/Boot/memdisk
APPEND iso raw
INITRD http:///reminst/Boot/LiteTouchPE_x86.iso


LABEL wds
MENU LABEL ^Windows Deployment Services
LINUX http:///reminst/Boot/memdisk
APPEND iso raw
INITRD http:///reminst/Boot/LiteTouchPE_x64.iso

Selecting either option will download memdisk and the iso, then boot from the ISO (which takes you into the MDT wizard, or if you configure a default task sequence per machine it’ll automatically begin to deploy). gPXE: You can get gPXE ROMs from here. I chose to use the all drivers one for simplicity, and because I found the UNDI-only one didn’t work with some NICs. The “PXE bootstrap loader” option is the right one (.kpxe) Other notes: Menu item for booting from local disk should be…


LABEL local
MENU DEFAULT
MENU LABEL Boot from ^Harddisk
LOCALBOOT -1

Links: Download SYSLINUXTFTPD

SQL 2012 unattended install + command line options

Here’s the help output from the SQL 2012 setup.exe:


Usage:
setup.exe /[option]={value} /[option]={value} ...

Options:
ACTION Specifies a Setup work flow, like INSTALL,
UNINSTALL, or UPGRADE. This is a required
parameter.
ADDCURRENTUSERASSQLADMIN Provision current user as a Database Engine
system administrator for SQL Server 2012 Express.
AGTDOMAINGROUP Either domain user name or system account
AGTSVCACCOUNT Either domain user name or system account
AGTSVCPASSWORD Password for domain user name. Not required for
system account
AGTSVCSTARTUPTYPE Startup type for the SQL Server Agent service.
Supported values are Manual, Automatic or
Disabled.
ALLINSTANCES Specifies that all instances are to be included
in the Setup operation. This parameter is
supported only when applying a patch.
ALLOWUPGRADEFORSSRSSHAREPOIN
RSInputSettings_AllowUpgradeForSSRSSharePointMode_Description
ASBACKUPDIR The location for the Analysis Services backup
files.
ASCOLLATION The collation used by Analysis Services.
ASCONFIGDIR The location for the Analysis Services
configuration files.
ASDATADIR The location for the Analysis Services data
files.
ASLOGDIR The location for the Analysis Services log files.
ASPROVIDERMSOLAP Specifies if the MSOLAP provider can run in
process.
ASSERVERMODE Specifies the server mode of the Analysis
Services instance. Valid values are
MULTIDIMENSIONAL and TABULAR. The default value
is MULTIDIMENSIONAL.
ASSVCACCOUNT The account used by the Analysis Services
service.
ASSVCPASSWORD The password for the Analysis Services service
account.
ASSVCSTARTUPTYPE Controls the service startup type setting for the
service.
ASSYSADMINACCOUNTS Specifies the list of administrator accounts to
provision.
ASTEMPDIR The location for the Analysis Services temporary
files.
BROWSERSVCSTARTUPTYPE Startup type for Browser Service.
CLTCTLRNAME The computer name that the client communicates
with for the Distributed Replay Controller
service.
CLTRESULTDIR The result directory for the Distributed Replay
Client service.
CLTSTARTUPTYPE The startup type for the Distributed Replay
Client service.
CLTSVCACCOUNT The account used by the Distributed Replay Client
service.
CLTSVCPASSWORD The password for the Distributed Replay Client
service account.
CLTWORKINGDIR The working directory for the Distributed Replay
Client service.
CLUSTERPASSIVE Specifies that SQL Server Setup should not manage
the SQL Server services. This option should be
used only in a non-Microsoft cluster environment.
COMMFABRICENCRYPTION MATRIXCOMMMESSAGEPROTECTION {0,1}
COMMFABRICNETWORKLEVEL MATRIXCOMMNETWORKISOLATION {0,1}
COMMFABRICPORT MATRIXCOMMPORT
CONFIGURATIONFILE Specifies the configuration file to be used for
Setup.
CONFIRMIPDEPENDENCYCHANGE Indicates that the change in IP address resource
dependency type for the SQL Server multi-subnet
failover cluster is accepted.
CTLRSTARTUPTYPE The startup type for the Distributed Replay
Controller service.
CTLRSVCACCOUNT The account used by the Distributed Replay
Controller service.
CTLRSVCPASSWORD The password for the Distributed Replay
Controller service account.
CTLRUSERS The Windows account(s) used to grant permission
to the Distributed Replay Controller service.
ENABLERANU Set to "1" to enable RANU for SQL Server Express.
ENU Detailed help for command line argument ENU has
not been defined yet.
ERRORREPORTING Specify if errors can be reported to Microsoft to
improve future SQL Server releases. Specify 1 or
True to enable and 0 or False to disable this
feature.
FAILOVERCLUSTERDISKS Specifies a cluster shared disk to associate with
the SQL Server failover cluster instance.
FAILOVERCLUSTERGROUP Specifies the name of the cluster group for the
SQL Server failover cluster instance.
FAILOVERCLUSTERIPADDRESSES Specifies an encoded IP address. The encodings
are semicolon-delimited (;), and follow the
format ;
;;<subnet
mask>. Supported IP types include DHCP, IPV4, and
IPV6.
FAILOVERCLUSTERNETWORKNAME Specifies the name of the SQ LServer failover
cluster instance. This name is the network name
that is used to connect to SQL Server services.
FAILOVERCLUSTERROLLOWNERSHIP Specifies whether the upgraded nodes should take
ownership of the failover instance group or not.
Use 0 to retain ownership in the legacy nodes, 1
to make the upgraded nodes take ownership, or 2
to let SQL Server Setup decide when to move
ownership.
FEATURES Specifies features to install, uninstall, or
upgrade. The list of top-level features include
SQL, AS, RS, IS, MDS, and Tools. The SQL feature
will install the Database Engine, Replication,
Full-Text, and Data Quality Services (DQS)
server. The Tools feature will install Management
Tools, Books online components, SQL Server Data
Tools, and other shared components.
FILESTREAMLEVEL Level to enable FILESTREAM feature at (0, 1, 2 or
3).
FILESTREAMSHARENAME Name of Windows share to be created for
FILESTREAM File I/O.
FTSVCACCOUNT User account for Full-text Filter Daemon Host.
FTSVCPASSWORD User password for Full-text Filter Daemon Host
account.
FTUPGRADEOPTION Full-text catalog upgrade option.
HELP Displays the command line parameters usage
IACCEPTSQLSERVERLICENSETERMS By specifying this parameter and accepting the
SQL Server license terms, you acknowledge that
you have read and understood the terms of use.
INDICATEPROGRESS Specifies that the detailed Setup log should be
piped to the console.
INSTALLSHAREDDIR Specify the root installation directory for
shared components. This directory remains
unchanged after shared components are already
installed.
INSTALLSHAREDWOWDIR Specify the root installation directory for the
WOW64 shared components. This directory remains
unchanged after WOW64 shared components are
already installed.
INSTALLSQLDATADIR The Database Engine root data directory.
INSTANCEDIR Specify the instance root directory.
INSTANCEID Specify the Instance ID for the SQL Server
features you have specified. SQL Server directory
structure, registry structure, and service names
will incorporate the instance ID of the SQL
Server instance.
INSTANCENAME Specify a default or named instance. MSSQLSERVER
is the default instance for non-Express editions
and SQLExpress for Express editions. This
parameter is required when installing the SQL
Server Database Engine (SQL), Analysis Services
(AS), or Reporting Services (RS).
ISSVCACCOUNT Either domain user name or system account.
ISSVCPASSWORD Password for domain user.
ISSVCSTARTUPTYPE Automatic, Manual or Disabled.
MATRIXCMBRICKCOMMPORT MATRIXCMBRICKCOMMPORT portNumber
MATRIXCMSERVERNAME MATRIXCMSERVERNAME hostName\instanceName
MATRIXNAME MATRIXNAME=
NPENABLED Specify 0 to disable or 1 to enable the Named
Pipes protocol.
PID Specify the SQL Server product key to configure
which edition you would like to use.
QUIET Setup will not display any user interface.
QUIETSIMPLE Setup will display progress only, without any
user interaction.
ROLE Detailed help for command line argument ROLE has
not been defined yet.
RSCATALOGSERVERINSTANCENAME The SQL Server server for the report server
catalog database.
RSINSTALLMODE RSInputSettings_RSInstallMode_Description
RSSHPINSTALLMODE RSInputSettings_RSInstallMode_Description
RSSVCACCOUNT Specify the service account of the report server.
This value is required. If you omit this value,
Setup will use the default built-in account for
the current operating system (either
NetworkService or LocalSystem). If you specify a
domain user account, the domain must be under 254
characters and the user name must be under 20
characters. The account name cannot contain the
following characters:
" / \ [ ] : ; | = , + * ?
RSSVCPASSWORD Specify a strong password for the account. A
strong password is at least 8 characters and
includes a combination of upper and lower case
alphanumeric characters and at least one symbol
character. Avoid spelling an actual word or name
that might be listed in a dictionary.
RSSVCSTARTUPTYPE Specifies the startup mode for the Report Server
service. Valid values include Manual, Automatic,
and Disabled. The default value for StartupType
is Manual, where the server is started when a
request is received.
RSUPGRADEDATABASEACCOUNT RSInputSettings_RSInstallMode_Description
RSUPGRADEPASSWORD RSInputSettings_RSInstallMode_Description
RULES Specifies the list of rule IDs or rule group IDs
to run.
SAPWD Password for SQL Server sa account.
SECURITYMODE The default is Windows Authentication. Use "SQL"
for Mixed Mode Authentication.
SQLBACKUPDIR Default directory for the Database Engine backup
files.
SQLCOLLATION Specifies a Windows collation or an SQL collation
to use for the Database Engine.
SQLSVCACCOUNT Account for SQL Server service: Domain\User or
system account.
SQLSVCPASSWORD A SQL Server service password is required only
for a domain account.
SQLSVCSTARTUPTYPE Startup type for the SQL Server service.
SQLSYSADMINACCOUNTS Windows account(s) to provision as SQL Server
system administrators.
SQLTEMPDBDIR Directory for Database Engine TempDB files.
SQLTEMPDBLOGDIR Directory for the Database Engine TempDB log
files.
SQLUSERDBDIR Default directory for the Database Engine user
databases.
SQLUSERDBLOGDIR Default directory for the Database Engine user
database logs.
SQMREPORTING Specify that SQL Server feature usage data can be
collected and sent to Microsoft. Specify 1 or
True to enable and 0 or False to disable this
feature.
TCPENABLED Specify 0 to disable or 1 to enable the TCP/IP
protocol.
UIMODE Parameter that controls the user interface
behavior. Valid values are Normal for the full
UI,AutoAdvance for a simplied UI, and
EnableUIOnServerCore for bypassing Server Core
setup GUI block.
UpdateEnabled Specify whether SQL Server Setup should discover
and include product updates. The valid values are
True and False or 1 and 0. By default SQL Server
Setup will include updates that are found.
UpdateSource Specify the location where SQL Server Setup will
obtain product updates. The valid values are "MU"
to search Microsoft Update, a valid folder path,
a relative path such as .\MyUpdates or a UNC
share. By default SQL Server Setup will search
Microsoft Update or a Windows Update service
through the Window Server Update Services.
X86 Specifies that Setup should install into WOW64.
This command line argument is not supported on an
IA64 or a 32-bit system.

Full unattended installation example, showing all required parameters:


setup.exe /Q /IACCEPTSQLSERVERLICENSETERMS /ACTION=install /PID= /FEATURES=SQL,AS,RS,IS,Tools
/INSTANCENAME=MSSQLSERVER /SQLSVCACCOUNT="MyDomain\MyAccount"
/SQLSVCPASSWORD="************" /SQLSYSADMINACCOUNTS="MyDomain\MyAccount "
/AGTSVCACCOUNT="MyDomain\MyAccount" /AGTSVCPASSWORD="************"
/ASSVCACCOUNT="MyDomain\MyAccount" /ASSVCPASSWORD="************"
/RSSVCACCOUNT="MyDomain\MyAccount" /RSSVCPASSWORD="************"
/ISSVCAccount="MyDomain\MyAccount" /ISSVCPASSWORD="************"
/ASSYSADMINACCOUNTS="MyDomain\MyAccount"

Answer files are still supported, so you can specify /ConfigurationFile on the command line and then use an answer file to set most of the other options, or set them on the command line. E.g. the answer file for a fairly default install would be:


[OPTIONS]
ACTION="install"
PID=
FEATURES=SQL,Tools
INSTANCENAME="MSSQLSERVER"
SQLSVCACCOUNT="NT AUTHORITY\SYSTEM"
SQLSVCPASSWORD="************"
SQLSYSADMINACCOUNTS="Builtin\Administrators"
AGTSVCACCOUNT="NT AUTHORITY\SYSTEM"
AGTSVCPASSWORD="************"

Save it as %TEMP%\SQL2012.ini and then run:

setup.exe /ConfigurationFile=%TEMP%\SQL2012.ini

I tend to put the passwords on the command line, to avoid having them sitting around in temporary files (same for PIDKEY).

Useful links:

Configuration file syntax
Configuration parameters

Modifying embedded properties in WMI using PowerShell

This isn’t immediately obvious. Say you have a WMI class, e.g. SMS_SCI_Component from the SCCM WMI provider (root\SMS\site_XXX). You can obtain a PowerShell object representing the various instances of this class easily enough:


$SiteCode = "XXX"
$WmiObjectNamespace = "root\SMS\site_$($SiteCode)"
$WmiObjectClass = SMS_SCI_Component
$WmiObjectFilter = "ComponentName='SMS_AD_SECURITY_GROUP_DISCOVERY_AGENT'"


$WmiObject = Get-WmiObject -Namespace $WmiObjectNamespace -Class $WmiObjectClass -Filter $WmiObjectFilter

$WmiObject will now be an instance of the [System.Management.ManagementObject] class, with properties similar to:


PS S:\SCCM2012> $WmiObject

__GENUS : 2
__CLASS : SMS_SCI_Component
__SUPERCLASS : SMS_SiteControlItem
__DYNASTY : SMS_BaseClass
__RELPATH : SMS_SCI_Component.FileType=2,ItemName="SMS_AD_SECURITY_GROUP_DISCOVERY_AGENT|DEVXX-CM01.DEVXX.local"
,ItemType="Component",SiteCode="XXX"
__PROPERTY_COUNT : 9
__DERIVATION : {SMS_SiteControlItem, SMS_BaseClass}
__SERVER : DEVXX-CM01
__NAMESPACE : root\SMS\site_D71
__PATH : \\DEVXX-CM01\root\SMS\site_D71:SMS_SCI_Component.FileType=2,ItemName="SMS_AD_SECURITY_GROUP_DISCOVER
Y_AGENT|DEVXX-CM01.DEVXX.local",ItemType="Component",SiteCode="XXX"
ComponentName : SMS_AD_SECURITY_GROUP_DISCOVERY_AGENT
FileType : 2
Flag : 2
ItemName : SMS_AD_SECURITY_GROUP_DISCOVERY_AGENT|DEVXX-CM01.DEVXX.local
ItemType : Component
Name : DEVXX-CM01.DEVXX.local
PropLists : {AD Accounts:test2, AD Attributes, AD Containers, Search Bases:blah...}
Props : {Days Since Last Logon, Days Since Last Password Set, Discover DG Membership, Enable Filtering Expir
ed Logon...}
SiteCode : XXX

Pretty much everything in SCCM WMI is like this, an object with a list of embedded SMS_EmbeddedPropertyList objects.

Accessing these is fairly simple, just access the PropLists member of the $WmiObject instance. E.g. to remove one:


$Name = "Testing"
$PropListName = "Search Bases:$($Name)"

# Apply filter
$proplists = $WmiObject.PropLists
$proplists = $proplists | where {$_.PropertyListName -ne $PropListName}

# Finally write changes back to the object
$WmiObject.PropLists = $proplists
$WmiObject.put() > $null

But how about adding one? Well we need to create an instance of an SMS_EmbeddedPropertyList and then add it to the parent object’s list. To create an instance we use:


$new = [WmiClass] "$WmiObjectNamespace:SMS_EmbeddedPropertyList"
$embeddedproperylist = $new.CreateInstance()

This will give you an instance of the [System.Management.ManagementObject] class with the following properties:


PS S:\SCCM2012> $embeddedproperylist

__GENUS : 2
__CLASS : SMS_EmbeddedPropertyList
__SUPERCLASS :
__DYNASTY : SMS_EmbeddedPropertyList
__RELPATH :
__PROPERTY_COUNT : 3
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ItemType :
PropertyListName :
Values :

So you fill in the required parameters, and then add it to the $proplists array for writing back…


$embeddedproperylist.PropertyListName = "testname"
$embeddedproperylist.Values = @("value1", "value2")

$WmiObject.PropLists += $embeddedproperylist

$WmiObject.put()

Ah…


PS S:\SCCM2012> $WmiObject.PropLists += $embeddedproperylist
Exception setting "PropLists": "Unable to cast object of type 'System.Management.Automation.PSObject' to type 'System.M
anagement.ManagementBaseObject'."
At line:1 char:12
+ $WmiObject. <<<< PropLists += $epl
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException

It seems that if you make any modifications to the instance it can no longer automatically convert it into its base type for writing back to WMI. The trick is to perform the cast manually:


$embeddedproperylist = [System.Management.ManagementBaseObject] $embeddedproperylist

$WmiObject.PropLists += $embeddedproperylist

$WmiObject.put()

Success!

DNSSEC + unbound local DNS

I’ve been playing with dnssec-trigger, a neat little utility from NLnet labs which configures a local instance of Unbound (a caching recursive DNS resolver) and a utility which listens for network configuration changes. It can then reconfigure your system’s DNS settings on the fly to ensure you’re always using DNSSEC secured resolvers (while still taking advantage of locally configured recursive resolvers assigned by DHCP).

I think that’s pretty cool 🙂

Only pitfall so far is that it doesn’t play nicely with VPN for accessing work. I think I can probably work around that by setting up a stub resolver configuration in Unbound though.

Further info:

http://jpmens.net/2011/10/21/automating-unbound-for-dnssec-on-your-workstation/
http://jpmens.net/2011/11/05/dnssec-trigger-on-mac-os-x/

It works nicely with the DNSSEC Validator Firefox addon (by CZ.NIC Labs).

Makes me really want to get my domain DNSSEC enabled now!

SixOrNot 0.7.0


It’s been a long time coming, but I finally finished off a new release. There’s actually an 0.7.1 which fixes a few additional bugs but that’s awaiting review.

So what’s new? Most visibly the UI has been replaced with a new panel-based design. This allows more information to be shown. This is needed because the addon now shows you not only the IPv6 status of the main domain you’re visiting, but also the status for all the domains contacted during the loading of the page. This is particularly useful for highlighting when a site’s CDN (content delivery network) isn’t IPv6 enabled despite the site itself claiming to be!

Another major change is that SixOrNot now takes advantage of changes to the Firefox API which allow you to find the actual IP address used to connect to a remote site. When the addon was first conceived this was not possible and I had to take the approach of using DNS lookups along with local address information to guess at the transport being used. This wasn’t 100% reliable however, and in dual-stack environments was only a best-guess as to the actual state. Now SixOrNot tells you the actual address you’re connecting to.

Of course it still shows the DNS information, and so can still show you when a site could potentially be contacted using IPv6. As far as I’m aware it’s the only addon which does this combined approach.

Under the hood I’ve completely re-engineered the way the addon works. Previously a polling loop was used (a hangover to the old code which was lifted from the Flagfox addon – now all completely re-written), now the architecture is entirely event-driven. This makes the addon much more efficient and reduces memory/CPU usage.

The code has also been heavily re-factored and re-organised. This aids maintainability and provides a good basis for new features. On that subject I’m planning on adding back the local IP address information (along with an optional lookup of your external IP address(es). The documentation also needs a major overhaul, and a proper website is on my todo list as well.

You can download SixOrNot from the Mozilla addons website here:

https://addons.mozilla.org/en-US/firefox/addon/sixornot/

The source code is available on Github:

https://github.com/tbentropy/sixornot

SCCM 2012 PowerShell automation library

So my latest project is to build a library to permit automated configuration of SCCM 2012. Currently this is in release candidate form, though a final release date is expected at MMS later this year. So far despite rumours there is no firm information about whether native PowerShell support (e.g. SCCM-specific cmdlets) will be provided by Microsoft.

We need this right now at work to start building test environments so I have a copy of the RC2 beta installed, a copy of the /\/\o\/\/ PowerShell WMI Explorer and a certain grim determination to produce a damn fine PowerShell library.

So far I’ve finished Boundaries and BoundaryGroups, currently working on Discovery Methods (via an interesting diversion into the world of CIM_DATETIME strings and SMS Schedules…)

I’ll be posting more as I build it. Code will be pushed to github:

https://github.com/tbentropy/SCCM2012PowerShell

SCCM scripted install note: Webdav prerequisite

http://technet.microsoft.com/en-us/library/cc431377.aspx

Installing SCCM 2007 on Server 2008 or Server 2008 R2 has a number of prerequisites related to IIS, namely:

– Remote Differential Compression
– IIS 7.0 for 2008, IIS 7.5 for 2008 R2
– BITS Server Extensions/Background Intelligent Transfer Services (BITS), Remote Differential Compression, WebDAV Publishing (2008 R2 only), ASP.NET, Windows Authentication
– On 2008, webdav needs to be installed manually

Most of these can be easily taken care of by installing the correct roles/role services on the platforms in question. This is easy to do on 2008/2008R2 using servermanagercmd.exe, e.g.:


servermanagercmd.exe -install BITS Web-Asp-Net

Once you have IIS installed (and on 2008, have manually installed webdav) you need to configure webdav. This can be done using the following scripted commands via the appcmd.exe utility which comes with IIS7.


%WinDir%\System32\InetSrv\appcmd.exe set config "Default Web Site" /section:system.webServer/webdav/authoring /enabled:true /commit:apphost
%WinDir%\System32\InetSrv\appcmd.exe set config "Default Web Site" /section:system.webServer/webdav/authoringRules /+[users='*',path='*',access='Read'] /commit:apphost
%WinDir%\System32\InetSrv\appcmd.exe set config "Default Web Site" /section:system.webServer/webdav/authoring /fileSystem.allowHiddenFiles:true /commit:apphost
%WinDir%\System32\InetSrv\appcmd.exe set config "Default Web Site" /section:system.webServer/webdav/authoring /properties.allowAnonymousPropfind:true /commit:apphost
%WinDir%\System32\InetSrv\appcmd.exe set config "Default Web Site" /section:system.webServer/webdav/authoring /properties.allowInfinitePropfindDepth:true /commit:apphost
%WinDir%\System32\InetSrv\appcmd.exe set config "Default Web Site" /section:system.webServer/webdav/authoring /properties.allowCustomProperties:false /commit:apphost

This performs the same actions as the instructions here.

Fileserver upgrades

The PSU on my fileserver (singularity) broke recently, and I decided to take the opportunity to upgrade it a bit.

New hardware:

Asus M4A88T-M motherboard
AMD Sempron 145 2.8GHz
4GB ECC DDR3 memory

This isn’t a massive upgrade over the old system, however it does give me ECC memory capability (the motherboard/CPU both support it – a nice feature of AMD kit that even their bottom-of-the-line kit has this) as well as a better-supported chipset for FreeBSD (the old motherboard used an nVidia chipset which never really worked well).

Here’s the dmesg for the new system:


Copyright (c) 1992-2011 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 8.2-RELEASE #0: Thu Feb 17 02:41:51 UTC 2011
root@mason.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
Timecounter "i8254" frequency 1193182 Hz quality 0
CPU: AMD Sempron(tm) 145 Processor (2812.64-MHz K8-class CPU)
Origin = "AuthenticAMD" Id = 0x100f63 Family = 10 Model = 6 Stepping = 3
Features=0x78bfbff
Features2=0x802009
AMD Features=0xee500800
AMD Features2=0x37fd
TSC: P-state invariant
real memory = 4294967296 (4096 MB)
avail memory = 3841773568 (3663 MB)
ACPI APIC Table:
ACPI Warning: Optional field Pm2ControlBlock has zero address or length: 0x0000000000000000/0x1 (20101013/tbfadt-655)
ioapic0 irqs 0-23 on motherboard
kbd1 at kbdmux0
acpi0: on motherboard
acpi0: [ITHREAD]
acpi0: Power Button (fixed)
acpi0: reservation of fee00000, 1000 (3) failed
acpi0: reservation of ffb80000, 80000 (3) failed
acpi0: reservation of fec10000, 20 (3) failed
acpi0: reservation of fed40000, 5000 (3) failed
acpi0: reservation of 100000, cfe00000 (3) failed
acpi0: reservation of 0, a0000 (3) failed
Timecounter "ACPI-fast" frequency 3579545 Hz quality 1000
acpi_timer0: port 0x808-0x80b on acpi0
cpu0: on acpi0
acpi_hpet0: iomem 0xfed00000-0xfed003ff on acpi0
Timecounter "HPET" frequency 14318180 Hz quality 900
pcib0: port 0xcf8-0xcff on acpi0
pci0: on pcib0
pcib1: at device 1.0 on pci0
pci1: on pcib1
vgapci0: port 0xd000-0xd0ff mem 0xd0000000-0xdfffffff,0xfeaf0000-0xfeafffff,0xfe900000-0xfe9fffff irq 18 at device 5.0 on pci1
pci1: at device 5.1 (no driver attached)
pcib2: irq 18 at device 2.0 on pci0
pci2: on pcib2
pcib3: at device 0.0 on pci2
pci3: on pcib3
arcmsr0: <Areca SATA Host Adapter RAID Controller
> mem 0xfebfb000-0xfebfbfff,0xfd800000-0xfdbfffff irq 16 at device 14.0 on pci3
ARECA RAID ADAPTER0: Driver Version 1.20.00.19 2010-11-11
ARECA RAID ADAPTER0: FIRMWARE VERSION V1.48 2009-12-31
arcmsr0: [ITHREAD]
pcib4: at device 0.2 on pci2
pci4: on pcib4
pcib5: irq 18 at device 10.0 on pci0
pci5: on pcib5
re0: port 0xe800-0xe8ff mem 0xfdfff000-0xfdffffff,0xfdff8000-0xfdffbfff irq 18 at device 0.0 on pci5
re0: Using 1 MSI messages
re0: Chip rev. 0x2c000000
re0: MAC rev. 0x00000000
miibus0: on re0
rgephy0: PHY 1 on miibus0
rgephy0: 10baseT, 10baseT-FDX, 10baseT-FDX-flow, 100baseTX, 100baseTX-FDX, 100baseTX-FDX-flow, 1000baseT, 1000baseT-master, 1000baseT-FDX, 1000baseT-FDX-master, 1000baseT-FDX-flow, 1000baseT-FDX-flow-master, auto, auto-flow
re0: Ethernet address: 14:da:e9:b7:f1:a9
re0: [FILTER]
atapci0: port 0xc000-0xc007,0xb000-0xb003,0xa000-0xa007,0x9000-0x9003,0x8000-0x800f mem 0xfe8ffc00-0xfe8fffff irq 22 at device 17.0 on pci0
atapci0: [ITHREAD]
atapci0: AHCI v1.10 controller with 4 3Gbps ports, PM supported
ata2: on atapci0
ata2: [ITHREAD]
ata3: on atapci0
ata3: [ITHREAD]
ata4: on atapci0
ata4: [ITHREAD]
ata5: on atapci0
ata5: [ITHREAD]
ohci0: mem 0xfe8fe000-0xfe8fefff irq 16 at device 18.0 on pci0
ohci0: [ITHREAD]
usbus0: on ohci0
ohci1: mem 0xfe8fd000-0xfe8fdfff irq 16 at device 18.1 on pci0
ohci1: [ITHREAD]
usbus1: on ohci1
ehci0: mem 0xfe8ff800-0xfe8ff8ff irq 17 at device 18.2 on pci0
ehci0: [ITHREAD]
usbus2: EHCI version 1.0
usbus2: on ehci0
ohci2: mem 0xfe8fc000-0xfe8fcfff irq 18 at device 19.0 on pci0
ohci2: [ITHREAD]
usbus3: on ohci2
ohci3: mem 0xfe8fb000-0xfe8fbfff irq 18 at device 19.1 on pci0
ohci3: [ITHREAD]
usbus4: on ohci3
ehci1: mem 0xfe8ff400-0xfe8ff4ff irq 19 at device 19.2 on pci0
ehci1: [ITHREAD]
usbus5: EHCI version 1.0
usbus5: on ehci1
pci0: at device 20.0 (no driver attached)
atapci1: port 0x1f0-0x1f7,0x3f6,0x170-0x177,0x376,0xff00-0xff0f at device 20.1 on pci0
ata0: on atapci1
ata0: [ITHREAD]
ata1: on atapci1
ata1: [ITHREAD]
isab0: at device 20.3 on pci0
isa0: on isab0
pcib6: at device 20.4 on pci0
pci6: on pcib6
ohci4: mem 0xfe8fa000-0xfe8fafff irq 18 at device 20.5 on pci0
ohci4: [ITHREAD]
usbus6: on ohci4
acpi_button0: on acpi0
atrtc0: port 0x70-0x71 irq 8 on acpi0
ppc0: port 0x378-0x37f irq 7 on acpi0
ppc0: Generic chipset (NIBBLE-only) in COMPATIBLE mode
ppc0: [ITHREAD]
ppbus0: on ppc0
plip0: on ppbus0
plip0: [ITHREAD]
lpt0: on ppbus0
lpt0: [ITHREAD]
lpt0: Interrupt-driven port
ppi0: on ppbus0
acpi_hpet1: iomem 0xfed00000-0xfed003ff on acpi0
device_attach: acpi_hpet1 attach returned 12
uart0: port 0x3f8-0x3ff irq 4 flags 0x10 on acpi0
uart0: [FILTER]
orm0: at iomem 0xc0000-0xcefff on isa0
sc0: at flags 0x100 on isa0
sc0: VGA
vga0: at port 0x3c0-0x3df iomem 0xa0000-0xbffff on isa0
atkbdc0: at port 0x60,0x64 on isa0
atkbd0: irq 1 on atkbdc0
kbd0 at atkbd0
atkbd0: [GIANT-LOCKED]
atkbd0: [ITHREAD]
acpi_throttle0: on cpu0
hwpstate0: on cpu0
Timecounter "TSC" frequency 2812644637 Hz quality 800
Timecounters tick every 1.000 msec
usbus0: 12Mbps Full Speed USB v1.0
usbus1: 12Mbps Full Speed USB v1.0
usbus2: 480Mbps High Speed USB v2.0
usbus3: 12Mbps Full Speed USB v1.0
usbus4: 12Mbps Full Speed USB v1.0
usbus5: 480Mbps High Speed USB v2.0
usbus6: 12Mbps Full Speed USB v1.0
ugen0.1: at usbus0
uhub0: on usbus0
ugen1.1: at usbus1
uhub1: on usbus1
ugen2.1: at usbus2
uhub2: on usbus2
ugen3.1: at usbus3
uhub3: on usbus3
ugen4.1: at usbus4
uhub4: on usbus4
ugen5.1: at usbus5
uhub5: on usbus5
ugen6.1: at usbus6
uhub6: on usbus6
ad0: 152627MB at ata0-master UDMA100
uhub6: 2 ports with 2 removable, self powered
uhub0: 3 ports with 3 removable, self powered
uhub1: 3 ports with 3 removable, self powered
uhub3: 3 ports with 3 removable, self powered
uhub4: 3 ports with 3 removable, self powered
uhub2: 6 ports with 6 removable, self powered
uhub5: 6 ports with 6 removable, self powered
pass1 at arcmsr0 bus 0 scbus0 target 16 lun 0
pass1: Fixed Processor SCSI-0 device
da0 at arcmsr0 bus 0 scbus0 target 0 lun 0
da0: Fixed Direct Access SCSI-5 device
da0: 166.666MB/s transfers (83.333MHz, offset 32, 16bit)
da0: Command Queueing enabled
da0: 5722045MB (11718749184 512 byte sectors: 255H 63S/T 729458C)
ugen1.2: at usbus1
ukbd0: on usbus1
kbd2 at ukbd0
uhid0: on usbus1
Trying to mount root from ufs:/dev/ad0s1a
re0: link state changed to DOWN
re0: link state changed to UP
acpi_aiboost0: on acpi0
acpi_hpet1: iomem 0xfed00000-0xfed003ff on acpi0
device_attach: acpi_hpet1 attach returned 12

The system uses an Areca 1210 hardware RAID card (highly recommended) attached to 4 2TB Western Digital disks to provide the primary storage array. The next step is to copy the system from the current 160GB IDE drive over to an old 320GB SATA drive I have (the previous motherboard only had 4 SATA ports, all of which were used for the backup drive array).

PowerShell remoting and certificates

Trying to use PowerShell remoting to connect to a server and I see:


[servername] Connecting to remote server failed with the following error message
: The WinRM client received an HTTP server error status (500), but the remote
service did not include any other information about the cause of the failure. F
or more information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:Re
moteRunspace) [], PSRemotingTransportException
+ FullyQualifiedErrorId : PSSessionOpenFailed

Mysterious. Checking the event logs on the remote machine reveals:


A fatal error occurred when attempting to access the SSL server credential private key. The error code returned from the cryptographic module is 0x8009030d. The internal error state is 10001.

So it’s trying to read from a certificate and failing. The certificate in question is stored under:


C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys

(Found by searching for the above error message).

It looks like the certificates have rolled over, so the old certificate which winrm has a reference to is no longer valid. I’m not actually even making use of certificate-based authentication so the easiest solution is to remove the CertificateThumbprint parameter from winrm configuration:


winrm set winrm/config/service @{CertificateThumbprint=""}

Make sure you don’t try running that from a PowerShell prompt though, as it’ll complain about it being an invalid command line even when it isn’t (since the @{} syntax is interpreted by PowerShell)…

And the working winrm configuration:


C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys>winrm get winrm/config
Config
MaxEnvelopeSizekb = 800
MaxTimeoutms = 600000
MaxBatchItems = 20
MaxProviderRequests = 4294967295
Client
NetworkDelayms = 5000
URLPrefix = wsman
AllowUnencrypted = false
Auth
Basic = true
Digest = true
Kerberos = true
Negotiate = true
Certificate = true
CredSSP = true
DefaultPorts
HTTP = 5985
HTTPS = 5986
TrustedHosts = *
Service
RootSDDL =
MaxConcurrentOperations = 4294967295
MaxConcurrentOperationsPerUser = 200
EnumerationTimeoutms = 600000
MaxConnections = 15
MaxPacketRetrievalTimeSeconds = 120
AllowUnencrypted = true
Auth
Basic = true
Kerberos = true
Negotiate = true
Certificate = false
CredSSP = true
CbtHardeningLevel = Relaxed
DefaultPorts
HTTP = 5985
HTTPS = 5986
IPv4Filter = *
IPv6Filter = *
EnableCompatibilityHttpListener = true
EnableCompatibilityHttpsListener = false
CertificateThumbprint
Winrs
AllowRemoteShellAccess = true
IdleTimeout = 180000
MaxConcurrentUsers = 5
MaxShellRunTime = 2147483647
MaxProcessesPerShell = 15
MaxMemoryPerShellMB = 150
MaxShellsPerUser = 5

This does I think mean that HTTPS transport for Winrm/remoting is disabled, but that’s not important in my environment. A better fix would be to switch it to use the most recent machine certificate, or even better to use a certificate created for this exact purpose (and then update it when it expires…)