If there any way can deploy the resources to different subscription from one centralized deployment console?
I'm planning create the resource monitoring dashboards in different subscription, as of now manually I'm importing the JSON configuration file into different subscription and changing the resource values.
Looking for the solution kind of centralized deployment.
You can do this using Azure Powershell or the Azure CLI. In order to change subscriptions, an Azure PowerShell Context object first needs to be retrieved with Get-AzSubscription and then the current context changed with Set-AzContext.
$context = Get-AzSubscription -SubscriptionId ...
Set-AzContext $context
For Azure CLI you can do:
az account set --subscription "My Demos"
CLI also lets you scope deployments to Subscriptions or Management Group. An example would be:
az deployment sub create --location <location> --template-file <path-to-template>
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/deploy-cli
Related
There are many questions similar to mine, but I hit a wall finding what I want, please help.
I am running Azure Dev ops pipeline within the organization "MyOrganization" and in the project "MyProject". The service connection or subscription I am connected to is "Subscription-Id" (something like this: abc123-def456..xyz3265)
Pipeline has several tasks.
The first task is a powershell taks that creates Azure Resource Group and then an Azure Key vault. (NewKeyVault)
Second task, will scan another existing key vault (SourceKeyVault) and copy its secrets into the NewKeyVault. I know how to do this and it works just fine when I run the powershell tasks from within my PCwhen I explicitly log in with my log in to azure.
Howerer, here when ran under Azure Dev Ops pipleline, I get error that the "logged in" user has no permissions to Create, get list, etc.. to the secrets.
I want to automatically assign access policy to newly created key vault.
If using the web portal, I can see the Devops as a registered application and can do it. I don't know how to access it from within power shell task within the devops running pipeline.
Based on your expectation, you may consider using the Azure CLI pipeline task, where you can run az keyvault set-policy command to configure keyvault access policies for specific user.
az keyvault set-policy -n $(TheAzureKeyVaultName) --secret-permissions get list --object-id $(UserPrincipalGUID)
See more information on az keyvault set-policy.
steps:
- task: AzureCLI#2
displayName: 'Azure CLI '
inputs:
azureSubscription: 'ARM_Svc_Cnn_Auto_Sub1'
scriptType: ps
scriptLocation: inlineScript
inlineScript: 'az keyvault set-policy -n $(TheAzureKeyVaultName) --secret-permissions get list --object-id $(UserPrincipalGUID)'
This task requires to use the Azure Resource Manager service connection to authenticate and login Azure.
For the automatically created ARM service connection, you can use this API to find out which service principal that the ARM service connection is referenced to az login.
In my case, the ARM service connection is referencing the service principal MyDevOpsOrg-TheProjectName-MySubID which is the contributor of my target KeyVault (inherited from subscription) and has sufficient permission to set key vault access policy.
I was able to resolve an issue in a simple manner - I am using Azure Power shell
script that creates the key vault itself
New-AzKeyVault -VaultName $newKvName -ResourceGroupName $resourceGroupName -Location $location
(all the variables referenced with $ are arguments passed to the script)
And then I get the context for a logged in principal
(AzDevOps pipeline is a principal in itself, registered in Azure AD)
#This gives a context object, which has principal
#id as a property of.
$Context = Get-AzContext
Then I set that principal as access policy
Set-AzKeyVaultAccessPolicy -VaultName $newKvName -ServicePrincipalName $Context.Account.Id -PermissionsToSecrets Get,List,Set
I've run into a snag with my powershell script that builds an azure function & all its dependencies.
This is what's happening: (i'm doing it manually here to demo...)
I request the storage account information like this:
PS C:\Users\me\> Get-AzStorageAccount -ResourceGroupName widget-resource-group
StorageAccountName ResourceGroupName PrimaryLocation SkuName Kind AccessTier CreationTime ProvisioningState EnableHttpsTrafficOnly LargeFileShares
------------------ ----------------- --------------- ------- ---- ---------- ------------ ----------------- ---------------------- ---------------
widgetx4ge6v27rlgdk widget-resource-group eastus Standard_LRS StorageV2 Hot 2022-03-10 2:00:26 PM Succeeded True
It comes back with the correct information. So then I try to get the connection string like this:
PS C:\Users\me> func azure storage fetch-connection-string widgetx4ge6v27rlgdk
Cannot find storage account with name widgetx4ge6v27rlgdk
But it says it can't find the storage account.
The actual code looks like this:
# Look up function app name that was dynamically created by ARM template:
$AZ_FUNCTION_APP = Get-AzFunctionApp -ResourceGroupName $currentEnv.AZ_RESOURCE_GROUP_NAME
#look up the storage account name for this resource group.
$AZ_STORAGE_ACCOUNT = Get-AzStorageAccount -ResourceGroupName $currentEnv.AZ_RESOURCE_GROUP_NAME
Write-Output $AZ_STORAGE_ACCOUNT.StorageAccountName
# Get new connection string for the storage account.
func azure storage fetch-connection-string $AZ_STORAGE_ACCOUNT.StorageAccountName
When the code runs, everything works until the call to "func azure storage fetch-connection-string".
Any tips on what I'm missing?
Edit 1
In case it helps, this logic works just fine when I run it against Tenant 1, Subscription A. But for Tenant 1, Subscription B it bombs.
I've made sure the service account principle it runs under is contributor on both subscriptions.
And for what it's worth, the script is able to create the resource group and many of the resources inside. It's just hat when I try to get the connection string, it bombs. It also bombs further down in the script when it tries to deploy the functions in my function app. The error message though is similar - it complains that it can't find the function app that I just finished creating.
Edit 2
So I figured out the problm but not sure how to fix it in a nice / simple way.
For 90% of the script, including login, i'm using the new Az Powershell modules. However, the "func azure" tool relies on login information provided by the az cli. (that seems to be cached??)
To get you on the same page, here's the relevant part of the code in the script:
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $AZ_DEPLOYMENT_CLIENT_ID, $Secure2
#Connect
Connect-AzAccount -ServicePrincipal -TenantId $AZ_TENANT_ID -Credential $Credential
#OPTIONAL - List the subscriptions available to the current User
Get-Azcontext -ListAvailable
#Set the subscription context to subscription 2
Set-Azcontext -Subscription $AZ_SUBSCRIPTION_ID -Tenant $AZ_TENANT_ID
#Create a new resource group
New-AzResourceGroup -Name $AZ_RESOURCE_GROUP_NAME -Location $AZ_RESOURCE_LOCATION -Force
New-AzResourceGroupDeployment -ResourceGroupName $AZ_RESOURCE_GROUP_NAME -TemplateFile (Join-Path $PSScriptRoot "./artifacts/widget-resources.json")
# Look up function app name that was dynamically created by ARM template:
$AZ_FUNCTION_APP = Get-AzFunctionApp -ResourceGroupName $AZ_RESOURCE_GROUP_NAME
#look up the storage account name for this resource group.
$AZ_STORAGE_ACCOUNT = Get-AzStorageAccount -ResourceGroupName $AZ_RESOURCE_GROUP_NAME
Write-Output $AZ_STORAGE_ACCOUNT.StorageAccountName
# this is where it is failing because it is using a subscription that is visible to az cli.
func azure storage fetch-connection-string $AZ_STORAGE_ACCOUNT.StorageAccountName
Here's what I did to troubleshoot from a powershell cli:
az account list
That returns this:
{
"cloudName": "AzureCloud",
"homeTenantId": "asdf-asdf-asdf-asdf-12312312313",
"id": "[guid]",
"isDefault": false,
"managedByTenants": [],
"name": "subscription-1",
"state": "Enabled",
"tenantId": "[our-tenant-id]",
"user": {
"name": "[another-guid]",
"type": "servicePrincipal"
}
}
When I ran the above command, it only returned one subscription called "subscription-1" for discussion purposes. It isn't/wasn't the one that the rest of the script was working with. The rest of script was dealing with subscription 2
As I test, I added the following lines of code just before call func azure storage:
az login --service-principal --username $AZ_APPLICATION_CLIENT_ID --password $AZ_SECRET --tenant $AZ_TENANT --allow-no-subscriptions
#set the subscription we want to use
az account set --subscription $subscription2
func azure storage fetch-connection-string $AZ_STORAGE_ACCOUNT.StorageAccountName
And now it finds the correct subscription and resource group / storage account. And now when I run az account list again, it shows me both subscriptions.
One addition comment / observation. Once the az login / az account set has been run with the desired subscription id, i've noticed that I can remove the az login and account set logic from the script and it just uses the cached values. I'm not saying this is what I want to do ... cuz I think it' best to be explicit. But just an observation which explains what bit me in the first place.
So my question is... is there anyway to avoid having to log in twice - once with az cli and another time with the Az Powerhsell modules?
I'm thinking of just abandoning the Az Powershell module and just rewriting everything in just az cli.
But asking the community to see if there's a better way to do this.
EDIT 3
Based on the docs for the azure core functions tools, technically I should be able to use the powershell modules or the cli:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=v4%2Cwindows%2Ccsharp%2Cportal%2Cbash#publish
"You must have the Azure CLI or Azure PowerShell installed locally to be able to publish to Azure from Core Tools."
Yes, using a mix of azcli and azure powershell, as they are their seperate entities in their own right, you would need to login to each of them individually.
And yes, you are right its better to ditch of them and choose one or the other ! Just much cleaner that way
The issue was that the azure core functions tool is using the cached az account list to find my resources.
So in other words, unbeknownst to me, the func method was using az cli, whereas the rest of the script is using the new Az Powershell modules.
For now, I've just rewritten everything in az cli syntax, and am happy with that. But per the docs it seems that the azure core functions tools should be able to work with either az cli or az powershell. Will open a separate question that addresses that point. For now, my script is working again.
I am trying to put some auto start policy on my VM on Azure.
So, I used automation account and power shell script to do this from this link: https://adamtheautomator.com/azure-vm-schedule/
But on testing it give me error of Run Login-AzureRmAccount to login
Please suggest how to fix this?
## Get the Azure Automation Acount Information
$azConn = Get-AutomationConnection -Name 'AzureRunAsConnection'
## Add the automation account context to the session
Add-AzureRMAccount -ServicePrincipal -Tenant $azConn.TenantID -ApplicationId $azConn.ApplicationId -CertificateThumbprint $azConn.CertificateThumbprint
## Get the Azure VMs with tags matching the value '10am'
$azVMs = Get-AzureRMVM | Where-Object {$_.Tags.StartTime -eq '10am'}
## Start VMs
$azVMS | Start-AzureRMVM
Regards
ESNGSRJ
This can happen when the Run As account isn't configured appropriately. You will need to create one to provide authentication for managing resources on the Azure Resource Manager using Automation runbooks.
When you create a Run As account, it performs the following tasks:
Creates an Azure AD application with a self-signed certificate, creates a service principal account for the application in Azure AD, and assigns the Contributor role for the account in your current subscription.
Creates an Automation certificate asset named AzureRunAsCertificate in the specified Automation account.
Creates an Automation connection asset named AzureRunAsConnection in the specified Automation account.
Please note the following requirements from the referenced link:
You must have an Azure Automation Account with an Azure Run As account already prepared. If you don’t have this yet, learn how to create one when you go to Create a new Automation account in the Azure portal.
The Azure PowerShell module must be installed. If you don’t have this yet, please go to the Install the Azure PowerShell module page for more information.
Note: You can configure your Runbook to use managed identities as well and it has added benefits as compared to using Run As accounts. You can get started with this tutorial to use managed identity.
I have created SPN for Azure devops pipeline and I need to access multiple subscription resources in a powershell task/deploymentScript ARM.I am using below command to switch between subscriptions
#Linking appinsight with storage account in Secondary Region
Get-AzSubscription -SubscriptionId $secSubscriptionId | Set-AzContext
This command works from my local powershell (as I have access to both subscriptions). But with CICD another subscription is not visible.I get below error even though both subs are under same tenant.
2020-05-12T17:17:14.9377680Z ##[error]Subscription XXXXXXX was not found in tenant ***. Please verify that the subscription exists in this tenant.
when you created the service principal, did you give it access to resources in both subscriptions?
like to know all the sites in Azure that are currently associated to our Azure Tenant includes full URL,azure web apps,azure SQL,Storage accounts,Datalake,Cosmosdb,container registries
Tried Get-AzureADTenantDetail and also az resource list but not able find it
Any Powershell script will help
You can use
Azure CLI
az resource list
Powershell
Get-AzureRmResource
You can use Get-AzureRmResource to get the list of resources in an Azure Subscription. By default this Cmdlet will list all resources in an Azure Subscription. To get a list of certain resource types, you can specify an OData filter query.
For example, the Cmdlet below will list all storage accounts and webapps in an Azure Subscription:
Get-AzureRmResource -ODataQuery "ResourceType eq 'Microsoft.Storage/storageAccounts' or ResourceType eq 'Microsoft.Web/sites'" | ft
You will need to find the proper resource type values for each kind of resource that you want to find.
Another thing to notice is that this Cmdlet is scoped to a single Azure Subscription. If your Azure Tenant serves as authentication/authorization source for multiple subscriptions, you would need to run this Cmdlet for each subscription separately.
If you have multiple tenants, you can switch between tenants and get resources within them (subscription by subscription) via
connect-azaccount -Tenant [different tenant id]
$context = Get-AzSubscription [subscriptionid in different tenant id]
set-azcontext $context
get-azresource > resources.tenantname.subcription.txt
where tenantname and subscription are the names of the tenant and subscription in english form (instead of id's).
you should probably not use those azurerm commands anymore, they will stop working sometime in 2024. use the az equivalents (basically replace azurerm with az (yeah, i could delete urerm but that seems weirder!))