Runbook Run Powershell as azure acccount - azure

I got a script on a VM within the subscription/rg that runs a ps module called Qlik-Cli, it uses a certificate and a login.
The certificate is stored in the local store for the serviceaccount, not a choise, how the product works.
I need to trigger this thorgh a powershell runbook.
In order for this to work, I need to trigger this with the service account, cause it won't find the certificate otherwise.
This is something we are going to schedule so it has to be done this way.
How can I run it this way, or is it not possible?
I can't find any good option when googeling it.
> Import-Module -Name Qlik-Cli
> [Net.ServicePointManager]::SecurityProtocol =
> [Net.SecurityProtocolType]::Tls12 $logpath =
> "E:\Tools\Scripts\log.txt" get-childitem cert:\currentuser\My\ |
> where {$_.Thumbprint -eq '"thumbprint"'} |
> Connect-Qlik "DNS" -UserName
> "user" -TrustAllCerts -verbose 4>&1 | Out-File
> -Append $logpath Start-QlikTask -id df9dfa2f-32ca-4db4-bdce-15ad924fd59f -verbose 4>&1 | Out-File -Append
> $logpath
The script in the runbook:
$ServicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
Add-AzAccount -ServicePrincipal -TenantId $ServicePrincipalConnection.TenantId -ApplicationId $ServicePrincipalConnection.ApplicationId -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint
$rgname ="Resource-Group"
$vmname ="Virtual machine name"
$ScriptToRun = "E:\Tools\Scripts\Tasktrigger.ps1"
Out-File -InputObject $ScriptToRun -FilePath ScriptToRun.ps1
Invoke-AzVMRunCommand -ResourceGroupName $rgname -Name $vmname -CommandId 'RunPowerShellScript' -ScriptPath ScriptToRun.ps1
Remove-Item -Path ScriptToRun.ps1
What the logs says from the script (local script) when I execute the runbook is that it can't find the certificate which is not strange.
Raw output:
Found 0 certificates in the current user store
Found 0 certificates in the local machine store
No valid certificate found, using windows credentials

Used the code on Github for the module Click-Cli to backtrack the error message. Had to change certificate and imporrt the new one in personal / machine store.
Also the default username when running it from outside the QlikServer is domain\Servername$, which means you have to change permissions on the account in QlikSense to allow it to execute tasks.
You can see the name if you use verbose logging to file once you added the right certficate all the way.

The Qlik-CLI module, reads the client, QlikClient, certificate from cert:\\CurrentUser\My.
So, if you are trying to run Qlik-CLI scripts as a different user than the Qlik Sense service user account (or on another machine), you need to log in as the service account, export the QlikClient certificate, including the private key, and install it under the user running the script.
The -UserName argument is just to tell Qlik who you want to be, given that you have the certificate in order.
To cut it short: Run the script as the Qlik service user. It will save you a lot of hassle. :)

Related

Start antivirus scan from a script on Azure Linux VM

I have a shell script inside Azure Linux vm. The Azure Linux VM has Sophos installed in it.The shell script can scan the files present in a directory by using savscan command. Challenge is , we are using azure data factory pipeline, which needs to call the azure function. The azure function should be able to ssh to linux vm, and execute the script. The function should pass the parameters like file path for the azure shared file storage where Sophos needs to perform the scan.
I understand thepipeline can call the http triggered azure function. But how can we ssh into a vm and run the scripts remotely from the azure function. Also the parameters for the file path will come from data factory.
inotifywait -mr -e close_write "/xyz/abc/" |
while read dir eve file; do
echo "new file '$path$file' detected - start scan"
savscan -eec $path$file
if [ $? -eq 0 ]
then
echo "1"
else
echo "0"
fi
done
Seems there is something wrong with your ScriptPath param . If you are using Azure Automation, we can't place static script files in it , but we can download our script first and place it in "c:/temp" folder of Azure automation.
I did some tests on my side , I placed my scripts in Azure storage account , before I need to run this script, I will download it to Azure automation temp folder so that I can specify a path to run it .
Try the PS below in Automation:
$appid = "<your Azure application ID>"
$passwd = "<your Azure application password>"
$tenant = "<tenant>"
$storageName = "<storage name>"
$containerName = "<container name>"
$scrtptName = "<script name>"
$storageResourceGroupName = "<storage group name>"
$vmName = "<vm name>"
$VMResourceGroupName = "<vm group name>"
$secpasswd = ConvertTo-SecureString -String $passwd -AsPlainText -Force
$cred = New-Object Management.Automation.PSCredential ($appid , $secpasswd)
login-AzAccount -Credential $cred -Tenant $tenant -ServicePrincipal
$storage = Get-AzStorageAccount -ResourceGroupName $storageResourceGroupName -Name $storageName
Get-AzStorageBlobContent -Container $containerName -Blob $scrtptName -Context $storage.Context -Destination "c:/temp"
$scriptPath = "c:/temp/$scrtptName"
$result = Invoke-AzVMRunCommand -VMname $vmName -ResourceGroupName $VMResourceGroupName -CommandId 'RunPowerShellScript' -ScriptPath $scriptPath
echo $result.Value
Remove-Item $scriptPath -Force
Modules I imported :
I place my script in my storage account, in this case , it is used for download something :
My test script content :
$url = "https://download.microsoft.com/download/1/E/7/1E7B1181-3974-4B29-9A47-CC857B271AA2/English/X64/msodbcsql.msi"
$outpath = "c:/odbc.msi"
Invoke-WebRequest -Uri $url -OutFile $outpath
Test on Azure automation and its result :
As you can see the file has been download successfully .
Btw, there is no need to use remote powershell here , you can use run command feature of Azure VMs to run your scripts on Azure VMs directly .
Nice work Stanley, I will test it too on an Ubuntu Machine. Hope it works :)

How to get output stream for Invoke-AzureRmVMRunCommand command?

I am trying to run the below command
Invoke-AzVMRunCommand -ResourceGroupName $instance.ResourceGroupName -Name $instance.Name -CommandId 'RunPowerShellScript' -ScriptPath 'C:\Users\tushar.raichand\Desktop\sample.ps1'
Sample.ps1 is as below
$output = Get-LocalUser
Write-Output $output
$output
The output i am getting for Invoke-AzVMRunCommand is
Microsoft.Azure.Commands.Compute.Automation.Models.PSRunCommandResult
First, make sure you have enough permission to show the details of a command, see Limiting access to Run Command:
Listing the run commands or showing the details of a command require the Microsoft.Compute/locations/runCommands/read permission, which the built-in Reader role and higher have.
Besides, the command Invoke-AzureRmVMRunCommand belongs to the AzureRM powershell module which has been deprecated, you may need to upgrade it to the new Az module, refer to this link to upgrade.
I test the script with the new Az command Invoke-AzVMRunCommand, it works fine.
Invoke-AzVMRunCommand -ResourceGroupName joywebapp -Name joyVM -CommandId 'RunPowerShellScript' -ScriptPath 'C:\Users\joyw\Desktop\sample.ps1'
sample.ps1:
$output = Get-LocalUser
Write-Output $output
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

How to create Azure Automation runbook that will start VM and then execute (local or Azure) script on the VM?

I wan't to create a Runbook that will start a specific (or parameter controlled) VM, and then run a script (locally or from blob storage) on the VM.
I have checked a lot of documentation, but so far without luck in getting it to work.
What I got so far under the same Resource Group:
VM created
Automation account created incl. Run As account
Azure Automation solution (OMS)
Credential (to my own account) under the automation account
Used several Runbook galleries and other code examples using functions as e.g.
Start-AzureVM ...
Invoke-Command ...
Anyone of you good people out there who can sample a guideline on what is needed depending on methods being used?
The VM start part is working, but I cannot get the login + executing of script to work!
I'm not a high skilled developer, and I have even doubts about choosing between the script languages in Azure.
Any help will be highly appreciated.
Thanks,
Tom
Invoke-Command
Invoke-AzureRmVMRunCommand
Set-AzureRmVMCustomScriptExtension
New-SSHSession + Invoke-SSHCommand
Code taken from e.g. gallary "Connect-AzureVM"
the parameter -ScriptPath of Invoke-AzureRmVMRunCommand should not point to the path in the remote computer, but should point to the local path of runbook environment.
Sample code like below(create a file named atestfile.txt in the remote vm):
$ServicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $ServicePrincipalConnection.TenantId `
-ApplicationId $ServicePrincipalConnection.ApplicationId `
-CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint
#define resource group and vm name
$resourceGroup ="xxx"
$VmName ="xxx"
#define the scripts in $scriptblock, and add the content of $scriptblock to aa.ps1 in current directory of runbook
write-output "create test file"
$scriptblock = "New-Item -path c:\test -name atestfile.txt -itemtype file -force"
Out-File -FilePath aa.ps1 -InputObject $scriptblock
#Note that the -ScriptPath should not point to the remote path(in remote vm), it should point to the local path where you execute the command Invoke-AzureRmVMRunCommand
Invoke-AzureRmVMRunCommand -ResourceGroupName $resourceGroup -Name $VmName -CommandId 'RunPowerShellScript' -ScriptPath aa.ps1
#after execution, you can remove the file
Remove-Item -Path aa.ps1
write-output "done now"
Test result:

Install extension on both Classic and ARM VMs with single PowerShell command

I have a script that installs OMS extensions to all ARM VMs in the subscription. The problem is that I have subscriptions that contain only ARM VMs, subscriptions that contain only Classic VMs, and subscription that have both types of VMs. How can I modify the script to work in all of the conditions? The script is:
#This script installs OMS Monitoring Agent to all VMs in the selected Subscription.
#Before running this script, the user must login to Azure account and select target subscription.
#Example:
#Login-AzureRmAccount
#Select-AzureRmSubscription 'SubscriptionName'
$WorkspaceID = 'Provide Workspace ID here'
$WorkspaceKey = 'Provide Workspace key here'
$VMs = Get-AzureRmVM
$VMs.where({$_.osprofile.windowsconfiguration}) | ForEach-Object {
"Installing Microsoft.EnterpriseCloud.Monitoring.MicrosoftMonitoringAgent Extension: {0}" -f $_.id
Set-AzureRmVMExtension -ResourceGroupName $_.ResourceGroupName -VMName $_.Name -Name omsAgent -Publisher 'Microsoft.EnterpriseCloud.Monitoring' `
-ExtensionType 'MicrosoftMonitoringAgent' -AsJob -TypeHandlerVersion '1.0' -Location $_.Location -ForceRerun 'yesh' `
-SettingString ( "{'workspaceId': '$WorkspaceID'}") `
-ProtectedSettingString "{'workspaceKey': '$WorkspaceKey'}" |
Add-Member -Name VM -Value $_.Id -MemberType NoteProperty
}
Since you got both classic and ARM VMs, you got two different deployment models, hence two different PowerShell modules you are using.
In other words, you need to log in separately for each and have separate scripts for using them.
In the classic model you need to run the following cmdlet to login and access your VMs:
Add-AzureAccount
Get-AzureVM | Set-AzureVMExtension ``
-Publisher 'Microsoft.EnterpriseCloud.Monitoring' ``
-ExtensionName 'MicrosoftMonitoringAgent' ``
-Version '1.*' ``
-PublicConfiguration "<workspace id>" ``
-PrivateConfiguration "<workspace key>" ``
While searching for information I found this script. It's a script for on-boarding VMs from single, or multiple subscriptions, using both deployment models.

Resources