Azure Container Service in Runbook schedule - azure

After consulting the Microsoft Support I am able to kick off a Docker container via Azure Automation with the following code:
$connection = Get-AutomationConnection -Name AzureRunAsConnection
$secpasswd = ConvertTo-SecureString "132asdf9asdf342" -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential ("somecontainerregistry", $secpasswd)
Connect-AzureRmAccount -ServicePrincipal -Tenant $connection.TenantID -ApplicationId $connection.ApplicationID -CertificateThumbprint $connection.CertificateThumbprint
New-AzureRmContainerGroup -RegistryCredential $credentials -ResourceGroupName automation-rg -Name jjcontainer03 -Image somecontainerregistry.azurecr.io/etl-pipeline -OsType Linux -DnsNameLabel aci-etl-pipeline-01 -RestartPolicy Never -Command "scrapy crawl data"
This seems to work fine when I test the pane inside the Azure Automation Portal, but when I schedule it to run every hour, I only see that the Runbook job has been executed (at the correct time), without creating a new Azure instance. Should I remove the old instance every time or is there something else I am missing?

If you are specifying the script to create a container with a static name - such as the one in your case - it will not be recreated since AzureRM module detects that the said container group already exists. Try adding 'Remove-AzureRmContainerGroup ...' one line above the 'New-AzureRmContainerGroup ...'

You can use a new guid as the name of the container if you want a unique name.

Related

Connect-AzAccount with Azure Devops Pipeline?

I am finding difficulties in finding the best and secure way to use connect-azaccount with azure devops pipeline. I have in the pipeline the following this simple powershell script which is used to create azure resources. Just to simplify things I only used the creation of a resource group:
$Location = "Location Name"
$resourceGroupName = "Resource Group Name"
try {
#Creation of Resource Group
$resourceGroup = Get-AzResourceGroup -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if($null -eq $resourceGroup)
{
New-AzResourceGroup -Name $resourceGroupName -Location $Location
}
else
{
Write-Host "The ResourceGroup with the name: $resourceGroupName already exists."
}
}
catch
{
Write-Host "Error occurred: $_"
}
The problem here is when the pipeline is being run and it reaches the Powershell task, it gives me an error, Error occurred: Run Connect-AzAccount to login.
My issue here is that I honestly don't know which way is the most secure way to connect without typing any user credentials. It should directly connect and create the resources. Note that I am using Multi-Factor Authentication. In order to achieve that I found several solutions but I need help in choosing the best way. I found several solutions by adding a powershell task in the Yaml file. Here is the Yaml showing the powershell task to run the script:
- task: PowerShell#2
inputs:
filePath: '$(Pipeline.Workspace)/Deploy/functionapp.ps1'
Option 1:
Connect-AzAccount -Tenant 'xxxx-xxxx-xxxx-xxxx' -SubscriptionId 'yyyy-yyyy-yyyy-yyyy'
Now the problem here is that the Tenant ID and Subscription are going to be visible in the code and that is a very bad practice
Option 2 is to use the following script:
$User = "xxx#xxxx.onmicrosoft.com"
$PWord = ConvertTo-SecureString -String "<Password>" -AsPlainText -Force
$tenant = "<tenant id>"
$subscription = "<subscription id>"
$Credential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $User,$PWord
Connect-AzAccount -Credential $Credential -Tenant $tenant -Subscription $subscription
This is very similar to the first, but if I am not mistaken it is limited to a specific user.
Option 3 is to use a service principal:
$azureAplicationId ="Azure AD Application Id"
$azureTenantId= "Your Tenant Id"
$azurePassword = ConvertTo-SecureString "strong password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
I don't know if creating a service principal will incur any costs and what steps should I do to make it work.
I am honestly new to all this, can someone please provide me what are the exact steps to achieve this. Thank you for your answers :)
The most secure way is to create an Azure Resource Manager service connection and use it in your pipeline. You can create it using automated way, or manually using previously created service principal.

restart cloud service using powershell

we have a problem with a Microsoft bot hosted in Azure.
As long as we haven't resolved it, we want to periodically restart it.
We found 3 sets of powershell commands and spent the full day on it without making it work.
Solution 1:
we found the cmdlets : Get-AzCloudService Restart-AzCloudService.
We didn't understand from the documentation what module to install.
It returns : The term 'Restart-AzCloudService' is not recognized as the name of a cmdlet.
They talk about an obscure "extended support" to have access to it.
Solution 2:
We are able to list the cloud service using:
Connect-AzAccount
get-azresource -name $serviceName -resourcetype
"Microsoft.BotService/botServices"
But we do not find the cmdlet to restart the resource.
Solution 3:
Reset-AzureRoleInstance -serviceName $serviceName -Slot "production" -InstanceName $serviceName
Error : No default subscription has been designated. Use Select-AzureSubscription -Default
We are using MFA. Login-AzureRmAccount systematically fails , evenly saying that our account is disabled.
We did no manager to run the sequence:
Login-AzureRmAccount
Select-AzureSubscription -Default
Reset-AzureRoleInstance -serviceName $serviceName -Slot "production" -InstanceName $serviceName
The idea is to run this script twice a day, either from a VM or from an Azure Runbook.
We managed to run this code using an automation Account but we are still missing the last command that would restart the bot (that we consider a cloud service).
Param()
$automationAccount = "xxx"
$resourceGroup = "xxx"
$serviceName = "xxx"
$subscriptionname ="xxx"
$subscriptionid ="xxx"
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave -Scope Process | Out-Null
# Connect using a Managed Service Identity
try {
$AzureContext = (Connect-AzAccount -Identity).context
}
catch{
Write-Output "There is no system-assigned user identity. Aborting.";
exit
}
#Set-AzureSubscription -SubscriptionId $subscriptionid
$AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription `
-DefaultProfile $AzureContext
get-azresource -name $serviceName -resourcetype "Microsoft.BotService/botServices"

Powershell Workflow runbook - authentication failed

I have an Azure Automation Run As account. When I run the following code (from step 5 of Azure online tutorial) on the runbook in Azure Portal, I get the error shown below. Question: What I may be missing here, and how can we resolve the issue?
runbook code:
# Ensures you do not inherit an AzContext in your runbook
Disable-AzContextAutosave –Scope Process
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Connect-AzAccount -ServicePrincipal -Tenant $Conn.TenantID `
-ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint
$AzureContext = Select-AzSubscription -SubscriptionId $Conn.SubscriptionID
Error:
Failed At line:4 char:1
+ Disable-AzContextAutosave –Scope Process
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Cannot find the 'Disable-AzContextAutosave' command. If this command is defined as a workflow, ensure it is defined before the workflow that calls it. If it is a command intended to run directly within Windows PowerShell (or is not available on this system), place it in an InlineScript: 'InlineScript { Disable-AzContextAutosave }'
I'm assuming you havn't imported the Az.Accounts module into your automation account. Disable-AzContextAutosave, Connect-AzAccount and Select-AzSubscription are from this module.
Follow this guide to Import Az modules.

login to azure account without popup using powershell

I'm trying to create Azure VM using powershell.I have also the script to create it.
First I need to login into Azure account :
Login-AzureRMAccount
This gives a pop-up to enter the credentials.
Second I need to run the below script:
$UserName = "username"
$Password = ConvertTo-SecureString "password" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($UserName, $Password)
New-AzureRmVm `
-ResourceGroupName "RG1" `
-Name "VM1" `
-ImageName "Image1" `
-Location "West US" `
-Credential $psCred
This is creating the VM successfully.
But now , I need to make these scripts run automatically, when ever there is requirement. The problem I'm facing is, the login step gives a popup to enter the credentials which I do not want. So I have tried something like this, but didn't work.
$username = "loginname#organization.com"
$SecurePassword = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username, $SecurePassword)
Login-AzureRmAccount -Credential $cred
The error message it is giving is :
Login-AzureRmAccount : accessing_ws_metadata_exchange_failed: Accessing WS metadata exchange failed: The underlying connection was closed: An unexpected error occurred on a send.
At line:4 char:1
+ Login-AzureRmAccount -Credential $cred
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (:) [Connect-AzureRmAccount], AadAuthenticationFailedException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Profile.ConnectAzureRmAccountCommand
Can anyone tell me what this means and how to rectify this? Thanks!
If you are planning to automate any services into Azure using PowerShell, then I'd recommend connecting azure using Service Principal rather than your own credentials, it will be a secure way to connect.
What is Service principal?
An Azure service principal is a security identity used by user-created
apps, services, and automation tools to access specific Azure
resources. Think of it as a 'user identity' (username and password or
certificate) with a specific role, and tightly controlled permissions.
It only needs to be able to do specific things, unlike a general user
identity. It improves security if you only grant it the minimum
permissions level needed to perform its management tasks.
Follow this tutorial to create a service principal
I also have published a sample PowerShell workflow into Microsoft gallery for creating Service Principal you can also follow that.
Once you created your service principal, you can use the below PowerShell commands to login into azure without any popup's
$applicationId = "<service prinicple application id>";
$securePassword = "<service prinicple password>" | ConvertTo-SecureString -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $applicationId, $securePassword
Connect-AzureRmAccount -ServicePrincipal -Credential $credential -TenantId "<your tenantid>"
Update1:
For some reason/bug the above will get fails. Refer this github issue
To solve this
Add the two lines before the script
Import-Module -Name AzureRM.Profile
Remove-AzureRmAccount
Update 2:
AzureRM will no longer receive new cmdlets or features. However, the AzureRM module is still officially maintained and will get bug fixes through December 2020.
You have to use the new Azure PowerShell Az module
Basically you can achieve this for all of your PowerShell sessions by adding the Logging in part as part of the $PSProfile. I use this trick to skip the login popup, so whenever i open powershell my account is automatically logged in.
Open Windows PowerShell as an administrator
Type Notepad $profile
A notepad file will be opened and here you can paste the below code to
log in automatically whenever it is opened.
$username = “”
$password = “”
$securepasswd = ConvertTo-SecureString $password -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($username, $ securepasswd)
Connect-AzureRmAccount -Credential $cred

How to stop all VMs with Azure Automation using Resource Manager module?

I have created some Azure VMs using the new Resource Manager and i'd like to stop them everyday.
To do so, i've published a runbook to stop aboth classic and ARM VMs, and i created a scheduler which runs the runbook every night :
workflow Stop-AzureVMs
{
$cred = Get-AutomationPSCredential -Name 'Cred'
Add-AzureAccount -Credential $cred
Select-AzureSubscription -Current 'SubscriptionName'
Get-AzureVM | Stop-AzureVM –Force
Get-AzureRmVM | Stop-AzureRmVM -Force
}
I have imported the AzureResourceManager module to my Azure Automation account :
But i am getting this error :
Exception
At line:34 char:2
+ Get-AzureRMVM | Stop-AzureRMVM -Force
+ ~~~~~~~~~~~~~ Cannot find the 'Get-AzureRMVM' command. If this command is defined as a workflow, ensure it is defined before the workflow that calls it. If it is a command intended to run directly within Windows PowerShell (or is not available on this system), place it in an InlineScript: 'InlineScript { Get-AzureRMVM }'
How is that possible ?
Edit : Below is the solution
$cred = Get-AutomationPSCredential -Name 'Cred'
Add-AzureRmAccount -Credential $cred
Select-AzureRmSubscription -Name 'SubscriptionName' -SubscipritionId 'SubscriptionId'
Get-AzureRmVM | Stop-AzureRmVM -Force
All workflows i found didn't mention the use of Add-AzureRmAccount and Select-AzureRmSubcription instead of the standard Add-AzureAccount and Select-AzureSubscription. I thought that the authentication process to our Azure account was the same.
Update : It is now possible to combine both ASM and ARM cmdlets within the same runbooks, see this post for more informations about ARM supported by default on Azure Automation
Looks like you imported the old version of the ARM cmdlets (before Azure PS 1.0) into Azure Automation. This was before the *-AzureRm* renaming. So tt should be Stop-AzureVM not Stop-AzureRmVM.
However, that makes it ambiguous as to whether you are trying to call Azure Service Management or Azure Resource Manager cmdlets -- which is exactly why the cmdlet names were renamed in Azure PS 1.0. I recommend you follow the guidance here.
As per my understanding ASM mode is default. If you are going for ARM command firstly switch mode is required using Switch-AzureMode
One more confusion is what is the purpose of Get-AzureRMVM command. I googled but coulndn't find anything -
The Get-AzureRMVM cmdlet is in the AzureRM.Compute module... The AzureRM* cmdlets are still in preview, I don't think they are available in Azure Automation yet.
The two modules in your screenshot above likely correspond to the 0.9.x version of the cmdlets and there were indeed two different modules (Azure=ASM and AzureResourceManager=ARM) behind Switch-AzureMode. Switch-AzureMode just unloads one and loads the other.
If Automation is still using the 0.9.x version of the cmdlets then you should be able to just use Get-AzureVM for ARM VMs using the AzureResourceManager module.
Below is the solution
$cred = Get-AutomationPSCredential -Name 'Cred'
Add-AzureRmAccount -Credential $cred
Select-AzureRmSubscription -Name 'SubscriptionName' -SubscriptionId 'SubscriptionId'
Get-AzureRmVM | Stop-AzureRmVM -Force
It is not yet possible to combine ARM and ASM cmdlets in same runbook apparently ... So you have to use only ARM cmdlet or ASM cmdlet.
Also, all workflows i found didn't mention the use of Add-AzureRmAccount and Select-AzureRmSubcription instead of the standard Add-AzureAccount and Select-AzureSubscription.
I thought that the authentication process to our Azure account was the same.
The Following code will work for both old style and new Style VM's but be aware this will shut down all machines with no warning.
{
# TODO: update to the name of the credential asset in your Automation account
$AutomationCredentialAssetName = "AzureAutomationRG"
# Get the credential asset with access to my Azure subscription
$Cred = Get-AutomationPSCredential -Name $AutomationCredentialAssetName
# Authenticate to Azure Service Management and Azure Resource Manager
Add-AzureAccount -Credential $Cred
Add-AzureRmAccount -Credential $Cred
"`n-Old Style VMS-`n"
# Get and output Azure classic VMs
$VMs = Get-AzureVM
$VMs.Name
Get-AzureVM | Stop-AzureVM -Force
"`n-New Style Resource Group VMs-`n"
# Get and output Azure v2 VMs
$VMsv2 = Get-AzureRmVM
$VMsv2.Name
Get-AzureRmVM | Stop-AzureRmVM -Force
}
For new Azure RM VMs use access extensions the following command:
Set-AzureRmVMAccessExtension -ResourceGroupName "ResourceGroupName" -VMName "VMName" -Username "Admin User Name" -Password "Admin Password" -Name "Extension Name"
Please note the -Name parameter is the arbitrary extension name.
This might be late to the party, but I would recommend you check out this link:
https://www.attosol.com/start-or-stop-all-vms-of-a-resource-group-in-azure/
Basically, you can create a script and write some aliases with switches to make your job super easy.

Resources