Ms Graph RestAPI create team 404 - microsoft-graph-api

the first try catch works, he is adding the ms graph AD group in office365.
But the second try catch (converting the group to a Team does not work. I receive an 404 error??
The groupID exists on the server I notice.
Whats going wrong to get an 404?
I did add a secret token on the azure control panel.
The script has the token, appid and tenantid in live time.
also: the tenant has graph roles like group.ReadWriteAll. same for Teams and Directories.
Clear-Host
$env:graphApiDemoAppId = "" # Replace with your Azure AD app id
$env:graphApiDemoAppSecret = "" # Replace with your Azure AD app secret
$env:tenantId = "" # Replace with your Azure AD tenant ID
$oauthUri = "https://login.microsoftonline.com/$env:tenantId/oauth2/v2.0/token"
# Create token request body
$tokenBody = #{
client_id = $env:graphApiDemoAppId
client_secret = $env:graphApiDemoAppSecret
scope = "https://graph.microsoft.com/.default"
grant_type = "client_credentials"
}
# Retrieve access token
$tokenRequest = Invoke-RestMethod -Uri $oauthUri -Method POST -ContentType "application/x-www-form-urlencoded" -Body $tokenBody -UseBasicParsing
# Save access token
$accessToken = ($tokenRequest).access_token
$headers = #{
"Authorization" = "Bearer $accessToken"
"Content-type" = "application/json"
}
try
{
# Create group request body
$groupName = "Test_Kenvh16"
$groupBodyParams = #{
displayName = $groupName
description = $groupName
mailNickName = $groupName
groupTypes = #("Unified")
mailEnabled = $true
securityEnabled = $false
visibility = "Private"
}
$groupBody = ConvertTo-Json -InputObject $groupBodyParams
$newGroup = Invoke-RestMethod -Uri "https://graph.microsoft.com/v1.0/groups" -Method POST -Headers $headers -Body $groupBody
$groupId = $newGroup.id
Write-Host "group created:" $groupName "id:" $groupId
try
{
#convert group to team..
$teamBodyParams = #{
memberSettings = #{
allowCreateUpdateChannels = $true
}
messagingSettings = #{
allowUserEditMessages = $true
allowUserDeleteMessages = $true
}
funSettings = #{
allowGiphy = $true
giphyContentRating = "strict"
}
}
$teamBody = ConvertTo-Json -InputObject $teamBodyParams
$teamUri = "https://graph.microsoft.com/v1.0/groups/" + $groupId + "/team"
$newTeam = Invoke-RestMethod -Uri $teamUri -Method POST -Headers $headers -Body $teamBody
$teamId = $newTeam.id
}
catch
{
Write-Host "createTeam ExceptionMessage:" $_.Exception.Message
Write-Host "createTeam StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "createTeam StatusDescription:" $_.Exception.Response.StatusDescription
}
}
catch
{
Write-Host "createGroup ExceptionMessage:" $_.Exception.Message
Write-Host "createGroup StatusCode:" $_.Exception.Response.StatusCode.value__
Write-Host "createGroup StatusDescription:" $_.Exception.Response.StatusDescription
}

Related

Getting Error while updating environments level variable on Azure devOps release

I am trying to update the Environment level variable on Azure DevOps Release using below code.
$url = "$(System.TeamFoundationServerUri)$(System.TeamProjectId)/_apis/Release/releases/$(Release.ReleaseId)/environments/$(RELEASE.ENVIRONMENTID)?api-version=7.0"
Write-Host "URL: $url"
$pipeline = Invoke-RestMethod -Uri $url -Headers #{
Authorization = "Bearer $(System.AccessToken)" # Provided by ADO thanks to OAuth checkbox
}
$pipeline.variables.Root.value = 'Test'
$T1 = [pscustomobject] #{ scheduledDeploymentTime = $null ; comment = $null ; variables = $pipeline.variables }
$json = #($T1) | ConvertTo-Json -Depth 99
Write-Host $json
Invoke-RestMethod -Uri $url -Method PATCH -Body $json -ContentType "application/json" -Headers #{Authorization = "Bearer $(System.AccessToken)"}
Error I am getting:
enter image description here.
What am I doing wrong?

Azure HTTP Trigger. How to avoid everytime the login

I have an Azure HTTP trigger function.
And it all works, except that I am executing everytime the slow
Connect-ExchangeOnline -Credential $Credential
How can I re-use the security token so it is only once slow.
And instead of using a normal login account, can I also use an applicationID and secret?
using namespace System.Net
param($Request, $TriggerMetadata)
$body = #{}
$user = "xxx#contoso.com"
$password = "example_password"
$securePassword = $password | ConvertTo-SecureString -AsPlainText -Force
$Credential = new-Object System.Management.Automation.PSCredential($user,$securePassword)
try {
Connect-ExchangeOnline -Credential $Credential
$filter = $Request.Body
$wildCard = $filter.wildCard
$SharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize:1000 $wildcard|
Select-Object Identity,User,AccessRights,SamaccountName, PrimarySmtpAddress,City ,UsageLocation,IsDirSynced, DisplayName,HiddenFromAddressListsEnabled, GrantSendOnBehalfTo, ExmployeeID
$body.values = $SharedMailboxes
}
catch {
Write-Error $_.Exception.Message
$body.error = $_.Exception.Message
}
finally {
Disconnect-ExchangeOnline -Confirm:$false
}
Push-OutputBinding -Name Response -Value ([HttpResponseContext]#{
StatusCode = [HttpStatusCode]::OK
Body = $body
})

Azure DevOps Export Import query to different project

Tried searching if there's any out of the box method to export import queries in new projects. Seems like there isn't any.
Can it be achieved by code? If yes, would like to know how.
Appreciate any tips.
Regards,
You can use the rest api to read and create queries: Queries
Powershell example to export queries into local folder:
$user = ""
$token = "<pat>" #https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page
$teamProject = "team_project_name"
$orgUrl = "https://dev.azure.com/<org>"
$sourceQueryFolder = "Shared Queries/Change Management"
$targetLocalFolder = "c:/temp/Change Management Queries"
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$queriesUrl = "$orgUrl/$teamProject/_apis/wit/queries/$sourceQueryFolder"+"?`$depth=1&`$expand=all&api-version=5.0"
function InvokeGetRequest ($GetUrl)
{
return Invoke-RestMethod -Uri $GetUrl -Method Get -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
}
$resQuries = InvokeGetRequest $queriesUrl
if (![System.IO.Directory]::Exists($targetLocalFolder))
{
New-Item -Path $targetLocalFolder -ItemType "directory"
}
if ($resQuries.isFolder -and $resQuries.hasChildren)
{
foreach($item in $resQuries.children)
{
if (!$item.isFolder)
{
$queryJson = "{`"name`":`"{queryname}`", `"wiql`":`"{querywiql}`"}"
$queryJson = $queryJson -replace "{queryname}", $item.name
$queryJson = $queryJson -replace "{querywiql}", $item.wiql
$filepath = "$targetLocalFolder/" + $item.name
Set-Content -Path $filepath -Value $queryJson
}
}
}
Powershell example to import queries from local folder:
$user = ""
$token = "<pat>" #https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page
$teamProject = "team_project_name"
$orgUrl = "https://dev.azure.com/<org>"
$sourceLocalFolder = "c:/temp/Change Management Queries"
$targetQueryFolder = "Shared Queries/Change Management Imported" #should exist
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$queriesUrl = "$orgUrl/$teamProject/_apis/wit/queries/$targetQueryFolder"+"?&api-version=5.0"
function InvokePostRequest ($PostUrl, $body)
{
return Invoke-RestMethod -Uri $PostUrl -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body
}
$files = Get-ChildItem -File -Path $sourceLocalFolder
foreach($wiqlfile in $files)
{
$wiqlBody = Get-Content $wiqlfile
InvokePostRequest $queriesUrl $wiqlBody
}
Example to copy a query folder content from one team project into another one in the same organization through rest API:
$user = ""
$token = "<pat>" #https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page
$teamProjectSource = "source_team_project_name"
$teamProjectTarget = "target_team_project_name"
$orgUrl = "https://dev.azure.com/<org>"
$sourceQueryFolder = "Shared Queries/Change Management"
$targetQueryFolder = "Shared Queries/Change Management" #should exist
$queryObject = [PSCustomObject]#{
name = $null
wiql = $null
columns = $null
sortColumns = $null
}
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$queriesPostUrl = "$orgUrl/$teamProjectTarget/_apis/wit/queries/$targetQueryFolder"+"?api-version=5.0"
$queriesGettUrl = "$orgUrl/$teamProjectSource/_apis/wit/queries/$sourceQueryFolder"+"?`$depth=1&`$expand=all&api-version=5.0"
function InvokeGetRequest ($GetUrl)
{
return Invoke-RestMethod -Uri $GetUrl -Method Get -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
}
function InvokePostRequest ($PostUrl, $body)
{
return Invoke-RestMethod -Uri $PostUrl -Method Post -ContentType "application/json" -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)} -Body $body
}
$resQuries = InvokeGetRequest $queriesGettUrl
if ($resQuries.isFolder -and $resQuries.hasChildren)
{
foreach($item in $resQuries.children)
{
if (!$item.isFolder)
{
$queryObject.name = $item.name
$queryObject.wiql = $item.wiql
$queryObject.columns = $item.columns
$queryObject.sortcolumns = $item.sortcolumns
$wiqlbody = ConvertTo-Json $queryObject -Depth 10
InvokePostRequest $queriesPostUrl $wiqlBody
}
}
}
You can use out of box function to export and import queries. Visual Studio and Team Explorer contain that.
Go to the Queries Tab:
Edit query
Save as
Select another project

Issue with dismissing Identity Risk Events via Graph API

I am trying to dismiss/close risk events using an automated process. For this we would need to make use of Graph API https://graph.microsoft.com/beta/riskyUsers/dismiss
I did searched for examples and couldn't find any.
I did tried using Post man by providing OAuth Bearer token in the header and I did tried with a PowerShell script and I also tried with .Net example provided in the page. None of them worked
PowerShell Code
{
$body = #{grant_type="client_credentials";resource=$resource;client_id=$ClientID;client_secret=$ClientSecret}
$oauthResponse = Invoke-RestMethod -Method POST -Uri $loginURL/$TenantName/oauth2/token?api-version=1.0 -Body $body
return $oauthResponse
}
$loginURL = "https://login.windows.net"
$resource = "https://graph.microsoft.com"
$ClientSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$ClientID="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
$TenantName="xxxxx.com"
$oauth=RefreshToken -loginURL $loginURL -resource $resource -ClientID $ClientID -clientSecret $ClientSecret -tenantName $TenantName
$headerParams = #{'Authorization'="$($oauth.token_type) $($oauth.access_token)"}
$url="https://graph.microsoft.com/beta/riskyUsers/dismiss"
$userIds=#()
$userIds+="xxxxx-xxxxx-xxxxx-xxxxx-xxxxx"
$body=(#{"userIds"=$userIds})|convertto-json
$Response = Invoke-WebRequest -UseBasicParsing -Headers $headerParams -Uri $url -Body $body -Method Post -ContentType "application/Json"
Response:
Invoke-WebRequest : The remote server returned an error: (500) Internal Server Error.
At C:\SourceCode\MIMSolution\PowerShellScripts\AzurePSMA\RiskyIdentityEvents\ExportScript_debug.ps1:19 char:13
+ $Response = Invoke-WebRequest -UseBasicParsing -Headers $headerParams -Uri $url ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
C# Code:
static void Main(string[] args)
{
var userIdsList = new List<String>();
userIdsList.Add("xxxxx-xxxxx-xxxxx-xxxxx-xxxx");
dismissUser(userIdsList);
}
static async void dismissUser(List<string> userIDs)
{
ClientCredential clientCredential = new ClientCredential("xxxxxxxxxxxxxxxxxxxxxxx");
string clientId = "xxxxxxxxxxxxxxxxxxxxxx";
IConfidentialClientApplication clientApplication = ClientCredentialProvider.CreateClientApplication(clientId, clientCredential);
ClientCredentialProvider authProvider = new ClientCredentialProvider(clientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
await graphClient.RiskyUsers.Dismiss(userIDs).Request().PostAsync();
}```
Exception:
{"Code: generalException\r\nMessage: An error occurred sending the request.\r\n"}
Inner Exception:
{"Code: generalException\r\nMessage: Unexpected exception occured while authenticating the request.\r\n"}
Finally after multiple trails , I have figured out the solution:
Issue was with the token which as OAuth 1.0 earlier.
I did fixed this snippet that request OAuth 2.0 and the issue resolved:
function RefreshToken($loginURL,$ClientID,$clientSecret,$tenantName)
{ $body = #{grant_type="client_credentials";client_id=$ClientID;client_secret=$ClientSecret;scope="https://graph.microsoft.com/.default"}
$oauthResponse = Invoke-RestMethod -Method POST -Uri $loginURL/$TenantName/oauth2/v2.0/token -Body $body
return $oauthResponse
}

TFS 2017 Update 3.1 Release approver report/history

Please help in how to get the Release approver list for each release definition in TFS 2017 update 3.1.
Thanks & Regards
You can call the REST API (Definitions - Get) to retrieve the approver list.
Below PowerShell script can get the Release approver list for each release definition: (Just replace the parameters accordingly)
Param(
[string]$baseurl = "http://SERVER:8080/tfs/DefaultCollection",
[string]$projectName = "0511ScrumTFVC",
[string]$user = "Domain\user",
[string]$token = "password/PAT"
)
# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))
$releasesuri = "$baseurl/$projectName/_apis/release/definitions"
$releasesresult = Invoke-RestMethod -Uri $releasesuri -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$redids = $releasesresult.value.id
foreach ($redid in $redids)
{
$uri = "$baseurl/$projectName/_apis/release/definitions/$redid"
$approvers = Invoke-RestMethod -Uri $uri -Method Get -Headers #{Authorization=("Basic {0}" -f $base64AuthInfo)}
$preApprovers = $approvers.environments.preDeployApprovals.approvals.approver.displayName
$postApprovers = $approvers.environments.postDeployApprovals.approvals.approver.displayName
write-host "Release ID: $redid - preApprovers:"
foreach ($preApprover in $preApprovers)
{
write-host $preApprover
}
write-host "`nRelease ID: $redid - postApprovers:"
foreach ($postApprover in $postApprovers)
{
write-host $postApprover
}
}

Resources