Azure Automation account Powershell Error setting context - azure

I am trying to run a simple powershell runbook using Azure automation account. I have a RunasAccount setup which has contributor previlege over the subscription and I am trying to get a list of IP's whitelisted in one of my Sql server.
Import-Module Az.Sql
Import-Module Az.Accounts
$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
}
}
Get-AzSqlServerFirewallRule -ResourceGroupName test-rg -ServerName test-server101
While I run this I get the below error.
Get-AzSqlServerFirewallRule : No subscription found in the context. Please ensure that the credentials you provided are authorized to access an Azure subscription, then run Connect-AzAccount to login. At line:36 char:1 + Get-AzSqlServerFirewallRule -ResourceGroupName test-rg -ServerName te ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [Get-AzSqlServerFirewallRule], AzPSApplicationException + FullyQualifiedErrorId : Microsoft.Azure.Commands.Sql.FirewallRule.Cmdlet.GetAzureSqlServerFirewallRule
I noticed that the Get-AzSqlServerFirewallRule commandlet has an option to set -DefaultProfile. However I am not sure what is to be given here.
What am I doing wrong here?

You're mixing PowerShell modules. If you're using the Az module, then you need to use Connect-AzAccount rather than Add-AzureRmAccount. If you're using the AzureRm module, then you need to use Get-AzureRmSqlServerFirewallRule rather than Get-AzSqlServerFirewallRule.

Related

Unable to run my ps script through automation account

I have a powershell script which I want to run through azure automation account. The script worked fine when running on cloudshell but when running it through a powershell runbook it is not doing the intended tasks and throwing errors.When I am using Select-AzSubscription -SubscriptionName 'xxx' it tells me to use Connect-AzAccount and when I use that it gives me Cannot find an open port error.
Can anyone help with this? I am listing down the four different error messages I am getting.
Connect-AzAccount : Cannot find an open port. At line:6 char:1 + Connect-AzAccount + ~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [Connect-AzAccount], Exception + FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand
Get-AzVM : Argument passed in is not serializable. Parameter name: value At line:19 char:12 + $vmOSDisk=(Get-AzVM -ResourceGroupName $resourceGroupName -Name $vmNa ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [Get-AzVM], ArgumentException + FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.GetAzureVMCommand
New-AzStorageContext : Context cannot be null. Please log in using Connect-AzAccount. At line:50 char:23 + ... onContext = New-AzStorageContext -StorageAccountName $destinationstor ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : CloseError: (:) [New-AzStorageContext], InvalidOperationException + FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.Storage.Common.Cmdlet.NewAzureStorageContext
Start-AzStorageBlobCopy : Cannot bind argument to parameter 'AbsoluteUri' because it is null. At line:55 char:38 + Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $d ... + ~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Start-AzStorageBlobCopy], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.WindowsAzure.Commands.Storage.Blo [![enter image description here][1]][1]b.Cmdlet.StartAzureStorageBlobCopy
Here is a snip of a part of code for reference. Az module is used in the script and new Azure automation account does not have Az module installed by default, even after importing Az.Accounts, Az.Automation, Az.Compute I am getting these errors.
In cloud shell, it will login your user account automatically, actually Connect-AzAccount does not work, but it will not give you an error, just a warning, so the script will work.
In the automation runbook, it does not support the interactive way to login your user account, if you use Connect-AzAccount directly, you will get the error, the other errors are follow-up issues based on this.
So to solve the issues, we always use the Run As Account of your automation account in this scenario, essentially it is an AD App along with a service principal in your AAD tenant. Make sure you have enabled it and give all the permissions to it the same as your user account to run the script, its name is like automationname_xxxxxxxxx, you can check it in the Run As Account blade in the automation account in the portal.
Then use the commands below to login.
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
Connect-AzAccount `
-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
}
}
After login, please use Set-AzContext -Subscription <subscription-id> instead of Select-AzSubscription, also please import Az.Storage module in the automation account, because some commands like New-AzStorageContext and Start-AzStorageBlobCopy belong to this module, after doing them, your script should work.
Update:
I test with the script you used with Storage Blob Data Contributor, it works fine.
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
Connect-AzAccount `
-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
}
}
$sas = Grant-AzSnapshotAccess -SnapshotName "joyvmsnap" -ResourceGroupName "xxxxx" -DurationInSecond 3600 -Access Read
$destinationContext = New-AzStorageContext -StorageAccountName "joystoragev2" -UseConnectedAccount
$storageContainerName="image"
$destinationVHDFileName="test.vhd"
Start-AzStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestContainer $storageContainerName -DestContext $destinationContext -DestBlob $destinationVHDFileName -Force
Make sure the firewall of the storage account is set to allow access from all networks and the Storage Blob Data Contributor role is assigned at the storage account level or higher, not the container level.

How to start vm from different subscription using Azure Automation Account

I have three subscription in same tenant say Sub1, Sub2 and Sub3. I have created Automation Account is in Sub1 and my VMs are in Sub3. (Cant create Automation account in Sub3 due to some restrictions). I want to write a powershell script which will start Sub3 VM.
When I ran Get-AzureRmSubscription it is giving me only my current subscription i.e. Sub1
My azure automation script is as below -
$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
}
}
Get-AzureRmSubscription
# $context = Get-AzureRmSubscription -SubscriptionId {subId}
# Set-AzureRmContext $context
# Start-AzureRmVM -ResourceGroupName "ResourceName" -Name "VMName"
Can you please guide how can I go this?
Since your subscriptions are in the same tenant, you can directly assign an Azure RABC role to your Azure Automation connection(service principal ) in your Sub3. Then you can manage Azure resource in Sub3
For example
Get the Connection Application ID
Assign role
Connect-AzAccount
$sp=Get-AzADServicePrincipal -ApplicationId < the appId you copy>
Set-AzContext -SubscriptionId <the id of sub3>
#assign Contributor role to the connection at subsciprion level
New-AzRoleAssignment -ObjectId $sp.id -RoleDefinitionName Contributor
Test
$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
}
}
Get-AzureRmSubscription

Get-AzureBlobContent throwing error when run from Azure Automation account

I am receiving a failure while trying to download blob (JSON file) from Azure storage account from my Azure Automation account. It looks like an authorization issue.
This works on my local laptop, but does not work on Azure Automation Account. Does not work even if I make the container "public"
I have assigned OWNER privileges for the Automation accounts's service principle on the Resource Group (Automation account + Storage account stay in this RG) and specifically on the Storage Account as well:
Below is the code:
$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
}
}
$config_file_resource_group_name = "vg-datalake-manjunath"
$config_file_storage_account_name = "datalakelog"
$primary_key = (Get-AzureRmStorageAccountKey -ResourceGroupName $config_file_resource_group_name -AccountName $config_file_storage_account_name).value[0]
$config_file_context = New-AzureStorageContext -StorageAccountName $config_file_storage_account_name -StorageAccountKey $primary_key
Get-AzureStorageBlobContent -Blob "mw_services.json" -Container "fwconfigfiles" -Destination "C:\temp\mw_services.json" -Context $config_file_context
get-content "C:\temp\mw_services.json" | write-output
ERROR:
Get-AzureStorageBlobContent : The remote server returned an error: (403) Forbidden. HTTP Status Code: 403 - HTTP Error
Message: This request is not authorized to perform this operation.
At line:30 char:2
+ Get-AzureStorageBlobContent -Blob "mw_services.json" -Container "fwc ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Get-AzureStorageBlobContent], StorageException
+ FullyQualifiedErrorId :
StorageException,Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet.GetAzureStorageBlobContentCommand
The possible reason is that you may configure to selected networks to access.
If you enable this option, and whether you tick "allow trusted microsoft services to access", you would get this error, since automation is not listed under MS trusted services. see https://learn.microsoft.com/en-us/azure/storage/common/storage-network-security#trusted-microsoft-services.

Azure PS Automation Provided subscription "xxxx" does not exists

I wish to select a subscription available for my service principle within an Azure Automation PS job. Running the following code locally works fine, but within the automation job, I only get the following error
Provided subscription xxxx-xxxx-xxxx-xxx-xxxx does not exist.
The subscription does exist, and the service principal has access to it when I log onto it locally.
$id = "someid"
$pass = "somepass"
$securePass = $pass | ConvertTo-SecureString -AsPlainText -Force
$cred = new-object -TypeName System.Management.Automation.PsCredential -ArgumentList $id, $securePass
$tenantId = "someID"
Add-AzureRmAccount -Credential $cred -TenantId $tenantId -ServicePrincipal
Select-AzureRmSubscription -SubscriptionId "someID"
Finally, I figured out this issue, after some days.
This issue is already reported here.
It is due to the issue related to Add-AzureRmAccount cmdlets with Service Principal.
There is a workaround to solve this issue, as mentioned by Hariharan
$connectionAssetName = "AzureRunAsConnection"
$conn = Get-AutomationConnection -Name $ConnectionAssetName
Login-AzureRmAccount `
-ServicePrincipal `
-CertificateThumbprint $conn.CertificateThumbprint `
-ApplicationId $conn.ApplicationId `
-TenantId $conn.TenantID `
-Environment AzureGermanCloud
Refer this S.O
For using Azure Automation, you should create the Automation account with AzureRunAsConnection enabled. Then from the script you utilize it like this
$connectionName = "AzureRunAsConnection"
try {
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
Connect-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
}
}
Hope this helps

Automation Runbook not able to set default subscription on run

Cloned a sample non classic runbook and attempted to set the subscription as default. This gives me following error:
Select-AzureSubscription : The subscription name {nameofsubscription} doesn't exist.
Parameter name: name
At step1_validate:18 char:18
+
+ CategoryInfo : CloseError: (:) [Select-AzureSubscription], ArgumentException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.Profile.SelectAzureSubscriptionCommand
How would it be possible to select or set a particular subscription as default? Below approaches throw above mentioned error:
Approach 1
Select-AzureSubscription -SubscriptionName $defaultSubscriptionname –Default
Get-AzureSubscription -SubscriptionId 123XXXXXXXXXXXXXXXXXX96eXX58 | Select-AzureSubscription
Approach 2
$subscriptionId = (Get-AzureRmSubscription | Out-GridView -Title 'Select Azure Subscription:' -PassThru).Id
Select-AzureRmSubscription -SubscriptionId $subscriptionId
Trying : To get particular resource name and make configurational changes, or to use Get-Azurewebsite cmdlet, setting a subscription appears mandatory.
Note: Hoping adding Service Principal used in the automation account to default subscription might help, I also tried to add the ApplicationId to Access control of Subscription as contributor. Though my Runbook being mentioned here and WebApps are in same subscription. Reference: https://blogs.technet.microsoft.com/knightly/2017/05/26/using-azure-automation-with-multiple-subscriptions/#comment-1555 ( Scenario for me is both are in same subscription )
EDIT: Pasting Code
<#
This PowerShell script was automatically converted to PowerShell Workflow so it can be run as a runbook.
Specific changes that have been made are marked with a comment starting with “Converter:”
#>
<#
.DESCRIPTION
To watch php version old in app, and if found turn it off and apply 5.6
.NOTES
AUTHOR: HBala
LASTEDIT: Jan 04, 2018
#>
workflow step1_validate {
# Converter: Wrapping initial script in an InlineScript activity, and passing any parameters for use within the InlineScript
# Converter: If you want this InlineScript to execute on another host rather than the Automation worker, simply add some combination of -PSComputerName, -PSCredential, -PSConnectionURI, or other workflow common parameters (http://technet.microsoft.com/en-us/library/jj129719.aspx) as parameters of the InlineScript
inlineScript {
$connectionName = "AzureRunAsConnection"
$myResourceGroupName = "DevstorageRG"
$defaultSubscriptionname = "StandardDevStaging"
$newPhpVersion = "5.6"
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
}
}
#Get all ARM resources from all resource groups
$ResourceGroups = Get-AzureRmResourceGroup
foreach ($ResourceGroup in $ResourceGroups)
{
Write-Output ("Showing resources in resource group " + $ResourceGroup.ResourceGroupName)
if( $ResourceGroup.ResourceGroupName -eq $myResourceGroupName ){
$Resources = Find-AzureRmResource -ResourceGroupNameContains $ResourceGroup.ResourceGroupName | Select ResourceName, ResourceType
ForEach ($Resource in $Resources)
{
Write-Output ($Resource.ResourceName + " of type " + $Resource.ResourceType)
Write-Output ($Resource.ResourceName + " of type " + $Resource.ResourceType)
#Switch-AzureMode AzureServiceManagement
# Local powershell connects and works perfect with what I wanted to achieve.
# On Automation account, Runbook migration, it threw Azure subcription not set error for Set-AzureWebsite.
# so remove rest of the code and focused on few options to get the default as below
# which led me to post the thread.
#
# Approach 1
Select-AzureSubscription -SubscriptionName $defaultSubscriptionname –Default
Get-AzureSubscription -SubscriptionId 1238XXXXXXXXXXXe5XXXX8 | Select-AzureSubscription
# Approach 2
$subscriptionId = (Get-AzureRmSubscription | Out-GridView -Title 'Select Azure Subscription:' -PassThru).Id
Select-AzureRmSubscription -SubscriptionId $subscriptionId
Write-Output ( "==============Subscription ID :===========")
Write-Output( $subscriptionId)
# Wants to update config / php version parameters.
Set-AzureWebsite -Name $Resource.ResourceName -HttpLoggingEnabled 1 -PhpVersion 5.6
# Had tried this as well which was suggested by Jason. But appears not working..
# looks like I have messed it up.
Get-AzureRmWebApp -ResourceGroupName $myResourceGroupName -Name $Resource.ResourceName
Set-AzureRmWebApp -ResourceGroupName $myResourceGroupName -Name $Resource.ResourceName -HttpLoggingEnabled 1 -PhpVersion 5.6
}
}
Write-Output ("Completed!#Line83")
}
}
}
Hoping adding the serviceprincipal type addition for the
automationaccount to default subscription might help
You are right, we can use Azure automation account connections to select subscription.
For example, we can new a connection and the type is Azure service principal.
like this:
Then use this powershell script to select the connection:
$connectionName = "jason"
try
{
# Get the connection "jason "
$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 this way, we can use connection to select subscription.
By the way, we can follow this article to create service principal.

Resources