Using Azure Automation DSC to configure and deploy the new SCSM Portal (Part 1)

On Nov 10th Microsoft released a new HTML portal for System Center Service Manager 2012 R2.

The installation is fairly straight forward, however there are still some pre-requisites that need to be in place, I also thought it would be good to introduce delivering this via Azure Automation Desired State Configuration (DSC).

The main reason to do this via DSC is the ongoing maintenance.

Things happen, people can make mistakes, features and roles can be accidentally removed.

Written by

Steve Beaumont

Steve Beaumont

Product Development Director

on

24th Dec 2015

DSC provides a set of configuration that;

  • * should be applied to a server
  • * will be applied to a server to bring it into compliance
  • * will then continue to check the server for compliance
  • * will attempt to remediate and bring it back into compliance should it drift.

So what do we need?

The new portal is an IIS site, therefore requires some windows features to be installed.

These are:

  • Web-Server
  • Web-Filtering
  • Web-Basic-Auth
  • Web-Windows-Auth
  • Web-Mgmt-Console
  • Web-Mgmt-Compat
  • Web-Net-Ext45
  • Web-ASP
  • Web-Asp-Net45
  • NET-Framework-45-ASPNET
  • NET-WCF-HTTP-Activation45

These can be easily added using a single PowerShell line:

Add-WindowsFeature Web-Server,Web-Filtering,Web-Basic-Auth,Web-Windows-Auth,Web-Mgmt-Console,Web-Mgmt-Compat,Web-Net-Ext45,Web-ASP,Web-Asp-Net45,NET-Framework-45-ASPNET,NET-WCF-HTTP-Activation45

installation as I mentioned, is only part of the story. Making sure these features remain in place is where DSC come in.

In DSC we create a “Configuration” file which lays out how the assigned server should be configured.

For Windows features there is a specific DSC Resource we use, aptly named, WindowsFeature.

For each windows feature we require, we use a block like this:

WindowsFeature WebServer  
{
Ensure = "Present"
Name = "Web-Server"
}

Basically we name the code block with something meaningful (as we may reference later) with the WindowsFeature resource, use the Name property to specify the Windows Feature to check,(Use Get-WindowsFeature in PowerShell to check for the name you require)  then use the Ensure property to state whether the named feature should either be present on the server or not (our intention).

Further properties and information can be found at Technet.

For all our Windows Feature requirements for the SCSM Portal we get:

#Install the required IIS features
WindowsFeature WebServer
{
Ensure = "Present"
Name = "Web-Server"
}
WindowsFeature WebFiltering
{
Ensure = "Present"
Name = "Web-Filtering"
}
WindowsFeature WebBasicAuth
{
Ensure = "Present"
Name = "Web-Basic-Auth"
}
WindowsFeature WebWindowsAuth
{
Ensure = "Present"
Name = "Web-Windows-Auth"
}
WindowsFeature WebMgmtConsole
{
Ensure = "Present"
Name = "Web-Mgmt-Console"
}
WindowsFeature WebMgmtCompat
{
Ensure = "Present"
Name = "Web-Mgmt-Compat"
}
WindowsFeature WebNetExt45
{
Ensure = "Present"
Name = "Web-Net-Ext45"
}
WindowsFeature WebASP
{
Ensure = "Present"
Name = "Web-Asp"
}
WindowsFeature WebASPNet45
{
Ensure = "Present"
Name = "Web-Asp-Net45"
}
WindowsFeature NETFramework45ASPNET
{
Ensure = "Present"
Name = "NET-Framework-45-ASPNET"
}
WindowsFeature NETWCFHTTPActivation45
{
Ensure = "Present"
Name = "NET-WCF-HTTP-Activation45"
}

Well, that’s the Windows Features sorted.

Please bare with me here, as it looks like a lot more work as opposed to that single PowerShell one liner…

Next is the installation of the SCSM Portal.

For this we utilise the DSC Package Resource which looks something like this:

Package SCSMSSP
{
Name = "SCSM SSP"
Path = "C:\DSC\SSP\SetupWizard.exe"
ProductId = "17F5D20F-47FB-485E-8CFC-4768C3C3F460"
Arguments = "/Install:SelfServicePortal /silent /accepteula /CustomerExperienceImprovementProgram:No /EnableErrorReporting:No /SMServerName:$SCSMSDKServer /PortalWebSiteName:SCSMPortal /PortalWebSitePort:81 /PortalAccount:$Domain\$SCSMUser\$SCSMPassword"
Ensure = "Present"
DependsOn = @("[WindowsFeature]WebServer","[WindowsFeature]WebFiltering","[WindowsFeature]WebBasicAuth","[WindowsFeature]WebWindowsAuth","[WindowsFeature]WebMgmtConsole","[WindowsFeature]WebMgmtCompat","[WindowsFeature]WebNetExt45","[WindowsFeature]WebASP","[WindowsFeature]WebASPNet45","[WindowsFeature]NETFramework45ASPNET","[WindowsFeature]NETWCFHTTPActivation45")
}

So again, we provide a name for the Package Resource code block (SCSMSSP) and a more friendly name for the Name property.

The Path property denotes where the installation file resides.

The ProductId property is the unique GUID for the application to allow DSC to check for it’s presence.

The Arguments property is used for any command line to be passed to control the installation.

Again, the Ensure property denotes if the software should be installed (present) or not installed (absent).

The DependsOn property allows us to specify various resources that DSC should first ensure are compliant before attempting to run this resource.

It’s easy to specify a dependant resource, just wrap the DSC Resource type name in [square brackets] and specify the name of that feature.

So WindowsFeature WebASPNet45 becomes [WindowsFeature]WebASPNet45.

One thing to note is that if you need to specify multiple dependencies, you need to specify them as a string formatted as an array.

Do this by putting each feature formatted as just discussed in quotation marks ” ” and separating with a comma. Finally enclose it as an array – @( ).

So if we required two features, WebMgmtCompat and WebASP we would have the following:

DependsOn = @("[WindowsFeature]WebMgmtCompat","[WindowsFeature]WebASP")

We’re almost there…

For those that were paying attention, you may have noticed that the arguments property string contained some variables.

This allows us to prompt when compiling the DSC configuration for various settings to prevent hard coding data and allow for reuse.

Just like normal PowerShell we put these at the beginning in a Param block.

Param(
[Parameter(Mandatory=$true)]
[string] $SCSMSDKServer,
[Parameter(Mandatory=$true)]
[string] $Domain
)
$SCSMSDKCred = Get-AutomationPSCredential -Name "SCSMSDKCredentialAsset"
$SCSMUser=$SCSMSDKCred.UserName
$SCSMPassword = $SCSMSDKCred.GetNetworkCredential().Password

I’m also going to leverage the Credentials Asset feature of Azure Automation.

This allows you to securely store username and password combo’s within Azure Automation as an asset to then be reused in Runbooks and DSC. Again, allowing us to avoid hardcoding sensitive data and not having to prompt for them at each compilation.

I’m using the Get-AutomationPSCredential command to retrieve it and then split the PSCredential object down to username and password.

However, I’m utilising this for the command line arguments for the executable installation I can’t use it as a PSCredential and have to supply a non encrypted password, hence the use of the .GetNetworkCredential().Password to pull the unencrypted password out of the object.

 .B. This has the side effect of storing the password in clear text within the MOF that gets compiled and pushed down to the DSC node, however this is encrypted during delivery using https and again encrypted by WMF before storing locally.

Because of this, it also means that compilation of the configuration can not be done via the Azure Portal and only by PowerShell as you will need to add configuration to the compilation task to tell it to allow the use of plain text passwords.

The final DSC Configuration script looks like this:

Configuration SCSMPortal
{
param(
[Parameter(Mandatory=$true)]
[string] $SCSMSDKServer,
[Parameter(Mandatory=$true)]
[string] $Domain
)

$SCSMSDKCred = Get-AutomationPSCredential -Name "SCSMSDKCredentialAsset"
$SCSMUser=$SCSMSDKCred.UserName
$SCSMPassword = $SCSMSDKCred.GetNetworkCredential().Password

Node "WebServer" 
{
#Install the required IIS features
WindowsFeature WebServer
{
Ensure = "Present"
Name = "Web-Server"
}
WindowsFeature WebFiltering
{
Ensure = "Present"
Name = "Web-Filtering"
}
WindowsFeature WebBasicAuth
{
Ensure = "Present"
Name = "Web-Basic-Auth"
}
WindowsFeature WebWindowsAuth
{
Ensure = "Present"
Name = "Web-Windows-Auth"
}
WindowsFeature WebMgmtConsole
{
Ensure = "Present"
Name = "Web-Mgmt-Console"
}
WindowsFeature WebMgmtCompat
{
Ensure = "Present"
Name = "Web-Mgmt-Compat"
}
WindowsFeature WebNetExt45
{
Ensure = "Present"
Name = "Web-Net-Ext45"
}
WindowsFeature WebASP
{
Ensure = "Present"
Name = "Web-Asp"
}
WindowsFeature WebASPNet45
{
Ensure = "Present"
Name = "Web-Asp-Net45"
}
WindowsFeature NETFramework45ASPNET
{
Ensure = "Present"
Name = "NET-Framework-45-ASPNET"
}
WindowsFeature NETWCFHTTPActivation45
{
Ensure = "Present"
Name = "NET-WCF-HTTP-Activation45"
}

Package SCSMSSP
{
Name = "SCSM SSP"
Path = "C:\DSC\SSP\SetupWizard.exe"
ProductId = "17F5D20F-47FB-485E-8CFC-4768C3C3F460"
Arguments = "/Install:SelfServicePortal /silent /accepteula /CustomerExperienceImprovementProgram:No /EnableErrorReporting:No /SMServerName:$SCSMSDKServer /PortalWebSiteName:SCSMPortal /PortalWebSitePort:81 /PortalAccount:$Domain\$SCSMUser\$SCSMPassword"
Ensure = "Present"
LogPath = "C:\DSC\SSP\SSP_Setup.log"
DependsOn = @("[WindowsFeature]WebServer","[WindowsFeature]WebFiltering","[WindowsFeature]WebBasicAuth","[WindowsFeature]WebWindowsAuth","[WindowsFeature]WebMgmtConsole","[WindowsFeature]WebMgmtCompat","[WindowsFeature]WebNetExt45","[WindowsFeature]WebASP","[WindowsFeature]WebASPNet45","[WindowsFeature]NETFramework45ASPNET","[WindowsFeature]NETWCFHTTPActivation45")
}

}
}

Notice the Node reference?

The DSC Resources used are wrapped within a Node section.

This isn’t mandatory, if you’re only using this to configure a single server, but as a side effect of using Plain Text password and Azure Automation DSC this is required.

N.B. Thanks to @bgelens for pointing me at that requirement as I couldn’t get it to work!!!

I mentioned previously that you can’t just import and compile this within the Azure Portal,

You can still import it via the console, so go ahead and open your Azure Automation account > Click DSC Configurations > Add a Configuration > Browse to your Config File > Click OK.

DSC Import Config

Then use this PowerShell code to compile the DSC Configuration:

$ConfigData = @{
AllNodes = @(
@{
NodeName = "*"
PSDscAllowPlainTextPassword = $True
}
)
} 

$Parameters = @{
"SCSMSDKSERVER" = "PONSCSM04"
"DOMAIN" = "PowerON"
}

$ResourceGroup="xxxxx"
$AccountName="xxxxx"
$ConfigurationName="xxxxx"

Login-AzureRmAccount
Start-AzureRmAutomationDscCompilationJob -ResourceGroupName $ResourceGroup -AutomationAccountName $AccountName -ConfigurationName $ConfigurationName -ConfigurationData $ConfigData -Parameters $Parameters

Main thing is the PSDscAllowPlainTextPassword. This flags the config to allow us to store the password in plain text within the MOF that gets downloaded to the DSC node, which we’re doing by pushing the plain text password from the PSCredentialObject into a variable.

Make sure you replace the $ResourceGroup, $AccountName, $ConfigurationName with relevant variables as well as the Prameters (SCSMSDKServer & Domain).

All that is left is to assign this configuration to a node and sit back and watch the SCSM Portal install.

Read Part 2 Now

Keep Up To Date - Join The Mailing List

The team are here to help

If there are any questions and want to learn more about PowerON’s services or Solutions, please get in touch and a member of the team will be in touch shortly. 

  • PowerON, Stanley Harrison House, York, YO23 1DE
  • 0800 3029280
  • info@poweronplatforms.com

Contact PowerON

Leave a Reply