Azure manage App Registration secrets API using a Service Principal user

347 Views Asked by At

Context

I'm implementing a service to rotate the secrets of the service principals. The authenticated user must be a Service Principal and it can only update the secrets from specifics service principals of my organization.

Ex.:

  • Service Principal: aadapp-manage -> this is the authenticated service principal
  • Service Principal: aadapp-user-01 -> this is a specifc SP that aadapp-manage can manage its secrets
  • Service Principal: aadapp-user-02 -> this is a specifc SP that aadapp-manage can manage its secrets
  • Service Principal: aadapp-user-03 -> this SP CANNOT be have its secrets modified by the aadapp-manage SP.

What I did

  • Created an AD Role named Got-ManagedSecrets-Role and assign the microsoft.directory/servicePrincipals/synchronizationCredentials/manage permission. Then, within the PIM, I assigned
  • Created an AD Group named aadgrp-managed-secrets and added the SPs aadapp-user-01 and aadapp-user-02.
  • Underneath PIM, created an assignment with the following entries:
    • Role: Got-ManagedSecrets-Role
    • Scope: Group
    • Selected Scope: aadapp-manage
    • Selected Application: aadgrp-managed-secrets

I granted Delegated / Application.ReadWrite.All, one of the required permission described in the MS Docs, but this is not useful when I want to restrict the SP that my authenticated user can do.

Source: https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0&tabs=http

enter image description here

Test Cases

HTTP Request 01

Validate if aadapp-managed-secrets SP can generate a secret for aadapp-user-01. Expeccted result: YES

POST /v1.0/applications(appId='[USER-01-ID]')/addPassword HTTP/1.1
Host: graph.microsoft.com
Content-Type: application/json
Authorization: Bearer [TOKEN]
Content-Length: 96

{
  "passwordCredential": {
    "displayName": "New Secret"
  }
}

Response

Status: OK (new secret generated)

HTTP Request 02

Validate if aadapp-managed-secrets SP can generate a secret for aadapp-user-02. Expeccted result: YES

POST /v1.0/applications(appId='[USER-02-ID]')/addPassword HTTP/1.1
Host: graph.microsoft.com
Content-Type: application/json
Authorization: Bearer [TOKEN]
Content-Length: 96

{
  "passwordCredential": {
    "displayName": "New Secret"
  }
}

Response

Status: OK (new secret generated)

HTTP Request 03

Validate if aadapp-managed-secrets SP CANNOT generate a secret for aadapp-user-03. Expeccted result: NO

POST /v1.0/applications(appId='[USER-03-ID]')/addPassword HTTP/1.1
Host: graph.microsoft.com
Content-Type: application/json
Authorization: Bearer [TOKEN]
Content-Length: 96

{
  "passwordCredential": {
    "displayName": "New Secret"
  }
}

Response

Status: OK (new secret generated). At this point, my test failed.

Problem

Given that (at least what I thought) I setup the Role and the assignment, it seems that the Graph API step through those securities concerns.

Any thoughts?

1

There are 1 best solutions below

0
Rukmini On

Note that, microsoft.directory/servicePrincipals/credentials/update, microsoft.directory/applications/credentials/update and microsoft.directory/servicePrincipals/synchronizationCredentials/manage permissions are required to create secrets for Service principal.

I created four Azure AD Applications like below:

enter image description here

And created a group aadgrp-managed-secrets and added Service Principals as members:

enter image description here

Now, created a custom role and assigned to the group as scope and aadgrp-managed-secrets as member:

enter image description here

enter image description here

I generated access token for aadapp-manage like below:

https://login.microsoftonline.com/TenantID/oauth2/v2.0/token

client_id:ClientID
client_secret:ClientSecret
scope:https://graph.microsoft.com/.default
grant_type:client_credentials

enter image description here

When I tried to create secret for aadapp-user-03, it got created, but it shouldn't be the case:

POST https://graph.microsoft.com/v1.0/applications/{id}/addPassword
Content-type: application/json

{
  "passwordCredential": {
    "displayName": "Password friendly name"
  }
}

enter image description here

Note that: As you granted Admin consent to the API permission Application.ReadWrite.All of the Application aadapp-manage, it is not possible to restrict the application to stop creating the secrets for aadapp-user-03. The Application can create secrets for all the applications in the tenant. The Graph API permission is allowing the Application to create secrets through those security concerns.

Reference:

Custom role permissions for app registration - Microsoft Entra