microsoftgraph / msgraph-bicep-types

Repo contains Microsoft Graph resource types to integrate with bicep templates.
MIT License
43 stars 7 forks source link

appRoleAssignedTo fails when deployed by application in DevOps pipeline #125

Closed Agazoth closed 4 months ago

Agazoth commented 4 months ago

Bicep version 0.27.1

Resource and API version Microsoft.Graph/appRoleAssignedTo@v1.0

Auth flow Automated - Azure DevOps pipeline

Deployment details {"error":{"code":"BadRequest","target":"/resources/appRoleAssignedTo[1]","message":"Unsupported token. Unable to initialize the authorization context. Graph client request id: a294e9fc-7bd2-45fa-badc-c8f33c8b4250. Graph request timestamp: Mon, 27 May 2024 14:58:35 GMT."}} (Code:DeploymentOperationFailed) Status Message: {"error":{"code":"BadRequest","target":"/resources/appRoleAssignedTo[0]","message":"Unsupported token. Unable to initialize the authorization context. Graph client request id: e2a79716-fc70-4f3c-856c-f071586fa797. Graph request timestamp: Mon, 27 May 2024 14:58:35 GMT."}} (Code:DeploymentOperationFailed) CorrelationId: a05e1c13-c5aa-4c04-b2c6-4a5ee8aedf6c

Describe the bug The deployment runs as expected without the appRoleAssignedTo resource.

The deployment runs as expected with the appRoleAssignedTo resource when run from an interactive PowerShell console with a user having GA access

To Reproduce main.bicep

provider microsoftGraph

param resourceGroupName string = 'rg-myapp-graphtest'
param location string = 'westeurope'
param groupPrefix string = 'gt'
param environment string = 'd'
param webApiName string = 'MyAppWebApi'
param webAppName string = 'MyAppWebApp'
param uniqueName string = 't3st6raph'

targetScope = 'subscription'

resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
  name: resourceGroupName
  location: location
}

var appRoles = [
  {
    id: guid('a7eaacc4-21ff-4398-8f06-c84fc4b18666')
    value: 'MyApp.SuperUser'
    displayName: 'SuperUser'
    description: 'Grants SuperUser access to MyApp'
    allowedMemberTypes: ['User']
  }
  {
    id: guid('a7eaacc3-21ff-4398-8f06-c84fc4b18666')
    value: 'MyApp.User'
    displayName: 'User'
    description: 'Grants User access to MyApp'
    allowedMemberTypes: ['User']
  }
]

// Create roles
resource groups 'Microsoft.Graph/groups@v1.0' = [
  for (item, index) in appRoles: {
    displayName: '${groupPrefix}-${item.displayName}-${environment}'
    mailEnabled: false
    mailNickname: '${groupPrefix}${item.displayName}${environment}'
    uniqueName: '${groupPrefix}${item.displayName}${environment}'
    description: '${item.displayName} access to MyApp ${environment} application'
    securityEnabled: true
    owners: [
      apiSpn.id
    ]
  }
]

resource appRoleAssignedTo 'Microsoft.Graph/appRoleAssignedTo@v1.0' = [
  for (item, index) in appRoles: {
    principalId: groups[index].id
    resourceId: appSpn.id
    appRoleId: appRoles[index].id
  }
]

// Create spns and apps
resource apiSpn 'Microsoft.Graph/servicePrincipals@v1.0' = {
  displayName: '${webApiName}-${environment}'
  servicePrincipalType: 'Application'
  appId: apiApp.appId
  accountEnabled: true
}

resource apiApp 'Microsoft.Graph/applications@v1.0' = {
  displayName: '${webApiName}-${environment}'
  uniqueName: '${webApiName}-${environment}'
  signInAudience: 'AzureADMyOrg'
  api: {
    oauth2PermissionScopes: [
      {
        adminConsentDescription: 'Access MyApp as user'
        adminConsentDisplayName: 'Access MyApp as user'
        id: guid('a7eaacc9-ba31-4d61-89e7-88639da4a666') // "Random" guid
        isEnabled: true
        type: 'Admin'
        userConsentDescription: 'Access MyApp as user'
        userConsentDisplayName: 'Access MyApp as user'
        value: 'access_as_user'
      }
    ]
  }
  requiredResourceAccess: [
    {
      resourceAppId: '00000003-0000-0000-c000-000000000000'
      resourceAccess: [
        {
          id: 'e1fe6dd8-ba31-4d61-89e7-88639da4683d' // User.Read
          type: 'Scope' // The type of the permission (Scope or Role)
        }
      ]
    }
  ]
}

// Frontend app and spn

resource appSpn 'Microsoft.Graph/servicePrincipals@v1.0' = {
  displayName: '${webAppName}-${environment}'
  servicePrincipalType: 'Application'
  appId: appApp.appId
  accountEnabled: true
}

resource appApp 'Microsoft.Graph/applications@v1.0' = {
  displayName: '${webAppName}-${environment}'
  uniqueName: '${webAppName}-${environment}'
  signInAudience: 'AzureADMyOrg'
  spa: {
    redirectUris: [
      'https://app-${uniqueName}-webapi.azurewebsites.net'
    ]
  }
  appRoles: appRoles
  requiredResourceAccess: [
    {
      resourceAppId: apiApp.appId
      resourceAccess: [
        {
          id: apiApp.api.oauth2PermissionScopes[0].id //'a7eaacc9-ba31-4d61-89e7-88639da4a666' // access_as_user
          type: 'Scope' // The type of the permission
        }
      ]
    }
    {
      resourceAppId: '00000003-0000-0000-c000-000000000000'
      resourceAccess: [
        {
          id: 'e1fe6dd8-ba31-4d61-89e7-88639da4683d' // User.Read
          type: 'Scope' // The type of the permission
        }
      ]
    }
  ]
}

module addPreAuthApps 'modules/AddPreauthenticationToApplication.bicep' = {
  name: 'addPreauth'
  scope: resourceGroup
  params: {
    appId: appApp.appId
    parentAppUniqueName: apiApp.uniqueName
    delegatedPermissionIds: [
      apiApp.api.oauth2PermissionScopes[0].id
    ]
  }
}

module/AddPreauthenticationToApplication.bicep (preauthentication can only be done after app creation)

provider microsoftGraph

param parentAppUniqueName string
param appId string
param delegatedPermissionIds array

resource parentApp 'Microsoft.Graph/applications@v1.0' existing = {
  uniqueName: parentAppUniqueName
}

resource preAuth 'Microsoft.Graph/applications@v1.0' = {
  displayName: parentApp.displayName
  uniqueName: parentApp.uniqueName
  identifierUris: [
    'api://${parentApp.appId}'
  ]
  api: {
    preAuthorizedApplications: [
      {
        appId: appId
        delegatedPermissionIds: delegatedPermissionIds
      }
    ]
  }
}

Additional context The service principal running the pipeline is owner on the subscription and have these permissions: image

These access rights are in accordance with the highest privileges in the documentation found here: https://learn.microsoft.com/en-us/graph/templates/reference/overview?view=graph-bicep-1.0

dkershaw10 commented 4 months ago

@eketo-msft Please investigate this issue.

Agazoth commented 4 months ago

@dkershaw10 or @eketo-msft were you able to reproduce the issue? I still have it.

eketo-msft commented 4 months ago

Hey @Agazoth, the issued has been narrowed down to a downstream microservice. We are working with their engineering team to mitigate this issue and I hope to have an ETA today or tomorrow. Thank you for your patience.

eketo-msft commented 4 months ago

Hey @Agazoth, we are on track to resolve this issue early next week after the downstream microservice completes their deployment work. I'll let you know here when the issue is resolved so you can test again.

eketo-msft commented 4 months ago

Hey @Agazoth, downstream dependencies are updated, and testing looks good. Can you please retry your deployment and let me know if everything is working now? Thanks!

Agazoth commented 4 months ago

Hey @eketo-msft, yes, it works now. Thanks!