New-PSSession in an Azure-runbook: Access denied (ARM) - azure

With the advice provided in this answer I was able to set up the winrm on a Azure VM(1).
Right now, I can open a PS-Session with New-PSSession from
any Azure VM(2) to the Azure VM(1)
my local machine which to the Azure VM(1)
But if I do exactly the same within an Azure runbook,
$cred = Get-AutomationPSCredential -Name "admin"
InlineScript
{
$vmSession = New-PSSession -ConnectionUri 'https://xxx.yyy.cloudapp.azure.com:5986' -Credential $cred -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)
}
it fails with the error message:
New-PSSession : [xxx.yyy.cloudapp.azure.com] Connecting to remote server
xxx.yyy.cloudapp.azure.com failed with the following error message : Access is denied.
As user I use `localhost\admin" and I'm positiv, the password is correct (double-checked it).
Q How can I overcome the Access denied?
Update
PS-workflow got the best of me. So, there is only a minor syntactical problem in the code above. If somebody shares the right answer I'm happy to up-vote and accept it.

According to this official documents.
By default, the variables that are defined in a workflow are not
visible to the commands in the InlineScript script block. To make
workflow variables visible to the InlineScript, use the $Using scope
modifier. The $Using scope modifier is required only once for each
variable in the InlineScript.
So, you need modify your script as below:
$cred = Get-AutomationPSCredential -Name "admin"
InlineScript
{
$vmSession = New-PSSession -ConnectionUri 'https://xxx.yyy.cloudapp.azure.com:5986' -Credential $Using:cred -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)
}

Related

Connect-AzAccount with Azure Devops Pipeline?

I am finding difficulties in finding the best and secure way to use connect-azaccount with azure devops pipeline. I have in the pipeline the following this simple powershell script which is used to create azure resources. Just to simplify things I only used the creation of a resource group:
$Location = "Location Name"
$resourceGroupName = "Resource Group Name"
try {
#Creation of Resource Group
$resourceGroup = Get-AzResourceGroup -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if($null -eq $resourceGroup)
{
New-AzResourceGroup -Name $resourceGroupName -Location $Location
}
else
{
Write-Host "The ResourceGroup with the name: $resourceGroupName already exists."
}
}
catch
{
Write-Host "Error occurred: $_"
}
The problem here is when the pipeline is being run and it reaches the Powershell task, it gives me an error, Error occurred: Run Connect-AzAccount to login.
My issue here is that I honestly don't know which way is the most secure way to connect without typing any user credentials. It should directly connect and create the resources. Note that I am using Multi-Factor Authentication. In order to achieve that I found several solutions but I need help in choosing the best way. I found several solutions by adding a powershell task in the Yaml file. Here is the Yaml showing the powershell task to run the script:
- task: PowerShell#2
inputs:
filePath: '$(Pipeline.Workspace)/Deploy/functionapp.ps1'
Option 1:
Connect-AzAccount -Tenant 'xxxx-xxxx-xxxx-xxxx' -SubscriptionId 'yyyy-yyyy-yyyy-yyyy'
Now the problem here is that the Tenant ID and Subscription are going to be visible in the code and that is a very bad practice
Option 2 is to use the following script:
$User = "xxx#xxxx.onmicrosoft.com"
$PWord = ConvertTo-SecureString -String "<Password>" -AsPlainText -Force
$tenant = "<tenant id>"
$subscription = "<subscription id>"
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User,$PWord
Connect-AzAccount -Credential $Credential -Tenant $tenant -Subscription $subscription
This is very similar to the first, but if I am not mistaken it is limited to a specific user.
Option 3 is to use a service principal:
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "strong password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
I don't know if creating a service principal will incur any costs and what steps should I do to make it work.
I am honestly new to all this, can someone please provide me what are the exact steps to achieve this. Thank you for your answers :)
The most secure way is to create an Azure Resource Manager service connection and use it in your pipeline. You can create it using automated way, or manually using previously created service principal.

login to azure account without popup using powershell

I'm trying to create Azure VM using powershell.I have also the script to create it.
First I need to login into Azure account :
Login-AzureRMAccount
This gives a pop-up to enter the credentials.
Second I need to run the below script:
$UserName = "username"
$Password = ConvertTo-SecureString "password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($UserName, $Password)
New-AzureRmVm `
-ResourceGroupName "RG1" `
-Name "VM1" `
-ImageName "Image1" `
-Location "West US" `
-Credential $psCred
This is creating the VM successfully.
But now , I need to make these scripts run automatically, when ever there is requirement. The problem I'm facing is, the login step gives a popup to enter the credentials which I do not want. So I have tried something like this, but didn't work.
$username = "loginname#organization.com"
$SecurePassword = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username, $SecurePassword)
Login-AzureRmAccount -Credential $cred
The error message it is giving is :
Login-AzureRmAccount : accessing_ws_metadata_exchange_failed: Accessing WS metadata exchange failed: The underlying connection was closed: An unexpected error occurred on a send.
At line:4 char:1
+ Login-AzureRmAccount -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Connect-AzureRmAccount], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand
Can anyone tell me what this means and how to rectify this? Thanks!
If you are planning to automate any services into Azure using PowerShell, then I'd recommend connecting azure using Service Principal rather than your own credentials, it will be a secure way to connect.
What is Service principal?
An Azure service principal is a security identity used by user-created
apps, services, and automation tools to access specific Azure
resources. Think of it as a 'user identity' (username and password or
certificate) with a specific role, and tightly controlled permissions.
It only needs to be able to do specific things, unlike a general user
identity. It improves security if you only grant it the minimum
permissions level needed to perform its management tasks.
Follow this tutorial to create a service principal
I also have published a sample PowerShell workflow into Microsoft gallery for creating Service Principal you can also follow that.
Once you created your service principal, you can use the below PowerShell commands to login into azure without any popup's
$applicationId = "<service prinicple application id>";
$securePassword = "<service prinicple password>" | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $applicationId, $securePassword
Connect-AzureRmAccount -ServicePrincipal -Credential $credential -TenantId "<your tenantid>"
Update1:
For some reason/bug the above will get fails. Refer this github issue
To solve this
Add the two lines before the script
Import-Module -Name AzureRM.Profile
Remove-AzureRmAccount
Update 2:
AzureRM will no longer receive new cmdlets or features. However, the AzureRM module is still officially maintained and will get bug fixes through December 2020.
You have to use the new Azure PowerShell Az module
Basically you can achieve this for all of your PowerShell sessions by adding the Logging in part as part of the $PSProfile. I use this trick to skip the login popup, so whenever i open powershell my account is automatically logged in.
Open Windows PowerShell as an administrator
Type Notepad $profile
A notepad file will be opened and here you can paste the below code to
log in automatically whenever it is opened.
$username = “”
$password = “”
$securepasswd = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($username, $ securepasswd)
Connect-AzureRmAccount -Credential $cred

File System Mapping on Azure Server

I have a windows Azure server where I want to mount a file mapping. Below code works fine when I try it on my local windows machine. But it says Access Denied when try the same on Azure Windows Server. What am I missing here?
$acctKey = ConvertTo-SecureString -String "<account_key>" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList "Azure\<account_username>", $acctKey
New-PSDrive -Name Z -PSProvider FileSystem -Root "\\server.name\files" -Credential $credential -Persist
P.S. It says here that I do have the access.
Could you please try to mount azure file share with command prompt:
net use Z: \\jasonvmdisks304.file.core.windows.net\jasonshare yjya1gkE0TK0lqx/OUh1kD4fxdhCLDjcOW6XPSF6Y4jyCxxMd45eFEvYRzKp8CMRjRpuz38RISA49qXWw3wKA== /user:Azure\jasonvmdisks304
If it still not work, could you please check the event view to find the log, and post it here.
Not sure if resolved so will chime in. One question, if the client is in a different Azure region (e.g. on premise or elsewhere) then SMB3.0 is required, else, SMB2.1 (if in the same region) is allowed. This is a security feature.

Login-AzureRmAccount from VS Code terminal

When I try to login to Azure RM from VS Code terminal it just hangs. No prompt with login / password is shown.
Is there any way to get logged in from that terminal? Otherwise running / debugging Azure PS scripts becomes more complicated than it should be :)
The login window pops-up in the background... if you minimize all your windows you'll eventually find it.
You need to wait for a moment, then you could see the login page.
According to your description, I suggest you could select Non-interactive login. You could create a service principal that can access resource. Please refer to this link:Use portal to create an Azure Active Directory application and service principal that can access resources. You will get clientid and client secret. You could use the following code to login your Azure account.
$subscriptionId=""
$tenantid=""
$clientid=""
$password=""
$userPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $clientid, $userPassword
Login-AzureRmAccount -TenantId $tenantid -ServicePrincipal -SubscriptionId $subscriptionId -Credential $userCredential

How to stop all VMs with Azure Automation using Resource Manager module?

I have created some Azure VMs using the new Resource Manager and i'd like to stop them everyday.
To do so, i've published a runbook to stop aboth classic and ARM VMs, and i created a scheduler which runs the runbook every night :
workflow Stop-AzureVMs
{
$cred = Get-AutomationPSCredential -Name 'Cred'
Add-AzureAccount -Credential $cred
Select-AzureSubscription -Current 'SubscriptionName'
Get-AzureVM | Stop-AzureVM –Force
Get-AzureRmVM | Stop-AzureRmVM -Force
}
I have imported the AzureResourceManager module to my Azure Automation account :
But i am getting this error :
Exception
At line:34 char:2
+ Get-AzureRMVM | Stop-AzureRMVM -Force
+ ~~~~~~~~~~~~~ Cannot find the 'Get-AzureRMVM' command. If this command is defined as a workflow, ensure it is defined before the workflow that calls it. If it is a command intended to run directly within Windows PowerShell (or is not available on this system), place it in an InlineScript: 'InlineScript { Get-AzureRMVM }'
How is that possible ?
Edit : Below is the solution
$cred = Get-AutomationPSCredential -Name 'Cred'
Add-AzureRmAccount -Credential $cred
Select-AzureRmSubscription -Name 'SubscriptionName' -SubscipritionId 'SubscriptionId'
Get-AzureRmVM | Stop-AzureRmVM -Force
All workflows i found didn't mention the use of Add-AzureRmAccount and Select-AzureRmSubcription instead of the standard Add-AzureAccount and Select-AzureSubscription. I thought that the authentication process to our Azure account was the same.
Update : It is now possible to combine both ASM and ARM cmdlets within the same runbooks, see this post for more informations about ARM supported by default on Azure Automation
Looks like you imported the old version of the ARM cmdlets (before Azure PS 1.0) into Azure Automation. This was before the *-AzureRm* renaming. So tt should be Stop-AzureVM not Stop-AzureRmVM.
However, that makes it ambiguous as to whether you are trying to call Azure Service Management or Azure Resource Manager cmdlets -- which is exactly why the cmdlet names were renamed in Azure PS 1.0. I recommend you follow the guidance here.
As per my understanding ASM mode is default. If you are going for ARM command firstly switch mode is required using Switch-AzureMode
One more confusion is what is the purpose of Get-AzureRMVM command. I googled but coulndn't find anything -
The Get-AzureRMVM cmdlet is in the AzureRM.Compute module... The AzureRM* cmdlets are still in preview, I don't think they are available in Azure Automation yet.
The two modules in your screenshot above likely correspond to the 0.9.x version of the cmdlets and there were indeed two different modules (Azure=ASM and AzureResourceManager=ARM) behind Switch-AzureMode. Switch-AzureMode just unloads one and loads the other.
If Automation is still using the 0.9.x version of the cmdlets then you should be able to just use Get-AzureVM for ARM VMs using the AzureResourceManager module.
Below is the solution
$cred = Get-AutomationPSCredential -Name 'Cred'
Add-AzureRmAccount -Credential $cred
Select-AzureRmSubscription -Name 'SubscriptionName' -SubscriptionId 'SubscriptionId'
Get-AzureRmVM | Stop-AzureRmVM -Force
It is not yet possible to combine ARM and ASM cmdlets in same runbook apparently ... So you have to use only ARM cmdlet or ASM cmdlet.
Also, all workflows i found didn't mention the use of Add-AzureRmAccount and Select-AzureRmSubcription instead of the standard Add-AzureAccount and Select-AzureSubscription.
I thought that the authentication process to our Azure account was the same.
The Following code will work for both old style and new Style VM's but be aware this will shut down all machines with no warning.
{
# TODO: update to the name of the credential asset in your Automation account
$AutomationCredentialAssetName = "AzureAutomationRG"
# Get the credential asset with access to my Azure subscription
$Cred = Get-AutomationPSCredential -Name $AutomationCredentialAssetName
# Authenticate to Azure Service Management and Azure Resource Manager
Add-AzureAccount -Credential $Cred
Add-AzureRmAccount -Credential $Cred
"`n-Old Style VMS-`n"
# Get and output Azure classic VMs
$VMs = Get-AzureVM
$VMs.Name
Get-AzureVM | Stop-AzureVM -Force
"`n-New Style Resource Group VMs-`n"
# Get and output Azure v2 VMs
$VMsv2 = Get-AzureRmVM
$VMsv2.Name
Get-AzureRmVM | Stop-AzureRmVM -Force
}
For new Azure RM VMs use access extensions the following command:
Set-AzureRmVMAccessExtension -ResourceGroupName "ResourceGroupName" -VMName "VMName" -Username "Admin User Name" -Password "Admin Password" -Name "Extension Name"
Please note the -Name parameter is the arbitrary extension name.
This might be late to the party, but I would recommend you check out this link:
https://www.attosol.com/start-or-stop-all-vms-of-a-resource-group-in-azure/
Basically, you can create a script and write some aliases with switches to make your job super easy.

Resources