-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Describe the bug
This command (and likely the other variations) performs object lookups in graph by display name. This is fundamentally inappropriate especially for a security-focused command that is meant to create a new identity and permission. Instead, this command attempts to find any existing one, and remove its existing credentials, set new ones, and assign RBAC to whatever it found.
Display name is not unique for applications or service principals, can be edited at any time, and can be different between them. Yet these commands treat display name like a durable identifier and attempt make arbitrary credential and rbac modifications to resolved identities.
Related command
az ad sp create-for-rbac
Errors
n/a
Issue script & Debug output
Take a look at this sequence of calls (I have edited the values of IDs etc for the purposes of this comment):
az ad sp create-for-rbac -n $appDisplayName --role 'Azure Service Bus Data Owner' --scopes /subscriptions/$($SubscriptionId) --debugThis command begins by trying to find ANY existing service principal with that display name:
GET /v1.0/servicePrincipals?$filter=displayName%20eq%20%27MessagingTestApp%27
{"@odata.context":https://graph.microsoft.com/v1.0/$metadata#servicePrincipals,"value":[]}This is already a huge problem, there can be many service principals already existing. This command is meant to create a new application, not find some arbitrary identity in the customer directory and start messing with its configuration and potentially grant it new permissions!
In our case, no service principal was found with this displayname, so the command next proceeds to try and find ANY application with that display name:
GET /v1.0/applications?$filter=startswith%28displayName%2C%27MessagingTestApp%27%29 HTTP/1.1
{"@odata.context":https://graph.microsoft.com/v1.0/$metadata#applications,"value":[{
"id":"cfbf39d0-df91-4ea9-95f3-f6931f6d282a","createdDateTime":"2025-10-16T23:50:48.7381945Z","deletedDateTime":null,"appId":"2f1
5aec7-a6e3-43f9-b802-94627dc4e511","description":null,"displayName":"MessagingTestApp","identifierUris":[],"notes":null,"signInA
udience":null,"tags":[],"additionalData":[],"api":{"requestedAccessTokenVersion":null},"appRoles":[],"info":{"logoUrl":null,"mar
ketingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"passwordCredentials"
:[{"customKeyIdentifier":"","displayName":"rbac","endDateTime":"2026-10-16T23:53:17Z","hint":"Q2O","keyId":"6dd17918-2845-4121-8
fd4-35c0ffc7e235","secretText":null,"startDateTime":"2025-10-16T23:53:17Z"}],"publicClient":{"redirectUris":[]},"spa":{"redirect
Uris":[]},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableIdTokenIssuance":false,"e
nableAccessTokenIssuance":false}}}]}In our case, it has found an already-existing application, that someone else could've created for a completely different application / test environment! It then proceeds to patch the display name on this application for no reason, since it just looked this up by display name:
PATCH /v1.0/applications/cfbf39d0-df91-4ea9-95f3-f6931f6d282a HTTP/1.1
{"displayName": "MessagingTestApp"}Next, it does another GET request for the same application it already found (why?):
GET /v1.0/applications/cfbf39d0-df91-4ea9-95f3-f6931f6d282a HTTP/1.1
{"@odata.context":https://graph.microsoft.com/v1.0/$metadata#applications/$entity,"i
d":"cfbf39d0-df91-4ea9-95f3-f6931f6d282a","createdDateTime":"2025-10-16T23:50:48.7381945Z","deletedDateTime":null,"appId":"2f15a
ec7-a6e3-43f9-b802-94627dc4e511","description":null,"displayName":"MessagingTestApp","identifierUris":[],"notes":null,"signInAud
ience":null,"tags":[],"additionalData":[],"api":{"requestedAccessTokenVersion":null},"appRoles":[],"info":{"logoUrl":null,"marke
tingUrl":null,"privacyStatementUrl":null,"supportUrl":null,"termsOfServiceUrl":null},"keyCredentials":[],"passwordCredentials":[
{"customKeyIdentifier":"","displayName":"rbac","endDateTime":"2026-10-16T23:53:17Z","hint":"Q2O","keyId":"6dd17918-2845-4121-8fd
4-35c0ffc7e235","secretText":null,"startDateTime":"2025-10-16T23:53:17Z"}],"publicClient":{"redirectUris":[]},"spa":{"redirectUr
is":[]},"web":{"homePageUrl":null,"logoutUrl":null,"redirectUris":[],"implicitGrantSettings":{"enableIdTokenIssuance":false,"ena
bleAccessTokenIssuance":false}}}Then, it proceeds to just remove the password credentials from this application completely! This breaks whatever was actually using that!!
POST /v1.0/applications/cfbf39d0-df91-4ea9-95f3-f6931f6d282a/removePassword HTTP/1.1It then places a new one on the application:
POST /v1.0/applications/cfbf39d0-df91-4ea9-95f3-f6931f6d282a/addPassword HTTP/1.1
{"passwordCredential": {"displayName": "rbac", "endDateTime": "2026-10-16T23:53:49Z",
"startDateTime": "2025-10-16T23:53:49Z"}}
{"@odata.context":"https://graph.microsoft.com/v1.0/$metadata#microsoft.graph.password
Credential","customKeyIdentifier":null,"displayName":"rbac","endDateTime":"2026-10-16T23:53:49Z","hint":"65x","keyId":"29fadcbe-
70e1-4a45-8fc3-e97c093b701a","secretText":"[redacted]","startDateTime":"2025-10-16T23:53:49Z"}Lasty, it attempts to create a service principal for this application, but one already exists, so it fails:
POST /v1.0/servicePrincipals HTTP/1.1
{"appId": "2f15aec7-a6e3-43f9-b802-94627dc4e511", "accountEnabled": true}
{"error":{"code":"Request_MultipleObjectsWithSameKeyValue","message":"Another object with the
same value for property servicePrincipalNames already exists.","details":[{"code":"ObjectConflict","message":"The service
principal cannot be created, updated, or restored because the service principal name 2f15aec7-a6e3-43f9-b802-94627dc4e511 is
already in use.","target":"servicePrincipalNames"}]}}Expected behavior
This command should NEVER assume modification for an existing application or service principal, and none of these commands should ever do lookups based on display name. Let the customer grep by display name in a separate call and be responsible to pass-in the specific and discrete appId or objectId for an existing identity to modify, otherwise, this command and its counterpart(s) should ONLY create net-new identities.
Environment Summary
azure-cli 2.67.0 *
Additional context
No response