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.