TFS 2017 build agent in untrusted domain

This week I was faced with a scenario where a TFS build/release agent was used to deploy software from TFS Release management. This agent was running in the same Windows domain as the servers where the software needed to be deployed. The TFS server itself was running in a different Windows domain. Because of security considerations (these are production servers we’re talking about), these two Windows domain did not have a domain trust configured between them.
Continue reading

Debugging a DSC script for Release Management

When preparing a DSC script for deploying an application using Release Management it is often handy to test and debug that script locally. Nobody writes code that works the first time, right? However, you’ll quickly run into the fact that Release Management does some things slightly different than “vanilla” DSC (for example: .psd1 is not .ps1) and also provides some extra’s, like the $ApplicationPath variable that holds the path to the bits you’re deploying and the configuration of WinRM. Because of this, I found myself using the following workflow:

  1. Write DSC script
  2. Test and debug locally
  3. Configure Release Management with this DSC script
  4. Test and debug deployment from Release Management
  5. Change DSC script to work from Release Management

I wanted to eliminate step #5 and seriously reduce the time needed for #4.

For that purpose, I have created a PowerShell wrapper script. This script takes the same input parameters that you would configure in Release Management and executes your DSC script for you, much in the same way as Release Management would. This means you can test and debug your DSC scripts locally (without using Release Management) and when you eventually configure them in Release Management you don’t have to change anything!

You can download the script from my GitHub: Deploy_RM_local.ps1. Here’s how it works.

In Release Management, you use a “Deploy Using PS/DSC” block for deploying using DSC:


The interesting variables here are:

  • PSScriptPath: the path to your DSC script. This path is relative to the location of the component you’re deploying (usually the folder from your TFS drop).
  • PSConfigurationPath: the path to the script that contains your configuration data. Again, this is a relative path.

Furthermore, Release Management will provide a variable $ApplicationPath that will contain the absolute path to the folder where Release Management will have copied your component. We’ll need these three variables.

  1. Download the bits that you want to deploy to the server you want to test on, e.g. to “C:\Deploy\SampleApp_20150527.3”.
  2. Make sure you have the “Deploy_RM_local.ps1” somewhere on the server, e.g. in “C:\Scripts”
  3. Open a PowerShell prompt and navigate to the folder containing the script:
    cd "C:\Deploy\SampleApp_20150527.3"
  4. Execute the “Deploy_RM_local.ps1” script, feeding it the three paths as input. Optionally, you can add the “-Verbose” parameter to get some more logging. For example:
    .\Deploy_RM_local.ps1 -ApplicationPath "C:\Deploy\SampleApp_20150527.3" -PSConfigurationPath "Deploy\DeployConfig_AzureD.ps1" -PSScriptPath "Deploy\Deploy.ps1" -Verbose

That’s it! Happy deploying!

Bug in xWebAdministration module in DSC resource kit on Windows 2008 / IIS7

At one of the clients that I’m working we’re doing a proof of concept on using Release Management vNext type release templates for deploying their application. We’re using Powershell Desired State Configuration (DSC) for the actual deployment script.

One of the requirements is that we should also be able to deploy to the existing environments, running Windows 2008R2 and IIS7. Since the application is a simple web application, I was using the xWebAdministration module from the DSC Resource kit. When deploying to a Windows 2012R2 machine with IIS8, everything worked like a charm. However, when deploying on a Windows 2008R2 machine with IIS7, I got all sorts of weird error messages. There were already a couple of websites running on that machine, and it seemed as if the DSC script was trying to update those. Of course, it shouldn’t touch already existing sites.

After a bit of searching, I ran into this bug on Connect. Apparently there is a problem with the “Get-Website” cmdlet on IIS7. It returns all websites, instead of only the one specified with the “-Name” parameter. Since the xWebAdministration module uses “Get-Website -Name xyz” to get a reference to the website it should modify, it’ll try to update all the websites in the IIS server. So that explains it. Now, how to solve this?

Actually, the solution is not very complicated. The easiest is to modify your copy of the xWebAdministration module. Open the “MSFT_xWebsite.psm1” file in your favourite editor. You’ll find it in the “DSCResources\MSFT_xWebsite” folder.

Then, do a “find and replace” and replace this:

$Website = Get-Website -Name $Name

With this:

$Website = Get-Website | Where { $_.Name -eq $Name }

You should find five occurrences of the above snippet. After doing the replace, save the file and run your deployment again. If all is well, it should work now 🙂

Happy deploying!

.psd is not .ps1

My first experiments with DSC consisted of a simple website that I wanted to deploy to a virtual machine I had running in Azure. Seems simple, doesn’t it? So I went ahead and created a DSC script and a file containing the configuration data, as described nicely on this blog: Separating “What” from “Where” in PowerShell DSC. So I ended up with two files: “Deploy.ps1” with my DSC configuration and “TestEnv.psd1” with the environment specific configuration data. Those two can be put together like so:

# Pass the configuration data to configuration as follows: 
Sample_xWebsite_FromConfigurationData -ConfigurationData TestEnv.psd1 

Where “Sample_xWebsite_FromConfigurationData” denotes the configuration as defined in the DSC script. When running this from a powershell prompt, it worked like a charm. Next step was to stick this in a vNext Release Template and run it from Release Management.

When configuring a vNext Release Template in Release Management, you’ll have to provide a “PSScriptPath” and “PSConfigurationPath” inside the “Deploy Using PS/DSC” block:


So I figured I’d provide the two files that I had prepared, one being the .ps1 file with the DSC configuration and the other being the .psd1 file with the configuration data. However, when running the deployment I got a bunch of weird errors, suggesting that my configuration data wasn’t passed to the DSC configuration. After doing some debugging I found that that was indeed the case.

Eventually I got the solution. Essentially: the “PSConfigurationPath” in Release Manager expects a regular Powershell script. So: a .ps1 file. If you supply a .psd1 file, Release Management will happilly run your deployment, but your configuration data will not be passed to your DSC configuration.

The solution is to put your configuration data in a variable, and pass that to your configuration. So, the DSC configuration looks something like this:

configuration Sample_xWebsite_FromConfigurationData {  	
  Node $AllNodes {
    # Copy the website content  		
    File WebContent 
      Ensure = "Present"
      SourcePath = $Node.SourcePath
      DestinationPath = $Node.DestinationPath
      Recurse = $true
      Type = "Directory"
Sample_xWebsite_FromConfigurationData -ConfigurationData $configData

Notice the “$configData” parameter in the last line? That comes from the configuration data script:

# Hashtable to define the environmental data
$configData = @{
  # Node specific data
  AllNodes = @(
      NodeName = "*"
      WebsiteName = "FourthCoffee"
      SourcePath = "C:\BakeryWebsite\"
      DestinationPath = "C:\inetpub\FourthCoffee"
      DefaultWebSitePath = "C:\inetpub\wwwroot"

Make sure you save this as a .ps1 file! Then include it in your vNext Release Template in the “PSConfigurationPath” and all will be well!

Happy releasing!

Release Management vNext pitfalls

Recently I have been playing around with vNext Release Templates in Microsoft Release Management. These type of deployments use Powershell Desired State Configuration (DSC) to perform the actual deployment of your application to the target environment. While this generally works very well, I had a couple of “head-against-brick-wall” experiences which – I must admit – did cause a bit of an headache. This post is the first in a series to share some of those experiences, so that you can avoid them.

Installing WMF 4 requires .Net 4.5

I knew that in order for DSC to work I needed to install Powershell 4, which is part of the Windows Management Framework (WMF) 4.0. So I went ahead and downloaded and installed WMF 4.0. However, my DSC scripts wouldn’t work. Turns out you need to install .Net Framework 4.5 before you install WMF 4.0. A good way to check if everything is OK is to open up a Powershell prompt and type:


That should return a PSVersion of 4.0:image

More information can be found in this post on the Windows Powershell Blog: WMF 4.0 – Known Issue: Partial Installation without .Net Framework 4.5

Happy DSC-ing!