Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MgGraph Requires Extra Permissions? #1409

Closed
aress31 opened this issue Jul 20, 2022 · 8 comments
Closed

MgGraph Requires Extra Permissions? #1409

aress31 opened this issue Jul 20, 2022 · 8 comments

Comments

@aress31
Copy link

aress31 commented Jul 20, 2022

Just trying to figure out why using the PowerShell modules AzureAD and MSOnline do not yield the following error message that appears whenever trying a Connect-MgGraph:

needs permission to access resources in your organisation that only an admin can grant. Please ask an admin to grant permission to this app before you can use it.

I tried different variant such as Connect-MgGraph -Scopes Directory.Read.All but it is the same thing, trying to migrate out of the Azure AD Graph to the Microsoft Graph as recommended by Microsoft, however, I cannot even get a listing of AZUsers and AZGroups and other information that are designed to be readable and accessible to all in an Azure tenant.

I am obviously able to obtain the AZUsers and AZGroups via AzureAD/MSOnline.

Before anyone asks, I am a security professional auditing various client's Azure configurations and I can't just ask them to authorise the app, etc.

So just for my knowledge I would like to understand why this behaviour occurs and why AzureAD module works out of the box without the need for Azure admin to install/configure/give privs to any app to interact with the Azure AD graph.

Looking forward to some explanations.

@ghost ghost added the ToTriage label Jul 20, 2022
@ghost ghost added this to Issues to triage in Graph SDK - Triage Jul 20, 2022
@JustinGrote
Copy link

JustinGrote commented Jul 21, 2022

We had a discussion in the twitter spaces about this. Basically it's a disagreement in philosophy about what a "delegated" app should do vs an "application" app should do.

The Microsoft Graph authentication process leverages OAuth and OpenID connect which has a concept of scopes, that is, to provide granular permissions to an app to limit its access that an app can either be by default assigned or dynamically request.
https://docs.microsoft.com/en-us/graph/permissions-reference

However, there is a key difference between delegated (act on behalf of the user) and application scenarios (allow noninteractive behavior and use the ID of the service principal as the "user" who made the change). Even the documentation above states:
image

The disagreement in philosophy between some of the community and the PowerShell Graph SDK team is that, unlike some other apps that use OAuth where scopes is their only method of authorization and access control, Microsoft Graph has its own separate authorization system (RBAC) which is the roles you get assigned like Teams Admin, Global Admin, etc. and the delegated scopes to administrative units, etc.

While these scopes make sense to assign to an app that doesn't have this layer, it makes no sense with Graph, it's just an extra nuisance with no benefit. Even worse, it violates the separation of concerns security principle because you need someone with App Admin rights to bless access to someone who is already a Teams Admin. Why should the Teams Admin need to ask the App admin to do his job?

Per the discussion, it was thought that more safety controls is better, and it helps people not shoot themselves in the foot by accidentally running a phish or script as global admin without also having the proper scopes. The statement was around "zero trust" and other buzzwords.

While I understand this position, I fundamentally disagree with it because we already have a tool for this, it's called Azure AD PIM. PIM lets a user normally operate not under admin, and they have to PIM to their role. Even without Azure AD PIM, one can simply manually add themselves to global admin and then remove themselves, or use a separate account for that purpose. We have long standing practices about this that are well established controls, we don't need some silly additional scopes layer for this purpose

Further, once someone has been granted those scopes (similar to once they've been granted global admin), they now have them and the phishing attack is going to work regardless, you just added annoyance when what you should have done is educate the user to your procedures and policies before you gave them global admin in the first place (which, if they have, they are just gonna create a separate app with proper scopes and admin consent it to do their graph based stuff since they ARE A FREAKING GLOBAL ADMIN)

Again, I want to emphasize that scopes have their purpose and are absolutely a valuable security tool, such as limiting permissions and scopes to service principals. They make sense when you are making an app that should work in a particular area, such as reading a calendar or setting email or managing roles and you should explicitly define the blast radius of those apps.

However, for the delegated scenario to specifically Microsoft Graph SDK, it is a meta application that manages the entire Graph space, so it's explicit app scope is everything, and where a users permissions should be determined by their Azure AD role and their Azure Resource Roles, not granting all scopes is just a silly and wasteful extra hoop without conferring any actual security. It's like having one person check your ID badge at one door to confirm you are an admin, and then the next door, check that you work at the same company. The guy at the first door basically already did that by virtual of the fact you had a badge so the only purpose of the second guy was to annoy you and waste time.

The Azure Portal team understands this and that is why you don't have to specify scopes to use the Azure Portal.

Phishing and other unattended attacks would "work" just fine here (hijacking the auth cookie from the browser and making calls on behalf of the portal) at the same level as the PowerShell Graph SDK, so why does the PowerShell Graph SDK have to be different.

Mitigation

It is already possible to define your own delegated app within a tenant that has all the scopes, and specify the -clientid when connecting in a delegated scenario to basically get the desired behavior. Jeff Kazimer on the spaces discussion even stated its his preferred method. While it does help with the issue, it's my opinion this is too much friction, and the MS Graph team should publish a separate verified MS-level built in app similar to the existing one that can be select with a special switch like connect-mggraph -AllScopes. This role should be default consented into all tenants just like the existing ones, however admin consent would also be viable as a "one and done" option (which still requires an App Admin or higher to tell a Teams admin what they can and can't do, violating separation of concerns). It can only be used in delegated scenarios so all activity logs would still show the user who is doing the work and the user would still need some kind of role rights to actually be able to work.

Barring that, a simplified procedure or cmdlet to automate the creation of an app in your own tenant and instructions how to use $PSDefaultParameterValues to automatically specify that alternate app is another viable, if crappy and high friction, alternative.

@JustinGrote
Copy link

JustinGrote commented Jul 21, 2022

@aress31 as to answer your specific question, AzureAD module uses a completely separate deprecated API that isn't as secure as Microsoft Graph, and it is going away, but I agree it shouldn't be harder to use in my opinion for the delegated "act as user" scenario.

@darrelmiller
Copy link
Contributor

I was in the process of suggesting the following... If you are a global admin of your tenant, you are welcome to go into the Enterprise Applications blade, find the Microsoft Graph PowerShell application and grant admin consent to the app for all the permissions for all users in your tenant. However, when I tried it, only a subset of permissions were consented. I think we should be able to configure that to allow you to consent to all permissions. This would make it mostly a one-time setup. /cc @maisarissi

Now, we could change our appId to what we call a first-party appId and get pre-consent for all permissions in all tenants. That's what Azure AD PowerShell did many years ago. However, in today's environment we will never get that past our security reviews. Consenting to applications is a level of control that tenant administrators want. Our Microsoft tenant administrators will not consent our Graph PowerShell built-in clientId to permissions in our Microsoft tenant. It is the organization's data and the admins' responsibility to protect that data and they expect to have that level of control, even if users have access to the data.

How would you feel about a one-time operation per tenant where you go to the Azure Portal and effectively say "users do not have to consent the Graph PowerShell SDK" ?

@JustinGrote
Copy link

JustinGrote commented Jul 21, 2022

This doesn't solve @aress31's scenario but I do think it's a good option, however is this going to be a special snowflake process just for Graph PowerShell SDK? Seems like you'd need a slew of checkboxes for every app that does meta.

"Our Microsoft tenant administrators will not consent our Graph PowerShell built-in clientId to permissions in our Microsoft tenant."
Then they shouldn't grant the relevant Azure AD Roles in the first place. This is the part I don't get. This makes sense for userspace data scopes like Calendar.ReadWrite where the user has default rights to that info for themselves, but for all the admin-type stuff like RoleAssignmentSchedule.ReadWrite.Directory it just doesn't make any sense whatsoever when you already have control of that via the roles you delegate.

I feel any role that a user does not have permissions to by default as a "normal user" should be included by default in the Graph API, because authorization is controlled by the venerable RBAC permissions and not some silly scope gatekeeping that has no granularity whatsoever (Sites.Selected being the current exception to that, which is extremely cumbersome vs. an RBAC based approach)

@JustinGrote
Copy link

JustinGrote commented Jul 21, 2022

And again to be very clear this is in the "delegated" scenario, not "application" scenario. I feel like not enough people understand the difference and so they see something like RoleAssignmentSchedule.ReadWrite.Directory and freak out without realizing they can't actually do anything unless they have the correct corresponding RBAC permission. This confusion is I think the biggest thing that is causing this friction and it's all borne out of FUD and ignorance (the good kind).

So @darrelmiller I still think delegated should be there by default, but I still think application SPs should follow the current procedures, and the default graph app should not be allowed to operate as an application SP, that would be a huge red flag.

@peombwa peombwa removed this from Issues to triage in Graph SDK - Triage Jul 25, 2022
@jpitcairn
Copy link

jpitcairn commented Sep 30, 2022

Just adding a voice in support of this.

like the original poster, I also conduct security assessments of clients azure tenants. Customers usually provide us with a user account with global reader/rbac reader permissions. Our more savvy customers will happily setup a SP with the appropriate permissions.

The graph app should have all scopes consented by default for delegated permissions just like AAD PowerShell/Az CLI.

I believe asking customers to setup delegated permissions to the graph app is going to cause some friction either due to a lack of understanding or corporate policy that prevents such a change.

@darrelmiller
Copy link
Contributor

Even in a delegated scenario there are two distinct security controls for all applications that call Microsoft Graph. There is what a user can do and what the application can do. Tenant administrators have told us that they need to ability to control what an application is allowed to do, irrespective of who the user is. It may be friction for administrators, but it is the level of control that administrators have asked for. Some might argue that PowerShell modules are different because they are intended to apply to the entire Graph surface area. That's fair, but there are other tenant administrators that don't agree. Microsoft IT will not consent the Graph PowerShell default appId to call the Microsoft tenant. That is their choice to make.

The graph app should have all scopes consented by default for delegated permissions just like AAD PowerShell/Az CLI.

Unless we get the ability to lock down the use of that appId to only be usable by PowerShell cmdlets published by Microsoft, this is never going to be an acceptable solution. It would make consent in every other application completely pointless because anyone could just borrow the appId to avoid consent in any application. Currently in OAuth2 there is no way to protect Public Client applications from impersonation, that I know of.

Even if we the Graph SDK team thought that pre-consented permissions were the right choice, in today's security environment, we would never be allowed to ship it. Azure PowerShell/CLI comes from a different world where historically the only scope for Azure APIs is user_impersonation. The only reason it has some Graph scopes consented is because someone decided breaking existing customers was a bigger risk than the security risk.

I believe asking customers to setup delegated permissions to the graph app is going to cause some friction either due to a lack of understanding or corporate policy that prevents such a change.

Yes it will cause friction. Security usually does. We need to do a better job of educating customers why they need to do this. If corporate policy prevents user consent, then we need to respect that. We can't pick and choose when corporate policies apply.

@ghost
Copy link

ghost commented Jan 28, 2023

This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants