Reputation: 3215
I need to execute PowerShell on VMs from an Azure Automation Runbook, akin to a WinRm execution/PowerShell Remoting.
I have created an Azure Runbook through the Azure Automation GUI, and am trying to run a script that works perfectly against physical and virtual machines to get key system information and ports. I am able to authenticate in Azure and it appears that I can execute some aspects of the script (unless it's only running against the Azure Automation Worker) via the Azure Runbook, such as getting the installed PowerShell Version of the targeted VMs using: $PSVersionTable.PSVersion
so I am not having issues with security/access from what I can tell.
However, several other components fail as follows, and I don't know if I need to import a Module to Azure Automation and if so, which ones. Or if this is failing because it is running against the Worker and not the VMs.
Here are some of the code snippets I am running:
$computerSystem = Get-CimInstance Win32_ComputerSystem
"CPU: " + $computerCPU.Name
Get-WmiObject -Class Win32_LogicalDisk |
Where-Object {$_.DriveType -ne 5} |
Sort-Object -Property Name |
Select-Object Name, VolumeName, FileSystem, Description, `
@{"Label"="DiskSize(GB)";"Expression"={"{0:N}" -f ($_.Size/1GB) -as [float]}}, `
@{"Label"="FreeSpace(GB)";"Expression"={"{0:N}" -f ($_.FreeSpace/1GB) -as [float]}}, `
@{"Label"="%Free";"Expression"={"{0:N}" -f ($_.FreeSpace/$_.Size*100) -as [float]}} |
Format-Table -AutoSize
Get-NetAdapter -Name "*" | Format-Table
Get-NetOffloadGlobalSetting | Format-List
Test-NetConnection -Port 80
Here are the error messages, which I strongly suspect are EITHER due to missing PowerShell Modules that I need to upload, but am unsure where to find these OR is this a situation where I am not targeting the VM correctly and instead running this against the AZ Host? (if so, any good examples of how to target a single VM):
Get-CimInstance : The specified service does not exist as an installed service.
Get-WmiObject : The specified service does not exist as an installed service.
Get-NetAdapter : The term 'Get-NetAdapter' is not recognized as the name of a cmdlet, function, script file, or operable program.
Get-NetOffloadGlobalSetting : The term 'Get-NetOffloadGlobalSetting' is not recognized as the name of a cmdlet, function, script file, or operable program.
Test-NetConnection : The term 'Test-NetConnection' is not recognized as the name of a cmdlet, function, script file, or operable program.
If it is an issue with targeting the VM properly, I need some guidance. I suspect that I am targeting the Worker running the Runbooks and not the actual VMs. I am using the RunAs account/the new Azure Automation security methods (not classic) so I don't believe certificates come into play. Here is how I am trying to target the VM (which I suspect is incorrect/should be changed):
$Resources = Get-AzureRmResource -ResourceType "Microsoft.Compute/virtualMachines" -ResourceGroupName "MyTestGroup" -ResourceName "MyTestVM"
ForEach ($Resource in $Resources)
{
# PowerShell Code from Above here
}
UPDATE 1:
Now that we have determined that I am not targeting the VM properly, I tried Joe's recommendation, but when I try to run the following I get an error on the WinRm. I found the Connect-AzureVM.ps1, but am unsure if this is old or aligns to the newer RunAs Connection I am using. Here is my current script that attempts to connect to the VM and Invoke PowerShell.
param(
[parameter(Mandatory=$true)][String] 'https://myvmname.eastus.cloudapp.azure.com:5986,
[parameter(Mandatory=$true)][String] 'MyVMName'
)
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
# Get credentials to Azure VM
$Credential = Get-AutomationPSCredential -Name $VMCredentialName
Invoke-Command -ConnectionUri $Uri -Credential $Credential -ScriptBlock {
# My PowerShell Here
}
This is the error the script produces. I suspect its because I need to import/create a WinRM certificate on the VM I am targeting, but unsure if the Connect-AzureVM.ps1 is the right script to use or if there is another/more updated method to use for WinRM access:
[myvmname.eastus.cloudapp.azure.com] Connecting to remote server myvmname.eastus.cloudapp.azure.com failed with the following error message : WinRM cannot complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By default, the WinRM firewall exception for public profiles limits access to remote computers within the same local subnet. For more information, see the about_Remote_Troubleshooting Help topic. + CategoryInfo : OpenError: (myvmname.eastus.cloudapp.azure.com:String) [], PSRemotingTransportException + FullyQualifiedErrorId : WinRMOperationTimeout,PSSessionStateBroken
Upvotes: 1
Views: 2316
Reputation: 574
Run this inside the VM at an elevated prompt
https://gist.github.com/jeffpatton1971/2321f0db8025e48ad8ec13c243153045
From inside your Runbook do whatever you normally to wire it up but create some session options to pass along your invoke-command.
$SessionOption = New-PSSessionOption -SkipCACheck -SkipCNCheck
Invoke-Command -ComputerName $VMname -Credential $Credential -UseSSL -SessionOption $SessionOption -ScriptBlock { }
Upvotes: 1
Reputation: 2540
You need to either add the VMs you want to run these scripts on as Azure Automation hybrid workers, so that you can target the script to run on them, or you need to, from your runbook running on Azure Automation's own workers, remote into each VM and from within the remoting block run the commands.
For the former, see: https://learn.microsoft.com/en-us/azure/automation/automation-hybrid-runbook-worker
For the ladder:
Invoke-Command -ConnectionUri $Uri -Credential $Credential -ScriptBlock {
$computerSystem = Get-CimInstance Win32_ComputerSystem
"CPU: " + $computerCPU.Name
Get-WmiObject -Class Win32_LogicalDisk |
Where-Object {$_.DriveType -ne 5} |
Sort-Object -Property Name |
Select-Object Name, VolumeName, FileSystem, Description, `
@{"Label"="DiskSize(GB)";"Expression"={"{0:N}" -f ($_.Size/1GB) -as [float]}}, `
@{"Label"="FreeSpace(GB)";"Expression"={"{0:N}" -f ($_.FreeSpace/1GB) -as [float]}}, `
@{"Label"="%Free";"Expression"={"{0:N}" -f ($_.FreeSpace/$_.Size*100) -as [float]}} |
Format-Table -AutoSize
Get-NetAdapter -Name "*" | Format-Table
Get-NetOffloadGlobalSetting | Format-List
Test-NetConnection -Port 80
}
Upvotes: 1