Tagging service principals with az ad sp update --id appID --add tags throws "Update to existing credential with KeyId 'keyID' is not allowed."
Describe the bug @jiasli New issue here. Thanks for all the examples of utilizing az rest to call service principals. I'm fighting with a possible edge case now. In an attempt to categorize and programmatically rotate client secrets we're aiming to use Tags on service principal objects. For the most part, this works fine by running az commands like: az ad sp update --id appID --add tags "tags:value"
Before I got to this point I ran into the nanosecond/microsecond Azure Portal bug with az cli and I am getting similar behavior when trying to update tags on a service principal using the above command. The client secrets were set using the "old" method, outlined below:
$servicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $spn.ApplicationId
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($servicePrincipal.Secret)
$spnPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
$SecureStringPassword = ConvertTo-SecureString -String $spnPassword -AsPlainText -Force
New-AzureRmADAppCredential -ApplicationId $spn.ApplicationId -Password $SecureStringPassword
When trying to tag service principals created this way I am finding the generic error: az : Update to existing credential with KeyId 'keyID' is not allowed.
Do you have any working examples of updating tags with the az rest method? I can't seem to get the payload correct. az rest -m "PATCH" -u https://graph.microsoft.com/v1.0/servicePrincipals/objID --headers "Content-Type=application/json" -b '{"tags":""tag:value""}'
Any help is appreciated, thanks!
To Reproduce Trying to apply a tag on service principal objects which contain "un-supported" client secrets throws the below error: az : Update to existing credential with KeyId 'keyID' is not allowed.
Expected behavior
Tags are set on the service principal successfully when I use the az ad sp tag command against service principals created the below method:
$servicePrincipal = New-AzADServicePrincipal -ApplicationId $appRegistration.ApplicationId
$azContext = Get-AzContext
$cache = $azContext.TokenCache
$cacheItems = $cache.ReadItems()
$azureADToken = ($cacheItems | where { $_.Resource -eq "https://graph.windows.net/" })
Connect-AzureAD -AadAccessToken $azureADToken.AccessToken -AccountId $azContext.Account.Id -TenantId $azContext.Tenant.Id
$endDate = (Get-Date).AddMonths(16)
$spnPassword = New-AzureADApplicationPasswordCredential -ObjectId $appRegistration.ObjectId -EndDate $endDate
add to S174
I can still repro this issue with AzureAD PowerShell module:
> Install-Module AzureAD
> Get-InstalledModule
Version Name Repository Description
------- ---- ---------- -----------
2.0.2.137 AzureAD PSGallery Azure Active Directory V2 General Availability Module....
> Connect-AzureAD -TenantId 54826b22-38d6-4fb2-bad9-b7b93a3e9c5a
> $endDate = (Get-Date).AddMonths(16)
> New-AzureADApplicationPasswordCredential -ObjectId ab2a396e-b4d4-4055-86ef-ef8917b04246 -EndDate $endDate
> az ad app show --id ab2a396e-b4d4-4055-86ef-ef8917b04246 --debug
msrest.http_logger: Request URL: 'https://graph.windows.net/54826b22-38d6-4fb2-bad9-b7b93a3e9c5a/applications/ab2a396e-b4d4-4055-86ef-ef8917b04246?api-version=1.6'
msrest.http_logger: Request method: 'GET'
...
msrest.http_logger: Response status: 200
msrest.http_logger: Response content:
"endDate":"2022-12-06T03:09:45.2705195Z"
^
Does it work if you use Azure CLI to create the service principal and its credentials, bypassing the nanosecond bug of AzureAD (or perhaps its design)? https://github.com/Azure/azure-cli/issues/12561#issuecomment-604991103
Per the definition of tags of Application and Service Principal:
tags: String collection, Custom strings that can be used to categorize and identify the application/service principal. Not nullable.
To update tags on applications, call Microsoft Graph API Update application:
az rest --method PATCH --url https://graph.microsoft.com/v1.0/applications/ab2a396e-b4d4-4055-86ef-ef8917b04246 --body '{"tags":["mytag1_app"]}'
az rest --method GET --url https://graph.microsoft.com/v1.0/applications/ab2a396e-b4d4-4055-86ef-ef8917b04246
...
"tags": [
"mytag1_app"
],
To update tags on service principals, call Microsoft Graph API Update servicePrincipal:
$ az rest --method PATCH --url https://graph.microsoft.com/v1.0/servicePrincipals/52e3d1ac-48c1-4486-8ed6-ad99a74415a7 --body '{"tags":["mytag2_sp"]}'
$ az rest --method GET --url https://graph.microsoft.com/v1.0/servicePrincipals/52e3d1ac-48c1-4486-8ed6-ad99a74415a7
...
"tags": [
"mytag2_sp",
"mytag1_app"
],
The above script only works in Bash (including Azure Cloud Shell). If you use PowerShell to call az command, beware of Quoting issues with PowerShell. You will need to escape double quotes with \:
... --body '{\"tags\":[\"mytag2_sp\"]}'
So, I can't seem to get the az rest call to work by loading an external file. No error is returned so it seems the call is succeeding but 'Tags' are not added to the SP manifest.
$updspn = (az rest --method PATCH --url https://graph.microsoft.com/v1.0/servicePrincipals/$($spn.id) --body "@.temp-body-tags.json" | ConvertFrom-Cli)
the .temp-body-tags.json file contains the following (as compressed JSON):
{"tags":["HideApp","WindowsAzureActiveDirectoryIntegratedApp"]}
Anyone?
@SjoerdV, could you share the --debug log?
seems to be getting a correct 204 reply, but the manifest of the App Principle stays empty (I changed the actual SP id to an empty guid in the snippet below, rest is as-is)
INFO: cli.azure.cli.core.util: Request URL: 'https://graph.microsoft.com/v1.0/servicePrincipals/00000000-0000-0000-0000-000000000000'
INFO: cli.azure.cli.core.util: Request method: 'PATCH'
INFO: cli.azure.cli.core.util: Request headers:
INFO: cli.azure.cli.core.util: 'User-Agent': 'python/3.10.4 (Linux-5.4.0-121-generic-x86_64-with-glibc2.31) AZURECLI/2.37.0 (DEB)'
INFO: cli.azure.cli.core.util: 'Accept-Encoding': 'gzip, deflate'
INFO: cli.azure.cli.core.util: 'Accept': '*/*'
INFO: cli.azure.cli.core.util: 'Connection': 'keep-alive'
INFO: cli.azure.cli.core.util: 'x-ms-client-request-id': '393faecd-48b7-4706-be0b-b68598c44fad'
INFO: cli.azure.cli.core.util: 'Content-Type': 'application/json'
INFO: cli.azure.cli.core.util: 'CommandName': 'rest'
INFO: cli.azure.cli.core.util: 'ParameterSetName': '--method --url --debug --body'
INFO: cli.azure.cli.core.util: 'Authorization': 'Bearer eyJ0eXAiOiJKV...'
INFO: cli.azure.cli.core.util: 'Content-Length': '63'
INFO: cli.azure.cli.core.util: Request body:
INFO: cli.azure.cli.core.util: {"tags":["HideApp","WindowsAzureActiveDirectoryIntegratedApp"]}
DEBUG: urllib3.connectionpool: Starting new HTTPS connection (1): graph.microsoft.com:443
DEBUG: urllib3.connectionpool: https://graph.microsoft.com:443 "PATCH /v1.0/servicePrincipals/00000000-0000-0000-0000-000000000000 HTTP/1.1" 204 0
INFO: cli.azure.cli.core.util: Response status: 204
INFO: cli.azure.cli.core.util: Response headers:
INFO: cli.azure.cli.core.util: 'Cache-Control': 'no-cache'
INFO: cli.azure.cli.core.util: 'Strict-Transport-Security': 'max-age=31536000'
INFO: cli.azure.cli.core.util: 'request-id': 'c791143d-6505-43c8-9c0b-94289eb1b717'
INFO: cli.azure.cli.core.util: 'client-request-id': 'c791143d-6505-43c8-9c0b-94289eb1b717'
INFO: cli.azure.cli.core.util: 'x-ms-ags-diagnostic': '{"ServerInfo":{"DataCenter":"West Europe","Slice":"E","Ring":"5","ScaleUnit":"005","RoleInstance":"AM4PEPF0001514D"}}'
INFO: cli.azure.cli.core.util: 'x-ms-resource-unit': '1'
INFO: cli.azure.cli.core.util: 'Date': 'Tue, 28 Jun 2022 22:27:20 GMT'
INFO: cli.azure.cli.core.util: Response content:
INFO: cli.azure.cli.core.util:
DEBUG: cli.knack.cli: Event: CommandInvoker.OnTransformResult []
DEBUG: cli.knack.cli: Event: CommandInvoker.OnFilterResult []
DEBUG: cli.knack.cli: Event: Cli.SuccessfulExecute []
I did notice that the tags were present after running az ad sp list:
...
resourceSpecificApplicationPermissions : {}
samlSingleSignOnSettings :
servicePrincipalNames : {00000000-0000-0000-0000-000000000000}
servicePrincipalType : Application
signInAudience : AzureADMyOrg
tags : {WindowsAzureActiveDirectoryIntegratedApp, HideApp}
tokenEncryptionKeyId :
verifiedPublisher : @{addedDateTime=; displayName=; verifiedPublisherId=}
...
But they were not in the Manifest page of the app in the Azure Portal: https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Manifest/appId/00000000-0000-0000-0000-000000000000/isMSAApp~/false
...
"samlMetadataUrl": null,
"signInUrl": null,
"signInAudience": "AzureADMyOrg",
"tags": [],
"tokenEncryptionKeyId": null
}
@SjoerdV, as az ad sp list is working as expected, I think this is a service issue. Could you create a support ticket to AAD team instead? Thanks for understanding.