Sunday, September 29, 2013

DevOps: A new wave for IT

Read this quick article (DevOps: A new wave for IT) and love this part:

All of a sudden we are seeing a shift were developers are the IT folks and IT are the developers

Working in integration, and metadirectory in particular, I’ve found myself wading deeper and deeper into the developer pool.  Seems the trend is not specific to FIM but part of DevOps.

I also love how Don Jones puts it (to paraphrase from PowerScripting PodCast 236 I think):

There will be people who make the buttons and people that push the buttons

Thursday, September 26, 2013

Rebranded

I’ve long believed Identity Management to be a subset of Systems Integration.  A lot of the work I do pertains to more than just identity (especially when PowerShell is involved) but it always fits neatly under integration (the mash-up of things that may not have been intended to fit together).  For that reason I figured it was time for a rebrand, so the name change:

Identity Trench –> Integration Trench

Sunday, September 22, 2013

An Even Better Way to Add Files to the GAC–PowerShell GAC Module

PowerShell is magic in many ways but today I was impressed by yet another community project.  There are so many of these lying around and with PowerShell they are pretty simple to cobble together into a nice solution.  In this case I used the module below to create a custom resource for Desired State Configuration. 

Here’s the module I’m referring to:

PowerShell GAC Module on CodePlex

This is a really nice module including documentation and samples, not to mention it just works.  Adding it to my toolbox for FIM deployments.  With this module it would be very simple to clean up the scripts that create the ActivityInformationConfiguration objects in the FIM Service.  My plan is to create a resource for AIC’s in DSC such that I only need to declare them (no more scripting the configuration).

Here’s a snippet from the PowerShell GAC project samples to show how nice it is:

# Show the assemblies in the GAC, including the file version

Get-GacAssembly SomeCompany* | Format-Table -View FileVersion

 

# Backup the assemblies in C:\Temp\SomeCompany

Get-GacAssembly SomeCompany* | Get-GacAssemblyFile | Copy-Item -Destination C:\Temp\SomeCompany

 

# Remove the assemblies from the GAC

# Can only be run from an elevated prompt

Get-GacAssembly SomeCompany* | Remove-GacAssembly

 

# Add the assemblies back to the GAC

# Can only be run from an elevated prompt

Add-GacAssembly C:\Temp\SomeCompany\*.dll

 

PowerShell DSC–Custom Resource for the Global Assembly Cache

Starting to realize the potential for Desired State Configuration, the new feature in PowerShell V4.  To get started I’ve been reading the material on TechNet:

Windows PowerShell Desired State Configuration Overview

For me, this changes the way I expect to do deployment automation.  Until now I’ve been mostly writing scripts to lay down configuration in FIM.  There have been some challenges with that approach, such as:

  • the deployment script is only really useful for a fresh deployment
  • the scripts are not usually reentrant, unless you do the work to make them so
  • the scripts do not usually prevent configuration drive of a running system
  • the scripts are, well, still code

DSC seems like an elegant solution to this, because it give the power of configuration declaratively, while still allowing me to write code for complex situations (you can bury this in Custom DSC Resources).  For moron Custom DSC Resources see:

Build Custom Windows PowerShell Desired State Configuration Resources

To learn more I decided to try a sample custom DSC resource to handle entries in the Windows Global Assembly Cache.  A FIM deployment always need to make sure the GAC is populated with the correct DLLs, so it made sense to start with this.  I followed the guidance on TechNet and was able to produce this custom resource in under an hour.  With that custom resource I can now declare the GAC items like this:

Sample DSC Script

 

 

Configuration FimServiceConfig

{

   ### Configuration for my FIM Service computer

   Node "MyFimBox"

   {

 

    ### Make sure the FIM Service is running and set to Automatic

    Service FimService

    {

        Name        = "FimService"

        StartupType = "Automatic"

        State       = "Running"

    }

 

    ### Make sure the GAC has the PowerShell Workflow for FIM

    GlobalAssemblyCacheItem FimWorkflowLibrary

    {

        Ensure       = "Present"

        Name         = "FimExtensions.FimActivityLibrary"

        Version      = "2.0.0.0"

        AssemblyFile = "C:\tfs\Output\FimExtensions.FimActivityLibrary.dll"

    }      

   }

} 

 

I plan on sharing the sample custom resource on PowerShell.org if they’ll have it.  They are trying to organize the custom modules so that they’re easier to find:

Need Desired State Configuration Modules?

Anyhow, with this little experiment mostly complete I’m really excited about doing the custom resources for FIM, then changing the way I do deployment automation to be largely declarative.  PowerShell is way too cool.

Tuesday, September 17, 2013

Switching a ReplicatorActivity from ‘Sequence’ to ‘Parallel’

Had a scenario in a FIM workflow activity where I needed to change the behaviour from ‘sequential’ to ‘parallel’.  Simple enough, it’s just a property on the ReplicatorActivity that I set and the framework magically handles the rest, right?

Well it compiled and ran just fine, but the results were not was you’d expect.  This behaviour is well documented I guess but I was a little surprised at how much work it took to make it work.  The blog post here –> ‘Using the ReplicatorActivity in Parallel mode’ was a really good explanation and I did try to follow the guidance but in the end chose to follow the common wisdom of “the ReplicatorActivity can only be used in parallel mode with a custom activity”.  That common wisdom may be incorrect, but the code became a lot cleaner when I just bit the bullet and created that custom activity.

Readers of this blog may be marveling at a post where I neglect to mention PowerShell.  This is not that post.  I’m impressed at PowerShell’s ability to dumb this stuff down.  Workflow is a big feature in PowerShell 3, and the awesome part is how easy they made it:

New-Workflow –MakeItEasy: Authoring Workflows using PowerShell Extended Syntax

Workflow in FIM can be challenging to a below-average developer, but workflow in PowerShell can be as simple as using the ‘workflow’ keyword, or adding the ‘-parallel’ parameter to a ‘foreach’ statement.  Very cool.

Thursday, September 12, 2013

Use PowerShell to GAC a FIM Workflow DLL without gacutil.exe

Sometimes you just don’t have the right paths, and can’t be bothered to search for gacutil.exe, or maybe you want to automate the operation without needing gacutil.exe.

Here’s how to do it from PowerShell:

###

### Re-GAC the WF DLL

###

$assemblyFileName = 'c:\sd\MySuperCoolFimActivityLibrary.dll'

if (-not (Test-Path $assemblyFileName))

{

    Throw "Unable to find the DLL: $assemblyFileName"

}

$fullFileName = dir $assemblyFileName | select -expand fullname

[Reflection.Assembly]::LoadWithPartialName("System.EnterpriseServices") | Out-Null

[System.EnterpriseServices.Internal.Publish] $publish = new-object System.EnterpriseServices.Internal.Publish

 

### This method call will never return errors or exceptions

### On failure however it does put an entry into the event viewer

$publish.GacInstall($fullFileName)

 

### Changes to WF DLLs Require a FIM Service restart

Restart-Service FimService

 

Use PowerShell to Cancel a Bunch of FIM Requests

Sometimes you just want to cancel a bunch of FIM Requests.  You can do it in the FIM Portal using the handy ‘Cancel’ button when viewing Requests.  With almost everything in the FIM Portal it is pretty easy to see how that operation is performed by looking at the FIM Request that gets submitted.  In this case I cancelled a Request then looked at the FIM Request history in the FIM Portal.  Turns out that to cancel a Request, you have to submit a new Request.  I put in the GUID of that request then looked at it in PowerShell.  From the output we can see that changing the ‘RequestControl’ attribute to ‘CancelOperation’ tells FIM to cancel the Request (just like operational attributes in LDAP I guess).

 

###

### Export a specific FIM Request and look at the Request Parameters

###

Export-FIMConfig -OnlyBaseResources -CustomConfig "/Request[ObjectID='2d6611f4-60bc-4c23-8de7-1c5b41ea4064']" |

Convert-FimExportToPSObject |

Get-FimRequestParameter

 

 

 

Value           Mode   PropertyName   Operation

-----           ----   ------------   ---------

CancelOperation Modify RequestControl Create  

 

 

So, given that I just need to modify the ‘RequestControl’ attribute on the Request, I can query for FIM Requests that need cancelling, then for each one submit a Request as shown below.

 

###

### Query for all Requests in 'Authorizing'

### then Cancel each one

###

Export-FIMConfig -OnlyBaseResources -CustomConfig "/Request[RequestStatus='Authorizing']" |

Convert-FimExportToPSObject |

ForEach-Object {

    Write-Verbose "Canceling Request: $($_.DisplayName)" -Verbose:$true

    New-FimImportObject -State Put `

    -ObjectType $_.ObjectType `

    -TargetObjectIdentifier ($_.ObjectID -replace 'urn:uuid:') `

    -Changes @{

            RequestControl = 'CancelOperation'

    } -ApplyNow

}

 

 

VERBOSE: Canceling Request: Update to Group:  'hoofhearted' Request

VERBOSE: Canceling Request: Update to Group:  'icemelted' Request

VERBOSE: Canceling Request: Update to Group:  'hoofhearted' Request

VERBOSE: Canceling Request: Update to Group:  'icemelted' Request

VERBOSE: Canceling Request: Update to Group:  'hoofhearted' Request

VERBOSE: Canceling Request: Update to Group:  'icemelted' Request

VERBOSE: Canceling Request: Update to Group:  'hoofhearted' Request

VERBOSE: Canceling Request: Update to Group:  'icemelted' Request

 

Note: –Verbose was used in an awkward way here to prevent harm to any puppies.  Using Write-Verbose is a very good habit, even when you think you should just Write-Host.

Sunday, September 08, 2013

What has your Management Agent done for you lately?

It is useful to look at the history of a particular management agent to spot trends in its behaviour and answer questions such as:

  • how long has this problem existed? (did my change cause this?)
  • is there always this much activity? (how much damage did this bug cause?)

The FIM Sync Engine maintains a great amount of detail in Run History but the Sync Engine Manager doesn’t always make it easy to answer questions.  No big deal, just use PowerShell (the ultimate tool for slicing through data).

Much of the data you see in the Sync Engine for Run History is exposed via WMI (pronounced ‘whammy’).  The FIM PowerShell Sync Module has a few commands that act as wrappers over the FIM Sync WMI classes, making them much friendlier, and allowing them to interact with some of my favourite commands like:

  • Where-Object
  • Out-GridView
  • Select-Object
  • Format-Table
  • Group-Object

Here is a simple example showing how to get a subset of the Run History data into Out-GridView.

 

###

### Get Run History for the FIM MA 'export' Run Profile

### Then Get the Counters Detail

### Then view in Out-GridView

###

Get-MIIS_RunHistory -MaName FIM -StartedAfter 9/1/2013 -RunProfile Export |

Get-RunHistoryDetailCounters |

Out-GridView

 

For a peak at what the results look like in Out-GridView, check out the documentation page at the FIM PowerShell Module at CodePlex:

Documentation –> Samples –> Summarize Run History Details

Thursday, September 05, 2013

FIM PowerShell Workflow Activity on Channel9

Fellow MVP Carol Wapshere did a presentation at TechEd on FIM2010 R2: Custom Workflow Activities, and highlighed the FIM PowerShell Workflow Activity.  Cool!

Here’s the link: FIM2010 R2: Custom Workflow Activities

Automating the SQL 2012 Install for FIM

Installing SQL Server can take quite a bit of time manually, and each time you do it the setup program flaunts the handy answer file in your face, almost taunting you to automate it the next time.  Well I took the challenge and have been installing SQL with the answer file lately, using PowerShell of course.

The challenge I ran across today was installing SQL into a VM that did not have connectivity to the Internet.  By default the answer file turns on updates for SQL, and when I ran the setup at home (disconnected) it failed.

A little looking around in the answer file found the setting, so I just turned the default of ‘true’ into ‘false’ and problem solved.  The documentation for it was pretty useful too, for those RTFM’ers here is the help I found for that feature:

Product Updates in SQL Server 2012 Installation

Most importantly, here is the script snippet (below).  The script is using a VM, and the commands are executed from the VM host which is why I am using Invoke-Command to issue commands into the VM.  This could easily be grafted to just run inside the VM.

The script uses a large string variable to contain the SQL answer file.  That contains the answer file contents generated by the SQL Setup program when you run it manually (I didn’t generate it by hand, I’m not that lucky).  The big string is saved to a file inside the VM, then Setup.exe just consumes that file.

 

###

### The Admin credential for the VM

###

$adminDomCredential = New-Object System.Management.Automation.PSCredential "hoofhearted\administrator",(ConvertTo-SecureString 'icemelted' -AsPlainText -Force)

 

###

### Mount the SQL DVD ISO

###

Set-VMDvdDrive -VMName $vmName -Path C:\ISO\en_sql_server_2012_enterprise_edition_with_sp1_x64_dvd_1227976.iso

 

###

### Install SQL

###

$sqlSetupScript = @'

;SQL Server 2012 Configuration File

[OPTIONS]

; Specifies a Setup work flow, like INSTALL, UNINSTALL, or UPGRADE. This is a required parameter.

ACTION="Install"

; Detailed help for command line argument ENU has not been defined yet.

ENU="True"

; 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.

;UIMODE="Normal"

; Setup will not display any user interface.

QUIET="True"

IAcceptSQLServerLicenseTerms="True"

; Setup will display progress only, without any user interaction.

;QUIETSIMPLE="True"

; 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.

UpdateEnabled="False"

; 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.

FEATURES=SQLENGINE,FULLTEXT,SSMS,ADV_SSMS

; 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.

;UpdateSource="MU"

; Displays the command line parameters usage

HELP="False"

; Specifies that the detailed Setup log should be piped to the console.

INDICATEPROGRESS="False"

; Specifies that Setup should install into WOW64. This command line argument is not supported on an IA64 or a 32-bit system.

X86="False"

; Specify the root installation directory for shared components.  This directory remains unchanged after shared components are already installed.

INSTALLSHAREDDIR="C:\Program Files\Microsoft SQL Server"

; Specify the root installation directory for the WOW64 shared components.  This directory remains unchanged after WOW64 shared components are already installed.

INSTALLSHAREDWOWDIR="C:\Program Files (x86)\Microsoft SQL Server"

; 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).

INSTANCENAME="MSSQLSERVER"

; 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.

INSTANCEID="MSSQLSERVER"

; 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.

SQMREPORTING="False"

; 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.

ERRORREPORTING="False"

; Specify the installation directory.

INSTANCEDIR="C:\Program Files\Microsoft SQL Server"

; Agent account name

AGTSVCACCOUNT="NT Service\SQLSERVERAGENT"

; Auto-start service after installation. 

AGTSVCSTARTUPTYPE="Manual"

; CM brick TCP communication port

COMMFABRICPORT="0"

; How matrix will use private networks

COMMFABRICNETWORKLEVEL="0"

; How inter brick communication will be protected

COMMFABRICENCRYPTION="0"

; TCP port used by the CM brick

MATRIXCMBRICKCOMMPORT="0"

; Startup type for the SQL Server service.

SQLSVCSTARTUPTYPE="Automatic"

; Level to enable FILESTREAM feature at (0, 1, 2 or 3).

FILESTREAMLEVEL="0"

; Set to "1" to enable RANU for SQL Server Express.

ENABLERANU="False"

; Specifies a Windows collation or an SQL collation to use for the Database Engine.

SQLCOLLATION="SQL_Latin1_General_CP1_CI_AS"

; Account for SQL Server service: Domain\User or system account.

SQLSVCACCOUNT="NT Service\MSSQLSERVER"

; Windows account(s) to provision as SQL Server system administrators.

SQLSYSADMINACCOUNTS="{0}"

; Provision current user as a Database Engine system administrator for SQL Server 2012 Express.

ADDCURRENTUSERASSQLADMIN="False"

; Specify 0 to disable or 1 to enable the TCP/IP protocol.

TCPENABLED="1"

; Specify 0 to disable or 1 to enable the Named Pipes protocol.

NPENABLED="0"

; Startup type for Browser Service.

BROWSERSVCSTARTUPTYPE="Disabled"

; Add description of input argument FTSVCACCOUNT

FTSVCACCOUNT="NT Service\MSSQLFDLauncher"

'@ -F $adminDomCredential.UserName

Invoke-Command -ComputerName hoofhearted -Credential $adminDomCredential -ScriptBlock {

  $using:sqlSetupScript | Out-File -FilePath c:\SqlSetupScript.txt 

  & d:\Setup.exe /ConfigurationFile=c:\SqlSetupScript.txt

}