From 3e3c16426f7fc12f42034b80ec92642c95224534 Mon Sep 17 00:00:00 2001 From: Georgi Matev Date: Wed, 5 Apr 2023 23:20:44 -0700 Subject: [PATCH] Graph PowerShell troubleshooter (#3026) Introduces a handy tool that can be used in troubleshooting to have Corso users issue specific Graph API calls using the Graph Powershell module --- #### Does this PR need a docs update or release note? - [ ] :white_check_mark: Yes, it's included - [ ] :clock1: Yes, but in a later PR - [ ] :no_entry: No #### Type of change - [x] :sunflower: Feature - [ ] :bug: Bugfix - [ ] :world_map: Documentation - [x] :robot: Supportability/Tests - [ ] :computer: CI/Deployment - [ ] :broom: Tech Debt/Cleanup #### Issue(s) * # #### Test Plan - [x] :muscle: Manual - [ ] :zap: Unit test - [ ] :green_heart: E2E --- src/cmd/graph_pwsh/Auth-Graph.ps1 | 39 +++++++++++ src/cmd/graph_pwsh/Dockerfile | 9 +++ src/cmd/graph_pwsh/README.md | 112 ++++++++++++++++++++++++++++++ src/cmd/graph_pwsh/env_names | 4 ++ 4 files changed, 164 insertions(+) create mode 100644 src/cmd/graph_pwsh/Auth-Graph.ps1 create mode 100644 src/cmd/graph_pwsh/Dockerfile create mode 100644 src/cmd/graph_pwsh/README.md create mode 100644 src/cmd/graph_pwsh/env_names diff --git a/src/cmd/graph_pwsh/Auth-Graph.ps1 b/src/cmd/graph_pwsh/Auth-Graph.ps1 new file mode 100644 index 000000000..e22d2dbe0 --- /dev/null +++ b/src/cmd/graph_pwsh/Auth-Graph.ps1 @@ -0,0 +1,39 @@ +$tenantId = $ENV:AZURE_TENANT_ID +$clientId = $ENV:AZURE_CLIENT_ID +$clientSecret = $ENV:AZURE_CLIENT_SECRET +$useBeta = ($ENV:MSGRAPH_USE_BETA -eq 1) -or ($ENV:MSGRAPH_USE_BETA -eq "1") -or ($ENV:MSGRAPH_USE_BETA -eq "true") + +# This version of Graph Powershell does not support app secret auth yet so roll our own +$body = @{ + Grant_Type = "client_credentials" + Scope = "https://graph.microsoft.com/.default" + Client_Id = $clientId + Client_Secret = $clientSecret +} + +$ConectionRequest = @{ + Uri = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" + Method = "POST" + Body = $body +} + +$connection = Invoke-RestMethod @ConectionRequest + +Write-Host "Authenticating with tenantId: $tenantId ..." +try { + Connect-MgGraph -AccessToken $connection.access_token + Write-Host "Successfully authenticated with tenantId: $tenantId ..." +} +catch { + Write-Host "Authentication failed..." + Write-Output $_ +} + +if ($useBeta) { + Write-Host "Switching to Beta Graph API..." + Select-MgProfile -Name "beta" +} + + + + diff --git a/src/cmd/graph_pwsh/Dockerfile b/src/cmd/graph_pwsh/Dockerfile new file mode 100644 index 000000000..24eabd647 --- /dev/null +++ b/src/cmd/graph_pwsh/Dockerfile @@ -0,0 +1,9 @@ +from m365pnp/powershell:2.1.1-alpine-3.14 + +RUN Install-Module PowerShellGet -Force +RUN Install-Module Microsoft.Graph -Force -RequiredVersion 1.25.0 -Scope AllUsers + +COPY ./Auth-Graph.ps1 /tmp/Auth-Graph.ps1 +RUN Move-Item -Path /tmp/Auth-Graph.ps1 -Destination $PROFILE.AllUsersAllHosts + +WORKDIR /usr/pwsh \ No newline at end of file diff --git a/src/cmd/graph_pwsh/README.md b/src/cmd/graph_pwsh/README.md new file mode 100644 index 000000000..276353d35 --- /dev/null +++ b/src/cmd/graph_pwsh/README.md @@ -0,0 +1,112 @@ +# Graph SDK Powershell Troubleshooter + +In certain cases, troubleshooting would be significantly simplified if a Corso +user had a simple mechanism to execute targeted MS Graph API commands against +their environment. + +One convenient mechanism to accomplish this without going down to the level of +wrapping individual Graph API calls is to use the +[Microsoft Graph PowerShell](https://learn.microsoft.com/en-us/powershell/microsoftgraph/overview?view=graph-powershell-1.0). +It provides a convenient wrapper and great coverage of the API surface. + +## Build container + +Before using the tool you want to build the container that packages it. + +```sh +docker build -t corso/graph_pwsh:latest . +``` + +## Prerequisites + +### Docker + +You need to have Docker installed on your system. + +### Azure AD app credentials + +The tool uses your existing Corso app to make Graph calls and for authentication +you want `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, and `AZURE_CLIENT_SECRET` to be +set as environment variables. You can read more about this [here](https://corsobackup.io/docs/setup/m365-access/). +You will then pass these into the container run so that authentication can be completed. + +## Using the tool + +### Interactive use + +This is suitable if you would like to issue a number of MS Graph API commands from an +interactive shell in the container. + +```sh +docker run --rm -it -v $(pwd):/usr/pwsh -e AZURE_TENANT_ID -e AZURE_CLIENT_ID -e AZURE_CLIENT_SECRET corso/graph_pwsh pwsh +``` + +Alternatively you can use an environment variable file `env_names` that has the names of the required environment variables + +```sh +docker run --rm -it -v $(pwd):/usr/pwsh --env-file env_names corso/graph_pwsh pwsh +``` + +Before you run any command you want to authenticate with Graph using a convenient script +that will create a connection using the default permissions granted to the app. + +```powershell +PS> ./Auth-Graph.ps1 +``` + +If you know what you are doing feel free to use `Connect-MgGraph` directly. + +### Specific command use + +Suitable when you want to run just a single command. Essentially running the `Auth-Graph.ps1` +before the actual command you want to run. + +```sh +docker run --rm -it -v $(pwd):/usr/pwsh --env-file env_names corso/graph_pwsh \ + pwsh -c "" +``` + +Here is a complete example to get all users + +```sh +# This is the equivalent of GET https://graph.microsoft.com/v1.0/users +docker run --rm -it -v $(pwd):/usr/pwsh --env-file env_names corso/graph_pwsh \ + pwsh -c "Get-MgUser -All" +``` + +Another example to retrieve an email message for a given user by ID. + +```sh +# This is the equivalent of GET https://graph.microsoft.com/v1.0//messages/ +docker run --rm -it -v $(pwd):/usr/pwsh --env-file env_names corso/graph_pwsh \ + pwsh -c "Get-MgUserMessage -UserId -MessageID " +``` + +## Debug output + +To see the requests and responses made by the specific Graph PowerShell commands, add `-Debug` to you command, +similar to the example below. + +```sh +# This is the equivalent of GET https://graph.microsoft.com/v1.0/users +docker run --rm -it -v $(pwd):/usr/pwsh --env-file env_names corso/graph_pwsh \ + pwsh -c "Get-MgUser -All -Debug" +``` + +## Using Beta API calls + +In order to use the Beta Graph API, make sure you have done `export MSGRAPH_USE_BETA=1` +before running the container and pass the environment variable in. + +Alternatively you can do the following: + +```sh +# This is the equivalent of GET https://graph.microsoft.com/v1.0/users +docker run --rm -it -v $(pwd):/usr/pwsh --env-file env_names corso/graph_pwsh \ + pwsh -c "Select-MgProfile -Name "beta" && Get-MgUser -All" +``` + +## Graph PowerShell reference + +To learn about specific commands, see the +[Graph PowerShell Reference](https://learn.microsoft.com/en-us/powershell/microsoftgraph/get-started?view=graph-powershell-1.0) diff --git a/src/cmd/graph_pwsh/env_names b/src/cmd/graph_pwsh/env_names new file mode 100644 index 000000000..4941e765d --- /dev/null +++ b/src/cmd/graph_pwsh/env_names @@ -0,0 +1,4 @@ +AZURE_TENANT_ID +AZURE_CLIENT_ID +AZURE_CLIENT_SECRET +MSGRAPH_USE_BETA