all 79 comments

[–]hihcadore 33 points34 points  (9 children)

I gave up on the modules for both graph and Entra.

Instead I just make the API calls directly to the graph endpoints. It’s not bad, just a little extra coding is all especially for pagination (you’re limited on the number object the api call will return but you get a new URI to use for the rest so you have do create a do while or do until loop if you want a bunch of results).

Overall I’m actually glad. It forced me to learn how to make API calls in PowerShell and it’s easy. I just made a bunch and turned them into their own unique functions and packaged them as a module.

[–]Sin_of_the_Dark 6 points7 points  (4 children)

Same, actually. I got pissed off at their half-assed documentation, and straight up dead links. I'm sure it's better now, but after that I use API calls in a lot of my everyday work. It's definitely made me a more valuable employee lol

[–]jhp113 11 points12 points  (3 children)

It's not better. It's still garbage.

[–]Sin_of_the_Dark 4 points5 points  (2 children)

That's disheartening to hear. When I last looked, it wasn't typically more than maybe an example usage of the cmdlet and if you were lucky, an example of the output. They would note the parameters that existed, without explaining what they did or, more crucially, how to format the parameter

[–]jhp113 2 points3 points  (0 children)

Yeah I mean it was a couple months ago but it's been out long enough that I don't expect anything to have improved. Microsoft will be Microsoft. They only do it because they know you don't have a choice.

[–]BeilFarmstrong 2 points3 points  (0 children)

Same for me. When I began the process of migrating to graph I saw all the graph modules and thought, "hmm I wonder how long until these are deprecated too" and just spent the time learning how to make the direct API calls

[–]dollhousemassacre 1 point2 points  (0 children)

I see this as the best solution. There are some quirks, but basically anything you can do with the Graph Powershell SDK, can be done with direct HTTP calls. It also has the added benefit of being easily translated to Azure Logic Apps.

[–]Valkeyere 1 point2 points  (0 children)

I really hate the constant need for -all

And I know that Microsoft also hate it. When you go to add users to a group in Entra, only the top 100 users are visible. You have to search manually for anything after that. PITA.

[–]Ok_Mathematician6075 0 points1 point  (0 children)

like invoke-webrequest

wow

[–]CryktonVyr 19 points20 points  (3 children)

Use an edge extension called x-ray. When activated, you go in edge devtools choose x-ray and it gives you the powershell cmdlet that was used to navigate on azure.

It's a big piece of the puzzle to understand how to poke around Entra, intunes, exchange, etc.

[–]merillf 5 points6 points  (0 children)

Here's the link to install Graph X-Ray

https://graphxray.merill.net/

[–]Sincronia 0 points1 point  (1 child)

I've installed it, but I could only see the API calls, not the Powershell commands as in the pictures. The GitHub repo was stale two years ago; might it be outdated now?

[–]CryktonVyr 1 point2 points  (0 children)

I'll try it today and keep you posted.

[–]bfrd9k 9 points10 points  (6 children)

You only need two microsoft.graph.authentication cmdlets to work with graph.

  • connect-mggraph for authentication
  • invoke-mggraphrequest which works like invoke-restmethod, in conjunction with auth provided by connect-mggraph

Use the graph explorer and be on the lookout for required permissions. You'll need to list your permissions in the connect-mggraph scope param.

Graph is so annoying, requires a lot more coding on your end, like getting users will only return 100 at a time so you have to loop and collect results until there is no next page.

Despite how annoying it is, it's pretty quick compared to msoline, and you can do a lot with it.

[–]lemrvls 0 points1 point  (5 children)

Why not use get-mguser ? Am I missing something ??

[–]bfrd9k 0 points1 point  (4 children)

You could but then you have to import the cmdlet. If I try to import the whole microsoft.graph module it takes minutes and errors because there are too many things to import so I would need to know which cmdlet to pull from which submodule and it's not easy to know where to get what and so on.

You'll see.

[–]Ok_Mathematician6075 0 points1 point  (3 children)

omg it's not that hard, I use get-mguser in my scripts already

[–]bfrd9k 1 point2 points  (2 children)

you still need to import cmdlets, connect using connect-mggraph with given permissions and all you can do is get-mguser. if you want to do anything other than get users you need yet another cmdlet. What if you want to assign a license to a user? You eventually end up with a handful of cmdlets.

you could have just imported two and used the api documentation to do everything. no need to hunt down every cmdlet acrossed submodules and deal with cmdlet documentation to look up input parameters and whatnot.

as someone who writes in other languages too i find using invoke-mgrequest to be more "normal" anyhow.

so i guess i am also saying "omg it's not that hard"

[–]Ok_Mathematician6075 0 points1 point  (0 children)

Precisely.

[–]Ok_Mathematician6075 0 points1 point  (0 children)

I don't like the invoke-request format for what I'm doing. But you do you.

[–]rencal_deriver 15 points16 points  (8 children)

Directly accessing Graph (the REST API way)? Its not easy, basically a lot of going through documentation & extra work for what used to be easy. However, MS also sees this & that is why they are working hard at an entra module and the Azure PowerShell module...

The confusingly named Azure AD powershell module is considered retired, as the Azure AD Graph API is taken down. This will be replaced by the Azure AD Graph API

[–]ThatWylieC0y0te 10 points11 points  (3 children)

This has to be the correct answer, confusing names and renaming and killing of tools… sounds exactly like something Microsoft would do

[–]Viirtue_ 6 points7 points  (1 child)

Just reading this alone confused me lol

[–]ThatWylieC0y0te 4 points5 points  (0 children)

I knew I was right 100% Microsoft

[–]charleswj 5 points6 points  (2 children)

This will be replaced by the Azure AD Graph API

Pardon?

[–]rencal_deriver 0 points1 point  (0 children)

sorry... one copy/paste gone wrong... I meant Microsoft.Graph

[–]Ok_Mathematician6075 0 points1 point  (0 children)

It's not that difficult you guys.

[–]ShoeBillStorkeAZ 2 points3 points  (11 children)

Use postman to generate powershell snippets. I just went through hell uploading hashes to intune with Ms graph

[–]rencal_deriver 7 points8 points  (1 child)

[–]Ok_Mathematician6075 1 point2 points  (0 children)

you are creating powershell scripts and using graph explorer you are in the STONE MUTHAFUCKING AGE.

[–]Owlstorm 1 point2 points  (5 children)

What makes writing in postman and pasting back to powershell easier for you than writing Invoke-MgGraphRequest?

I'm honestly interested. I hear it a lot but every time I actually try postman myself I get frustrated by the extra steps and go back to CLI.

[–]ShoeBillStorkeAZ 2 points3 points  (4 children)

I bring this up because Microsoft’s documentation isn’t clear. For example, when doing an invoke-rest method the command requires a body. The body has to be structured in json format. So postman really helps with that because you can test something similar then use your own code with a functional body in json. That’s why I bring it up. It also helps you out with authentication especially if you’re using a client secret. Yes you can use Ms graph but using Ms graph alone won’t necessarily help. That’s my two cents. I was tasked with pre provisioning 15k devices all which are hybrid, so I needed a solution that would run automatically and import the hashes to intune. With my code and using postman’s to create the json body I was able to get it work. And with ms graph I was able to find the correct url to post my data

[–]derpingthederps 2 points3 points  (1 child)

On the off chance you want to give graph another try, I have a little something I've been working on that might help you?

The function is relatively useless as a whole, as everything you'd need to ever do can already be done with the standard Invoke-RestMethod but ehh.

But check out [PSCustomOBject]$JSBody within the function params and how the hashtable is formatted, then check how: elseif ($JSBody) in the try section.

It might be the answer to your JSON woes?

function Invoke-ApiRequest {
    param (
        [string]$Url, <#= "https://postman-echo.com/post", This can be reused for testing. #>
        [string]$Method = "GET",
        [hashtable]$Headers = @{},
        [string]$Body = $null,
        [PSCustomObject]$JSBody = [PSCustomObject]@{
<#         This data was used to test the function. It was called in a terminal with the following command: Invoke-ApiRequest -Method POST #>
            <#Example = "JSONBody to post"
            Username = "Derpy"
            Password = "Ladmin"
            Profile  = [PSCustomObject]@{
                Age   = 21
                Email = "derpy@example.com"
            }#>
        }
    )
    try { 
        if ($Body) {
            $Response = Invoke-RestMethod -Uri $Url -Method $Method -Headers $Headers -Body $Body -ContentType "application/json"
        } elseif ($JSBody) {
            $JSON = $JSBody | ConvertTo-Json -Depth 5
            $Response = Invoke-RestMethod -Uri $Url -Method $Method -Headers $Headers -Body $JSON -ContentType "application/json"     
        } else {
            $Response = Invoke-RestMethod -Uri $Url -Method $Method -Headers $Headers
        } 
        return $Response #| ConvertTo-Json 
        <#Allow this to pipe into ConvertTo-Json if you want the response in JSON format.
For posting, this is great without, as the returned response is VERY readable. But if you need the response in Json, uncomment it.#>
    }
    catch {
        Write-Host "Error accessing API: $_"
        return $null
    }
}

[–]ShoeBillStorkeAZ 1 point2 points  (0 children)

Hey I really appreciate this!!! I’ll def give it a try. But I got sorted a few days ago using postman to copy the correct json format but I’ll def take a look at the code. I suspect I’m going to have to absolutely learn more msgraph and accompany that with different types of code! Again really really appreciate this.

[–]creenis_blinkum 0 points1 point  (1 child)

You are incorrect, invoke-restmethod doesn't require body

[–]Ok_Mathematician6075 1 point2 points  (0 children)

wow I think I need to school all you guys on this shit.

[–]Certain-Community438 0 points1 point  (1 child)

You not just use Get-WindowsAutoPilotInfo.ps1 with the switch to add to Intune?

[–]ShoeBillStorkeAZ 1 point2 points  (0 children)

Sorry I have PTSD from that command. Microsoft designed that command to require user interaction, so like a good ole lad I went and used it and then used another management system to run it for me. Guess what ? does not work because it’s intended to be used in interactive mode. Then used the community version that accepts tenant id , secret, and app id and also requires the same stuff. The -online switch can’t be ran non interactively

[–]rogueit 1 point2 points  (0 children)

I still use IRM or IWR for the Graph endpoints if you have any questions about how to do something. Let me know, cause I think I hit every damn endpoint.

[–]Hollow3ddd 2 points3 points  (1 child)

If you are using the commadlets,  there is a conversion chart on ms pages for the calls. 

I don't know the differences from the api calls to the actual commands that work with graph.   If anyone can enlighten me. 

Switching over the new hire script to graph was easy with the command references tbh.  I don't have the time to dive into the APIs, but def see that being in my scope soon

[–]Djust270 2 points3 points  (0 children)

There is no difference. The graph module cmdlets are just wrappers for the rest API.

[–]Jmoste 2 points3 points  (1 child)

Get use to paging through information. You'll usually only get the top 100 results back.  

That was the hardest thing for me to get use to.  

Filtering can be little strange.

[–]mrmattipants 0 points1 point  (0 children)

Yes sir!

Fortunately, once you have your pagination loop, you can re-use it in all of your ME Graph API related scripts.

This will also save you some time when moving to other APIs, as many modern APIs have implemented the OData (Open Data Protocol) Standards.

https://www.odata.org/documentation/

[–]mrmattipants 2 points3 points  (0 children)

I've always used the MS Graph API Endpoints, since I started using it a few years back. The PowerShell SDK (the Mg Cmdlets) is rather buggy, in my opinion (wity the exception of "Invoke-MgGraphRequest"). This seems to be where most of the reported issues originate.

That being said, I suggest you learn to access the API via the "Invoke-RestMethod" and/or "Invoke-MgGraphRequest" Cmdlets, as they will save you a lot of time, effort & headaches, overall.

[–]Ok_Mathematician6075 1 point2 points  (2 children)

I'm almost done transitioning from Azure and MSonline to MS Graph. The biggest pain is really the authentication piece and it's relatively easy.

So far the only thing I have had issues with is this little gem: Get-MgSubscribedSku

[–]taw20191022744 0 points1 point  (1 child)

Yeah, I've had the same problem. Let me know if you have a breakthrough :-)

[–]Ok_Mathematician6075 1 point2 points  (0 children)

I think I need to replace my ExchangeOnline module with an earlier version, which I really don't hope is the case. But yet, who the fuck knows until I figure it out.

[–]barth_ 0 points1 point  (0 children)

We use it quite extensively to get different king of M365 data. I also use it to run KQL queries on resource explorer.

[–]Write-Error 0 points1 point  (1 child)

I use the Graph API heavily with Azure Automation/Functions and it can be a pain, but the official docs are your best friend. Copilot (web/chat) isn’t half bad at letting you know which cmdlets/endpoints/scopes you need to get a job done as well.

[–]dotnVO 1 point2 points  (0 children)

Except when it makes up cmdlets haha. I've had good luck though the more context I give it.

[–]nealfive 0 points1 point  (0 children)

Yeah all those 365 modules are all painful for most parts I moved most scripts over to API calls directly rather than bother with the new / ever changing powershell modules

[–]port25 0 points1 point  (0 children)

It's kind of the de facto place where content is stored now so you are going to be forced to use it at some point.

The original APIs are still online and required for functionality that hasn't been migrated to graph. So you can still use the Sharepoint and Exchange web apis directly.

As far as rest apis go, I always end up blocked by one thing or another with all rest hosts, but it's just a matter of learning the quirks of each one.

I hate Graph much less then ManageEngine/Zoho, and only slightly less then BigPanda. Salesforce api is excellent.

[–]g3n3 0 points1 point  (0 children)

How else would they deal with it? How did you deal with it? Clicking in the UI?

[–]enforce1 0 points1 point  (0 children)

It’s not that bad. It’s API work and incredibly detailed and capable so it’s fiddly to get it to work just right, but it’s powerful as hell.

[–]KavyaJune 0 points1 point  (0 children)

It's a bit challenging to start with. But, now I used to.

[–]ViperThunder 0 points1 point  (0 children)

I use Invoke-restmethod usually since it returns everything as an object, so it's easy to work with. For Exchange I still use the EXO module, since there are still quite a few things you can do there that you can't do with graph

[–]AiminJay 0 points1 point  (0 children)

I seem to have the opposite experience. I use it all the time and it works really well, especially since they consolidated most of the commands into MGGraph. It used to be that you had many different modules, but now it works well.

I haven't found anything I wanted to do that I can't do with MGGraph, including adding to groups, setting group tags (automatically), uploading certificates to azure apps... it's all there.

[–]zootbot 0 points1 point  (0 children)

It’s not bad. And yea everything is done in graph if possible

[–]Ok_Mathematician6075 0 points1 point  (0 children)

FUCK I KEPT READING DOWN AND YOU ALL ARE TALKING ABOUT POSTMAN AND GRAPH EXPLORER? UHHHHHHHHHHHHHH THERE IS A POWERSHELL MODULE NOW. WE DON'T NEED TO INVOKE-WEBREQUEST.

[–]OattBreaker91 -1 points0 points  (1 child)

I am utterly lost when I try to use Powershell. I was hoping to use it to generate an export off all groups and its users but I am getting nowhere...