There are several Runbooks examples in the Azure Runbook Gallery, such as:
Deploy a Windows Azure Web Site Pointing to a SQL Database and Storage Account
that use the following syntax with Get-Credential:
$credential = Get-Credential
which implies that the command should prompt for the credentials -- but this fails in a Runbook with the following message:
Get-Credential : Cannot process command because of one or more missing mandatory parameters: Credential.
The credentials that are desired here are for this purpose:
# Get credentials from user to setup administrator access to new SQL Azure Server
which then should get used in downstream cmdlet calls in the Runbook such as
$databaseServer = New-AzureSqlDatabaseServer -AdministratorLogin $credential.UserName `
-AdministratorLoginPassword $credential.GetNetworkCredential().Password -Location $Location
But because Get-Credential fails the downstream calls fail.
What I am doing wrong?
Why does a Runbook in the Gallery have statements that seem to be incompatible (prompt for Credentials) with allowable Runbook behaviors?
So with Azure Automation, you would create a credential asset (for example, named AzureAdmin) and then you would reference that in the runbook, to get those credentials:
$cred = Get-AutomationPSCredential -Name AzureAdmin
As for the reference script, I suppose, it was just added to the runbook gallery without any verification, so in reality its not Azure Automation friendly
Related
I have a powershell script that attempts to retrieve a secret stored in Azure key vault using this command.
$password = (Get-AzureKeyVaultSecret -vaultName $vaultName -name $secretName).SecretValueText
It is working perfectly fine when I execute my powershell script locally. But, when I try to do the same on Azure Devops, it fails giving below error.
[error]Operation returned an invalid status code 'Forbidden'
I feel it isn't an access policy issue, as I am able to successfully perform read/write on my vault using powershell script running locally.
I'm quite sure it is a access policy issue.
Go to your DevOps Project Settings - Pipelines - Service Connections and click on "Update Service Connection" (Use the full version of the dialog). There you can find the Subscription Id and Service Principal ID.
You then have to give explicit permissions to this SPN:
Login-AzureRmAccount -subscription <YourSubscriptionID>
$spn= Get-AzureRmADServicePrincipal -spn <YourSPN>
Set-AzureRmKeyVaultAccessPolicy -VaultName <YourVaultName> -ObjectId $spn.Id -PermissionsToSecrets get,list;
TL;DR
In summary the steps are:
Use the correct code (the last code in this post)
Manually add your app id in SSMS as either a server administrator or a database administrator
and then you can process an Azure Analysis Services cube from an Azure Automation Account without needing to create another seperate service account
Actual Question:
I am trying to process an Azure Analysis Services cube using the Azure Automation RunAs Service Principal. This is run within an Azure automation account
This code
#Get the existing AzureRunAsConnection connection
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
# Login with service principal account
Login-AzureRMAccount
-ServicePrincipal
-Tenant $Conn.TenantID
-ApplicationId $Conn.ApplicationID
-CertificateThumbprint $Conn.CertificateThumbprint
# Process cube
Invoke-ProcessASDatabase -databasename "DB" -server "Server" -RefreshType "Full"
Results in
Authentication failed: User ID and Password are required when user interface is not
available.
My understanding is that when you create an Azure Automation Account, it also creates a 'RunAs' account, which in turn creates a service principal account. (Although the doco seems a bit light on)
I have tried finding this principal account in Azure AD and adding it to SSAS Admins in the Azure portal, but I can't find the actual account. Do service principals actually appear as accounts?
The code below works fine, but it uses a pre saved credential but I don't want to have to manage yet another account.
# Purpose: Run a full process the SSAS cube
$AzureCred = Get-AutomationPSCredential -Name "MyCredential"
Add-AzureRmAccount -Credential $AzureCred | Out-Null
Invoke-ProcessASDatabase -databasename "MyDB" -server "MyServer" -RefreshType "Full" -Credential $AzureCred
Update 1
I have also tried manually adding these in the SSMS membership area (after looking up the guids in the RunAs Account area in the automation account):
app:applicationid#tenantid
obj:serviceprincipalobjectid#tenantid
and I get the same error message.
I also ran the script with a non-admin user and got
The "zzz" database does not exist on the server.
So it would appear my issue is authentication, not authorisation. In other words it's not that I don't access, it's that I can't log in. I'm thinking based on that error, that -credential is not optional when calling Invoke-ProcessAsDatabase against Azure Analysis services
Also, I note that for the -credential option, the help says
If no credentials are specified, the default Windows account of the user running the script is assume
Given that Azure Analysis Services appears to only be able to use SQL credentials when connecting to a data source (no kind of AD credentials), I can only surmise that Azure Analysis Services is unable to use any kind of Azure Ad authentication for internal processes.
The annoying thing is that this isn't stated anywhere.
Update 2
So I did not read the link carefully enough. The code that works is mostly on the site posted by both answerers here. To pre authenicate to Azure Analysis Server you need to use Add-AzureAnalysisServicesAccount (The linked blog uses Login-AzureAsAccount but I couldn't get it working and couldn't find doco). You need to install powershell module "Azure.AnalysisServices" to use this.
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Add-AzureAnalysisServicesAccount -RolloutEnvironment "australiasoutheast.asazure.windows.net" -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint
Invoke-ProcessASDatabase -databasename "MYDB" -server "MyServerEndpoint" -RefreshType "Full"
You can use the RunAs account with this, and afterwards you don't need to use -credential
So.. this actually works and logs in without needing a seperate credential, but now it doesn't have access to the database. Instead of a login error, I get
The "ZZZZ" database does not exist on the server.
I would appear that the RunAs account has access to the server but not the database and I can't work out to find it to give it access.
Update 3:
This is a more direct guide on how to give the app access to the model so it can be built:
Azure analysis service connection using Service principal not working
Note you can't add in the Azure portal as it won't find it. Add it "manually" in SSMS and it will work, and it will also appear in the Azure Portal as an admin
It all works now.
Update 4:
This has become a handy spot to store my discoveries around authenticating through MSI
Although this question is solved, no I want to connect to SQL Azure from something else using MSI security. No connection string supports this - none of the authentication methods in any connection string support MSI authentication. I did find this interesting link which implies you can create a connection string that supports authentication as MSI:
https://learn.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi
The bit of code of interest is:
az webapp config connection-string set
--resource-group myResourceGroup
--name <app name>
--settings MyDbConnection='Server=tcp:<server_name>.database.windows.net,1433;Database=<db_name>;'
--connection-string-type SQLAzure
I can't find any reference to the parameter --connection-string-type. But it looks like you simply exclude the authentication piece altogether.
In your example 1, it seems not your login Azure Login-AzureRMAccount get the error log. Based on my knowledge, Invoke-ProcessASDatabase is not a Azure Power Shell cmdlet. In fact, you no need to login your Azure subscription. Only Invoke-ProcessASDatabase -databasename "MyDB" -server "MyServer" -RefreshType "Full" -Credential $AzureCred should works for you.
Yes if I supply a credential it works, but I want to use the RunAs
credential. If I can't, then what is the point of it.
RunAs credential only works for login your Azure subscription, it does not stores credential for your SQL. In your scenario, you could store your SQL credential in runbook PSCredential, like your example2. In fact, in your example, you could remove Add-AzureRmAccount -Credential $AzureCred | Out-Null.
Update:
You should use following script in runbook.
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Login-AzureASAccount -RolloutEnvironment "southcentralus.asazure.windows.net" -ServicePrincipal -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint -TenantId $Conn.TenantID
Invoke-ProcessTable -Server "asazure://southcentralus.asazure.windows.net/myserver" -TableName "MyTable" -Database "MyDb" -RefreshType "Full"
More information about this please check this blog.
Per the official documentation:
Once the service principal is created, its application ID can be assigned permissions in the Azure Analysis Services server or model roles using the following syntax. The example below adds a service principal to the server administrators group in SSMS.
I didn't see the use of Run-as option, i'd recommend checking this blog
It also contains information about storing credentials in azure automation, this will help you in not hard writing credentials in the code.
I want to execute a runbook from subscription A which will create a storage a/c on subscription B. I provided the (Username/Password) of subscription B in credential asset.
Firstly, please let me know is it possible to do that ?
When i try to run the below code, it gives an error "Unable to acquire token for tenant 'Common' " when i run Get-AzureRmSubscription
$CredentialAssetName = "login";
$Cred = Get-AutomationPSCredential -Name $CredentialAssetName
if(!$Cred) {
Throw "Could not find an Automation Credential Asset named
'${CredentialAssetName}'. Make sure you have created one in this Automation
Account."
}
add-azurermaccount -credential $Cred
login-AzureRMAccount -Credential $Cred
Select-AzureRmSubscription -SubscriptionName 'Free Trial'
get-azurermsubscription
Unable to acquire token for tenant 'Common'
It just a WARNING, that will not affect your script.
please let me know is it possible to do that?
Yes, it is possible, we can use Azure runbook to login subscription B, and use PowerShell to create an Azure storage account in that subscription.
Runbook just like PowerShell, when we use subscription B to log in, the script will work on subscription B.
If subscription B is a Microsoft account, we can follow this answer to login Azure runbook. (Microsoft account does not support non-interactive login.)
I have this Azure Powershell script, which successfully backs up a SQL Azure DB to Azure Blob.
In its current form, it requires me to log in via AD.
I now need to implement this script to execute via a Azure Function at specific intervals.
The first snippet of the script:
$subscriptionId = "YOUR AZURE SUBSCRIPTION ID"
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId $subscriptionId
I thus need to not use Login-AzureRmAccount, but replace it with a method that does not require human input.
I have found this link:
https://cmatskas.com/automate-login-for-azure-powershell-scripts/
In short, the author:
Creates an Azure AD Application (with its own password)
Creates a Service Principal
Assigns Permissions to the Service Principal
This is a once-off manual creation - which is perfect.
The author then logs in to this newly created application
$psCred = New-Object System.Management.Automation.PSCredential($azureAccountName, $azurePassword)
Add-AzureRmAccount -Credential $psCred -TenantId e801a3ad-3690-4aa0-a142-1d77cb360b07 -ServicePrincipal
My questions:
Is this what I should do to be able to automate my application and prevent human login?
This Azure AD app created in step 1 - can I use this app as a starting point in my of my Azure functions?
Yes, you can use that route, or use certificate auth, or use an Azure AD user, it can login with user\password, but is considered less secure than service principal.
Yes, you can use one service principal for any number of Azure Functions you would like to.
To use Azure PowerShell in Azure Functions, you may refer to the following response in another SO thread. The example is an HTTP-Trigger, but you can modify it to use a Timer-Trigger for your use-case. Here's the link:
Azure Function role like permissions to Stop Azure Virtual Machines
Run PowerShell as Administrator, you need to install AzureRM in PowerShell,
Login to Azure
Login-AzureRmAccount
Enter your Azure credentials
To get your subscription(s) details
enter
Get-AzureRmSubscription
Use the subscription id to select the subscription.
Select-AzureRmSubscription -SubscriptionId xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Save the AzureProfile using the below command
Save-AzureRmProfile -Path "C:\AzureScripts\profile.json"
The json file can be used to login to Azure
Select-AzureRmProfile -Path "C:\AzureScripts\profile.json"
Put this line on top of you .ps1 file, you does not require human input.
Ref : http://www.smartcoding.in/blog/auto-login-azure-power-shell
I'm trying to create an Azure Automation job to create a standard set of tags/values in a subscription.
Working with Tags requires AzureResourceManager, which is not available in Automation out of the box (Go vote for this feedback item!), so I followed these steps to upload the ARM module.
When I test my runbook I get the following output:
-------------------------
PSComputerName : localhost
PSSourceJobInstanceId : a8b85213-ee0f-40ea-842f-d33f2e87c910
Id : xxxxx-56ad-42c2-97f4-e364456fc4a6
Name : xxxxx
Environment : AzureCloud
Account : my-service-principal-app-id
Properties : {Default, Tenants, SupportedModes}
-------------------------
New-AzureTag : Your Azure credentials have not been set up or have expired, please run Add-AzureAccount to set up your
Azure credentials.
At Add-SubscriptionTags:41 char:41
+
+ CategoryInfo : CloseError: (:) [New-AzureTag], ArgumentException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Tags.Tag.NewAzureTagCommand
Here's my runbook:
workflow Add-SubscriptionTags
{
param
(
# Subscription
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]
$SubscriptionName
)
# Get the PowerShell credential and prints its properties
$cred = Get-AutomationPSCredential -Name 'AzureMaint'
# Connect to Azure
Add-AzureAccount -Credential $cred -ServicePrincipal -Tenant 'xxx-49ab-8a9c-4abce32afc1e' | Write-Verbose
# Set subscription
$subscription = Select-AzureSubscription -SubscriptionName $SubscriptionName -PassThru
write-output '-------------------------'
write-output $subscription
write-output '-------------------------'
# Add tags (Requires AzureResourceManager module)
New-AzureTag -Name 'Managed' -Value $true
New-AzureTag -Name 'Managed' -Value $false
}
The AzureMaint PSCredential contains a service principal ID and key, and the service principal has been granted the Contributor role on the specified subscription. I can do Add-AzureAccount in the ISE with those credentials and add tags just fine. Since it successfully prints the subscription info I assume that means Add-AzureAccount was successful, so why do I get the error?
Update:
I created a new Automation Account without the ARM module and I'm still having the same issue, although the error message is slightly different:
Your Azure credentials have not been set up or have expired, please run Add-AzureAccount
to set up your Azure credentials. (Your Azure credentials have not been set up or
have expired, please run Add-AzureAccount to set up your Azure credentials. (Unable
to retrieve service key for ServicePrincipal account xxx-4a00-becf-952fda93edc5.
Please run the Add-AzureAccount cmdlet to supply the credentials for this service principal.))
So now I'm wondering if it doesn't like me using a Service Principal?
Just to update here, we've discovered that service principal authentication does not work in Azure Automation currently. Given you are trying to use a service principal, that is the reason for the issues you are hitting.
For now, a user principal should be used to work around this issue.
Please see the following for more info:
Authenticating to Azure Resource Manager with a Service Principal in Azure Automation
https://github.com/Azure/azure-powershell/issues/655
Using ARM cmdlets in Azure Automation is not officially supported yet. That said, various people have been successful doing so. Are your ARM and Azure PowerShell modules the same version? Weird things can happen if they are loaded side by side but are not the same version.