I am trying to execute a runbook in an automation account within azure.
I have set a managed identity following the instructions here, then i issue the following in my runbook:
Connect-AzAccount -Identity
Set-AzContext -Subscription Subscription1
As instructed here
But i get the following error:
Set-AzContext : Please provide a valid tenant or a valid subscription.
At line:134 char:1
+ Set-AzContext -Tenant $tenantId -Subscription $subscriptionId
I pass the tenantId and subscriptionId through as parameters, and have written them out to confirm they are correct.
Can anyone see where I am going wrong?
Update
I have added the owner role to the system assigned managed identity and now it seems to get the connection ok with Dilly B's suggestion below:
$null = Disable-AzContextAutosave -Scope Process # Ensures you do not inherit an AzContext in your runbook
$AzureContext = (Connect-AzAccount -Identity -AccountId $managedIdentity).context # Connect to Azure with user-assigned managed identity
$connectionResult = Set-AzContext -Subscription $subscriptionId -DefaultProfile $AzureContext
however when i do:
$virtualMachine = Get-AzVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName
I now get the following error:
Get-AzVM : The client '****************' with object id '*****************' does
not have authorization to perform action 'Microsoft.Compute/virtualMachines/read' over scope '/subscriptions/******************/resourceGroups/***************/providers/Microsoft.Compute/virtualMachines/************' or the scope is invalid. If access was recently granted, please refresh your credentials.
ErrorCode: AuthorizationFailed
ErrorMessage: The client '******************' with object id '*****************************'
does not have authorization to perform action 'Microsoft.Compute/virtualMachines/read' over scope '/subscriptions/******************/resourceGroups/**************/providers/Microsoft.Compute/virtualMachines/**************' or the scope is invalid.
Please find the sample code below. Hope this helps!
$subscription = "000000-0000-0000-0000-000000000"
$identity = "000000-0000-0000-0000-000000000"
$null = Disable-AzContextAutosave -Scope Process # Ensures you do not inherit an AzContext in your runbook
$AzureContext = (Connect-AzAccount -Identity -AccountId $identity).context # Connect to Azure with user-assigned managed identity
$connectionResult = Set-AzContext -Subscription $subscription -DefaultProfile $AzureContext
Make sure you have up-to-date modules for Az.Accounts (2.10.2), Az.Resources (6.3.0), Az.Automation (1.8.0).
https://learn.microsoft.com/en-us/azure/automation/automation-update-azure-modules
Related
I am trying to make a code using PowerShell so that secrets are not hardcoded on my runbook so that it will not be exposed in the script. I created encrypted variables in my automation account. These variables are AppID, AppSecret and TenantID.
This is the part of the script to login automatically to Azure. I didn't use managed identity for some compatibility reasons with the script.
My script is running fine when secrets and IDs are hardcoded but when I created variables it is not working. Error message is "Run Connect-AzAccount". Below is my code. Need help on how to correct this. Thank you in advance.
$AzVariableApplicationID = 'AppID'
$AzVariableAppSecret = 'AppSecret'
$AzVariableTenantID = 'TenantID'
$AppID = Get-AzAutomationVariable -Name $AzVariableApplicationID
$AppSecret = Get-AzAutomationVariable -Name $AzVariableAppSecret
$TenantID = Get-AzAutomationVariable -Name $AzVariableTenantID
$SecureSecret = $AppSecret | ConvertTo-SecureString -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential `
-ArgumentList $AppID, $SecureSecret
Connect-AzAccount -ServicePrincipal -Credential $Credential -Tenant $TenantID
As described in PsCustom Object - Hitchikers GUID(e) to Automation
, It is not possible to retrieve values for encrypted variables as they’re available within the runbook at runtime via the Get-AutomationVariable cmdlet
I found an alternative approach to "Connect Azure" by using "Certificate-based authentication" inside PowerShell runbook without hardcoding the values:
Created a new Service principal and provided the "Owner" role access to avoid any restrictions.
To authenticate via service principal, I create a new self-signed certificate with the command:
$cert=New-SelfSignedCertificate -Subject "CN=xxxxxCert" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature
Upload a certificate under Certifications & Secrets:
Click windows + R to open the run box and give certmgr.msc as shown here.
Export a certificate without private key.
Upload a certificate in the below path:
AzureAD -> App registrations -> Serviceprincipal
Now, I have exported the same certificate with key and uploaded inside my automation account to authenticate Service principal connection:
Added an "Azure Service Principal" connection inside automation accounts by providing "ApplicationID, TenantID, Certificate Thumbprint" of my Service principal as shown:
Inside PowerShell runbook, I ran the below script that works for me:
$connectionName = "serviceprincipalname"
try
{
$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
}
}
Logged in to Azure:
Register an App in App registrations and create a service principal in AzureAD
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.
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"
Working on this as below - Using a power-shell script inside the Automation Account for run-book. The power-shell script will help in adding a rule inside the resource of the function-app of the networking rule. But somehow the following happens -
Not able to login the azure account
And it says Subscription ID doesn't exists. (Login is done via Service principle)
Code for reference
$azureAplicationId="XXXX"
$azureTenantId="XXXXX"
$azurePassword=ConvertToSecureString "XXXXXX" -AsPlainText -Force
$psCred=New-Object System.Management.Automation.PSCredential($azureAplicationId ,$azurePassword)
Login-AzureRmAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
Select-AzureSubscription -SubscriptionId "XXXXXX"
Add-AzWebAppAccessRestrictionRule -ResourceGroupName "XXXXX" -WebAppName "XXXXX" -Name "iprule" -Priority 100 -Action Allow -IpAddress x.x.x.x/x –
I am currently trying to write a powershell script which logs into azure and then deletes an SQL database.
When it gets to the database deletion it gives an error:
Remove-AzureSqlDatabase : No default subscription has been designated. Use Select-AzureSubscription -Default <subscriptionName> to set the default
subscription.
When i try to add a default subscription with Select-AzureSubscription -Default -SubscriptionName Pay-As-You-Go i get an error aswell:
Select-AzureSubscription : The subscription name Pay-As-You-Go doesn't exist.
I'm confused as to what the problem is and have tried connecting to the account via connect-AzAccount aswell.
The full script is:
$passwd = ConvertTo-SecureString password -AsPlainText -Force
$pscredential = New-Object System.Management.Automation.PSCredential('accountname', $passwd)
Connect-AzureRmAccount -Credential $pscredential -Tenant "tenant string"
# Set-AzContext -SubscriptionId "subscription id"
Select-AzureSubscription -Default -SubscriptionName Pay-As-You-Go
# Get-AzureSubscription -SubscriptionName “Pay-As-You-Go” | Select-AzureSubscription -Default
Remove-AzureSqlDatabase -ServerName migrate -DatabaseName "AWS-Copy"
You could not mix the three powershell module Azure, Az, AzureRm together, and if you have installed the Az module, I recommend you to uninstall the AzureRm module, it was deprecated and will never be updated.
To remove sql db with Az module, your script should be like below. Make sure your account has an RBAC role(e.g. Owner, Contributor) of your subscription/SQL Server.
$passwd = ConvertTo-SecureString password -AsPlainText -Force
$pscredential = New-Object System.Management.Automation.PSCredential('accountname', $passwd)
Connect-AzAccount -Credential $pscredential -Tenant "<tenant-id>"
Set-AzContext -Subscription "<subscription-id>"
Remove-AzSqlDatabase -ResourceGroupName "<ResourceGroupName>" -ServerName "<ServerName>" -DatabaseName "<DatabaseName>"