Passing parameter from Runbook Invoke-AzVMRunCommand to Powershell on VM - azure

I'm trying to execute the Invoke-AzVMRunCommand in PowerShell and pass parameters to the script that needs to be executed.
Before I Run the Runbook I can define the parameter name:
Define Parameter
Code from the Runbook:
param(
[Parameter(Mandatory=$true)]
[string]$name
)
Write-Output "Connecting to azure via Connect-AzAccount -Identity"
Connect-AzAccount -Identity
Write-Output "Successfully connected with Automation account's Managed Identity"
Write-Output "Run Script Against Machines"
$ScriptToRun = "C:\testps.ps1"
Out-File -InputObject $ScriptToRun -FilePath ScriptToRun.ps1
Invoke-AzVMRunCommand -ResourceGroupName "RG" `
-VMName "VM" `
-CommandId 'RunPowerShellScript' `
-ScriptPath ScriptToRun.ps1 `
-Parameter #{"name" = $name}
Remove-Item -Path ScriptToRun.ps1
Script on the server I want to execute with the parameters:
param(
[string]$name
)
MKdir -Path "C:\Users" -Name $name
The script does not produce the expected output: Creating a folder with name from the parametr under C:\Users. No folder is being created.
If I execute the Invoke-AzVMRunCommand on the same script with hardcoded arguments like so:
MKdir -Path "C:\Users" -Name "TEST"
it does work and the folder gets created.

Firstly, I have script on VM and i have followed Microsoft-Document:
param(
[string]$name
)
MKdir -Path "C:\Users" -Name $name
Then i have used az invoke command in your script instead of Invoke-AzVMRunCommand and used below command:
az vm run-command invoke --command-id RunPowerShellScript --name "name of the VM" -g "name of the resourcegrp" --scripts "C:\test.ps1 $name"
Here $name is the param that you have send to runbook.
By this way you can create the folder with the name you want.
References taken from:
Executing Powershell script on Remote VM on Azure with Parameters - Stack Overflow
How to pass json file as parameter to Azure Powershell Runbook? - Stack Overflow

Related

Export to csv a Parallel invoke-AZVMRUNcommand

I'm having trouble finding out how to export data from a invoke-AZVMRUNcommand in parallel to a csv file. Usually this is simple to do but this time it got me the csv is not showing any data.. Can someone share a little knowledge of what to do.
$myAzureVMs | ForEach-Object -Parallel {
$out = Invoke-AzVMRunCommand `
-ResourceGroupName *********** `
-Name $_.Name `
-CommandId 'RunPowerShellScript' `
-ScriptPath C:\Users\user******\Downloads\ListCertificates\ListCertificates.ps1
#Formating the Output with the VM name
$output = $_.Name + " " + $out.Value[0].Message
$output} | Export-Csv -Path C:\CertList\CertEXPlist.csv
You can use the below PowerShell script to export into CSV file along with Invoke-AzVMRunCommand without using -Parallel as this works only with latest version of Powershell.
We've run a sample Powershell script by using the above cmdlet which in turn returns the result from the VM and saves in the csv file locally.
$out = Invoke-AzVMRunCommand `
-ResourceGroupName RGName `
-Name myVmrajkumarvm `
-CommandId 'RunPowerShellScript' `
-ScriptPath 'C:\Users\*****\xxxxxxxxxxxx\Documents\test.ps1'
#Formating the Output with the VM name
$out | Export-Csv -Path C:\Users\*******\CertEXPlist.csv
After running the above ps script, the output will be stored in the directory which is given above:
Sample Output screen:

'Unauthorized' error creating app service plan

Don't know where exactly it is failing. I'm using VS Code to create the following script and running from there only:
$ResourceGroupName="powershell-grp"
$Location="North Europe"
$AppServicePlanName="PowershellAppService1975"
$WebAppName="PowershellWebApp1975"
Connect-AzAccount
Get-AzSubscription -SubscriptionName "Visual Studio Enterprise" | Select-AzSubscription
New-AzResourceGroup -Name $ResourceGroupName -Location $Location
New-AzAppServicePlan -Name $AppServicePlanName -Location $Location -Tier "B1" -NumberofWorkers 1 -ResourceGroupName $ResourceGroupName
New-AzWebApp -ResourceGroupName $ResourceGroupName -Name $WebAppName -Location $Location -AppServicePlan $AppServicePlanName
And in the powershell console, i get this error:
New-AzAppServicePlan: C:\Temp\AzureCmds\Azure Powershell-WebApp\Script1.ps1:9:1
Line |
9 | New-AzAppServicePlan -Name $AppServicePlanName -Location $Location -T …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Operation returned an invalid status code 'Unauthorized'
New-AzWebApp: C:\Temp\AzureCmds\Azure Powershell-WebApp\Script1.ps1:10:1
Line |
10 | New-AzWebApp -ResourceGroupName $ResourceGroupName -Name $WebAppName …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Operation returned an invalid status code 'Unauthorized'
Used -debug cmdlet option that gave the exact info on the issue.
The resource group location supported 0 instances for the chosen app service plan. Therefore, deployed app service plan and the web app to an altogether different location

How to reach a script file in a VM from Powershell runbook

I have a script file in a VM that I want to reach from the azure portal in a Powershell runbook but it can't find the file. The file is manually saved in c:\ of the VM.
Code snippet in azure runbook:
IF ($VmAction -eq "Shutdown") {
try
{
Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroupName -VMName $VmName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\\stopservice.ps1' -ErrorVariable result
Stop-AzVM -Name $VmName -ResourceGroupName $ResourceGroupName -Force
}
catch
{
throw "Error: $($_.Exception.Message)"
}
The command "Invoke-AzVMRunCommand -ResourceGroupName $ResourceGroupName -VMName $VmName -CommandId 'RunPowerShellScript' -ScriptPath 'C:\stopservice.ps1' -ErrorVariable result" can be used on powershell on my computer so I think the issue is somewhere in Azure possibly.
script file (c:\stopservice.ps1):
try
{
Stop-Service -Name SSASTELEMETRY
}
catch
{
throw "Error: $($_.Exception.Message)"
}
(ps. the service name is for testing purposes, will stop different service when this works)
Have your Azure Automation runbook something like shown below. It should accomplish your requirement.
$ServicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
Add-AzAccount -ServicePrincipal -TenantId $ServicePrincipalConnection.TenantId -ApplicationId $ServicePrincipalConnection.ApplicationId -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint
$rgname ="rrrrrrrrrrrrrr"
$vmname ="vvvvvvvvvvvvvv"
$ScriptToRun = "c:\test.ps1"
Out-File -InputObject $ScriptToRun -FilePath ScriptToRun.ps1
Invoke-AzVMRunCommand -ResourceGroupName $rgname -Name $vmname -CommandId 'RunPowerShellScript' -ScriptPath ScriptToRun.ps1
Remove-Item -Path ScriptToRun.ps1
Note: Before you run your runbook, make sure you update "rrrrrrrrrrrrrr" with your resource group name and "vvvvvvvvvvvvvv" with your VM name and also make sure you have the PowerShell named test.ps1 in C:\ drive of the VM.

Azure Invoke-AzVMRunCommand -

I am wondering if there is way to use the Invoke-AzVMRunCommand to run a single command, rather than a powershell ps1 file?
As an example, I want to execute a single command... "C:\app\app.exe -c exit". Without the need to push a powershell commandlet to the system.
I am able to do this via the Azure Portal "RunPowerShellScript" and it works but would like to do it to multiple systems via the command line via Invoke-AzVMRunCommand. These systems do not share a command account that can be used.
According to Microsoft, here is the syntax...
Invoke-AzVMRunCommand -ResourceGroupName 'rgname' -VMName 'vmname' -CommandId 'RunPowerShellScript' -ScriptPath 'sample.ps1' -Parameter #{param1 = "var1"; param2 = "var2"}
I don't want to run a script, I merely want to be able to execute a command on the system. Is this possible?
There is no direct way of doing it. But, you can write a script block and generate a file from it and then run Invoke-AzVMRunCommand using that file and later on delete that file if required.
$Server = "server01"
[System.String]$ScriptBlock = {Get-Process}
$FileName = "RunScript.ps1"
Out-File -FilePath $FileName -InputObject $ScriptBlock -NoNewline
$vm = Get-AzVM -Name $Server
Invoke-AzVMRunCommand -ResourceGroupName $vm.ResourceGroupName -Name $Server -CommandId 'RunPowerShellScript' -ScriptPath $FileName
Remove-Item -Path $FileName -Force -ErrorAction SilentlyContinue
It's now possible to use the:
-ScriptString
... option, however you need to ensure that the Az version will support it.
Azure Pipelines as of 2022-07-21 don't support it:
"A parameter cannot be found that matches parameter name 'ScriptString'."
See the documentation:
https://learn.microsoft.com/en-us/powershell/module/az.compute/invoke-azvmruncommand?view=azps-8.1.0

Grant access to Azure Data Lake Gen2 using a parameterized script

We are trying to grant read/write access to many folders in our Azure data Lake gen 2 containers and although we can do this through the UI, it's quite tedious and has to be repeated for all environments. Has anyone used a better way using Powershell to automate or at least parameterize this process of granted access to Azure Data Lake gen 2 containers and avoid granting access manually?
Unfortunately I couldn't get this to work using the following link or other documentation as it's for Gen 1 but it's very similar to what I need to do for gen 2.
https://www.sqlchick.com/entries/2018/3/17/assigning-data-permissions-for-azure-data-lake-store-part-3
According to my test, we can use the PowerShell to manage Azure Data Lake Gen2 permissions. For more details, please refer to the document
Install the required module
install-Module PowerShellGet –Repository PSGallery –Force
install-Module Az.Storage -Repository PSGallery -RequiredVersion 1.9.1-preview –AllowPrerelease –AllowClobber –Force
Besides, please note that if you want to install the module, you need to meet some conditions
.NET Framework is 4.7.2 or greater installed
PowerShell is 5.1 or higher
Script
Connect-AzAccount
$groupName=""
$accountName=""
$account= Get-AzStorageAccount -ResourceGroupName $groupName -Name $accountName
$ctx = $account.Context
$filesystemName = "test"
$dirname="template/"
$Id = "<the Object ID of user, group or service principal>"
$dir=Get-AzDataLakeGen2Item -Context $ctx -FileSystem $filesystemName -Path $dirname
$acl = New-AzDataLakeGen2ItemAclObject -AccessControlType user -EntityId $id -Permission "rw-" -InputObject $dir.ACL
Update-AzDataLakeGen2Item -Context $ctx -FileSystem $filesystemName -Path $dirname -Acl $acl
$dir=Get-AzDataLakeGen2Item -Context $ctx -FileSystem $filesystemName -Path $dirname
$dir.ACL
Thanks Jim Xu for providing the script above. I'm just complementing the code with the following items :
Get all folders from the container
Assign ACL for all folders
Propagate ACL to all subfolders
$groupName="resource group name"
$accountName="storage account name"
$account= Get-AzStorageAccount -ResourceGroupName $groupName -Name $accountName
$ctx = $account.Context
$filesystemName = "container name"
$Id = (Get-AzADGroup -DisplayName '<type user / group name here>').Id
$items = Get-AzDataLakeGen2ChildItem -Context $ctx -FileSystem $filesystemName
foreach ( $item in $items) {
$dir = Get-AzDataLakeGen2Item -Context $ctx -FileSystem $filesystemName -Path "$($item.Path)/"
$acl = New-AzDataLakeGen2ItemAclObject -AccessControlType group -EntityId $id -Permission "rwx" -InputObject $dir.ACL -DefaultScope
# Update ACL on blob item
Update-AzDataLakeGen2Item -Context $ctx -FileSystem $filesystemName -Path "$($item.Path)/" -Acl $acl
# Propagate ACL to child blob items
Set-AzDataLakeGen2AclRecursive -Context $ctx -FileSystem $filesystemName -Path "$($item.Path)/" -Acl $acl
}

Resources