Using Azure Powershell commandlets, I want to provision a new Linux VM with no SSH password and only SSH keys (necessary when provisioning CoreOS). When using the Azure CLI along with a public key file specified on the command line, everything works well. Apparently this is not available for the Powershell commandlet Add-AzureProvisioningConfig. It takes two possible SSH Key arguments, but they are both lists of key pairs. As documented here, the argument -SSHKeyPairs specifies a list of SSH key pairs already deployed in the subscription. I have no idea how to deploy key pairs in the subscription, nor can I find it documented anywhere. Likewise, -SSHPublicKeys specifies a list of SSH public keys already deployed in the subscription.
You can use Openssl.exe utility to generate the certificate.
Here is an example of what this command :
openssl.exe req -x509 -nodes -days 365 -newkey rsa:2048 -keyout myPrivateKey.key -out myCert.pem
Complete example of how to provision a Linux virtual machine using an SSH:
$location = "West US"
$serviceName = "contosolinux1"
$vmName = "linuxvm1"
$size = "Small"
$adminUser = "[admin user name]"
$password = "[admin password]"
$imageFamily = "Ubuntu Server 14.10 DAILY"
$imageName = Get-AzureVMImage |
where { $_.ImageFamily -eq $imageFamily } |
sort PublishedDate -Descending |
select -ExpandProperty ImageName -First 1
$certPath = "$PSScriptRoot\MyCert.pem"
New-AzureService -ServiceName $serviceName `
-Location $location
$cert = Get-PfxCertificate -FilePath $certPath
Add-AzureCertificate -CertToDeploy $certPath `
-ServiceName $serviceName
$sshKey = New-AzureSSHKey -PublicKey -Fingerprint $cert.Thumbprint `
-Path "/home/$linuxUser/.ssh/authorized_keys"
New-AzureVMConfig -Name $vmName `
-InstanceSize $size `
-ImageName $imageName |
Add-AzureProvisioningConfig -Linux `
-AdminUsername $adminUser `
-Password $password `
-SSHPublicKeys $sshKey |
New-AzureVM -ServiceName $serviceName
Source : https://www.microsoftpressstore.com/store/exam-ref-70-533-implementing-microsoft-azure-infrastructure-9780735697065
Related
I am creating a certificate inside Azure Key Vault and then attempting to export it with private key as a PFX.
# Create new Certificate in Key Vault
$policy = New-AzKeyVaultCertificatePolicy -SecretContentType "application/x-pkcs12" -SubjectName "CN=contoso" -IssuerName "Self" -ValidityInMonths 12 -ReuseKeyOnRenewal -KeySize 4096 -KeyType 'RSA-HSM';
Add-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName -CertificatePolicy $policy;
# From https://learn.microsoft.com/en-us/powershell/module/az.keyvault/get-azkeyvaultcertificate?view=azps-5.8.0
# Export new Key Vault Certificate as PFX
$securePassword = "fBoFXYD%dg^Q" | ConvertTo-SecureString -AsPlainText -Force; # This is a throwaway password
$certificate = Get-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName;
$secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name $certificate.Name -AsPlainText;
$secretByte = [Convert]::FromBase64String($secret)
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($secretByte, "", "Exportable,PersistKeySet")
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx
$pfxFileByte = $x509Cert.Export($type, $securePassword);
[System.IO.File]::WriteAllBytes("C:\Repos\Certificate.pfx", $pfxFileByte)
Get-PnPAzureCertificate -Path "C:\Repos\Certificate.pfx" -Password $securePassword
However, the PFX file is not valid
Error with Get-PnPAzureCertificate
Error with Certificate Import
Any ideas? Using Import-AzKeyVaultCertificate is not an option because there's a bug with it in environments that have policies that forces key lengths
Also, might be worth mentioning that I am using PowerShell 7
According to my test, we need to change keytype as RSA when we create cert policy.
For example
$VaultName=""
$ADServicePrincipalCertificateName=""
$policy = New-AzKeyVaultCertificatePolicy -SecretContentType "application/x-pkcs12" `
-SubjectName "CN=contoso.com" -IssuerName "Self" `
-ValidityInMonths 12 -ReuseKeyOnRenewal `
-KeySize 4096 -KeyType 'RSA';
Add-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName -CertificatePolicy $policy;
Start-Sleep -Seconds 30
# From https://learn.microsoft.com/en-us/powershell/module/az.keyvault/get-azkeyvaultcertificate?view=azps-5.8.0
# Export new Key Vault Certificate as PFX
$securePassword = "fBoFXYD%dg^Q" | ConvertTo-SecureString -AsPlainText -Force; # This is a throwaway password
$certificate = Get-AzKeyVaultCertificate -VaultName $VaultName -Name $ADServicePrincipalCertificateName;
$secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name $certificate.Name -AsPlainText;
$secretByte = [Convert]::FromBase64String($secret)
$x509Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($secretByte, "", "Exportable,PersistKeySet")
$type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pfx
$pfxFileByte = $x509Cert.Export($type, $securePassword);
[System.IO.File]::WriteAllBytes("E:\Certificate.pfx", $pfxFileByte)
Get-PnPAzureCertificate -Path "E:\Certificate.pfx" -Password $securePassword
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
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
I'm trying to move an existing Azure VM with a Managed Disk into an existing Availability Set. However, when I apply the command:
New-AzureRmVM -ResourceGroupName $rg -Location $OriginalVM.Location -VM $NewVM -DisableBginfoExtension
I get the following error:
New-AzureRmVM : Changing property 'osDisk.name' is not allowed.
ErrorCode: PropertyChangeNotAllowed
ErrorMessage: Changing property 'osDisk.name' is not allowed.
StatusCode: 409
ReasonPhrase: Conflict
OperationID : c179070b-e189-4025-84b0-87ba748f5844
At line:2 char:5
+ New-AzureRmVM -ResourceGroupName $rg -Location $OriginalVM.Locati ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzureRmVM], ComputeCloudException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.NewAzureVMCommand
In Azure ,once the disk is attached to the VM ,there is no way to change the name of the disk. The OS disk will get the name of the VM as provided by you during the creation of the VM. You can refer to this link to find more details.
I did a test and reproduced the same error as yours. Because I changed the OS disk name with Set-AzureRmVMOSDisk. Then I deleted the cmdlet which changed the OS disk’s name and succeed.
You can refer to create the vm without changing the OS disk name like the following cmdlet:
$VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $disk.Id -CreateOption Attach -Windows
The whole powershell cmdlet I used :
#Provide the subscription Id
$subscriptionId = 'xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx'
$resourceGroupName ='yangsatest'
$diskName = 'VM1_OsDisk_1_xxxxxxxxxxxx'
$location = 'eastus'
$virtualNetworkName = 'yangsatest-vnet'
$virtualMachineName = 'VM2'
$virtualMachineSize = 'Standard_A1'
Select-AzureRmSubscription -SubscriptionId $SubscriptionId
$disk = Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName $diskName
$VirtualMachine = New-AzureRmVMConfig -VMName $virtualMachineName -VMSize $virtualMachineSize -AvailabilitySetId /subscriptions/xxxxx-xxxxxx-xxx-xxxx8-xxxxxx/resourceGroups/yangsatest/providers/Microsoft.Compute/availabilitySets/Myset
#Use the Managed Disk Resource Id to attach it to the virtual machine. Please change the OS type to linux if OS disk has linux OS
$VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $disk.Id -CreateOption Attach -Windows
$publicIp = New-AzureRmPublicIpAddress -Name ($VirtualMachineName.ToLower()+'_ip') -ResourceGroupName $resourceGroupName -Location $location -AllocationMethod Dynamic
$vnet = Get-AzureRmVirtualNetwork -Name $virtualNetworkName -ResourceGroupName $resourceGroupName
$nic = New-AzureRmNetworkInterface -Name ($VirtualMachineName.ToLower()+'_nic') -ResourceGroupName $resourceGroupName -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $publicIp.Id
$VirtualMachine = Add-AzureRmVMNetworkInterface -VM $VirtualMachine -Id $nic.Id
#Create the virtual machine with Managed Disk
New-AzureRmVM -VM $VirtualMachine -ResourceGroupName $resourceGroupName -Location $location
----------Update----------
Updating Script to fit Official document :Change the availability set for a Managed Windows VM(https://learn.microsoft.com/en-us/azure/virtual-machines/windows/change-availability-set):
#set variables
$rg = "demo-resource-group"
$vmName = "demo-vm"
$newAvailSetName = "demo-as"
$outFile = "C:\temp\outfile.txt"
#Get VM Details
$OriginalVM = get-azurermvm -ResourceGroupName $rg -Name $vmName
#Output VM details to file
"VM Name: " | Out-File -FilePath $outFile
$OriginalVM.Name | Out-File -FilePath $outFile -Append
"Extensions: " | Out-File -FilePath $outFile -Append
$OriginalVM.Extensions | Out-File -FilePath $outFile -Append
"VMSize: " | Out-File -FilePath $outFile -Append
$OriginalVM.HardwareProfile.VmSize | Out-File -FilePath $outFile -Append
"NIC: " | Out-File -FilePath $outFile -Append
$OriginalVM.NetworkProfile.NetworkInterfaces.Id | Out-File -FilePath $outFile -Append
"OSType: " | Out-File -FilePath $outFile -Append
$OriginalVM.StorageProfile.OsDisk.OsType | Out-File -FilePath $outFile -Append
"OSDisk: " | Out-File -FilePath $outFile -Append
$OriginalVM.StorageProfile.OsDisk.ManagedDisk.Id| Out-File -FilePath $outFile -Append
if ($OriginalVM.StorageProfile.DataDisks) {
"Data Disk(s): " | Out-File -FilePath $outFile -Append
$OriginalVM.StorageProfile.DataDisks.Id | Out-File -FilePath $outFile -Append
}
#Remove the original VM
Remove-AzureRmVM -ResourceGroupName $rg -Name $vmName
#Create new availability set if it does not exist
$availSet = Get-AzureRmAvailabilitySet -ResourceGroupName $rg -Name $newAvailSetName -ErrorAction Ignore
if (-Not $availSet) {
$availset = New-AzureRmAvailabilitySet -ResourceGroupName $rg -Name $newAvailSetName -Location $OriginalVM.Location -Managed -PlatformFaultDomainCount 2 -PlatformUpdateDomainCount 2
}
#Create the basic configuration for the replacement VM
$newVM = New-AzureRmVMConfig -VMName $OriginalVM.Name -VMSize $OriginalVM.HardwareProfile.VmSize -AvailabilitySetId $availSet.Id
Set-AzureRmVMOSDisk -VM $NewVM -ManagedDisk $OriginalVM.StorageProfile.OsDisk.ManagedDisk.Id -CreateOption Attach -Windows
#Add Data Disks
foreach ($disk in $OriginalVM.StorageProfile.DataDisks ) {
Add-AzureRmVMDataDisk -VM $newVM -Name $disk.Name -ManagedDiskId $OriginalVM.StorageProfile.DataDisks.Id -Caching $disk.Caching -Lun $disk.Lun -CreateOption Attach -DiskSizeInGB $disk.DiskSizeGB
}
#Add NIC(s)
foreach ($nic in $OriginalVM.NetworkProfile.NetworkInterfaces.Id) {
Add-AzureRmVMNetworkInterface -VM $NewVM -Id $nic
}
#Create the VM
New-AzureRmVM -ResourceGroupName $rg -Location $OriginalVM.Location -VM $NewVM -DisableBginfoExtension
for me the problem was that I created a Managed Disk (from Azure Portal) which I selected the wrong OS which caused me this , I re-created managed disk with the right OS and then deployment worked.
I can get the publish settings use the following method:
$website = Get-AzureWebSite -Name $webSiteName
$websitePreProd = ($website | ?{ $_.Name -like "*Preprod)" })
$siteProperties = $websitePreProd.SiteProperties.Properties
$url = ($siteProperties | ?{ $_.Name -eq "RepositoryURI" }).Value.ToString() + "/MsDeploy.axd"
$userName = ($siteProperties | ?{ $_.Name -eq "PublishingUsername" }).Value
$pw = ($siteProperties | ?{ $_.Name -eq "PublishingPassword" }).Value
But ideally I want to use ARM via:
$existingSlot = Get-AzureWebApp -Name $websiteName -ResourceGroupName $resourcegroup -Slot "PreProd" -ErrorAction SilentlyContinue
How do I get URL, username and password using ARM?
#juvchan's answer will work. Here in an alternative for completeness:
$res = Invoke-AzureRmResourceAction -ResourceGroupName <RG name> -ResourceType Microsoft.Web/sites/config -ResourceName <sitename>/publishingcredentials -Action list -ApiVersion 2015-08-01 -Force
$userName = $res.Properties.PublishingUserName
$pwd = $res.Properties.PublishingPassword
You can try the simple script below to solve your problem.
I assume you are trying to get the MS-Deploy publish profile.
Note: You should install the latest Azure PowerShell to be able to use the new Azure RM commands.
$webAppSlot = Get-AzureRMWebAppSlot -ResourceGroupName <Res-Grp-Name> -Name <webAppName> -Slot <slotName>
$pp = Get-AzureRMWebAppSlotPublishingProfile -WebApp $webAppSlot -OutputFile <OutputFileFullPathName>
[xml]$ppXml = Get-Content <OutputFileFullPathName>
# MSDeploy Publish Profile
$publishUrl = $ppXml.publishData.FirstChild.publishUrl
$userName = $ppXml.publishData.FirstChild.userName
$userPWD = $ppXml.publishData.FirstChild.userPWD