Azure Key Vault - create policy - insufficient privileges to complete the operation

Access policies management with Azure AD Service Principal seems to be trivial - it's just an API method / CLI function - and using Service Principal instead of User Principal should not matter. But...

Let's create our SP:

az ad sp create-for-rbac -n "TestApp" --role owner --scopes /subscriptions/ssssssss-ssss-ssss-ssss-ssssssssssss

and in the output I will get:

{
  "appId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "displayName": "TestApp",
  "name": "http://TestApp",
  "password": "pppppppp-pppp-pppp-pppp-pppppppppppp",
  "tenant": "tttttttt-tttt-tttt-tttt-tttttttttttt"
}

Next, let's login as SP:

az login --service-principal --tenant tttttttt-tttt-tttt-tttt-tttttttttttt --username xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --password pppppppp-pppp-pppp-pppp-pppppppppppp

Output:

[
  {
    "cloudName": "AzureCloud",
    "id": "ssssssss-ssss-ssss-ssss-ssssssssssss",
    "isDefault": true,
    "name": "Subscription Name",
    "state": "Enabled",
    "tenantId": "tttttttt-tttt-tttt-tttt-tttttttttttt",
    "user": {
      "name": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "type": "servicePrincipal"
    }
  }
]

And now, let's try to create Key Vault policy:

az keyvault set-policy -n mdskv --upn tester@free-media.eu --secret-permissions get list

Output (client_exception):

GraphErrorException: Insufficient privileges to complete the operation.

But if we will try to set the same policy using User's obejctId instead of UPN:

az keyvault set-policy -n mdskv --object-id iiiiiiii-iiii-iiii-iiii-iiiiiiiiiiii --secret-permissions get list

Output:

{
  "id": "/subscriptions/ssssssss-ssss-ssss-ssss-ssssssssssss/resourceGroups/testrg/providers/Microsoft.KeyVault/vaults/mdskv",
  "location": "westeurope",
  "name": "mdskv",
  "properties": {
    "accessPolicies": [
      {
        "applicationId": null,
        "objectId": "iiiiiiii-iiii-iiii-iiii-iiiiiiiiiiii",
        "permissions": {
          "certificates": null,
          "keys": null,
          "secrets": [
            "get",
            "list"
          ],
          "storage": null
        },
        "tenantId": "tttttttt-tttt-tttt-tttt-tttttttttttt"
      }
    ],
    "createMode": null,
    "enableSoftDelete": null,
    "enabledForDeployment": false,
    "enabledForDiskEncryption": false,
    "enabledForTemplateDeployment": false,
    "sku": {
      "name": "standard"
    },
    "tenantId": "tttttttt-tttt-tttt-tttt-tttttttttttt",
    "vaultUri": "https://mdskv.vault.azure.net/"
  },
  "resourceGroup": "testrg",
  "tags": {},
  "type": "Microsoft.KeyVault/vaults"
}

So as we see, UPN-based policy creation does not work - we need to know an objectId of the user. In most cases (for me), my team mates uses UPN instead of objectId in their daily communication. Probably it is the same for you ;)
It is simple to get objectId for UPN if you are logged-in as User:

az ad user list --query "[?contains(objectId, 'iiiiiiii-iiii-iiii-iiii-iiiiiiiiiiii')]"

Output:

[
  {
    "displayName": "tester",
    "mail": null,
    "mailNickname": "tester",
    "objectId": "iiiiiiii-iiii-iiii-iiii-iiiiiiiiiiii",
    "objectType": "User",
    "signInName": null,
    "usageLocation": null,
    "userPrincipalName": "tester@free-media.eu"
  }
]

...and not so simple if you are logged-in as SP:

az ad user list --query "[?contains(objectId, 'iiiiiiii-iiii-iiii-iiii-iiiiiiiiiiii')]"

Output (client_exception):

GraphErrorException: Insufficient privileges to complete the operation.

That's because of no default privileges to read the directory for SP. I have described this case here. You need to add your SP to the "Directory Readers" AAD role to translate UPN to objectId.

comments powered by Disqus