Friday, November 22, 2013

PowerShell DSC Security Context

One of the first challenges I ran into with PowerShell Desired State Configuration (DSC) custom resources was the security context in which the custom resources were running (System).  The custom resources I was making needed to call FIM with a known security context.  This seemed fair to me, as I’d expect to do the same when calling other systems such as AD or SharePoint.
FIM requires a ‘Person’ object in the FIM Service for the person calling the web service endpoints.  Stated another way; the FIM Service in my demo environment did not know who the System account was, so it told DSC to go away with ‘access-denied’.
My workaround was to include a Credential parameter in all of my custom resources for DSC, then to use that inside my custom resources to make the FIM calls.  I did not like this at all, because it meant I had to have these credentials lying around and would then have to protect and update them (boo!).  This forced me to learn about how DSC protects credentials, which was quite useful but still not my favourite solution.
While demonstrating this at the MVP Summit, my co-worker and DS MVP (Brian Desmond) suggested that I just create the System account in the FIM Service.  I love working with smart people, too bad they get to suffer my foolishness!  Anyhow, I tried Brian’s suggestion and at first it didn’t work. 
My first attempt was to create the Person object in FIM using the computer name and its ObjectSID from AD.
 
###
### Create a the Computer Account as a FIM Person
###
New-FimImportObject -State Create -ObjectType Person -Changes @{
    AccountName = (hostname)
    DisplayName = (hostname)
    Domain      = 'Redmond'
    ObjectSID   = (Get-ObjectSid -AccountName (hostname))
} -ApplyNow
 
This didn’t work, but looking at the error in the event log gave me a clue.  The error details were:
GetCurrentUserFromSecurityIdentifier: No such user NT AUTHORITY\SYSTEM, S-1-5-18
Looking at the ObjectSID and account details, it was not using the specific computer but instead the well-known name and ObjectSID.  The error suggested what FIM was looking for so I tried this:
 
###
### Create a the NT AUTHORITY\SYSTEM as a FIM Person
###
New-FimImportObject -State Create -ObjectType Person -Changes @{
    AccountName = 'SYSTEM'
    DisplayName = 'SYSTEM'
    Domain      = 'NT AUTHORITY'
    ObjectSID   = (Get-ObjectSid -AccountName 'NT AUTHORITY\SYSTEM')
} -ApplyNow
 
It worked!  Now I can rip the credentials out of my custom DSC resources but I might leave them in and make them optional since I’ve already done most of the work.

Thursday, November 21, 2013

DSC Sample for FIM MPR and Set Objects

Couldn’t help but share this sample from yesterday’s DSC talk.

Below is the demo script I used to show what a FIM DSC script would look like.  Pretty exciting that there is no imperative stuff going on at all (it all lives in the DSC Custom Resources).

In the example the MPR depends on the Set objects using a string array.  In future examples I will show using DependsOn to link the MPR to workflows as well.

md c:\dsccm

Set-Location c:\dsccm

<#

notepad C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\DSCResources\FimService_Set\FimService_Set.schema.mof

 

notepad C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\DSCResources\FimService_ManagementPolicyRule\FimService_ManagementPolicyRule.schema.mof

#>

 

$fimAdminCredential = New-Object System.Management.Automation.PSCredential ("administrator", (ConvertTo-SecureString 'HoofHearted' -AsPlainText -Force))

 

Configuration FimConfiguration

{

    Node (hostname)

    {

        FimService_Set _DscTestSet1

        {

            Ensure       = "Present" 

            DisplayName  = "_DscTestSet1"

            Credential   = $fimAdminCredential

            SetFilter    = "/Person"

        }

 

        FimService_Set All_People

        {

            Ensure       = "Present" 

            DisplayName  = "All People"

            Credential   = $fimAdminCredential

            SetFilter    = "/Person"

        }

       

        FimService_ManagementPolicyRule _DscTestMpr1

        {

            Ensure                   = "Present"

            DisplayName              = "_DscTestMpr1"

            Description              = "why is this required?"

            Request                  = $true

            Enabled                  = $false

            GrantPermission          = $false

            RequestType              = @('Read','Create')

            RequestorSet             = '_DscTestSet1' 

            ResourceSetBeforeRequest = 'All People' 

            ResourceSetAfterRequest  = 'All People'  

            ResourceAttributeNames   = @('DisplayName','Description')                           

            ActionWorkflowDefinition = @('_TestActionWF','_TestActionWF2')

            Credential               = $fimAdminCredential

            DependsOn                = @('[FimService_Set]_DscTestSet1','[FimService_Set]All_People')

        }

    }

}

 

$Global:AllNodes =

@{

    AllNodes = @(

        @{ 

            NodeName                    = (hostname)

            PSDscAllowPlainTextPassword = $true

        }

    )

}

 

FimConfiguration -ConfigurationData $Global:AllNodes

 

Start-DscConfiguration -Wait -Verbose -Path "C:\dsccm\FimConfiguration"

 

 

PowerShell DSC – Getting Your DependsOn

Had the opportunity yesterday to give a short talk on PowerShell Desired State Configuration at the Microsoft MVP Summit.  I figured delivering the talk in the FIM track was a safe bet, but to my terror at least two PowerShell MVPs showed up, eliminating my ability to just make shit up and look smart.

The talk went great (well, that just means I had fun) and I plan on sharing the demo code.  When the FIM custom resources are in usable form I will be doing a lot of sharing, but for now I want to share just a sample with the built-in resources because it is a simple way to demonstrate the ‘DependsOn’ parameter.

In the example below, I have two items in my configuration; a user and a group.  Note the ‘DependsOn’ entry in the group definition.  That makes DSC aware of the dependency, and DSC is smart enough to process the configuration items in order.

For FIM this is incredibly useful since most objects in FIM depend on other objects.  For example, a FIM MPR depends on attributes, sets, and workflows.  This simple feature in DSC paves the way for using custom DSC resources to manage a FIM deployment over time.  I’ll share demos later showing an MPR definition that depends on the Set and Attribute objects.  I have this working right now, but again, it is not in a sharable state.

In the example below I also show how to specify a password for the user.  It is pretty interesting how this works, in that the User resource takes Password as a parameter.  If you specify the Password, then DSC will throw an error because it does not like to pass around plain text passwords.  You can disable that FOR DEMO PURPOSES but to do it for real you can supply DSC with a certificate that it will use to encrypt/decrypt the password (more on that later).

 

md C:\dsccm

 

Configuration SampleConfiguration

{

    Node (hostname)

    {

        User UserExample

        {

            Ensure    = "Present" 

            UserName  = "MyFooUser"

            Password  = New-Object System.Management.Automation.PSCredential ("thisIsIgnored", (ConvertTo-SecureString "H00fHearted?" -AsPlainText -Force))

        }

 

        Group GroupExample

        {

            Ensure    = "Present"

            GroupName = "MyFooGroup"

            Members   = @("MyFooUser")

            DependsOn = "[User]UserExample"

        }

    }

}

 

 

$Global:AllNodes =

@{

    AllNodes = @(

        @{ 

            NodeName                    = (hostname)

            PSDscAllowPlainTextPassword = $true

        }

    )

}

 

SampleConfiguration -ConfigurationData $Global:AllNodes

 

Start-DscConfiguration -Wait -Verbose -Path "C:\dsccm\SampleConfiguration"

 

Sunday, November 17, 2013

Debugging a PowerShell DSC Custom Resource

Been working with custom DSC resources for FIM for a few weeks now and embarrassingly it just occurred to me that I can call my custom DSC resources directly.  I had been following the guidance from TechNet whereby I would call my DSC using the Start-DscConfiguration cmdlet.  It is a great way to make sure that your DSC resource is properly wired up in PowerShell but as you start to make lots of changes it gets a bit tedious.

Another option is just to load the DSC script module using the Import-Module cmdlet, then call its functions directly.  Pretty simple, and also lets you use a couple of great features such as breakpoints and splatting.

By using splatting, you can take the hashtable (almost) directly from your DSC configuration and splat it into the DSC custom resource function.  There are a couple of parameters that won’t work (such as DependsOn) but they can easily be commented out as I’ve done in the sample below.

###

### Load the module required by my DSC resource

###

ipmo FimPowerShellModule

 

###

### Load my DSC resource

###

ipmo C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\DSCResources\FimService_ManagementPolicyRule\FimService_ManagementPolicyRule.psm1

 

###

### The contents of this HashTable are from my DSC configuration

###

$dscSetParameters = @{

    Ensure             = "Present"

    DisplayName        = "_DscTestMpr1"

    Description        = "why is this required?"

    Enabled            = $false

    GrantPermission    = $false

    RequestType        = @('Read','Create')

    PrincipalSet       = "_DscTestSet1"

    ResourceCurrentSet = "All People"

    ResourceFinalSet   = "Administrators" 

    ResourceAttributeNames = @('DisplayName','Description')                     

    ActionWorkflowDefinition = @('_TestActionWF','_TestActionWF2')

    Credential         = $fimAdminCredential

    #DependsOn          = "[FimService_Set]_DscTestSet1"

}

 

###

### Use the HashTable to splat into my DSC function

##

Set-TargetResource @dscSetParametersVerbose

 

 

Thursday, November 14, 2013

PowerShell DSC: Cannot invoke the SendConfigurationApply method

Been hitting this error when doing some PowerShell Desired State Configuration (DSC) work:

 

Cannot invoke the SendConfigurationApply method. The SendConfigurationApply method is in progress and must return before SendConfigurationApply can be invoked.

    + CategoryInfo          : NotSpecified: (root/Microsoft/...gurationManager:String) [], CimException

    + FullyQualifiedErrorId : MI RESULT 1

    + PSComputerName        : localhost

 

 

Found a nice blog post where the same error was hit, and was hoping to get root cause on this but got lucky instead.  This error was transient in his case, and proved transient in mine too.  I tried to flush it by resetting DSC surgically:

 

###

### find the Process that is hosting the DSC engine

###

$dscProcessID = Get-WmiObject msft_providers |

Where-Object {$_.provider -like 'dsccore'} |

Select-Object -ExpandProperty HostProcessIdentifier

 

###

### Kill it

###

Get-Process -Id $dscProcessID | Stop-Process

 

No luck.

Tried then to force the matter by restarting the WMI service (REALLY BAD idea on a real server), but still no luck. 

Walked away, grabbed a beer, came back and the repro was gone.  Moral of the story is that Canadians are onto something with all that beer consumption.