Automation Runbook not able to set default subscription on run - azure

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.

Related

Azure Automation account Powershell Error setting context

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.

Azure update management generate patch status report in a csv format

I'm creating a Azure Automation runbook to generate a report on the patch status of the virtual machines under a management group.
The query used is as below
union Update , workspace('xxxx').Operation,workspace('yyyy').Operation
| where TimeGenerated > ago(10d)
| where Classification in ("Security Updates", "Critical Updates", "Critical and security updates") and ResourceType == "virtualMachines"
| summarize updates=makeset(Title) by Computer,Classification, UpdateState,Product, PublishedDate, MSRCSeverity
| order by UpdateState
$result = Invoke-AzOperationalInsightsQuery -WorkspaceId $WorkspaceID -Query $query
here I need to query log analytics workspace from different subscriptions under the same management group..
Run As Account has RBAC set to "Log Analytics Reader" at management group level.
But the query results is empty record set, Same query fetches records when its executed on the Log Analytics workspace directly.
Any guidance on what I'm missing here will be a great help.
Thank you
This command Invoke-AzOperationalInsightsQuery can just do operations against one subscription, so in your case, you need to use a loop to set the subscription with Set-AzContext -Subscription <subscription-id>, to get all the subscriptions your RunAs account can access, use Get-AzSubscription.
Sample:
$connectionName = "AzureRunAsConnection"
try
{
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName
"Logging in to Azure..."
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
}
}
$query = "xxxxxx"
$subs = Get-AzSubscription
foreach($sub in $subs){
Set-AzContext -Subscription $sub.Id
#do the things you want e.g. $result = Invoke-AzOperationalInsightsQuery -WorkspaceId $WorkspaceID -Query $query
}
This is just a sample, to make it work, also remember to loop the different $WorkspaceID in the script.

Azure Automation Runbook Workflow looses AzContext

I have written the following runbook workflow, but from time to time I see the error when it try's to start or stop a VM:
Start-AzVM : Your Azure credentials have not been set up or have expired, please run Connect-AzAccount to set up your
Azure credentials.
At StartStopVmByTag:46 char:46
+
+ CategoryInfo : CloseError: (:) [Start-AzVM], ArgumentException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.StartAzureVMCommand
I have tried passing the $azContext variable in, but I still get this issue, how can I further investigate?
workflow StartStopVmByTag {
$connectionName = "AzRunAsConnection2042";
try {
# Get the connection "AzureRunAsConnection "
$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
Write-Output "Logging in to Azure..."
$null = Add-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
}
}
[DateTime]$now = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId((Get-Date), 'GMT Standard Time')
$startTag = 'Start Schedule'
Write-Output "*** $now - Runbook Started ***"
# Get Subscriptions
$Subscriptions = Get-AzSubscription
ForEach ($Subscription in $Subscriptions) {
$azContext = Set-AzContext -SubscriptionId $Subscription.Id
# Get all VM's with a Start or Stop Schedule
Write-Output "$($Subscription.Name): Getting VM's..."
[Array]$taggedVms = Get-AzResource -TagName $startTag -ResourceType 'Microsoft.Compute/virtualMachines'
$taggedVms = $taggedVms | Sort-Object -Property Name -Unique
# For each VM, check if start schedule is valid for now
Foreach -Parallel ($taggedVm in $taggedVms) {
Write-Output "$($Subscription.Name): Found Tagged VM: $($taggedVm.Name), $($startTag): $($taggedVm.Tags.$startTag -replace '\s', '')"
$WORKFLOW:null = Start-AzVM -ResourceGroupName $taggedVm.ResourceGroupName -Name $taggedVm.Name -DefaultProfile $azContext -NoWait
}
}
}
I have been struggling with this issue for a while, and I've tried dozens of different workarounds and nothing has worked. I finally resolved it with these registry settings that force .NET applications to use TLS 1.2. I find it very strange that this solution works, but possibly because the TLS 1.2 set as part of any parent task doesn't get passed on to the job.
They probably aren't all required, but it seems to be a best practice these days anyway.
set-itemproperty "HKLM:\SOFTWARE\Microsoft\.NETFramework\v2.0.50727" -name SystemDefaultTlsVersions -value 1 -Type DWord
set-itemproperty "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -name SchUseStrongCrypto -value 1 -Type DWord
set-itemproperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v2.0.50727" -name SystemDefaultTlsVersions -value 1 -Type DWord
set-itemproperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -name SchUseStrongCrypto -value 1 -Type DWord

How to start or stop appservices in Azure

I want to stop my appservices at midnight and want to start them at morning.So i came across two things , runbooks and webjobs .So first i included a runbook which start/stop services in a resource group.But when i tested it out , i faced an error -
And also when i tried using a webjob , i used this code from here , but i was not able to see the result.The webjob was working as a script but was it actually starting/stoping the services i dont know.I am new to powershell scripts so i dont know where to make necessary changes in the code.I dont know whether i am doing it right or wrong , please help me out.Thank You.
If you want to manage Azure ARM Resource with Azure Runbook, you can create Run As accounts in your Azure automation account. When we create it, it will create a new service principal user in Azure Active Directory (AD) and assigns the Contributor role to this user at the subscription level. For more details, please refer to the document and the document.
For example
Create Run As accounts
a. Search for and select Automation Accounts.
b. On the Automation Accounts page, select your Automation account from the list.
c. In the left pane, select Run As Accounts in the account settings section.
d. Depending on which account you require, select either Azure Run As Account or Azure Classic Run As Account.
e. Depending on the account of interest, use the Add Azure Run As or Add Azure Classic Run As Account pane. After reviewing the overview information, click Create.
Create a PowerShell Workflow runbook
Script
workflow START_STOP_APP_SERVICE_BY_RESOURCE
{
Param(
[Parameter (Mandatory= $true)]
[bool]$Stop,
[Parameter (Mandatory= $true)]
[string]$ResourcegroupName
)
try
{
# use Azure As Account to log in Azure
$servicePrincipalConnection=Get-AutomationConnection -Name "AzureRunAsConnection"
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
}
}
$status = 'Stopped'
if ($Stop)
{
$status = 'Running'
}
# Get Running WebApps (website_Processings_Running)
$website_Processings_Running = Get-AzureRMWebAPP -ResourceGroupName $ResourcegroupName | where-object -FilterScript{$_.state -eq $status }
foreach -parallel ($website_Processing In $website_Processings_Running)
{
if ($Stop)
{
$result = Stop-AzureRmWebApp -ResourceGroupName $ResourcegroupName -Name $website_Processing.Name
if($result)
{
Write-Output "- $($website_Processing.Name) shutdown successfully"
}
else
{
Write-Output "+ $($website_Processing.Name) did not shutdown successfully"
}
}
else
{
$result = Start-AzureRmWebApp -ResourceGroupName $ResourcegroupName -Name $website_Processing.Name
if($result)
{
Write-Output "- $($website_Processing.Name) start successfully"
}
else
{
Write-Output "+ $($website_Processing.Name) did not started successfully"
}
}
}
}
Today in 2022 you have to use Az module instead of AzureRM. You also have to switch to 7.1 Runtime if you want to succeed.
Param(
[bool]$Stop,
[string]$ResourcegroupName,
[string]$WebAppName
)
try
{
# use Azure As Account to log in Azure
$servicePrincipalConnection=Get-AutomationConnection -Name "AzureRunAsConnection"
Write-Output $servicePrincipalConnection.TenantId
Write-Output $servicePrincipalConnection.ApplicationId
Write-Output $servicePrincipalConnection.CertificateThumbprint
Add-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
}
}
$status = 'Stopped'
if ($Stop)
{
$status = 'Running'
}
# Get Running WebApps (website_Processings_Running)
$website_Processings_Running = Get-AzWebApp `
-ResourceGroupName $ResourcegroupName] `
-Name $WebAppName | where-object -FilterScript{$_.state -eq $status}
Write-Output "- $($website_Processing.Name) WebApp to manage"
foreach ($website_Processing In $website_Processings_Running)
{
if ($Stop)
{
$result = Stop-AzWebApp -ResourceGroupName $ResourcegroupName -Name $website_Processing.Name
if($result)
{
Write-Output "- $($website_Processing.Name) shutdown successfully"
}
else
{
Write-Output "+ $($website_Processing.Name) did not shutdown successfully"
}
}
else
{
$result = Start-AzWebApp -ResourceGroupName $ResourcegroupName -Name $website_Processing.Name
if($result)
{
Write-Output "- $($website_Processing.Name) start successfully"
}
else
{
Write-Output "+ $($website_Processing.Name) did not started successfully"
}
}
}

Azure Automation Runbook missing mandatory parameters

I'm trying to set a Tag on all virtual machines in my subscription but I keep getting errors when running the Runbook.
The error is the following:
Get-AzureRmVM : Cannot process command because of one or more missing mandatory parameters: ResourceGroupName. At line:30
Here is my Runbook:
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Add-AzureRmAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzureRmVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzureRmVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzureRmResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzureRmResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"
I tried importing the right modules but this doesn't seem to affect the outcome.
Running the same commands in Cloud Shell does work correctly.
I can reproduce your issue, the error was caused by this part Get-AzureRmVM -Name $azurevm, when running this command, the -ResourceGroupName is needed.
You need to use the Az command Get-AzVM -Name $azurevm, it will work.
Running the same commands in Cloud Shell does work correctly.
In Cloud shell, azure essentially uses the new Az module to run your command, you can understand it runs the Enable-AzureRmAlias before the command, you could check that via debug mode.
Get-AzureRmVM -Name joyWindowsVM -debug
To solve your issue completely, I recommend you to use the new Az module, because the AzureRM module was deprecated and will not be updated.
Please follow the steps below.
1.Navigate to your automation account in the portal -> Modules, check if you have imported the modules Az.Accounts, Az.Compute, Az.Resources, if not, go to Browse Gallery -> search and import them.
2.After import successfully, change your script to the one like below, then it should work fine.
$azureConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
#Authenticate
try {
Clear-Variable -Name params -Force -ErrorAction Ignore
$params = #{
ServicePrincipal = $true
Tenant = $azureConnection.TenantID
ApplicationId = $azureConnection.ApplicationID
CertificateThumbprint = $azureConnection.CertificateThumbprint
}
$null = Connect-AzAccount #params
}
catch {
$errorMessage = $_
Throw "Unable to authenticate with error: $errorMessage"
}
# Discovery of all Azure VM's in the current subscription.
$azurevms = Get-AzVM | Select-Object -ExpandProperty Name
Write-Host "Discovering Azure VM's in the following subscription $SubscriptionID Please hold...."
Write-Host "The following VM's have been discovered in subscription $SubscriptionID"
$azurevms
foreach ($azurevm in $azurevms) {
Write-Host "Checking for tag $vmtagname on $azurevm"
$tagRGname = Get-AzVM -Name $azurevm | Select-Object -ExpandProperty ResourceGroupName
$tags = (Get-AzResource -ResourceGroupName $tagRGname -Name $azurevm).Tags
If ($tags.UpdateWindow){
Write-Host "$azurevm already has the tag $vmtagname."
}
else
{
Write-Host "Creating Tag $vmtagname and Value $tagvalue for $azurevm"
$tags.Add($vmtagname,$tagvalue)
Set-AzResource -ResourceGroupName $tagRGname -ResourceName $azurevm -ResourceType Microsoft.Compute/virtualMachines -Tag $tags -Force `
}
}
Write-Host "All tagging is done"

Resources