When I try to use Powershell to make a peering link in Azure, between vnets in different subscriptions but in the same tenant, I get the following error messages.
Without specifying tenant:
Set-AzureRmContext : Please provide a valid tenant or a valid subscription.
So I tried specifying the tenant:
Get-AzureRmSubscription : Subscription was not found in tenant ****. Please verify that the subscription exists in this tenant.
I'm using Jenkins with a root account that has access to the dev subscription. I'm setting those credentials using the Microsoft Azure Service Principal bindings, before the job is run.
Does anyone know how I can code my Powershell script so that the Azure end recognises the 2nd subscription ID that I'm trying to peer to?
Current code below.
Write-Host "Create Vnet Peering from dev-vnet to test-centralhub-vnet"
$Subscription1 = Get-AzureRmSubscription -TenantId '(sanitised for Stackoverflow)' -SubscriptionId '(sanitised for Stackoverflow)'
Set-AzureRmContext -Subscription $subscription1
$Vnet1 = Get-AzureRmVirtualNetwork -name 'test-centralhub-vnet' -ResourceGroupName 'test-networks-hub-rg'
$Subscription2 = Get-AzureRmSubscription -TenantId '(sanitised for Stackoverflow)' -SubscriptionId '(sanitised for Stackoverflow)'
Set-AzureRmContext -Subscription $Subscription2
$Vnet2 = Get-AzureRmVirtualNetwork -name 'dev-vnet' -ResourceGroupName 'networks-dev-rg'
Set-AzureRmContext -Subscription '(sanitised for Stackoverflow)'
Add-AzureRmVirtualNetworkPeering -Name 'dev-vnet_to_test-centralhub-vnet' -VirtualNetwork $Vnet2 -RemoteVirtualNetworkId $Vnet1.ID -UseRemoteGateways
As the comment points out, the account you log in with must have the necessary permissions to create a virtual network peering. You can peer virtual networks that exist in two different subscriptions as long as a privileged user of both subscriptions authorizes the peering and the subscriptions are associated with the same Active Directory tenant.
For a list of permissions, see Virtual network peering permissions.
I just test this on my local Powershell. My account was assigned a contributor role in another subscription level, then run your Powershell scripts with the same account successfully.
If you create peering with a different account in the different subscription. You may log in to Azure by entering the Connect-AzureRmAccount command for each subscription. More details from Create peering - PowerShell. Note, the linking scripts are using new Az module. You can refer it to replace Az with AzureRm for AzureRm module.
Related
I am trying to automate the creation of certain azure resources via an Azure PowerShell script that is triggered from an Azure DevOps release pipeline. I want to create a function app, and automatically integrate reading right access to secrets in an already existing Key Vault. This Key Vault is in the same Azure subscription.
While I can create most resources following the documentation, there seems to be a lack of documentation regarding the creation of certain resources using Azure PowerShell (or I can't find it).
If I follow the sample from this link, I can accomplish it without a problem by using the UI in the Azure Portal, but I can't find any documentation on Microsoft Docs to do it using PowerShell.
Write-Host "Creating Function App..."
$fnApp = New-AzFunctionApp -Name $functionAppName `
-ResourceGroupName $emailFunctionRg `
-Location "$(AzureRegion)" `
-StorageAccount $storageName `
-Runtime dotnet `
-FunctionsVersion '3' `
-IdentityType SystemAssigned
Write-Host "Function App created!"
Write-Host "Assigning Key Vault access..."
$appId = Get-AzADServicePrincipal -DisplayName $functionAppName
Set-AzKeyVaultAccessPolicy -VaultName EmailSettings -ServicePrincipalName $appId -PermissionsToSecrets Get,List
Write-Host "Key Vault access granted!"
Running Set-AzKeyVaultAccessPolicy fails with "Insufficient privileges to complete the operation.". But I am not sure if this is the right path to follow, it was just a guess, based on the available functions in the documentation.
Any ideas?
Two potential issues to check out here:
your app creation assigns the result to $fnApp. perhaps $fnApp or as commented above, $fnApp.ApplicationId is what you should be using for the -ServicePrincipalName parameter on the access policy grant.
you don't have privileges to assign RBAC roles. Go to the Key Vault, choose Access Control, then click the Role Assignments tab and verify that your user appears in the list as an Administrator, User Access Administrator, or Owner.
Edit: With respect to the RBAC privilege, since this is running in Azure Powershell from Azure DevOps, you need to check the role assignment for the Service Connection's service principal - under Azure Active Directory in the Azure Portal, look up the principal used to create the service connection, and make sure THAT gets the correct Role on the key vault.
After a little of trial and error I just came to the conclusion I was not using the right parameter for the Set-AzKeyVaultAccessPolicy cmdlet.
The following script will work (if the service principle running it has the appropriate role, like WaitingForGuacamole mentioned in his/her answer):
Write-Host "Creating Function App..."
$fnApp = New-AzFunctionApp -Name <FnAppName> `
-ResourceGroupName <ResourceGroupName> `
-Location <AzureRegion> `
-StorageAccount <StorageAccount> `
-Runtime dotnet `
-FunctionsVersion '3' `
-IdentityType SystemAssigned
Write-Host "Function App created!"
Write-Host "Assigning Key Vault access..."
Set-AzKeyVaultAccessPolicy -VaultName <NameOfTheKeyVault> -ObjectId (Get-AzADServicePrincipal -DisplayName <FnAppName>).Id -PermissionsToSecrets <Get, List, etc...>
Write-Host "Key Vault access granted!"
Using Powershell in an Azure DevOps pipeline, I am trying to assign the key vault's principal the role Storage Account Key Operator Service Role to a storage account.
Command Line
The command line is run after I connected Azure with the service principal:
$credentials = New-Object -TypeName System.Management.Automation.PSCredential($servicePrincipalApplicationId, $clientSecret)
Connect-AzAccount -ServicePrincipal -Credential $credentials -Tenant $tenantId
Here is the command line that I execute :
New-AzRoleAssignment -ApplicationId $keyVaultServicePrincipalId -ResourceGroupName $resourceGroupName -ResourceName $storageAccountName -ResourceType "Microsoft.Storage/storageAccounts" -RoleDefinitionName "Storage Account Key Operator Service Role"
Where:
$keyVaultServicePrincipalId is the pre-registered principal ID for Key Vault. Its value is cfa8b339-82a2-471a-a3c9-0fc0be7a4093.
$resourceGroupName is the name of the resource group in which the storage is located. Its value is accountsmanager-test-global-rg.
$storageAccountName is the name of my storage account. Its value is accountsmanagertest.
Service Principal
Here are the permission of the service principal under which the command is run:
The command is run as a Service Principal that has the Owner role in the subscription:
The resource group created in that subscription is also owned by that Service Principal:
Question
When I run the command, I get the following error:
New-AzRoleAssignment: The provided information does not map to an AD object id.
Why do I get the error The provided information does not map to an AD object id. when executing the command New-AzRoleAssignment?
I can also reproduce this on my side, there are two issues.
1.In your command, the ResourceType should be Microsoft.Storage/storageAccounts, not Microsoft.Storage/storageAccount.
2.In the API permission of your AD App related to the service principal used in the DevOps servcie connection, you need to add the Application permission Directory.Read.All in Azure Active Directory Graph, not Microsoft Graph.
After a while to take effect, it will work fine.
I am trying to add a subnet to SQL Server using Azure Az Module. The command I am using is
New-AzSqlServerVirtualNetworkRule -VirtualNetworkRuleName "newvnetrule1" -ServerName $sqlServer.ServerName -ResourceGroupName $sqlServer.ResourceGroupName -VirtualNetworkSubnetId $newsubnetId -ErrorAction Stop
I get an exception saying:
The client with object id does not have permission to perform this action
The object id belong to a SPN of name Azure SQL Virtual Network to Network Resource Provider.
I get the exact same issue while provisioning cosmos db account with ARM template only this time the erroneous SPN is Azure Cosmos DB Virtual Network to Network Resource Provider
Can anyone throw some light on this? The same code used to work fine. All the services are registered for the subnet too
The Owner role is enough, I test it on my side, it works fine.
$virtualNetworkSubnetId = "/subscriptions/xxxxxxx/resourceGroups/joynet/providers/Microsoft.Network/virtualNetworks/joysqlnet/subnets/default"
New-AzSqlServerVirtualNetworkRule -ResourceGroupName joynet -ServerName joyser -VirtualNetworkRuleName vnetrule1 -VirtualNetworkSubnetId $virtualNetworkSubnetId
To fix the issue, try to use Clear-AzContext to clear all the local account information, then use the script below to login again.
$azureAplicationId ="<Application ID>"
$azureTenantId= "<Tenant ID>"
$azurePassword = ConvertTo-SecureString "<Client secret>" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Connect-AzAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
Then run (Get-AzContext).Account, make sure the Id is the same as the Application ID of the service principal you are using, also the Tenant ID of the service principal should be the same as the GUID in Tenants.
I am trying to setup a powershell code which would update the storage account credentials every once in a while and below is the script that I have come across and it works perfectly fine.
function setupContext(){
Add-AzureRmAccount
Save-AzureRmContext -Path “path\to\json\file”
}
#setupContext
Import-AzureRmContext -Path “path\to\json\file”
$subscriptionId='***********************************'
Select-AzureRMSubscription -SubscriptionId $subscriptionId -WarningAction SilentlyContinue
$resourceGroup="**************"
$storageAccountName="******************"
$BLOBKey= New-AzureRmStorageAccountKey -ResourceGroupName $resourceGroup -Name $storageAccountName -KeyName key2
Write-Host "BLOB Key:"$BLOBKey.Keys[0]
The above code does the required work, however it requires us to login to the azure-rm account which basically defeats the idea of automating this process since I would need keep updating this generated profile.
Note: I am not allowed to use az module as of now since the environment in which I work has some .NET version limitations.
So if there any other solution which could overcome the azure rm login issue, please suggest.
Use Azure Automation. This automatically sets up something called RunAs account. Which simply said is just Azure AD Service Principal.
Then assign this principal privileges on the storage account just like any other user and you are done.
And in the Automation Runbook do
$connection = Get-AutomationConnection -Name AzureRunAsConnection
Connect-AzureRmAccount `
-ServicePrincipal `
-Tenant $connection.TenantID `
-ApplicationID $connection.ApplicationID `
-CertificateThumbprint $connection.CertificateThumbprint
$AzureContext = Select-AzureRmSubscription -SubscriptionId $connection.SubscriptionID
... run rest of the code ...
If you want to run this from outside of Azure like on-prem server then set up manually service principal. Here is guide
https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal
And just log into this app from powershell instead of the user.
Looks you want to use a non-interactive way to do that automatically. To access the azure resource with a non-interactive way, your best option currently is to use the service principal(AD App).
An Azure service principal is an identity created for use with applications, hosted services, and automated tools to access Azure resources.
The other reply is for azure automation runbook, you could follow my steps to automate it in other places else.
1.Create an Azure Active Directory application and create a secret for the app, save the secret and get values for signing in.
2.Navigate to the storage account(or the subscription which the storage account located) in the portal -> Access control (IAM) -> Add -> Add role assignment -> search your service principal(AD App) with name and add it as a role(e.g. Owner/Contributor) -> Save.
Note: To give the role, you need to use an account which is an Owner of the specific scope(storage account/subscription).
3.Then use the script as below, replace the specific properties with the values in step 1.
function setupContext(){
$azureAplicationId ="<application id>"
$azureTenantId= "<tenant id>"
$azurePassword = ConvertTo-SecureString "<client secret>" -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential($azureAplicationId , $azurePassword)
Add-AzureRmAccount -Credential $psCred -TenantId $azureTenantId -ServicePrincipal
Save-AzureRmContext -Path “path\to\json\file”
}
#setupContext
Import-AzureRmContext -Path “path\to\json\file”
$subscriptionId='***********************************'
Select-AzureRMSubscription -SubscriptionId $subscriptionId -WarningAction SilentlyContinue
$resourceGroup="**************"
$storageAccountName="******************"
$BLOBKey= New-AzureRmStorageAccountKey -ResourceGroupName $resourceGroup -Name $storageAccountName -KeyName key2
Write-Host "BLOB Key:"$BLOBKey.Keys[0]
Besides, if you want to learn more about the service principal, you could take a look at this link - Application and service principal objects in Azure Active Directory
I want to execute a runbook from subscription A which will create a storage a/c on subscription B. I provided the (Username/Password) of subscription B in credential asset.
Firstly, please let me know is it possible to do that ?
When i try to run the below code, it gives an error "Unable to acquire token for tenant 'Common' " when i run Get-AzureRmSubscription
$CredentialAssetName = "login";
$Cred = Get-AutomationPSCredential -Name $CredentialAssetName
if(!$Cred) {
Throw "Could not find an Automation Credential Asset named
'${CredentialAssetName}'. Make sure you have created one in this Automation
Account."
}
add-azurermaccount -credential $Cred
login-AzureRMAccount -Credential $Cred
Select-AzureRmSubscription -SubscriptionName 'Free Trial'
get-azurermsubscription
Unable to acquire token for tenant 'Common'
It just a WARNING, that will not affect your script.
please let me know is it possible to do that?
Yes, it is possible, we can use Azure runbook to login subscription B, and use PowerShell to create an Azure storage account in that subscription.
Runbook just like PowerShell, when we use subscription B to log in, the script will work on subscription B.
If subscription B is a Microsoft account, we can follow this answer to login Azure runbook. (Microsoft account does not support non-interactive login.)