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.
Related
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 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
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.
I have code where i'm trying to get the azurevaultsecret and keep that secrete in one variable. while running the code i am getting forbidden error. Please share the valuable solution.
$ssAADKey = ConvertTo-SecureString $AADKey -AsPlainText -Force
$psCredential = New-Object System.Management.Automation.PSCredential($AADAppID, $ssAADKey)
Connect-AzureRmAccount -ServicePrincipal -Credential $psCredential -TenantId $TenantId
$myApp = Get-AzureADApplication -Filter "DisplayName eq '$($AppName)'" -ErrorAction SilentlyContinue
$Secrets = Get-AzureKeyVaultSecret -VaultName "TestVault1" -name "TestSecret1" -ErrorAction Stop
$password =$Secrets.SecretValueText
I test with your code in my site and it works well.
According to your description and error message you provided, I assume that you may not give full permision to your Azure Key Vault. You could refer to the following steps to troubleshoot.
1.Add a new app registration in Azure AD. Then we can get tenantId, appId, secretKey from the Azure Portal, please refer to this article.
2.Add permission with "Key Vault" to the registered app.
3.In Key vault channel, you need to Add policies to your registered application or user. And in Access Control you need to add permission to your registered application or user.
For more details, you could refer to this SO thread.
One more recent cause of the 'Forbidden' error is that you've enabled the Firewalls and virtual networks feature, and haven't enabled the "Allow trusted Microsoft services to bypass this firewall?" option which can be found here:
Log into the Azure Portal
Navigate to your Key Vault
From Settings, select Firewalls and virtual networks
Scroll down to the section entitled Exception
Make sure your Azure CLI /Client public IP is allowed Key Vault Network Firewall access to the key vault in question (Azure Key Vault; Networking; Firewall; IPv4 address or CIDR) in addition to having permission to update/modifying the key vault.
Determine your CLI public IP by use:
(Invoke-WebRequest -Uri https://myexternalip.com/raw -UseBasicParsing).Content
I'm trying to create an Azure Automation job to create a standard set of tags/values in a subscription.
Working with Tags requires AzureResourceManager, which is not available in Automation out of the box (Go vote for this feedback item!), so I followed these steps to upload the ARM module.
When I test my runbook I get the following output:
-------------------------
PSComputerName : localhost
PSSourceJobInstanceId : a8b85213-ee0f-40ea-842f-d33f2e87c910
Id : xxxxx-56ad-42c2-97f4-e364456fc4a6
Name : xxxxx
Environment : AzureCloud
Account : my-service-principal-app-id
Properties : {Default, Tenants, SupportedModes}
-------------------------
New-AzureTag : Your Azure credentials have not been set up or have expired, please run Add-AzureAccount to set up your
Azure credentials.
At Add-SubscriptionTags:41 char:41
+
+ CategoryInfo : CloseError: (:) [New-AzureTag], ArgumentException
+ FullyQualifiedErrorId : Microsoft.Azure.Commands.Tags.Tag.NewAzureTagCommand
Here's my runbook:
workflow Add-SubscriptionTags
{
param
(
# Subscription
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]
$SubscriptionName
)
# Get the PowerShell credential and prints its properties
$cred = Get-AutomationPSCredential -Name 'AzureMaint'
# Connect to Azure
Add-AzureAccount -Credential $cred -ServicePrincipal -Tenant 'xxx-49ab-8a9c-4abce32afc1e' | Write-Verbose
# Set subscription
$subscription = Select-AzureSubscription -SubscriptionName $SubscriptionName -PassThru
write-output '-------------------------'
write-output $subscription
write-output '-------------------------'
# Add tags (Requires AzureResourceManager module)
New-AzureTag -Name 'Managed' -Value $true
New-AzureTag -Name 'Managed' -Value $false
}
The AzureMaint PSCredential contains a service principal ID and key, and the service principal has been granted the Contributor role on the specified subscription. I can do Add-AzureAccount in the ISE with those credentials and add tags just fine. Since it successfully prints the subscription info I assume that means Add-AzureAccount was successful, so why do I get the error?
Update:
I created a new Automation Account without the ARM module and I'm still having the same issue, although the error message is slightly different:
Your Azure credentials have not been set up or have expired, please run Add-AzureAccount
to set up your Azure credentials. (Your Azure credentials have not been set up or
have expired, please run Add-AzureAccount to set up your Azure credentials. (Unable
to retrieve service key for ServicePrincipal account xxx-4a00-becf-952fda93edc5.
Please run the Add-AzureAccount cmdlet to supply the credentials for this service principal.))
So now I'm wondering if it doesn't like me using a Service Principal?
Just to update here, we've discovered that service principal authentication does not work in Azure Automation currently. Given you are trying to use a service principal, that is the reason for the issues you are hitting.
For now, a user principal should be used to work around this issue.
Please see the following for more info:
Authenticating to Azure Resource Manager with a Service Principal in Azure Automation
https://github.com/Azure/azure-powershell/issues/655
Using ARM cmdlets in Azure Automation is not officially supported yet. That said, various people have been successful doing so. Are your ARM and Azure PowerShell modules the same version? Weird things can happen if they are loaded side by side but are not the same version.