Get-AzureStorageKey Error on Azure Automation - powershell

I'm configuring a Azure Automation Runbook with a "Classic RunAs Connection".
After I select the Azure Subscription with this connection, I'm getting the storage key for one of my storage accounts, but the problem is that sometimes it works and sometimes it doesn't. Here is what I'm doing:
$ConnectionAssetName = "AzureClassicRunAsConnection"
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
$CertificateAssetName = $Conn.CertificateAssetName
$Cert = Get-AutomationCertificate -Name $CertificateAssetName
Set-AzureSubscription -SubscriptionName $Conn.SubscriptionName -SubscriptionId $Conn.SubscriptionID -Certificate $AzureCert
Select-AzureSubscription -SubscriptionId $Conn.SubscriptionID
$storageAccountKey = Get-AzureStorageKey -StorageAccountName "MyStorageAccountName"
The transient error that occurs is:
Get-AzureStorageKey : An error occurred while sending the request.
At line:38 char:26
... eAccountKey = Get-AzureStorageKey -StorageAccountName "MyStorageAccountName"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : CloseError: (:) [Get-AzureStorageKey], HttpRequestException
FullyQualifiedErrorId :
Microsoft.WindowsAzure.Commands.ServiceManagement.StorageServices.GetAzureStorageKeyCommand
It works most of the time, but sometimes this exception is thrown.
Can somebody help me?
Thanks!

After some unsucessful testing, I decided to store the StorageKey inside an encrypted variable.
I know that this is not the best solution, but I didn't find the problem.
The original solution worked most of the time, but the exception thrown when the error occurs, didn't help me to find it.

You need to use a RunAs connection - the ClassicRunAsConnections are for RDFE, the KeyVault cmdlets use your AzureRm credentials. The RunAs credentials provide you with a Service Principal, and you need to give that service principal access to your KeyVault in KeyVault configuration

Related

List all my Azure websites using an Azure Powershell Function

Im testing the new Azure Functions, and would like to write a function that return all my Azure Websites. But needless to say I run into some problems, and documantation is still minimal.
run.ps1
# Get the input request
$in = Get-Content $req -Raw | ConvertFrom-Json
Write-Output "Loading..."
Get-AzureRmSubscription -SubscriptionId $in.SubscriptionId | Select-AzureRmSubscription
$Result = Get-AzureWebsite
Write $Result
This function take the subscription id as a parameter, and is supposed to list the available websites. But I get this exception.
2017-06-13T12:43:57.763 Get-AzureRmSubscription : Run Login-AzureRmAccount to login.
So I tried to add Login-AzureRmAccount but then I get.
2017-06-13T12:45:04.959 Login-AzureRmAccount : Error HRESULT E_FAIL has been returned from a call to a COM component.
And that is where I stand now.
Update
After help from #4c74356b41 I now am able to login. My code for logging in looks like this.
$subscriptionId = "<SubscriptionId>"
$tenantid = "<TenantId>"
$clientid = "<ApplicationId>"
$password = "<Password>"
$userPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$userCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $clientid, $userPassword
Add-AzureRmAccount -TenantId $tenantid -ServicePrincipal -SubscriptionId $subscriptionId -Credential $userCredential
I can see that this work when I test the code. But as soon as I add this line.
Select-AzureSubscription -Current -SubscriptionId $subscriptionId
I get this exception.
Select-AzureSubscription : The subscription id <SubscriptionId> doesn't exist.
Parameternavn: id
At line:11 char:1
+ Select-AzureSubscription -Current -SubscriptionId $subscriptionId
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Select-AzureSubscription], ArgumentException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.Profile.SelectAzureSubscriptionCommand
I also tried to add this line.
Get-AzureRmSubscription –SubscriptionId $subscriptionId | Select-AzureRmSubscription
Which look like is working, it only thows a warning WARNING: Unable to acquire token for tenant 'Common' but still list the correct subscription details without any exceptions.
Then when I try
Get-AzureWebsite
I get this exception.
Get-AzureWebsite : No default subscription has been designated. Use Select-AzureSubscription -Default <subscriptionName> to set the default subscription.
At line:15 char:1
+ Get-AzureWebsite
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzureWebsite], ApplicationException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.Websites.GetAzureWebsiteCommand
Well, how do you expect to work with your subscription without authenticating? would you like anybody to be able to modify your resources without any validation at all? so you need to authenticate before doing anything.
Working with powershell in Azure Function is no different from working with powershell on your machine (except module management).
To login you could use service principal auth ang login with something like:
Add-AzureRmAccount -TenantId $tenantid -ServicePrincipal -SubscriptionName $name `
-Credential ([pscredential]::new($clientid,(ConvertTo-SecureString -String $password -AsPlainText -Force)))
you can replace variables (hardcoded in the code) with environment variables.
Add 4c74356b41's answer, Get-AzureWebsite is an Azure Classic mode cmdlet. Now, you login your ARM subscription, so, it requires you login classic subscription. Select-AzureSubscription is a classic cmdlet that use to select classic subscription.
In Azure ARM mode, website is renamed Webapp, you could check Azure App Service announcement.
So, if you want to list your all webapp, you should use cmdlet Get-AzureRmWebApp.
More information please refer to this link: Using Azure Resource Manager-Based PowerShell to Manage Azure Web Apps.

Azure Runbook : What credential to use?

I'm trying to create a runbook to restart my web app. I'm new to this so I created a credential in the automation blade but I don't know what is the username/pwd is supposed to be? Is it the same with my azure login account?
Tried that and obviously when I test the runbook this error shows up :
Add-AzureAccount : unknown_user_type: Unknown User Type
At RestartJob:13 char:13
+ + CategoryInfo : CloseError: (:) [Add-AzureAccount],
AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.Profile.AddAzureAccount
Been trying to figure this out on msdn as well.. any help?
According to your description, I test in my lab. The fowwling cmdlets work for me.
$ConnectionAssetName = "shuitest"
# Get the connection
$connection = Get-AutomationConnection -Name $connectionAssetName
# Authenticate to Azure with certificate
Write-Verbose "Get connection asset: $ConnectionAssetName" -Verbose
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
if ($Conn -eq $null)
{
throw "Could not retrieve connection asset: $ConnectionAssetName. Assure that this asset exists in the Automation account."
}
$CertificateAssetName = $Conn.CertificateAssetName
Write-Verbose "Getting the certificate: $CertificateAssetName" -Verbose
$AzureCert = Get-AutomationCertificate -Name $CertificateAssetName
if ($AzureCert -eq $null)
{
throw "Could not retrieve certificate asset: $CertificateAssetName. Assure that this asset exists in the Automation account."
}
Write-Verbose "Authenticating to Azure with certificate." -Verbose
Set-AzureSubscription -SubscriptionName $Conn.SubscriptionName -SubscriptionId $Conn.SubscriptionID -Certificate $AzureCert
Select-AzureSubscription -SubscriptionId $Conn.SubscriptionID
Before you execute the runbook, you should create AssetName and Certificate on Azure Portal.
1.Certificate assets in Azure Automation
Please select your runbook-->ASSETS--Certificate.
2.Create Connection(AssetName). Please select your runbook-->ASSETS--Connections. According to your scenario, you should select AzureClassicCertificate

How to login from an Azure Resource Manager Runbook?

Using the new Azure portal, I am trying to add a powershell runbook that will start a specific VM. This is not something that will be run in powershell from my PC, it will instead run as an ARM job. I can't seem to find a way to successfully login.
If running from my desktop in powershell I can just call Login-AzureRmAccount and it will launch a login dialog before running any further steps. From what I've read on the web it seemed that what I needed to do was add a credential to my automation account, retrieve it and then call the same Login method. I've now done that, but still can't log in.
Import-Module AzureRM.Compute
$AutomationCredentialAssetName = "automation"
$Cred = Get-AutomationPSCredential -Name $AutomationCredentialAssetName
Write-Output $Cred
Login-AzureRmAccount -Credential $Cred
Start-AzureRmVm -Name 'myvmname' -ResourceGroupName 'myresourcegroupname'
The credential is being retrieved correctly (get's written to output) but the call to the Login-AzureRmAccount fails with:
Login-AzureRmAccount : unknown_user_type: Unknown User Type
At line:10 char:1
+ Login-AzureRmAccount -Credential $Cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Add-AzureRmAccount], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Common.Authentication.AadAuthenticationFailedException,Microsoft.Azure.Com
mands.Profile.AddAzureRMAccountCommand
If I don't attempt to log in first I get a message telling me to call Login-AzureRmAccount first.
How do I authenticate from within a runbook so that I can run automation tasks? What am I doing wrong?
We have subsequently discovered the the automation account created a connection when created that can be used to login:
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
At a guess you are trying to log in with a Microsoft account, which can only be done interactively (as it needs to redirect through live.com). You will need to create a user within the tenant (Active Directory) that you are authenticating against in order for non-interactive login to work.
The easiest method to make this work is to create an account in the old portal (the new portal doesn't support Active Directory management yet) and then to add that user as a co-administrator in settings > administrators.
You can create a user through Powershell, and assign much more granular permissions, but while you're working your way around things it is probably easier to stay within the portal.
There is no significant difference between a user created through the old portal and one created via AzureRm commands.
I just encountered the same problem and while the information posted here was helpful it didn't solve the problem completely.
The key insight I needed was that in order to use Azure Cmdlets one has to configure a 'Run as Account'. (See https://learn.microsoft.com/en-us/azure/automation/automation-sec-configure-azure-runas-account)
It can be set up under Account Settings section of the azure automation account.
Once you have the 'Run as Account' you can use the method proposed by BlackSpy to log in. Namely:
# Get the connection
$servicePrincipalConnection = Get-AutomationConnection -Name AzureRunAsConnection
"Logging in to Azure..."
Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $servicePrincipalConnection.TenantId `
-ApplicationId $servicePrincipalConnection.ApplicationId `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint
Hope this might help someone.
The official advice is to use a ServicePrincipal for automation - you can either use Secret or Certificate credentials with a service principal, and certificates work the best.
It is still possible to use a work or school account for automated login (Login with just -Credential), but this requires that your organization does not require two-factor authentication. It is unfortunately not possible to use a Microsoft Account for this - microsoft accounts require user interaction for any login.

Azure PowerShell automation "no default subscritpion has been designated"

I am getting the following error. I am in fact setting the default subscription name.
4/27/2015 10:28:28 AM, Error: Get-AzureVM : No default subscription
has been designated. Use Select-AzureSubscription -Default
to set the default subscription. At test:9 char:9
+
+ CategoryInfo : CloseError: (:) [Get-AzureVM], ApplicationException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.ServiceManagement.IaaS.GetAzureVMCommand
Here is my code:
workflow test
{
# Initial set up
$Cred = Get-AutomationPSCredential -Name "******"
Add-AzureAccount -Credential $Cred
Select-AzureSubscription -Default -SubscriptionName 'Beebunny'
$vmName = "MyMachineName"
Get-AzureVM -servicename $vmName
Write-output "All done."
}
If I try Select-AzureSubscription -Default 'SubscriptionName' it throws an error saying the syntax is invalid.
Edit: I have also tried Select-AzureSubscription -SubscriptionName 'SubscriptionName' without the Default flag.
Funny thing is that if I run this in AzurePS directly from Windows, it runs just fine. I am about 95% sure this is an Azure bug but wanted to get a second opinion first.
What version of the Azure module do you have loaded? Are you using the default module provided by the Automation service? Also, have you imported any other modules to this subscription?
Try creating a clean runbook with the following code, replacing the credential and subscription with the proper names. Can you get the credential and authenticate successfully?
workflow Test-GetVM
{
$Cred = Get-AutomationPSCredential -Name 'AdAzureCred'
if(!$Cred) {
Throw "Could not find an Automation Credential Asset named. Make sure you have created one in this Automation Account."
}
$Account = Add-AzureAccount -Credential $Cred
if(!$Account) {
Throw "Could not authenticate to Azure. Make sure the user name and password are correct."
}
Select-AzureSubscription -SubscriptionName "Visual Studio Ultimate with MSDN"
Get-AzureVM
}
UPDATE: Do you have the Resource Manager module loaded to the subscription as well?
I had the same problem and the solution was execute Add-AzureAccount, do the login process requested and once done all was working.

Azure Powershell to stop VM's in a subscription

I am new to Powershell, and to be specific entirely new to Azure Powershell. I need to create a powershell script to switch off all the VM's found on a subscription. I guess this needs to be done with the help of management certificate. But not sure where to start. I just done some simple lines of code to list all VM's as shown below:
Add-AzureAccount -Environment "AzureCloud"
$subscription = "my-sub-scri-ption"
Select-AzureSubscription -Current "SubName"
Set-AzureSubscription -SubscriptionName "SubName"
Get-AzureVM -ServiceName "VM1"
The output recieved is "Get-AzureVM : Value cannot be null.
Parameter name: subscriptionId".
Can someone please help me in this regard?
**EDIT:**
The powershell script which I am using is given below:
Add-AzureAccount -Environment "AzureCloud"
Set-AzureSubscription -SubscriptionName "My Subs"
$serviceName = "Service01"
$vmName = "Service01"
Get-AzureVM | Stop-AzureVM -Force
Though while running it shows script execution is successful, I can see still that vm is powered on. Please note that the serviceName and vmName is same in my case. Anything wrong here in my code?
**Re-Edit**
Executed code:
Add-AzureAccount -Environment "AzureCloud"
Set-AzureSubscription -SubscriptionName "My Subs"
$serviceName = "Service01"
$vmName = "Service01"
Get-AzureVM
Error for the above code:
Get-AzureVM : Value cannot be null.
Parameter name: subscriptionId
At D:\TC_PS\Untitled1.ps1:5 char:1
+ Get-AzureVM
+ ~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzureVM], ArgumentNullException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.ServiceManagement.IaaS.GetAzureVMCommand
You can start from here: Getting Started with Windows Azure PowerShell
Then you can simply run Get-AzureVM that will return all the virtual machines for every cloud service.
To stop a VM: Stop-AzureVM -ServiceName xxx -Name vm-test-01
To stop all the VMs in the subscription simply run: Get-AzureVM | Stop-AzureVM -Force
The -Force switch is necessary to stop the last virtual machine of the cloud service, otherwise the system would throw an error when trying to stop the last VM in the service, to avoid drop all the resources of your published app.
If you don't specify the -StayProvisioned switch, the virtual machine will be deallocated. This is the default behavior of Stop-AzureVM.