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
Related
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
I want to create a key vault that will store a TLS certificate. This key vault needs to be accessible from Azure pipeline tasks, which will retrieve the said certificate and bind it to their apps. Microsoft mentions:
By default, 'Microsoft.Azure.WebSites' Resource Provider (RP) doesn't have access to the Key Vault specified in the template hence you need to authorize it by executing the following PowerShell commands before deploying the template:
Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId AZURE_SUBSCRIPTION_ID
Set-AzureRmKeyVaultAccessPolicy -VaultName KEY_VAULT_NAME -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets get
This works for my key vault when I do it manually. However, I want to automate this as part of my master pipeline. I've tried defining this task:
- task: AzurePowerShell#5
displayName: 'Set key vault policy'
inputs:
azureSubscription: …
azurePowerShellVersion: 'LatestVersion'
ScriptType: 'InlineScript'
Inline: |
Set-AzKeyVaultAccessPolicy -VaultName … -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets get
But it fails:
##[error]Operation returned an invalid status code 'Forbidden'
I've also noticed that this service principal for "Microsoft Azure App Service" isn't even available to my task; the following prints a blank:
$azureAppServicePrincipal = Get-AzADServicePrincipal -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd
Write-Output "azureAppServicePrincipalId = $($azureAppServicePrincipal.Id)"
Is there a way of making this service principal accessible to my pipeline?
When i tested with parameter Set-AzKeyVaultAccessPolicy -ServicePrincipalName other-service-principal. I get the same error.
You can use ObjectId and add the -BypassObjectIdValidation parameter in Set-AzKeyVaultAccessPolicy command as workaround. See the Note on this document.
When using a service principal to grant access policy permissions, you must use the -BypassObjectIdValidation parameter.
Set-AzKeyVaultAccessPolicy -VaultName myvault -ObjectId "ObjectId" -PermissionsToSecrets get -BypassObjectIdValidation
The Object id is the ObjectId resides in Managed application in local directory
You can also use below Az cli command in the Azure CLI task
az keyvault set-policy -n levikeyv --secret-permissions get --object-id "object-id"
For the command Get-AzADServicePrincipal was not returning any results. It is probably
the service principal associated with your ARM connection service donot have the Read Directory Data permission in the Microsoft Grap
You can try go to the Api permissions of your service principal app and add the proper permission. It may require your Admin's consent. See this thread and this for information.
Levi Lu's answer set me on the right track, but I'm adding my own answer to clarify the exact requirements.
To be able to access the service principal for "Microsoft Azure App Service" (abfa0a7c-a6b6-4736-8310-5855508787cd), you need two things:
Your subscription must have the "Microsoft.Web" resource provider registered. This often gets registered automatically when creating a new subscription, but sometimes it doesn't.
The service principal associated with your ARM service connection (under which your pipeline runs) must have the "Directory.Read.All" permission from the Azure Active Directory Graph. Open your Azure DevOps project settings, click "Service Connections", open your service connection, and click "Manage Service Principal". Then go to "API permissions", click "Add a permission", scroll down and click "Azure Active Directory Graph", "Application permissions", and add "Directory.Read.All". Click "Grant admin consent". If this button is greyed out, you need to get an AAD admin to do this step for you.
Importantly, you must pick the "Directory.Read.All" permission from Azure Active Directory Graph, despite this API being marked as legacy and on a deprecation path. Picking the said permission from Microsoft Graph instead will not work. That said, it's not a bad idea to add the permission from both APIs, in case the requirement eventually switches from one to the other. Something else I found bizarre is that the permission, once it has been granted and consumed, continues to work even after it gets revoked. To get the task to fail again (for the sake of testing), I needed to create a new tenant (Azure Active Directory).
With those two in place, you can grant permission for the "Microsoft Azure App Service" service principal to your key vault through this task (substitute $env:keyVaultName accordingly):
- task: AzurePowerShell#5
displayName: 'Grant key vault access to service principal'
inputs:
azureSubscription: '${{ parameters.armConnection }}'
azurePowerShellVersion: 'LatestVersion'
ScriptType: 'InlineScript'
Inline: |
if (!(Get-AzADServicePrincipal -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd)) {
throw "Current account cannot retrieve service principal `"abfa0a7c-a6b6-4736-8310-5855508787cd`" (Microsoft Azure App Service)."
}
Write-Host "Granting access to service principal `"abfa0a7c-a6b6-4736-8310-5855508787cd`" (Microsoft Azure App Service) on vault `"$($env:keyVaultName)`"..."
Set-AzKeyVaultAccessPolicy -VaultName $env:keyVaultName -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets Get,List -PermissionsToCertificates Get,List
Update May 2022:
Microsoft seem to have broken this. The Azure Active Directory Graph API is greyed out, despite that Set-AzKeyVaultAccessPolicy still uses it.
The Microsoft CLI team is in the process of migrating from the Azure Active Directory Graph API to the Microsoft Graph API. Until that is released, the best workaround seems to be to give Application administrator permissions to the service principal, as explained in this answer.
I created a keyvault and secrets from the MS docs and confirmed that I can list the keyvault and secrets from an Azure CLI session. When somebody else granted my access to another keyvault in our Azure tenant, I am not able to list that vault from the Azure CLI.
The CLI command I am using is : 'az keyvault list'
I have compared the individual policies applied in two vaults, and have 'owner' role access to both. I can see the vaults and secrets when I use a browser to navigate to the azure portal.
Thanks in advance for any suggestions on what I should check.
I suppose the keyvault is in another subscription in your Azure AD tenant, in Azure CLI, you could just use az keyvault list to list the keyvaults in the default subscription, if you want to do operations in another subscription, you need to set the subscription with it.
Navigate to the keyvault which you want to list in the portal, copy the Subscription ID like below.
Then run the command below before you list the keyvaults.
az account set --subscription <Subscription ID>
az keyvault list
In my case, my login had expired, but unlike with other commands, I did not get a warning to that effect. It simply returned the [] empty list.
Renewing my login with az login allowed az keyvault list to work.
In my case I had to go to the subscription / RG where the key-vault was and give the user / service principal the Reader role. You can do that by clicking on the subscription/RG and then selecting "Access Control (IAM)" on the left side. And then add the role assignment. Instructions - https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal?tabs=current
I have Azure Pipeline setup with Azure CLI task
I am using Service Connection. In az cli task I want to retrieve current Service Connection details (like appId name objectId etc..) which I am using to run this task.
az ad sp show required id parameter, which will not work in my case. I want to know that id dynamically
Is there any way to get current SP details?
You can now use a checkbox to expose the service principal id, secret and tenant in the Azure CLI script.
You can get your current session context with
az account show
and then simply get some extra details on the service principal
az ad sp show --id <guid>
and application
az ad app show --id <guid>
I found Service principle is in Azure Active Directory. And i cannot add them to azure devops service connection. What i can add is Azure subscription or azure resource group.
Not sure show how did you add your applications to azure service connection.
If you want to get the connection details. You can try az accout show for azure subscription, or az group show --name for azure resource group
Ran into this same issue, and found out the simplest possible way to get the SP Id in Azure Cli task in the pipeline:
First, define in the task addSpnToEnvironment like this:
- task: AzureCLI#2
continueOnError: true
inputs:
addSpnToEnvironment: true
scriptLocation: inlineScript
After that, you can get the SP Id from $env:servicePrincipalId and use it like this:
az deployment group create ... --parameters SPId=$env:servicePrincipalId
Combine with Adam Marczak's solution with python in one liner,
az ad sp show --id $(az account show| python -c 'import json,sys;print json.load(sys.stdin)["user"]["name"]')
I have a powershell script that attempts to retrieve a secret stored in Azure key vault using this command.
$password = (Get-AzureKeyVaultSecret -vaultName $vaultName -name $secretName).SecretValueText
It is working perfectly fine when I execute my powershell script locally. But, when I try to do the same on Azure Devops, it fails giving below error.
[error]Operation returned an invalid status code 'Forbidden'
I feel it isn't an access policy issue, as I am able to successfully perform read/write on my vault using powershell script running locally.
I'm quite sure it is a access policy issue.
Go to your DevOps Project Settings - Pipelines - Service Connections and click on "Update Service Connection" (Use the full version of the dialog). There you can find the Subscription Id and Service Principal ID.
You then have to give explicit permissions to this SPN:
Login-AzureRmAccount -subscription <YourSubscriptionID>
$spn= Get-AzureRmADServicePrincipal -spn <YourSPN>
Set-AzureRmKeyVaultAccessPolicy -VaultName <YourVaultName> -ObjectId $spn.Id -PermissionsToSecrets get,list;