Azure Automation Job runs fine manually but fails when triggered by webhook - azure

I've got an Automation Account in Azure that runs a Powershell runbook.
It runs perfectly fine when I trigger it via the portal, manually specifying the inputs
I've created a webhook with the same input settings. I call it from CURL like
curl -d '' https://800b2bec-b1ae-4fa1-ba30-8c7d32096828.webhook.ae.azure-automation.net/webhooks?[redactedtoken]
The webhook shows as triggered successfully in the portal, however the job fails with no visible error.
There is no output, even though the first line in my powershell function is Write-Output "Hello"
There are no exception messages, no logs at all.
Any idea how I might get more information as to what might be going wrong?
I've updated the Az modules and enabled verbose logging in the runbook.
Full source below, if it helps.
Param(
[string]$resourceGroup,
[string]$VMName,
[string]$method,
[string]$UAMI
)
Write-Output "Hello"
$automationAccount = "AlsAutomation"
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process | Out-Null
# Connect using a Managed Service Identity
try {
$AzureContext = (Connect-AzAccount -Identity).context
}
catch{
Write-Output "There is no system-assigned user identity. Aborting.";
exit
}
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
-DefaultProfile $AzureContext
if ($method -eq "SA")
{
Write-Output "Using system-assigned managed identity"
}
elseif ($method -eq "UA")
{
Write-Output "Using user-assigned managed identity"
# Connects using the Managed Service Identity of the named user-assigned managed identity
$identity = Get-AzUserAssignedIdentity -ResourceGroupName $resourceGroup `
-Name $UAMI -DefaultProfile $AzureContext
# validates assignment only, not perms
if ((Get-AzAutomationAccount -ResourceGroupName $resourceGroup `
-Name $automationAccount `
-DefaultProfile $AzureContext).Identity.UserAssignedIdentities.Values.PrincipalId.Contains($identity.PrincipalId))
{
$AzureContext = (Connect-AzAccount -Identity -AccountId $identity.ClientId).context
# set and store context
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
}
else {
Write-Output "Invalid or unassigned user-assigned managed identity"
exit
}
}
else {
Write-Output "Invalid method. Choose UA or SA."
exit
}
# Get current state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName `
-Status -DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Beginning VM status: $status `r`n"
# Start or stop VM based on current state
if($status -eq "Powerstate/deallocated")
{
Start-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext
}
elseif ($status -eq "Powerstate/running")
{
Stop-AzVM -Name $VMName -ResourceGroupName $resourceGroup -DefaultProfile $AzureContext -Force
}
# Get new state of VM
$status = (Get-AzVM -ResourceGroupName $resourceGroup -Name $VMName -Status `
-DefaultProfile $AzureContext).Statuses[1].Code
Write-Output "`r`n Ending VM status: $status `r`n `r`n"
Write-Output "Account ID of current context: " $AzureContext.Account.Id

We have tested this in our local environment it is working fine, Below statements are based on the analysis.
In our local environment, We have created a Powershell runbook running with different PowerShell Versions 7.1 & Version 5.1.
Using the above share Script & webhook URI, when we are trying to invoke the runbook (PowerShell version 7.1) using the `Invoke-webRequest method it is continuously failing.
Alternatively, We have tried to invoke the runbook (PowerShell version 5.1) using the Invoke-webRequest method it is working fine.
We would suggest you to use Powershell Version 5.1 instead of 7.1 in your Runbook.
Here is the sample Output for reference:

Related

How to get the certifcate from Key vaults using power shell script?

I need help on this scenario. we have a cert in azure key vault which needs to be download to a windows VM for our .net application to run on iis. I am able to upload the cert to Azure keyvault with out issues. I am running a azure devops powershell tasks inline powershell script.
it will connect to azure using conenct-azaccount with appropriate login creds.enter code here
we run invoke-azvmssruncommand and specific the script path and variable which needs to be passed as parameters.
in the PowerShell script we have script to get the cert from azure keyvualt once its connected to azure vm
below is the error
error: an error occurred while sending request. need your thoughts on it.
Invoke-AzVmssVMRunCommand -VMScaleSetName dev-CTUS -ResourceGroupName RG -InstanceId $instanceid -CommandId 'RunPowerShellScript'-ScriptPath "path"\downloadcertfromkeyvault.ps1" -Parameter #{"vaultname"= "keyvault name";"certname"="app-DEV";"password"= "jdksjkdjalksd";"said"="";"sapuserid"; password"="password";"devSubscriptionId"="ZXXXXXXXXXX"} -Debug
this is the command which i used in azure devops powershell inline script .
inside powershell script
$SecurePassword = "$sapassword" | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $said, $SecurePassword
Connect-AzAccount -Credential $Credential -Tenant "XXXXXXXXXXXX-a68c-41e5-XXXXXXXX"
Write-log "setting subscription to retrive certs"
Set-AzContext $devSubscriptionId
$password = "$password"
$password = ConvertTo-SecureString -String "$password" -AsPlainText -Force
$cert = Get-AzKeyVaultCertificate -VaultName $vaultname -Name $certname
$secret = Get-AzKeyVaultSecret -VaultName $vaultname -Name $cert.Name
$pfxpath = [System.Environment]::GetFolderPath("Desktop")
$secretByte = [Convert]::FromBase64String($secret.SecretValueText)
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($secretByte, "", "Exportable,PersistKeySet")
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx
$pfxFileByte = $x509Cert.Export($type, $password)
# Write to a file
[System.IO.File]::WriteAllBytes("$pfxpath\$certname.pfx", $pfxFileByte)
$certificate= Get-ChildItem -path cert:\LocalMachine\My` `
Write-Log $certificate

Runbook automation fails but powershell cmd line works fine

I have the following powershell code for suspending azure d/w
$TenantId = "<>"
$SubscriptionId = "<>"
# Get the service principal credentials connected to the automation account.
$SPCredential = Get-AutomationPSCredential -Name "psvar"
# Login to Azure ($null is to prevent output, since Out-Null doesn't work in Azure)
Write-Output "Login to Azure using automation account 'psvar'."
$null = Login-AzureRmAccount -TenantId $TenantId -SubscriptionId $SubscriptionId -Credential $SPCredential
Write-Output "Login Status "
# Select the correct subscription
Write-Output "Selecting subscription '$($SubscriptionId)'."
$null = Select-AzureRmSubscription -SubscriptionID $SubscriptionId
$ResourceGroupName = '<>'
$ServerName = '<>'
$DatabaseName = '<>'
Write-Output "Suspending $($DatabaseName)..."
$null = Suspend-AzureRmSqlDatabase `
-ResourceGroupName $ResourceGroupName`
-DatabaseName $DatabaseName`
-ServerName $ServerName
Write-Output "Done"
Suspend azure rm sqldatabase works fine in PowerShell Azure Command line interface
But in runbook automation it fails with
Suspend-AzureRmSqlDatabase : Run Login-AzureRmAccount to login.
At line:33 char:9
+ $null = Suspend-AzureRmSqlDatabase `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Suspend-AzureRmSqlDatabase], PSInvalidOperationException
+ FullyQualifiedErrorId :
InvalidOperation,Microsoft.Azure.Commands.Sql.DatabaseActivation.Cmdlet.SuspendAzureSqlDatabase
Any idea what could be wrong. Appreciate any pointers regarding this
I test your script, it works in the runbook.
Navigate to the automation account -> Credentials, make sure your user account name and password are correct.
If it still not work, you could try my solution here, it works.
For Azure Synapse analytics we need to use
Update-AzSynapseSqlPool -WorkspaceName <wsname>-Name <dbname> -Pause

Spinning up VM from Powershell with multiple admins

I have a script which spins up an Azure VM and specifies an admin username and password.
Is it possible to have the script setup a second admin? The reason for this is so that more than one user can be on the machine at the same time.
Do you have access to the vm with Invoke-Command?
If yes, might this helps: How to Manage Local Users and Groups using PowerShell
According to my research, two users can access Azure windows VM concurrently. A maximum of two concurrent connections are supported unless the server is configured as a Remote Desktop Services session host. Regarding how to add local user to Azure VM, you use the the VM Access extension in Azure PowerShell. For more details, please refer to the document
For example
Connect-AzAccount
$vm = Get-AzVM -ResourceGroupName jimtest -Name jimtest
$name = "jimtest1"
$password = "Pass***!"
$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
$mycred= New-Object System.Management.Automation.PSCredential ($name, $secpasswd)
Set-AzVMAccessExtension -Credential $mycred -ResourceGroupName $vm.ResourceGroupName -VMName $vm.Name -Location $vm.Location -Name VMAccessAgent -TypeHandlerVersion "2.0"
You can use this PowerShell command below to add an admin account to your VM :
$adminName = "testadmin"
$passstr = "password123!"
$Password = ConvertTo-SecureString -String $passstr -AsPlainText -Force
New-LocalUser $adminName -Password $Password -FullName $adminName -Description "test admin account"
Add-LocalGroupMember -Group "Administrators" -Member $adminName
And you can use the Powershell command below to run your custom Powershell command on your Azure VMs(get started with azure powershell see here):
Connect-AzAccount
$vm = Get-AzVM -Name "<your vm name>" -ResourceGroupName "<your vm resource group>"
Invoke-AzVMRunCommand -VM $vm -CommandId 'RunPowerShellScript' -ScriptPath "<path of adding admin account command>"
so just save the first part command as a .ps1 file , and copy the path as value of you can add an local admin account to your VM.
Result :

Provisioning failed. OS Provisioning for VM 'VM Name' did not finish in the allotted time

I'm new to Azure. I'm trying to create resources in Azure using powershell.
My requirement is to create an image from a VM. I have followed to ways to do it :
Process 1: Do it manually
Generalize the VM : Login to VM -> Open command prompt -> cd %windir%\system32\sysprep --> run sysprep.exe --> Check generalize button--> Shutdown.
Create snapshot : Go to Azure portal-> Go to the VM which is generalized --> Click on Capture button --> Give image name and mention resource group and click on Create.
This will create an Image.
Process 2: Do it with powershell
# create session of the VM
$UserName = "$IPAddress\$adminUsername"
$Password = ConvertTo-SecureString $adminPassword -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($UserName, $Password)
$s = New-PSSession -ComputerName $IPAddress -Credential $psCred
# Run SysPrep for generalizing the VM
$sysprep = 'C:\Windows\System32\Sysprep\Sysprep.exe'
$arg = '/generalize /oobe /shutdown /quiet'
Invoke-Command -Session $s -ScriptBlock {param($sysprep,$arg)Start-Process -FilePath $sysprep -ArgumentList $arg} -ArgumentList $sysprep,$arg
#Stop the VM
Stop-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $virtualMachineName -Force
# Generalize the VM
Set-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $virtualMachineName -Generalized
# Create the Image
$vm = Get-AzureRmVM -Name $virtualMachineName -ResourceGroupName $ResourceGroupName
$image = New-AzureRmImageConfig -Location $location -SourceVirtualMachineId $vm.ID
New-AzureRmImage -Image $image -ImageName $ImageName -ResourceGroupName $ResourceGroupName
Both the processes will create a Image. But the problem I'm facing here is when I spin VM from the image created from Process 1 , it is created successfully without any issue.
But when I spin VM from image created from Process2 , it is getting created but with below error message :
Provisioning failed. OS Provisioning for VM 'VM Name' did not finish
in the allotted time. However, the VM guest agent was detected
running. This suggests the guest OS has not been properly prepared to
be used as a VM image (with CreateOption=FromImage).
Can anyone tell me what it is I'm doing wrong with powershell script, that I'm getting this error.
Time seems to be the issue.
Sysprep normally takes 10 - 15 minutes, you have no sleep time. You are shutting down VM as soon as the sysprep script is sent, no time to actually sysprep system.
You can either put a sleep time or a loop to check when VM is in a Stopped state.
There are quite a few docs on papering and creating VMs from images in Azure. As the error suggests, you likely missed a step.
If you are uploading a VHD from on prem to use in Azure, start with these docs
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/prepare-for-upload-vhd-image
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/upload-generalized-managed
If the VM you are capturing an image of is already in Azure and working, then start with these
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/capture-image-resource
https://learn.microsoft.com/en-us/azure/virtual-machines/windows/create-vm-generalized-managed?toc=%2fazure%2fvirtual-machines%2fwindows%2ftoc.json
The last link shows you how to create the VM from that image via the portal or a simple PS command
New-AzVm `
-ResourceGroupName "myResourceGroup" `
-Name "myVMfromImage" `
-ImageName "myImage" `
-Location "East US" `
-VirtualNetworkName "myImageVnet" `
-SubnetName "myImageSubnet" `
-SecurityGroupName "myImageNSG" `
-PublicIpAddressName "myImagePIP" `
-OpenPorts 3389

checking the stopped VM's with different resources by Powershell script

How to check stopped virtual Machines with different resources by azure powershell script
iam tried to do that script please help me
To get status of the vm’s you can try the below script:
#login
Connect-AzureRmAccount
Select-AzureRmSubscription –SubscriptionName 'subscription-name'
Get-AzureRmVM -Status | Format-Table
If you want ResourceGroup group wise you try this script:
Connect-AzureRmAccount
Select-AzureRmSubscription –SubscriptionName 'subscription-name'
$RG = "ResourceGroupName"
$VM = "vmname"
$VMStats = (Get-AzureRmVM -Name $VM -ResourceGroupName $RG -Status).Statuses
($VMStats | Where Code -Like 'PowerState/*')[0].DisplayStatus

Resources