7

Update:

Seems like someone else had the same issue and reported it.


I am facing an issue with a simple PowerShell script when invoking it from an Azure Automation Runbook. The same piece of code works flawless when running it locally.

I have added a Service Principal in an Azure Active Directory (hosted in Azure German Cloud) with password credential and grant it contributor access to a subscription (also hosted in Azure German Cloud).

The Azure Automation service is hosted in North Europe since it's currently not available in the Azure German Cloud.

All I try to do is to login to my subscription with the above mentioned principal using the Add-AzureRmAccount cmdlet. After that I try to set the current context using the Set-AzureRmContext and getting the following error message:

Set-AzureRmContext : Please provide a valid tenant or a valid subscription.
At line:26 char:1
+ Set-AzureRmContext -TenantId $TenantId -Su ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Set-AzureRmContext], ArgumentException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.SetAzureRMContextCommand

Here is the script I try to run (left the configuration blank):

$TenantId = ""
$ApplicationId = ""
$ClientSecret = ""
$SubscriptionId = ""

$secpasswd = ConvertTo-SecureString $ClientSecret -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($ApplicationId , $secpasswd)

Add-AzureRmAccount -ServicePrincipal -Environment 'AzureGermanCloud' -Credential $mycreds -TenantId $TenantId
Set-AzureRmContext -TenantId $TenantId -SubscriptionId $SubscriptionId

I also tried to use Login-AzureRmAccount without success. Also I am able to use the Get-AzureRmResourceGroup cmdlet to retrieve the resource groups so the login seems to work.

All Azure modules are updated to the latest version.


TLTR:

My main goal is to start a SQL export job using the New-AzureRmSqlDatabaseExport from the runnbook but it seems like the above mentioned error causes the cmdlet to fail with the following message:

New-AzureRmSqlDatabaseExport : Your Azure credentials have not been set up or have expired, please run 
Login-AzureRMAccount to set up your Azure credentials.
At line:77 char:18
+ ... rtRequest = New-AzureRmSqlDatabaseExport -ResourceGroupName $Resource 
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • so if the login works, why do you needs `set-azurermcontext`? just add `-SubscriptionId` to `add-azurermaccount` – 4c74356b41 Sep 26 '17 at 13:42
  • @4c74356b41 Because the `New-AzureRmSqlDatabaseExport` will still throw that exception. I tried to provide a minimal example to reproduce my issue and I think the answer why the `Set-AzureRmContext` doesn't work will help me with my main goal. – Martin Brandl Sep 26 '17 at 13:45
  • why would it still do that? – 4c74356b41 Sep 26 '17 at 13:47
  • @4c74356b41 If I knew that I would not asked that question. I tried it already. Also when I try to get the subscription using the `Get-AzureRmSubscription` with the `-SubscriptionId` and `-TenantId` parameter, I receive the message `Subscription xxx was not found in tenant ` – Martin Brandl Sep 26 '17 at 13:52
  • wrong tenantid or subscriptionid? – 4c74356b41 Sep 26 '17 at 13:56
  • No, as I mentioned, it does run locally. Both ids are correct. – Martin Brandl Sep 26 '17 at 14:05
  • by default every automation account has 2 runas accounts...i always use the one with the certificate ...so is that not an option for u? – Kiran Reddy Sep 26 '17 at 16:46
  • @Kiran I wan't to login from a runbook hosted in North Europe to a subscription hosted in Azure German Cloud. So unfortunately no. – Martin Brandl Sep 26 '17 at 18:02
  • @MartinBrandl Do you try `Add-AzureRmAccount -ServicePrincipal -Environment 'AzureGermanCloud' -Credential $mycreds -TenantId $TenantId -SubscriptionId $subscriptionId`? When you login use specified subscription id. – Shui shengbao Sep 27 '17 at 05:33

4 Answers4

3

I had the same issue a few weeks ago and what worked was to first login to Azure account (which I think you already did) using:

Login-AzureRmAccount

Then get the subscription ID from Azure and use select the subscription using the ID instead of the name as follows:

Select-AzureRmSubscription -SubscriptionId {insert-subscription-id}
Clive Ciappara
  • 558
  • 5
  • 11
  • Thanks Clive, I will give it a try and come back to you – Martin Brandl Sep 26 '17 at 14:05
  • You're welcome, just in case you might also try to do this: "Add-AzureAccount" which logs on to your Azure account and adds your account. – Clive Ciappara Sep 26 '17 at 14:06
  • Thanks for that hint but I doubt it will help since I am using Azure Resource Manager (RM) cmdlets. – Martin Brandl Sep 26 '17 at 14:08
  • Unfortunately I get the error message: `Select-AzureRmSubscription : Please provide a valid tenant or a valid subscription` – Martin Brandl Sep 26 '17 at 14:22
  • Can you change the Service Principal role to owner from contributor just to make sure it's not a permission issue? Although a contributor should be able to manage everything as well. Or else is it possible to run "Login-AzureRmAccount" again and use the account created for the service principal locally? – Clive Ciappara Sep 26 '17 at 14:36
  • 1
    I tried to set the permission to owner but receiving the same error (also the script works locally). The New-AzureRmSqlDatabaseExport doesn't take any context parameter so your second idea won't help me. But thanks a lot for your effort. – Martin Brandl Sep 26 '17 at 16:05
  • @CliveCiappara. Thank you Just don't understand why in microsoft documentation they can give one line of example like that . The documentation is too verbose and still does not cover the basic use cases. – rmehra76 Jan 04 '21 at 17:48
3

Below is the code that worked for me (regular dc regions). If it doesn't work, go to the Automation Account >> Modules >> Update Azure Modules.

$ClientSecret = ""
$ApplicationId = ""
$SubscriptionId = ""

#New PSCredential Object
$secpasswd = ConvertTo-SecureString $ClientSecret -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($ApplicationId , $secpasswd)

#Login to subscription
Login-AzureRmAccount -Credential $mycreds -SubscriptionId $SubscriptionId

#Export Database
New-AzureRmSqlDatabaseExport -ResourceGroupName "<RG>" -ServerName "<SQLSERVERNAME>" -DatabaseName "<DATABASENAME>" -StorageKeyType "StorageAccessKey" -StorageKey "<STRKEY>" -StorageUri "<URITOFILE>" -AdministratorLogin "<DBLOGIN>" -AdministratorLoginPassword "<DBPASS>"

Update

Maybe running with a Run As Account can be a workaround for the issue. Create one by navigating to the Azure Automation Account >> Account Settings >> Run As Accounts. Here's an example code.

# Authenticate to Azure with service principal and certificate, and set subscription
$connectionAssetName = "AzureRunAsConnection"
$conn = Get-AutomationConnection -Name $ConnectionAssetName

Add-AzureRmAccount -ServicePrincipal -Tenant $conn.TenantID -ApplicationId $conn.ApplicationId -CertificateThumbprint $conn.CertificateThumbprint -ErrorAction Stop | Write-Verbose
Set-AzureRmContext -SubscriptionId $conn.SubscriptionId -ErrorAction Stop | Write-Verbose
Bruno Faria
  • 5,219
  • 3
  • 24
  • 27
  • Thanks for your effort. Im not storing my sensitive data in the script code, this is just an example to reproduce that issue. Also the login using `Login-AzureRmAccount` or `Add-AzureRmAccount` does work without any issue (as I wrote). So this doesn't solve my issue. – Martin Brandl Oct 02 '17 at 07:52
  • There's nothing else you need to do. I included the New-AzureRMSqlDatabaseExport cmdlet as well. Fully tested. Working as expected with just the code I provided. – Bruno Faria Oct 02 '17 at 08:29
  • Did you read my question? I have a script that runs without any issues locally. But when I run it within an Azure Automation Runbook, I receive an error. The issue is probably related with the fact that the resources are located in MCD (Microsoft Cloud Deutschland) and the Runbook is hosted within the North Europe Cloud. Or maybe something else. When you tell me that is nothing else I need, it doesn't solve my issue. – Martin Brandl Oct 02 '17 at 08:36
  • It doesn't matter where your resources are, and yes I read your question and yes I replicated your environment to test. I tested through Automation, not on my local machine. Good luck. – Bruno Faria Oct 02 '17 at 08:55
  • 1
    Sorry Bruno, I was a little bit rude. Thanks for your effort. Unfortunately this doesn't work in my environment. I also tried to setup a new automation account without success. If I will try to setup a new service principal if I don't find another solution but the strange thing is that the same script works when executed locally. Best regards – Martin Brandl Oct 03 '17 at 13:26
  • hm. strange. I don't know what we are missing. It's supposed to be straightforward. Are you sure this credential has access to the subscription? I assume when you run locally, you're using the same principal account, right? – Bruno Faria Oct 04 '17 at 09:07
  • Yes, thats why I currently store the credentials within the code. If I execute the script locally, everything is working fine. When I copy paste it (without any changes) to a runbook (already tried to create a second account), I get an error. – Martin Brandl Oct 04 '17 at 09:12
  • I found a report on feedback.azure.com (I edited my question). Unfortunately there is no answer to this. – Martin Brandl Oct 04 '17 at 09:21
  • Do you think you can try with a Run As Account just in case? https://learn.microsoft.com/en-us/azure/automation/automation-create-runas-account – Bruno Faria Oct 04 '17 at 09:23
  • I can give it a try. Unfortunately the script doesn't support AzureGermanCloud so I probably have to adopt it first. I don't have time for that today but maybe tomorrow. Anyhow, thanks a lot for your effort! – Martin Brandl Oct 04 '17 at 09:32
  • Sorry, it's better if you do it through the portal. Just navigate to the automation account >> scroll down to account settings >> run as account >> create. If you already have one, just use it instead. I've updated my answer with an example of certificate-based authentication. – Bruno Faria Oct 04 '17 at 10:04
  • Im trying to work with resources within the AzureGermanCloud. But there is no Azure Automation Service available there yet. So I can't create the RunAsAccount through the portal. I can try to create the RunAsAccount using PowerShell in the AzureGermanCloud and add the Assets in the Automation Account in NorthEurope. – Martin Brandl Oct 04 '17 at 10:35
  • I don't have experience with sovereign Azure datacenters such as German Cloud, but I'm checking with some folks from Microsoft what's the catch here. Hopefully, we will have an answer for this. – Bruno Faria Oct 04 '17 at 11:01
  • Thanks Bruno. Looking forward for your feedback. Meanwhile I try to create a runasaccount with certificate. – Martin Brandl Oct 04 '17 at 11:52
  • I invested the time now and created a RunAsAccount with client certificate in the german cloud and added the asset to the automation account manually. Your solution almost works and you guided me to the right path thus I gave you the reputation. Thanks a lot. I answered the question myself since I wanted to describe both workarounds and also I had to use Login-AzureRmAccount. – Martin Brandl Oct 04 '17 at 14:26
2

It looks like this is a known issue and I wasn't able to find a fix for that. But there are two workarounds:

  1. Using a Hybrid Runnbook Worker (mentioned by Walter - MSFT)
  2. Using a RunAsAccount with certificate credentials (mentioned by Bruno Faria)

It is important to specify the -Environment parameter. Otherwise I got the following exception:

Login-AzureRmAccount : AADSTS90038: Confidential Client is not supported in Cross Cloud request.

Here is the code I am using to login to AzureGermanCloud (MCD) from an Azure Runbook hosted in NorthEurope:

$connectionAssetName = "AzureRunAsConnection"
$conn = Get-AutomationConnection -Name $ConnectionAssetName

Login-AzureRmAccount `
    -ServicePrincipal `
    -CertificateThumbprint $conn.CertificateThumbprint `
    -ApplicationId $conn.ApplicationId `
    -TenantId $conn.TenantID `
    -Environment AzureGermanCloud
Martin Brandl
  • 56,134
  • 13
  • 133
  • 172
  • Glad it worked. I'm still chasing Microsoft about this. Not sure if it's a bug or a "feature" (aka known limitation). It's been there for quite a while now, so they should be aware of this. – Bruno Faria Oct 04 '17 at 21:47
1

When you login your Azure account, you could use specified subscription id. You could try following script.

$subscriptionId=""
$tenantid=""
$clientid=""
$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 -Environment 'AzureGermanCloud'
Shui shengbao
  • 18,746
  • 3
  • 27
  • 45
  • Sorry Walter for my late reply. Unfortunately this doesn't change anything. I also put a `Get-AzureRmSubscription` after the last line and getting this exception: `Get-AzureRmSubscription : Subscription XXX was not found in tenant . Please verify that the subscription exists in this tenant.` – Martin Brandl Sep 29 '17 at 16:47
  • 1
    @MartinBrandl Another solution for your scenario, maybe you could use [`Hybrid Runbook Worker`](https://learn.microsoft.com/en-us/azure/automation/automation-hybrid-runbook-worker). Run your runbook in your local VM. – Shui shengbao Oct 02 '17 at 02:08
  • Yes Walter, the script works on my local computer. While your second approach could work, I realy don't wan't to use / try it. – Martin Brandl Oct 02 '17 at 07:53
  • I found the same issue reported [here](https://feedback.azure.com/forums/246290-automation/suggestions/16304161-add-azurermaccount-doesn-t-work-with-service-princ) – Martin Brandl Oct 04 '17 at 09:22
  • Hi Walter, the best workaround I found was to create a RunAsAccount with certificate credentials. I answered my own question and also added your hint with the Hybrid Runbook Worker. Thanks a lot for your effort. – Martin Brandl Oct 04 '17 at 14:27