Deploying multiple scripts with CustomScriptExtension on an Azure Windows VM - azure

I'm trying to deploy multiple PowerShell scripts to an Azure Windows VM by using the CustomScriptExtension.
The scripts are independent from each other so the order of their deployment doesn't matter. Also the scripts are in same blob container.
I have already a working template as below for installing one script at the moment:
$resourceGroup = "myResourceGroup"
$vmName = "myVM"
$location = "easteurope"
$storageAcctName = "myStorageAcct"
$storageKey = $env:ARM_ACCESS_KEY
$fileUri = #("https://xxxxx.blob.core.windows.net/xxxx/01-installTools.ps1")
$protectedSettings = #{"storageAccountName" = $storageAcctName; "storageAccountKey" = $storageKey};
$settings = #{"fileUris" = $fileUri;"commandToExecute" ="powershell -ExecutionPolicy Unrestricted -File 01-installTools.ps1"};
#run command
Set-AzVMExtension -ResourceGroupName $resourceGroup `
-Location $location `
-ExtensionName "IIS" `
-VMName $vmName `
-Publisher "Microsoft.Compute" `
-ExtensionType "CustomScriptExtension" `
-TypeHandlerVersion "1.8" `
-Settings $settings `
-ProtectedSettings $protectedSettings;
Also is it possible to use 2 CustomScriptExtensions?
I get a TypeHandlerVersion error if i try to do that.

Related

Custome Linux VM Extension on Azure

Ttrying to run .sh script via custome script extension via set-azvmextension but nither its througing an error nor output gettting generated on linux vm.
$resourceGroupName = "abc-RG"
$storageAccountName = "abcdiag"
$containerName = "public"
$location = "Central India"
$vmName = "abclinux2"
$extensionName = "vm_rwq"
$deploymentScript = "dd.sh"
$destintionPath = "/tmp/"
$storageAccountKeys = (Get-AzStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName).Value
$storageAccountKey = $storageAccountKeys[0]
$Settings = #{"fileUris" = "[https://abcdiag.blob.core.windows.net/public/dd.sh]"; "commandToExecute" = "sh dd.sh"};
$ProtectedSettings = #{"storageAccountName" = $storageAccountName; "storageAccountKey" = $storageAccountKey};
Set-AzVMExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $vmName >>
If you want to use Azure Custom Script Extension Version 1 with Linux virtual machines, the publisher should be Microsoft.OSTCExtensions and the type should be CustomScriptForLinux. For more details, please refer to the document
For example
$resourceGroupName = ""
$storageAccountName = ""
$location = ""
$vmName = ""
$extensionName = "vm_rwq"
$fileUri = #("https://jimtestperfdiag516.blob.core.windows.net/test/config-music.sh")
$storageAccountKeys = (Get-AzStorageAccountKey -ResourceGroupName "test" -Name $storageAccountName).Value
$storageAccountKey = $storageAccountKeys[0]
$Settings = #{'fileUris' =$fileUri; "commandToExecute" = "./config-music.sh"};
$ProtectedSettings = #{"storageAccountName" = $storageAccountName; "storageAccountKey" = $storageAccountKey};
Set-AzVMExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $vmName -Name $extensionName -Publisher "Microsoft.OSTCExtensions" -Type "CustomScriptForLinux" -TypeHandlerVersion "1.5" -Settings $Settings -ProtectedSettings $ProtectedSettings
Update
According to my research, Azure Custom Script Extension Version 1 does not support Red Hat operating System VM. For more details, please refer to the document
So if you want to install Custom Script Extension on Red Hat VM, we should use the new version: version 2. For further information, please refer to the article. Besides, if you want to use script to install the extension on Azure Linux VM, Azure CLI is a better way.
az vm extension set \
--resource-group myResourceGroup \
--vm-name myVM \
--name customScript \
--publisher Microsoft.Azure.Extensions \
--settings ./script-config.json \
--protected-settings ./protected-config.json
But, if you still want to use PowerShell, please refer to the following script
$resourceGroupName = ""
$storageAccountName = ""
$location = ""
$vmName = ""
$extensionName = "vm_rwq"
$fileUri = #("https://jimtestperfdiag516.blob.core.windows.net/test/config-music.sh")
$storageAccountKeys = (Get-AzStorageAccountKey -ResourceGroupName "test" -Name $storageAccountName).Value
$storageAccountKey = $storageAccountKeys[0]
$Settings = #{'fileUris' =$fileUri; "commandToExecute" = "./config-music.sh"};
$ProtectedSettings = #{"storageAccountName" = $storageAccountName; "storageAccountKey" = $storageAccountKey};
Set-AzVMExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $vmName -Name $extensionName `
-Publisher "Microsoft.Azure.Extensions" -Type "CustomScript" `
-TypeHandlerVersion "2.1" -Settings $Settings -ProtectedSettings $ProtectedSettings

Change password of Azure VM using PowerShell

I have tried this approach to change a password of an Azure VM:
$resgroup = "rsource1"
$vmName = "virtualmachine1"
$VM = Get-AzVM -ResourceGroupName $resgroup -Name $vmName
$Credential = Get-Credential
$VM | Set-AzureVMAccessExtension –UserName $Credential.UserName `
–Password $Credential.GetNetworkCredential().Password
$VM | Update-AzVM
But I keep getting this error:
Object reference not set to an instance of an object.
When I console.log the values of $Credential.UserName and $Credential.GetNetworkCredential().Password I got the values of username and password that I have inputted.
What am I missing here?
I've never used Set-AzureVMAccessExtension, but I've used the Az PowerShell equivalant Set-AzVMAccessExtension. It needs you to pass -Credential $Credential instead of -UserName and -Password.
You can try this script I made a while ago to to reset passwords for Azure VMs:
# Replace these values with your own
$resourceGroupName = "Servers-RG"
$vmName = "server1"
# Get the VM into an object
$vm = Get-AzVM -ResourceGroupName $resourceGroupName -Name $vmName
# Store credentials you want to change
$credential = Get-Credential -Message "Enter your username and password for $vmName"
# Store parameters in a hashtable for splatting
# Have a look at https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting?view=powershell-7
$extensionParams = #{
'VMName' = $vmName
'Credential' = $credential
'ResourceGroupName' = $resourceGroupName
'Name' = 'AdminPasswordReset'
'Location' = $vm.Location
}
# Pass splatted parameters and update password
Set-AzVMAccessExtension #extensionParams
# Restart VM
# Don't need to pass any switches since they are inferred ByPropertyName
# Have a look at https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pipelines?view=powershell-7
$vm | Restart-AzVM
I found that the password update doesn't happen until you restart the VM, so Restart-VM is required.
If anyone interested in the Linux (KISS) version (no VM restart needed):
$settings = '{}'
$protectedSettings = '{
"username": "<yourusername, prefer using Credentials object>",
"password": "<yourpassword, prefer using Credentials object>"
}'
Set-AzVMExtension `
-VMName $vmName `
-ResourceGroupName $rgName `
-Location $location `
-Name "VMAccessForLinux" `
-Publisher "Microsoft.OSTCExtensions" `
-ExtensionType "VMAccessForLinux" `
-TypeHandlerVersion "1.4" `
-Settingstring $settings `
-ProtectedSettingString $protectedSettings

How to Create App Service with a subType of api

In powershell and using the new-azwebapp to create a website in our app service plan. But it only ever seems to create a type of app
I'm trying to create it with the type of api like you can when you select from the Azure Portal UI, but I can't see a setting in the configuration to do this.
After creating I set the AppSettings and then try to update the Type, but it doesn't seem to matter.
Hoping that I'm missing something simple.
$siteName = "namegoeshere"
$sitePlan = "myplanname"
$siteLocation = "Australia East"
$siteResourceGroup = "resourcegroupname"
$createdSite = new-azWebApp -Name $siteName -ResourceGroupName $siteResourceGroup -AppServicePlan $sitePlan -Location $siteLocation
$newAppSettings = #{ "name"="value"}
Set-AzWebApp -Name $siteName -ResourceGroupName $siteResourceGroup -AppSettings $newAppSettings -AppServicePlan Grower #-PhpVersion 0
$p = #{ 'type' = "api" }
$r = Set-AzResource -Name $siteName -ResourceGroupName $siteResourceGroup -ResourceType Microsoft.Web/sites -PropertyObject $p -ApiVersion 2016-03-01 -Kind "app"
echo $r.Properties
The type api is not set with type, in the New-AzureRmResource parameters there is a parameter to set it, it's [-Kind <String>]. You could check it here.
Here is an example.
# CREATE "just-an-api" API App
$ResourceLocation = "West US"
$ResourceName = "just-an-api"
$ResourceGroupName = "demo"
$PropertiesObject = #{
# serverFarmId points to the App Service Plan resource id
serverFarmId = "/subscriptions/SUBSCRIPTION-GUID/resourceGroups/demo/providers/Microsoft.Web/serverfarms/plan1"
}
New-AzureRmResource -Location $ResourceLocation `
-PropertyObject $PropertiesObject `
-ResourceGroupName $ResourceGroupName `
-ResourceType Microsoft.Web/sites `
-ResourceName "just-an-api/$ResourceName" `
-Kind 'api' `
-ApiVersion 2016-08-01 -Force

Create VM in Azure with powershell with no public IP

I'm creating VM on Azure from an Image using powershell.
This is the script I'm using .
$UserName = "username"
$Password = ConvertTo-SecureString "password#123" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($UserName, $Password)
New-AzureRmVm `
-ResourceGroupName "RSG" `
-Name "VMName" `
-ImageName "ImageName" `
-Location "West US" `
-VirtualNetworkName "VNName" `
-SubnetName "default" `
-Credential $psCred
-PublicIpAddressName "None" `
-OpenPorts 3389
But, when I got into the Azure portal and see, some Public Ip is getting assigned by default. I have also tried without giving PublicIpAddressName property assuming , it wont assign any IP, but still it is assigning.
I want the Public IP to be none.Can anyone help me achieve this.Thanks!
Currently this an issue which is still in Open state on official azure-powershell github. You can refer it here . Incase if you still want to bypass this you can try using New-AzureReservedIP or after the deployment command try to remove the public ip by yourself Remove-AzureRmPublicIpAddress.
Note : I have'nt tested it yet. Just an idea.
Refer : Docs
To set no public ip address you have can just define it as "" , in powershell you will need to quote that again so it will be """" .
If you are using PowerShell, then you will need to escape all empty parameters by changing "" to '""' to properly pass an empty string into the command. Without this, PowerShell will not pass the empty string, and you will get an error from the command indicating it's missing a parameter.
$winVmCred = Get-Credential `
-Message "Enter username and password for the Windows management virtual machine."
# Create a NIC for the VM.
$winVmNic = New-AzNetworkInterface -Name "winVMNIC01" `
-ResourceGroupName $resourceGroup.ResourceGroupName `
-Location $location `
-SubnetId $targetVMSubnet.Id `
-PrivateIpAddress "10.10.12.10"
# Configure the Windows management VM.
$winVmConfig = New-AzVMConfig -VMName $winVmName -VMSize $winVmSize | `
Set-AzVMOperatingSystem -Windows -ComputerName $winVmName -Credential $winVmCred | `
Set-AzVMSourceImage -PublisherName $winVmPublisher `
-Offer $winVmOffer `
-Skus $winVmSku `
-Version $winVmVersion | `
Add-AzVMNetworkInterface -Id $winVmNic.Id
# Create the VM.
$winVM = New-AzVM -ResourceGroupName $resourceGroup.ResourceGroupName `
-Location $location `
-VM $winVmConfig `
-ErrorAction Stop

placing the results of Get-AzureRmVM into an array and using a loop to add them to the domain

I need to query a resource group for the number of VMs in the resource group, I then need to run the following command to add each machine to the domain.
In the below example I'm only adding server1 but if there are multiple servers in this resource group, whats the best way of ensuring each machine gets added based on the results of Get-AzureRmVM?
Set-AzureRmVMExtension -ResourceGroupName "abcd" -ExtensionType "JSONADDomainExtension" `
-Name "joindomain" -Publisher "Microsoft.Compute" -TypeHandlerVersion "1.0" `
-VMName "server1" -Location "uk west" -SettingString $string1 `
-ProtectedSettingString $String2
If you want to run Set-AzureRmVMExtension for each VM in a resource group, then you could run
$rg = "abcd"
# Fetch all the machines from one resource group
$machines = Get-AzureRmVM -ResourceGroupName $rg
# Loop over each object in the $machines array and add the extension
$machines | ForEach { Set-AzureRmVMExtension -ResourceGroupName $rg `
-ExtensionType "JSONADDomainExtension" -Name "joindomain" `
-Publisher "Microsoft.Compute" -TypeHandlerVersion "1.0" -VMName $_.Name `
-Location "uk west" -SettingString $string1 -ProtectedSettingString $String2 }

Resources