Using PowerShell for automated UNIX/Linux Agent Discovery

PowerShell cmdlets for administration of UNIX/Linux agents were added in the System Center 2012 release of Operations Manager. There is good documentation available on the cmdlet use, but a basic discovery script might look something like this:

$SSHCredential=Get-SCXSSHCredential
$WSCredential=Get-Credential
$Pool = Get-SCOMResourcePool -DisplayName “All Management Servers Resource Pool”
$DiscResult = Invoke-SCXDiscovery -name $HostName -ResourcePool $Pool -WsManCredential $WSCredential -SshCredential $SSHcredential
$DiscResult | Install-scxagent

In this example, the Invoke-SCXDiscovery cmdlet is provided the following parameters:

  • $Hostname – the fqdn of the agent to discover
  • $Pool – the Resource Pool object used to discover and manage the agent, from Get-SCOMResourcePool
  • $WSCredential – a PSCredential object used for WSMan authentication, from Get-Credential
  • $SSHCredential – an ssh Credential object used for ssh authentication, from Get-SCXSSHCredential

If you have tried a PowerShell discovery like this, you’ll know that both Get-Credential and Get-SCXSSHCredential prompt you for credential input and don’t allow specification of passwords as command-line arguments.  This is for good reason, as plain-text scripts are a bad place to store passwords. However, this does have the effect of limiting your ability to truly automate UNIX/Linux agent discovery.  Well, with a bit of extra scripting, you can actually embed your credentials in a script in a fairly secure manner.

This article does a great job explaining how to securely write a password to a file, and then retrieve it from a script.  The steps to do this are:

  1. Logged in as the user that will run the script, create a credential object with:  $Credential = Get-Credential
  2. Write this as a secure string to a file:
    $credential.Password | ConvertFrom-SecureString | Set-Content $env:userprofile\password.txt

Now, this password can be read back into a script (but only if the script is run with the same user that wrote the password to the file), by using the following scriptlet:

$wsmanuser=”monuser”
$wsmanpassword =  Get-Content $env:userprofile\password.txt | ConvertTo-SecureString
$WSCredential = New-Object System.Management.Automation.PSCredential ($wsmanuser, $wsmanpassword)

Using this method, we can securely create the credential object to use as our WSManCredential value without a prompt, but Invoke-SCXDiscovery also needs an ssh Credential.  The ssh Credential is a bit more involved, but can be done in a similar fashion.

A function to create the ssh Credential object, using encrypted passwords stored in files is:

function Get-SCXSSHCredentialFromScript{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$True)]
[string]$UserName,
[string]$PassphraseFile,
[string]$SSHKeyFile,
[string]$SuPasswordFile,
[string]$ElevationType
)

process {
$SSHcredential=”"
$scred=”"
$SSHcredential = New-Object Microsoft.SystemCenter.CrossPlatform.
ClientLibrary.CredentialManagement.Core.CredentialSet
$scred = New-Object Microsoft.SystemCenter.CrossPlatform.
ClientLibrary.CredentialManagement.Core.PosixHostCredential
$scred.Usage = 2
$scred.PrincipalName = $username

if ($PassphraseFile.Length -gt 0){
$sPassphrase=Get-Content $PassphraseFile | ConvertTo-SecureString
$scred.Passphrase = $sPassphrase
}

if ($SSHKeyFile.Length -gt 0)  {
$scred.KeyFile = $SSHKeyFile
Write-Host “Validating SSH Key”
$scred.ReadAndValidateSshKey()
}

#add posixhost credential to credential set
$SSHcredential.Add($scred)

if ($elevationType.Equals(“su”)) {
$sucred = New-Object Microsoft.SystemCenter.CrossPlatform.
ClientLibrary.CredentialManagement.Core.PosixHostCredential
$sucred.Usage = 32 #su elevation
$sucred.PrincipalName = “root”
$sucred.Passphrase = Get-Content $SUPasswordFile | ConvertTo-SecureString
$SSHcredential.Add($sucred)
}

if ($elevationType.Equals(“sudo”)) {
$sudocred = New-Object Microsoft.SystemCenter.CrossPlatform.
ClientLibrary.CredentialManagement.Core.PosixHostCredential
$sudocred.Usage = 16 #su elevation
$SSHcredential.Add($sudocred)
}
Return $SSHCredential
}
}

With this function defined, it can be used like this:

PS C:\Users\Administrator> $SSHCredential=Get-SCXSSHCredentialFromScript -username:monuser -PassphraseFile:$env:userprofile\password.txt –ElevationType:sudo

PS C:\Users\Administrator> $SSHCredential
SshUserName      : monuser
SshElevationType : sudo
Credentials      : {, }
Count            : 2
IsSSHKey         : False
Usage            : 0

Of course, this needs to be run in an OpsMgr shell, or the script needs to be prefaced with:

Import-Module “C:\Program Files\System Center 2012\Operations Manager\Powershell\OperationsManager\OperationsManager”
New-SCOMManagementGroupConnection localhost;

So, now we have snippets to create WSMan and ssh Credential objects, using an ecrypted password stored in a file.  Building on this, we can define a function to invoke UNIX/Linux discovery and install the agent:

function DiscoverSCXAgents{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$True)]
[string]$Hostname
)
$PassphraseFile=”$env:userprofile\password.txt”
$SSHCredential=Get-SCXSSHCredentialFromScript -username:monuser -PassphraseFile:$PassphraseFile –ElevationType:sudo
$wsmanuser=”monuser”
$wsmanpassword =  Get-Content $PassphraseFile | ConvertTo-SecureString
$WSCredential = New-Object System.Management.Automation.PSCredential ($wsmanuser, $wsmanpassword)
$Pool = Get-SCOMResourcePool -DisplayName “All Management Servers Resource Pool”
Write-Output “Attempting discovery of $Hostname”
$DiscResult = Invoke-SCXDiscovery -name $HostName -ResourcePool $Pool -WsManCredential $WSCredential -SshCredential $SSHcredential
$DiscResult | fl Succeeded, ErrorData
$DiscResult | Install-scxagent
}

Testing out the new function:

DiscoverSCXAgents “lnx-db-007.contoso.com”

Attempting discovery of lnx-db-007.contoso.com

Name            AgentVersion  ManagementPackPlatformIdentifier  Id                                  
—-            ————  ——————————–  –                                  
lnx-db-007.c… 1.4.0-906     Microsoft.Linux.SLES.11           c5944ea1-e4f4-1908-ea15-d5be6ba7d14e

 

And with that, we can use an Orchestrator runbook to call our discovery script and fully automate UNIX/Linux agent discovery.

About these ads

2 Responses

  1. Kris,
    I can’t tell you how much I appreciate this post and it has helped me greatly in my endeavors to fully automate the Linux installs using Orchestrator and SCOM. With that said, I am still having difficulty getting this to work with Orchestrator. Here is the script I am using and this works fine when I run it from Powershell directly;

    {
    $ErrorActionPreference = “Stop”
    try
    {

    Import-module OperationsManager

    function Get-SCXSSHCredentialFromScript{
    [CmdletBinding()]
    param
    (
    [Parameter(Mandatory=$True)]
    [string]$UserName,
    [string]$Passphrase,
    #[string]$SSHKeyFile,
    [string]$SuPassword,
    [string]$ElevationType
    )

    process {
    $SSHcredential=”"
    $scred=”"
    $SSHcredential = New-Object Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.Core.CredentialSet
    $scred = New-Object Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.Core.PosixHostCredential
    $scred.Usage = 2

    $scred.PrincipalName = $username

    if ($Passphrase.Length -gt 0){
    $sPassphrase=ConvertTo-SecureString “$Passphrase” -AsPlainText -Force
    $scred.Passphrase = $sPassphrase
    }

    if ($SSHKeyFile.Length -gt 0)
    {
    $scred.KeyFile = $SSHKeyFile
    Write-Host “Validating SSH Key”
    $scred.ReadAndValidateSshKey()
    }

    #add posixhost credential to credential set
    $SSHcredential.Add($scred)

    if ($elevationType.Equals(“su”))
    {
    $sSUPassword=ConvertTo-SecureString “$SUPassword” -AsPlainText -Force
    $sucred = New-Object Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.Core.PosixHostCredential
    $sucred.Usage = 32 #su elevation
    $sucred.PrincipalName = “root”
    $sucred.Passphrase = $SUPassword
    $SSHcredential.Add($sucred)
    }

    if ($elevationType.Equals(“sudo”))
    {
    $sudocred = New-Object Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.Core.PosixHostCredential
    $sudocred.Usage = 16 #su elevation
    $SSHcredential.Add($sudocred)
    }
    Return $SSHCredential
    }
    }

    $username = “”
    $password = “”
    $secstr = New-Object -TypeName System.Security.SecureString
    $password.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
    $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $secstr
    $PrimaryMgmtServer = “”
    $sshcredential = Get-SCXSSHCredentialFromScript -username: -Passphrase: –ElevationType:sudo
    New-SCOMManagementGroupConnection -ComputerName $PrimaryMgmtServer
    $mypool = Get-SCOMResourcePool “LinuxPool”
    Invoke-SCXDiscovery -Name “\`d.T.~Ed/{4DEB0A89-36FF-402E-9EB5-798E8556E912}.{25F33803-055F-4CBD-B836-E801C108AE6B}\`d.T.~Ed/” -ResourcePool $mypool -WSManCredential $cred -SshCredential $sshcredential | Install-SCXAgent
    }
    catch
    {
    Throw $_.Exception
    }

    }| Out-file c:\err1Script.ps1

    When I put the SAME script into a .NET script activity in Orchestrator, the script runs but the install never happens and I never receive any errors. This is my last step towards a fully automated install, so any help would be appreciated. Even better would be if you had a working example. Thanks for all your hard work with the XPlat monitoring!

    Garion

    • I suspect the issue has to do with the version of the PowerShell host. The UNIX/Linux Cmdlets require PowerShell V3 (v4 CLR), but the .NET activity uses CLR v2. There are two potential workarounds: Something like this:
      http://karlprosser.com/coder/2012/04/16/calling-powershell-v3-from-orchestrator-2012/

      or saving the script as a .ps1 in the file system and calling PowerShell.exe as a “Run Program” instead of a .NET script. If you go with the Run Program route, the parameters would be something like:
      Program Path: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
      Parameters: D:\scriptlibrary\discoverscxagent.ps1 {Computer Name variable}
      Working folder: D:\ScriptLibrary

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 43 other followers

%d bloggers like this: