Azure automation - credentials delivered by Get-PSAutomationCredential don't work with Add-AzureAccount? - azure-powershell

I'm modifying a gallery runbook that copies a live database to a test database on a schedule. It's failing at the first hurdle; authenticating and selecting the relevatn azure subscription
The runbook looks like this:
$Cred = Get-AutomationPSCredential -Name 'automationCredential'
Write-Output "UN: $($Cred.Username)"
Add-AzureAccount -Credential $Cred
I've used the portal credentials blade to create a credential named "automationCredential". For the username and password I supplied the username/pw that I log into the azure portal with. Note: this is NOT a school/work microsoft account, but a personal one
I can tell the call to Get-PSAutomationCredential is working out, because the Write-Ouput call shows the correct value
Add-AzureAccount however, delivers the following error:
Add-AzureAccount : unknown_user_type: Unknown User Type At
Set-DailyDatabaseRestore:22 char:22 CategoryInfo :
CloseError: (:) [Add-AzureAccount], AadAuthenticationFailedException
FullyQualifiedErrorId :
Microsoft.WindowsAzure.Commands.Profile.AddAzureAccount
Any pointers how to get a working credential?

According to your description, it seems that your account is a Microsoft account(such as *#outlook.com, *#hotmail.com). Microsoft does not support non-interactive login. It is also unsafe for you to use your account to login your subscription directly. For a runbook, you could use the following codes to logon.
$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
}
}
In above code, you need use connection AzureRunAsConnection, it is created by Azure default, you could use it directly, you could check this connection, it includes your subscription information.
Also, you could create a new connection, please refer to this link.

Have you tried using the resource manager version off the login cmdlet (Add-AzureRmAccount)?

Related

Unable to connect to SQL server via PowerShell using secure password

I'm trying to connect to SQL server via PowerShell using the below (I'm new to this). I always get the error "login failed" when I use secure password (from Get-Credential or password stored in file). But if I pass the password as plaintext instead of secure string, it connects successfully. Could any one please suggest a method to pass secure password, ideally stored in an external file.
The code I ran and the error is below:
$cred = Get-Credential
$pwd = $cred.Password
$uid = $cred.UserName
$SQLServer = "."
$SQLDBName = "TestDB"
#Initialize connection string
$connString = "Data Source=$SQLServer;Database=$SQLDBName;User ID=$uid;Password=$pwd"
#Create a SQL connection object
$conn = New-Object System.Data.SqlClient.SqlConnection $connString
#Attempt to open the connection
$conn.Open()
if($conn.State -eq "Open")
{
# We have a successful connection here
# Notify of successful connection
Write-Host "Test connection successful"
$conn.Close()
}
Exception calling "Open" with "0" argument(s): "Login failed for user 'TestUser'."
At line:18 char:1
+ $conn.Open()
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SqlException
Further details of error from SQL server:
Login failed for user 'TestUser'. Reason: Password did not match that for the login provided. [CLIENT: <local machine>]
Change this
$pwd = $cred.Password
to this
$pwd = $cred.GetNetworkCredential().Password
However, I would advise against storing a plain text password in memory like this. Your method requires it to--at best--be passed as a parameter in plain text, so you need a better method.
Try using this sqlserver module which supports the -Credential parameter in the Invoke-Sqlcmd function.
I was able to pass secure string as password by adding Integrated Security = True; parameter in connection string.
Thank you.

How to enable auto scaling for SQL app in Azure Portal

I am looking to allow auto-scaling from my SQL DB app in Azure portal so that allow it to increase to 200 DTUs on a particular day and then automatically scale back down to 20. I seem to be getting confused as to how to go about it as I'm aware I will need to use Azure cli also. Any help would be much appreciated.
If you wanna scale SQL in Azure on some schedule I would recommend you to prepare Automation service with PowerShell script and schedules connected to that Runbook. Also you would need to configure Run as options.
I personally use this script to scale DB up and down on daily base.
## Authentication
Write-Output ""
Write-Output "------------------------ Authentication ------------------------"
Write-Output "Logging into Azure ..."
$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
}
}
##DB Part
$vCores = 18
$currentTier = "GP_Gen5"
$size = 200
$resourceGroup = ""
$serverName = ""
$databaseName = ""
$db_size = "GP_Gen5_4"
Write-Output "Changing DB type to GP_Gen5_4"
Set-AzureRmSqlDatabase `
-ServerName $serverName `
-ResourceGroupName $resourceGroup `
-DatabaseName $databaseName `
-RequestedServiceObjectiveName $db_size
# -RequestedServiceObjectiveName "$currentTier" + "_" + "$vCores"
Write-Output "Writing current DB parameters"
Get-AzureRmSqlDatabase `
-ServerName $serverName `
-ResourceGroupName $resourceGroup `
-DatabaseName $databaseName

Azure Powershell Workflow : Failed to convert 'System.Activities.InArgument`1[System.String]' to type 'System.String'

I have a couple of Azure Powershell Workflow runbooks that copy a production database and then run cleanup scripts against it and scale it down to generate dev and stage environemnts. I started getting the error "Failed to convert 'System.Activities.InArgument`1[System.String]' to type 'System.String'" from the parent workbook when I was editing it. I recreated the problem in a set of test runbooks: Test_Child and Test_Parent.
Test_Child is just an empty shell meant to receive a single input string.
workflow Test_Child
{
param(
[parameter(Mandatory=$True)]
[String] $Input
)
}
Test_Parent connects to Azure automation and executes the child workbook. If I run both processes in this order it fails. If I run either one separately or reverse the order of execution it succeeds.
workflow Test_Parent
{
$servicePrincipalConnection=Get-AutomationConnection -Name 'AzureRunAsConnection'
Write-Output "Logging into Azure AD ..."
Connect-AzAccount -Tenant $servicePrincipalConnection.TenantID `
-ApplicationID $servicePrincipalConnection.ApplicationID `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint `
-ServicePrincipal
try
{
Test_Child -Input "input"
}
catch
{
exit
}
}
If I execute the parent runbook I get an error.
Failed
Failed to convert 'System.Activities.InArgument`1[System.String]' to type 'System.String'.
If I remove the runbook call the process completes.
Test_Parent with runbook call removed:
workflow Test_Parent
{
$servicePrincipalConnection=Get-AutomationConnection -Name 'AzureRunAsConnection'
Write-Output "Logging into Azure AD ..."
Connect-AzAccount -Tenant $servicePrincipalConnection.TenantID `
-ApplicationID $servicePrincipalConnection.ApplicationID `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint `
-ServicePrincipal
}
Here is the output:
Logging into Azure AD ...
PSComputerName : localhost
PSSourceJobInstanceId : [My PSSourceJobInstanceId]
Environments : {AzureCloud, AzureUSGovernment, AzureChinaCloud, AzureGermanCloud}
Context : Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext
If I only call the workbook the process completes as well.
Here is the runbook Test_Parent with the Azure automation connection call removed:
workflow Test_Parent
{
try
{
Test_Child -Input "input"
}
catch
{
exit
}
}
The output
Completed
If I reverse the order of execution it completes.
workflow Test_Parent
{
try
{
Test_Child -Input "input"
}
catch
{
exit
}
$servicePrincipalConnection=Get-AutomationConnection -Name 'AzureRunAsConnection'
Write-Output "Logging into Azure AD ..."
Connect-AzAccount -Tenant $servicePrincipalConnection.TenantID `
-ApplicationID $servicePrincipalConnection.ApplicationID `
-CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint `
-ServicePrincipal
}
Output
Completed
Logging into Azure AD ...
PSComputerName : localhost
PSSourceJobInstanceId : [My PSSourceJobInstanceId]
Environments : {AzureCloud, AzureUSGovernment, AzureChinaCloud, AzureGermanCloud}
Context : Microsoft.Azure.Commands.Profile.Models.Core.PSAzureContext
Any idea why making the automation connection and then executing the workbook creates a data type mismatch error?
I had the exact same problem. In our Test environment the runbooks ran without problem. In our UAT environment, which was set up at a later time, we had the same error as you.
After some investigation I noticed that both environments used a different version of the Az.Accounts module. (2.5.2 in Test, 2.6 in UAT).
After upgrading the Az.Accounts module to 2.7.2 the issue seems to have dissapeared, so i guess it was a bug in the 2.6 version.

Get All blob names from Storage account from Runbook

I have a very simple script which absolutely works fine when run from remote powershell ISE (not using the RUNAS credentials from the Automation Runbook), but when we try to run it from Automation Runbook it returns 0 . Following is the code:-
$connectionName = "AzureRunAsConnection"
$SubId = "XXXXXXXXXXXXXXXXXX"
try
{
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
Write-Verbose "Logging in to Azure..." -Verbose
Connect-AzAccount -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint -ApplicationId $servicePrincipalConnection.ApplicationId -Tenant $servicePrincipalConnection.TenantId -ServicePrincipal
Write-Verbose "Setting Subscription......" -Verbose
Set-AzContext -SubscriptionId $SubId | Write-Verbose
}
catch {
if (!$servicePrincipalConnection)
{
$ErrorMessage = "Connection $connectionName not found."
throw $ErrorMessage
} else{
Write-Error -Message $_.Exception
throw $_.Exception
}
}
$storageAccount = Get-AzStorageAccount -ResourceGroupName $ResourceGroup -Name $StorageAccountName -ErrorAction SilentlyContinue
# Resource group name for the storage acccount
$ResourceGroup = "MYDEV01-RG"
# Storage account name
$StorageAccountName = "myDev01StrgName"
# Container name for analytics logs
$ContainerName = "`$logs"
$storageContext = $storageAccount.Context
$containers = New-Object System.Collections.ArrayList
$container = Get-AzStorageContainer -Context $storageContext -Name $ContainerName -ErrorAction SilentlyContinue |
ForEach-Object { $containers.Add($_) } | Out-Null
Write-Output("> Container count: {0}" -f $containers.Count)
Not sure if we are missing something like permissions or some other thing because of with the Automation Account (Runbook) is not working, any help?
Thank you,
After spending 24 hours on this one and staring and trying everything, it turned out that the ABOVE SCRIPT is correct and nothing is wrong in it but the STORAGE ACCOUNT's FIREWALL and NETWORK Setting were set to SELECTED NETWORK (You can either add the network IP addresses which you want to permit or select All Networks and that helped me resolve my issue). In NO WAYS I am suggesting SELECTING ALL NETWORKS but for testing we can and then add only the Selected networks and that should work.

How to run a SQL batch within an Azure runbook?

I need to execute a batch to perform some maintenance tasks in my database but all the examples on Azure Automation I see are dealing with a single SQL command.
How do I do it if creating an SP is not an option? I think I need to either somehow embed my script.sql file into a runbook script or reference it (like here, for example)?
You could store the .sql file in Azure Blob Storage, and within the runbook download the .sql file, read its contents, and pass that to the SqlCommand object.
Something like:
try {
# Connect to Azure using service principal auth
$ServicePrincipalConnection = Get-AutomationConnection -Name $AzureConnectionAssetName
Write-Output "Logging in to Azure..."
$Null = Add-AzureRmAccount `
-ServicePrincipal `
-TenantId $ServicePrincipalConnection.TenantId `
-ApplicationId $ServicePrincipalConnection.ApplicationId `
-CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint
}
catch {
if(!$ServicePrincipalConnection) {
throw "Connection $AzureConnectionAssetName not found."
}
else {
throw $_.Exception
}
}
$Path = "C:\abc.sql"
Set-AzureRmCurrentStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageAccountName
Get-AzureStorageBlobContent -Container $Container -Blob $Blob -Destination $Path
$Content = Get-Content $Path
$Cmd = New-Object System.Data.SqlClient.SqlCommand($Content, $Conn)