Error Message when Running Azure Automation Runbook - powershell

I'm trying to create an Azure Automation Runbook to write messages to an existing Azure Storage Queue using information from a SQL Query. The below works perfectly in Powershell ISE on my Windows 10 machine, but I'm getting an error when testing it in Azure the Automation.
The script is:
Connect-AzureRmAccount
Get-AzureRmSubscription
Set-AzureRmContext -SubscriptionId <our subscription id>
$resourceGroup = "our resource group"
$storageAccountName = "our storage account name"
$queueName = "our queue name"
$queue = Get-AzureRmStorageQueueQueue -resourceGroup $resourceGroup -storageAccountName $storageAccountName -queueName $queueName
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "our Azure SQL connection string"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $("SELECT SourceId FROM dbo.batches GROUP BY SourceId HAVING SourceId > 101")
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$Table = new-object system.data.datatable
$SqlAdapter.Fill($Table) | out-null
$SqlConnection.Close()
$compArray = #($Table | select -ExpandProperty SourceId)
foreach ($array in $compArray) {
Add-AzureRmStorageQueueMessage -queue $queue -message #{"SourceId"=$array;"RetryCount"=0;}
}
Again, this works perfectly in Powershell on my local machine, but in Azure Automation, I get this error:
Failed
Queue <our queue name> could not be retrieved/created from Storage Account <our storage account> on resource group (Queue <our queue name> could not be retrieved/created from Storage Account <our storage account> on resource group )
Set-AzureRmContext : Run Connect-AzureRmAccount to login.
At line:3 char:1
+ Set-AzureRmContext -SubscriptionId <our subscription id> ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Set-AzureRmContext], PSInvalidOperationException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.SetAzureRMContextCommand
Get-AzureRmStorageAccount : No subscription found in the context. Please ensure that the credentials you provided are
authorized to access an Azure subscription, then run Connect-AzureRmAccount to login.
At C:\Modules\User\AzureRmStorageQueue\AzureRmStorageQueueCoreHelper.psm1:86 char:19
+ ... aContext = (Get-AzureRmStorageAccount -ResourceGroupName $resourceGro ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzureRmStorageAccount], ApplicationException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Management.Storage.GetAzureStorageAccountCommand
Get-AzureStorageQueue : Could not get the storage context. Please pass in a storage context or set the current storage
context.
At C:\Modules\User\AzureRmStorageQueue\AzureRmStorageQueueCoreHelper.psm1:88 char:94
+ ... ue]$queue = Get-AzureStorageQueue -Name $queueName -Context $saContex ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzureStorageQueue], InvalidOperationException
+ FullyQualifiedErrorId :
InvalidOperationException,Microsoft.WindowsAzure.Commands.Storage.Queue.GetAzureStorageQueueCommand
New-AzureStorageQueue : Could not get the storage context. Please pass in a storage context or set the current storage
context.
At C:\Modules\User\AzureRmStorageQueue\AzureRmStorageQueueCoreHelper.psm1:92 char:95
+ ... ue]$queue = New-AzureStorageQueue -Name $queueName -Context $saContex ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzureStorageQueue], InvalidOperationException
+ FullyQualifiedErrorId :
InvalidOperationException,Microsoft.WindowsAzure.Commands.Storage.Queue.NewAzureStorageQueueCommand
Could someone assist me in what I'm missing here? (I have confirmed that the AzureRmStorageQueue module is installed in Azure Automation.)

In the azure runbook, no need to use the interactive login, if you create an automation account, it will create a service principal and add it to your subscription as a contributor role automatically. So you just need to use the service principal to do what you need.
The command should be like as below, you could try it.
$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
}
}
$resourceGroup = "our resource group"
$storageAccountName = "our storage account name"
$StorageAccountKey = (Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroup -AccountName $storageAccountName).Value[1]
$context=New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
$queueName = "our queue name"
$queue = Get-AzureRmStorageQueueQueue -resourceGroup $resourceGroup -storageAccountName $storageAccountName -queueName $queueName -Context $context
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "our Azure SQL connection string"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $("SELECT SourceId FROM dbo.batches GROUP BY SourceId HAVING SourceId > 101")
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$Table = new-object system.data.datatable
$SqlAdapter.Fill($Table) | out-null
$SqlConnection.Close()
$compArray = #($Table | select -ExpandProperty SourceId)
foreach ($array in $compArray) {
Add-AzureRmStorageQueueMessage -queue $queue -message #{"SourceId"=$array;"RetryCount"=0;}
}

Related

Cannot find an overload for “ExecuteQuerySegmentedAsync” and the argument count: “2” in Get-AzTableRow

I am trying use the Get-AzTableRow to retrieve a Azure Table row, followed by updating it. But the cmdlet is throwing the below errors:
PS C:\WINDOWS\system32> Get-AzTableRow -ColumnName "NsgName" -Value "subnet1invnet4-nsg" -Operator "Equal"
You cannot call a method on a null-valued expression.
At C:\Users\sayghosh\Documents\WindowsPowerShell\Modules\AzTable\2.0.2\AzureRmStorageTableCoreHelper.psm1:52 char:4
+ $Results = $Table.ExecuteQuerySegmentedAsync($TableQuery, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
PS C:\WINDOWS\system32> Get-AzTableRow -table $storageCloudTable
Cannot find an overload for "ExecuteQuerySegmentedAsync" and the argument count: "2".
At C:\Users\sayghosh\Documents\WindowsPowerShell\Modules\AzTable\2.0.2\AzureRmStorageTableCoreHelper.psm1:52 char:4
+ $Results = $Table.ExecuteQuerySegmentedAsync($TableQuery, ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Any lead here will be helpful.
Check out the below script to set the storage context and using cloudtable to read the table row and updating it.
#To install the AzTable module if not already installed
#Install-Module AzTable
#set the subscription contenxt if not already set
#Set-AzContext -Subscription "Subscription Name"
$storageAccountName = "storageaccountName"
$tableName = "storagetableName"
$partitionKey1 = "partitionKey"
$resourceGroup = "ResourceGroup Name"
$storageAccount = Get-AzStorageAccount -ResourceGroupName $resourceGroup -Name $storageAccountName
# Get the Storage Contenxt
$ctx = $storageAccount.Context
# Usage of CloudTable is mandatory when working with AzTable PowerShell module.
$cloudTable = (Get-AzStorageTable -Name $tableName -Context $ctx ).CloudTable
# different ways to get the table row
#Get-AzTableRow -table $cloudTable -customFilter "(username eq 'bob2')"
#Get-AzTableRow -Table $cloudTable -ColumnName "username" -Value "bob2" -Operator Equal
#Create a filter and get the entity to be updated.
[string]$filter = [Microsoft.Azure.Cosmos.Table.TableQuery]::GenerateFilterCondition("username",
[Microsoft.Azure.Cosmos.Table.QueryComparisons]::Equal,"bob2")
$user = Get-AzTableRow -table $cloudTable -customFilter $filter
# Change the entity.
$user.username = "james"
# To commit the change, pipe the updated record into the update cmdlet.
$user | Update-AzTableRow -table $cloudTable
# To see the new record, query the table.
Get-AzTableRow -table $cloudTable -customFilter "(username eq 'james')"`
Additional Documentation reference
Hope this helps.

Insert document in Cosmos DB using PowerShell (SQL API)

I'm getting an error when I am trying to insert data in Cosmos DB collection having Partition Key.
Without Partition key, it's working fine
$resourceGroupName = "myrg"
$cosmosDbAccountName = "mydb"
$databaseName = "test"
$cosmosDbContext = New-CosmosDbContext -Account $cosmosDbAccountName -
Database $databaseName -ResourceGroup $resourceGroupName
New-CosmosDbCollection -Context $cosmosDbContext -Id 'events' -OfferThroughput 1000 -PartitionKey 'RuleType' -DefaultTimeToLive 604800
$document = #"
{
"id": "$([Guid]::NewGuid().ToString())",
"createTime": "2018-05-21T22:59:59.999Z",
"RuleType": "FTOD"
}
"#
New-CosmosDbDocument -Context $cosmosDbContext -CollectionId 'events' -
DocumentBody $document -PartitionKey 'RuleType'
"RuleType": This is my Partition Key
Invoke-WebRequest : The remote server returned an error: (400) Bad Request.
At C:\Program Files\WindowsPowerShell\Modules\CosmosDB\2.1.4.536\lib\utils.ps1:554 char:30
+ ... estResult = Invoke-WebRequest -UseBasicParsing #invokeWebRequestParam ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Anyone know about this??
I reproduced your issue on my side.
Based on parameter list which Get-Help New-CosmosDbDocument command shows:
You need to add partitionkey and you could insert document successfully.
$resourceGroupName = "***"
$cosmosDbAccountName = "***"
$databaseName = "db"
$cosmosDbContext = New-CosmosDbContext -Account $cosmosDbAccountName -Database $databaseName -ResourceGroup $resourceGroupName
$document = #"
{
"id": "6fa9b3d5-ce1a-4b38-9068-9d17de5b1c69",
"createTime": "2018-05-21T22:59:59.999Z",
"RuleType": "FTOD"
}
"#
$partitionkey = "FTOD"
New-CosmosDbDocument -Context $cosmosDbContext -CollectionId 'part' -DocumentBody $document -PartitionKey $partitionkey
Hope it helps you.

Retrieve Azure Service Bus Shared Access Connection String via Powershell

It's possible to retrieve the access key to an Azure storage account using Get-AzureRmStorageAccountKey from Powershell. How would I get hold of the access key to a shared access policy of an Azure Service Bus?
More clarification
This is what I get when I use the Get-AzureRmServiceBusNamespaceKey cmdlet:
PS C:\Windows\system32> Login-AzureRmAccount -Credential $cred
Environment : AzureCloud
Account : ***redacted***
TenantId : ***redacted***
SubscriptionId : ***redacted***
CurrentStorageAccount :
PS C:\Windows\system32> Set-AzureRmContext -SubscriptionId ***redacted***
Environment : AzureCloud
Account : ***redacted***
TenantId : ***redacted***
SubscriptionId : ***redacted***
CurrentStorageAccount :
PS C:\Windows\system32> Get-AzureRmServiceBusNamespaceKey -ResourceGroup testresourcegroup -Name test-bus -AuthorizationRuleName SendPolicy
Get-AzureRmServiceBusNamespaceKey : Run Login-AzureRmAccount to login.
At line:1 char:1
+ Get-AzureRmServiceBusNamespaceKey -ResourceGroup testresourcegroup -Name test-bus ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-AzureRmServiceBusNamespaceKey], PSInvalidOperationException
+ FullyQualifiedErrorId : InvalidOperation,Microsoft.Azure.Commands.ServiceBus.Commands.Namespace.GetAzure RmServiceBusNamespaceKey
PS C:\Windows\system32> Get-AzureRmStorageAccountKey -ResourceGroupName testresourcegroup -Name teststoragexxx
Key1 Key2
---- ----
***redacted*** ***redacted***
Not with Get-AzureRmStorageAccountKey, but you can use Get-AzureRmServiceBusNamespaceKey
$resourceGroup = "myResourceGroup"
$serviceBusName ="myservicebusname"
$policyName = "policyname"
Get-AzureRmServiceBusNamespaceKey -ResourceGroup $resourceGroup -Name
$serviceBusName -AuthorizationRuleName $policyName
This will return the whole object, so you can pass it into a variable and get the keys or connection strings from that.
Please have a try to login with tenantId and ServicePrincipal. I do a demo test about that, it works correctly for me.
Login-AzureRmAccount -Credential $psCred -TenantId $azureTenantId  -ServicePrincipal -SubscriptionId $subscriptionId
The following is may detail steps.
1 . We need to install service Bus module if it is not install. More detail info about AzureRM.ServiceBus please refer to document.
Install-Module -Name AzureRM.ServiceBus
2.More detail info about Automatically login script please refer to another SO thread.
3.Run the test script and check the result.
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "strong password" -AsPlainText -Force
$subscriptionId="Your subcription"
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Login-AzureRmAccount -Credential $psCred -TenantId $azureTenantId  -ServicePrincipal -SubscriptionId $subscriptionId
$resourceGroup = "Resource Group name"
$serviceBusName ="Service Bus Name"
$policyName = "Policy Name"
Get-AzureRmServiceBusNamespaceKey -ResourceGroup $resourceGroup -Name $serviceBusName -AuthorizationRuleName $policyName

Azure Powershell Script: Parse Error

Trying to setup a new VM via PowerShell. Works fine when I copy & paste commands step by step to PowerShell ISE but, fails when I try to run them in one rush.
I have removed other parts of the script, it is also failing with only this lines:
$VM_NAME = "VMNAME"
$VM_SIZE = "Small"
$VM_IMAGE = "5112500ae3b842c8b9c604889f8753c3__OpenLogic-CentOS-71-20150605"
$LOCATION = "West Europe"
$STORAGE_ACCOUNT = "disktest"
$CLOUD_SERVICE = "disktest"
$SSH_USER = "azureuser"
$SSH_PASSWORD = "324w##eANC"
$VIRTUAL_NETWORK = "Playground"
$SUBNET = "P"
$BOOTSTRAP_CHEF = $FALSE
$PATH_PUBLIC_CONFIG = "publicconfig.json"
$PATH_PRIVATE_CONFIG = "privateconfig.json"
$DISK_CREATE = $TRUE
$DISK_SIZE = 500
$DISK_COUNT = 2
$DISK_LABEL = "datadisk"
$DISK_LUN = 0
$REMOVE_SSH_ENDPOINT = $FALSE
$HTTP_ENDPOINT = $FALSE
$SHUTDOWN = $FALSE
Select-AzureSubscription -SubscriptionName "SUB" -Current;
if (!(Test-AzureName -Storage $STORAGE_ACCOUNT)) {
New-AzureStorageAccount -StorageAccountName $STORAGE_ACCOUNT -Location $LOCATION
}
if (!(Test-AzureName -Service $CLOUD_SERVICE)) {
New-AzureService -ServiceName $CLOUD_SERVICE -Location $LOCATION
}
Set-AzureSubscription -SubscriptionName "SUB" -CurrentStorageAccountName $STORAGE_ACCOUNT
$existing = Get-AzureVM -ServiceName $CLOUD_SERVICE -Name $VM_NAME
Error message:
In Zeile:36 Zeichen:1
+ $existing = Get-AzureVM -ServiceName $CLOUD_SERVICE -Name $VM_NAME
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ausführbarer Skriptcode wurde im Signaturblock gefunden.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TokenAfterEndOfValidScriptText
If i first set the variables, remove them from script window, and run again it works like a charm.
Issue is "Solved" - after some hours talking to Microsoft: It is a bug in PowerShell 3.0 in combination with Windows 7!
To solve this, install PowerShell 4.0, Re-Install Azure PowerShell and reboot the workstation.

Creating Azure SQL Database Server connection context New-AzureSqlDatabaseServerContext

I am trying to create an Azure SQL Database connection context e.g.
$cred = Get-Credential
$ctx = New-AzureSqlDatabaseServerContext -ServerName “mydatabasename” -credential $cred
or
$pwd = ConvertTo-SecureString "[password1234]" -AsPlainText -Force;
$cred1 = New-Object System.Management.Automation.PSCredential -ArgumentList "databaseadmin", $pwd
New-AzureSqlDatabaseServerContext -ServerName "myservername" -Credential $cred1
And the response is:
New-AzureSqlDatabaseServerContext : Object reference not set to an instance of an object.
At line:2 char:8
+ $ctx = New-AzureSqlDatabaseServerContext -ServerName “myservername” - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [New-AzureSqlDatabaseServerContext], NullReferenceException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.SqlDatabase.Database.Cmdlet.NewAzureSqlDatabaseServerContext
I've been through the docs and google searches but to no avail.
https://msdn.microsoft.com/en-us/library/dn546736.aspx
http://sqlmag.com/powershell/manage-azure-sql-databases-powershell
Thanks
Pavel
I recently ran into this issue in a PS runbook. After doing some searching, I found a solution that worked for me. Hopefully it will help you.
The error message isn't particularly helpful (big surprise), but the null object being referenced is the Azure subscription; I'm assuming the exception bubbles up from within the cmdlet rather than being thrown by your own code. By adding these three lines to my code:
$cert = Get-AutomationCertificate -Name $automationCertificateName;
Set-AzureSubscription -SubscriptionName $subName -Certificate $cert -SubscriptionId $subID;
Select-AzureSubscription -Current $subName;
I was able to get past the exception. Above, $automationCertificateName is a variable asset that I added to the automation account. See https://github.com/Microsoft/sql-server-samples/tree/master/samples/manage/azure-automation-automated-export for details about how to set that up.
Here is how I successfully created connection context:
$sqlServerUser = "test-user"
$sqlServerUserPassword = "P#$$w0rd"
$sqlServerName = "mysqlserver"
$sqlCred = New-Object System.Management.Automation.PSCredential($sqlServerUser, ($sqlServerUserPassword | ConvertTo-SecureString -asPlainText -Force))
$sqlContext = New-AzureSqlDatabaseServerContext -ServerName $sqlServerName -Credential $sqlCred
Please see this for more details.