Skip to content

Commit

Permalink
Added support folder (#667)
Browse files Browse the repository at this point in the history
* Added support folder with troubleshooting scripts

* reworked readme

Co-authored-by: Robin Meure <[email protected]>
  • Loading branch information
robinmeure and robinmeure authored Jun 17, 2022
1 parent 15cef76 commit f2fd855
Show file tree
Hide file tree
Showing 4 changed files with 416 additions and 0 deletions.
144 changes: 144 additions & 0 deletions Support/Check-AppRegistrations.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<#
.SYNOPSIS
Script to test if the Applications can get an access token using the stored secrets
.DESCRIPTION
To make sure that the configuration which is stored in the keyvault is correct this script will
1. Fetch the applicationId's from the Application Registrations
2. Fetch the application secrets from the KeyVault
3. Try to fetch an acces token using the combination of the AppId and AppSecret
.PARAMETER ConfigFile
Path to where the parameters.json is stored which was used to deploy the application.
.PARAMETER TenantId
TenantId (see the Azure Portal to retrieve this GUID, this is also known as the DirectoryId which can be found in the Application Registration as well)
.PARAMETER BaseResourceName
"Base" name of the resources (e.g. how all the resources are named) in the Resource Group, this is the same name as in the parameters.json file
See https://github.com/OfficeDev/microsoft-teams-apps-company-communicator/wiki/Deployment-guide step 5), this name is used in the script to find all the components in the Resource Group
.NOTES
Author: Robin Meure MSFT
ChangeLog:
1.0.0 - Robin Meure, 2022-Feb-23 - First Release.
Make sure that the account which is used to connect to the Azure environment has read access on the KeyVault secrets.
Azure Portal -> Company Communicator Resource Group -> KeyVault > Access policies -> Add user to read the secrets
See https://docs.microsoft.com/en-us/azure/key-vault/general/assign-access-policy?tabs=azure-portal for more information.
#>

[CmdletBinding(DefaultParametersetName="Variables")]
Param
(
[Parameter( ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName="ConfigFile",
HelpMessage="Load the configfile of the deployment folder.")]
[switch]$ConfigFile,

[Parameter( ParameterSetName="ConfigFile",
HelpMessage="The path where the parameters.json which is used for the deployment is located.")]
[string]$configFilePath,

[Parameter( ParameterSetName="Variables",
HelpMessage="The TenantId where the application is deployed.")]
[string]$tenantId,
[Parameter( ParameterSetName="Variables",
HelpMessage="'Base' name of the resources (e.g. how all the resources are named) in the Resource Group.")]
[string]$baseName
)

Function Get-AccessToken
{
param(
[Parameter(Mandatory = $true, HelpMessage = "ApplicationId")]
[string]
$appId,
[Parameter(Mandatory = $true, HelpMessage = "ApplicationSecret")]
[string]
$appSecret,
[Parameter(Mandatory = $true, HelpMessage = "Resource to authenticate against (e.g. https://graph.microsoft.com)")]
[string]
$resource,
[Parameter(Mandatory = $true, HelpMessage = "Authority to receive the token from (e.g. 'https://login.microsoftonline.com/tenant/oauth2/v2.0/token'))")]
$authority
)

$body = [string]::Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=https%3A%2F%2F{2}%2F.default", $appId, $appSecret, $resource)

Write-Output ("Fetching access token using for Application: {0}." -f $appId)
$token = Invoke-RestMethod -Uri $authority -Method Post -Body $body

if ($token.access_token -ne $null)
{
Write-Output ("Got an access token")
}
else
{
Write-Output ("Failed to retrieve an access token")
}
}

# check if we have a config file we're using and need to parse
if ($ConfigFile)
{
if ([string]::IsNullOrEmpty($configFilePath))
{
Write-Output ("No config file is set, trying to fetch the configuration from the deployment folder.")
$config = Get-Content '..\deployment\parameters.json' | Out-String | ConvertFrom-Json
Write-Verbose ("Found following configuration: {0}." -f $config)
}
else
{
Write-Output ("FilePath set, trying to fetch the configuration from the specified folder.")
$config = Get-Content -Path $configFilePath | Out-String | ConvertFrom-Json
}
# Fetching the configuration of the deployment
$tenantId = $config.tenantId.Value
$baseName = $config.baseResourceName.Value
}



# Connecting to the Azure Portal, please make sure you're connecting using the same account as for the deployment
$connectionSucceeded = $false
try{
$connectionSucceeded = Connect-AzAccount -Tenant $tenantId
}
catch{
$connectionSucceeded = $false
}

# if we could successfully connect to Azure, then we're going to try to fetch the App Registrations and secrets from the KeyVault
if ($connectionSucceeded)
{
# Fetching the App registrations with their Id's
$applications = Get-AzADApplication -DisplayNameStartWith $baseName | Select-Object ApplicationId, DisplayName
$graphAppId = $applications | Where-Object { $_.DisplayName -eq $baseName}| Select-Object ApplicationId -ExpandProperty ApplicationId
$userAppId = $applications | Where-Object { $_.DisplayName -eq [string]::Format("{0}-users",$baseName)} | Select-Object ApplicationId -ExpandProperty ApplicationId
$authorAppId = $applications | Where-Object { $_.DisplayName -eq [string]::Format("{0}-authors",$baseName)}| Select-Object ApplicationId -ExpandProperty ApplicationId

# setting up keyvaultName
$keyVaultName = [string]::Format("{0}{1}", $baseName,"vault")

# Defining the secretNames to retrieve the actual secrets from the Keyvault
$graphAppSecretName = [string]::Format("{0}{1}", $keyVaultName, "GraphAppPassword")
$userAppSecretName = [string]::Format("{0}{1}", $keyVaultName, "UserAppPassword")
$authorAppSecretName = [string]::Format("{0}{1}", $keyVaultName, "AuthorAppPassword")

# Fetch the secrets from the KeyVault
$graphAppSecret = Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $graphAppSecretName -AsPlainText
$userAppSecret = Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $userAppSecretName -AsPlainText
$authorAppSecret = Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $authorAppSecretName -AsPlainText

# First check the Graph App
$graphAuthorityUrl = [string]::Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", $tenantId)
$graphResource = "graph.microsoft.com"

Get-AccessToken -appId $graphAppId -appSecret $graphAppSecret -authority $graphAuthorityUrl -resource $graphResource

# Checking the User and Author Apps
$botAuthorityUrl = [string]::Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", "botframework.com")
$botResource = "api.botframework.com"

Get-AccessToken -appId $userAppId -appSecret $userAppSecret -authority $botAuthorityUrl -resource $botResource
Get-AccessToken -appId $authorAppId -appSecret $authorAppSecret -authority $botAuthorityUrl -resource $botResource
}
82 changes: 82 additions & 0 deletions Support/Check-GraphApp.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<#
.SYNOPSIS
Script to test if the created Applications in the Application Registration work
.DESCRIPTION
To make sure that the AppReg itself is working, this script is meant to test the basic AppId + AppSecret combination to see if an access token is being returned.
Also, this can be used to see the App has the proper permissions granted to lookup users and/our groups.
.PARAMETER TenantId
TenantId (see the Azure Portal to retrieve this GUID, this is also known as the DirectoryId which can be found in the Application Registration as well)
.PARAMETER AppId
ApplicationId of the Graph App (main application, not the user nor the author bot App registration)
.PARAMETER AppSecret
Secret of the Application
.PARAMETER FetchDataFromGraph
When supplied, a call is done to the Graph API using the App and the access token to retrieve O365 groups and/or users
.NOTES
Author: Robin Meure MSFT
ChangeLog:
1.0.0 - Robin Meure, 2022-Feb-23 - First Release.
This script does not make use of any Graph libraries/SDK's but just 'simple' Invoke-RestMethod cmdlets,
this to eliminate the dependencies and/or elevated powershell sessions to install these dependencies like MSGraph
#>

[CmdLetBinding()]
param(
[Parameter(Mandatory = $true, HelpMessage = "The TenantId where the application is deployed")]
[string]
$tenantId,
[Parameter(Mandatory = $true, HelpMessage = "The ApplicationId of the application")]
[string]
$AppId,
[Parameter(Mandatory = $true, HelpMessage = "The Application secret of the application.")]
[string]
$AppSecret,
[Parameter(Mandatory = $false, HelpMessage = "When provided, will call into the graph using the access token.")]
[switch]
$FetchDataFromGraph
)

$graphAuthorityUrl = [string]::Format("https://login.microsoftonline.com/{0}/oauth2/v2.0/token", $tenantId)
$graphResource = "graph.microsoft.com"

$body = [string]::Format("grant_type=client_credentials&client_id={0}&client_secret={1}&scope=https%3A%2F%2F{2}%2F.default", $AppId, $AppSecret, $graphResource)
$token = Invoke-RestMethod -Uri $graphAuthorityUrl -Method Post -Body $body

if (!$token)
{
Write-Warning ("No token received")
}
else {
Write-Output ("Fetched access token using for Application: {0}." -f $appId)
$graphAccessToken = $token.access_token
}


if ($FetchDataFromGraph)
{
# This is fetching O365 groups when drafting a message as option 4 to send the message to.
# https://graph.microsoft.com/v1.0/groups?$filter=groupTypes/any(c:c+eq+'Unified')

# GroupMember.Read.All check
$fetchGroupsUrl = [string]::Format("https://graph.microsoft.com/v1.0/groups?`$filter=groupTypes/any(c:c+eq+'Unified')")
$fetchGroupsResponse = Invoke-RestMethod -Uri $fetchGroupsUrl -Headers @{Authorization = "Bearer $graphAccessToken"} -ContentType "application/json" -Method Get
if ($fetchGroupsResponse -ne $null)
{
Write-Output ("Fetched o365 groups using graph API for Application: {0}." -f $appId)
$fetchGroupsResponse.value | Select-Object DisplayName, Id
Write-Output ("---------------------------------------------------------")
}

# This is fetching users from AAD (e.g. used to send a message to all users (option 3 in the message ux))
# https://graph.microsoft.com/v1.0/users

# User.Read.All check
$fetchUsersUrl = [string]::Format("https://graph.microsoft.com/v1.0/users")
$fetchUsersResponse = Invoke-RestMethod -Uri $fetchUsersUrl -Headers @{Authorization = "Bearer $graphAccessToken"} -ContentType "application/json" -Method Get
if ($fetchUsersResponse -ne $null)
{
Write-Output ("Fetched AAD users using graph API for Application: {0}." -f $appId)
$fetchUsersResponse.value | Select-Object DisplayName, Id
}
}
Loading

0 comments on commit f2fd855

Please sign in to comment.