Azure HTTP Trigger. How to avoid everytime the login - azure-http-trigger

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
})

Related

Ms Graph RestAPI create team 404

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
}

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

How to integrate AxoCover (NUnit) with Jenkins

I've not been able to find article or tutorial described the topic.
Thus, my question is how to integrate AxoCover with Jenkins:
Mark build failed or secussefful in accordance of code coverage percentage
Sent email with notification to specific users
Thanks in advance
So, in general i founded out solution in creating powershell script and executing it during the jenkins job:
<#
.SYNOPSIS
Runs NUnit unit tests in given Visual Studio solution and provides code coverage result
Duplicate for CodeCoverageRunner fix for NUnit 3.
https://github.com/nunit/nunit-console/issues/117
.PARAMETER TestConfig
{
"SolutionFile": "\\project.sln",
"BuildConfiguration": "Debug",
"TestResultDirectory": "\\tempFolder",
"TestRunnerPath": "\\nunit3-console.exe",
"CodeCoverageToolPath" : "\\OpenCover.Console.exe",
"ReportGeneratorPath": "\\ReportGenerator.exe",
"AssemblyFilters": "+[*]*"
}
#>
$config = ConvertFrom-Json $TestConfig
$testRunnerArgs = GetTestProjects `
-SolutionFile $config.SolutionFile `
-BuildConfiguration $config.BuildConfiguration
$workingDirectory = $config.TestResultDirectory
$testRunner = $config.TestRunnerPath
$codeCoverageTool = $config.CodeCoverageToolPath
$reportGenerator = $config.ReportGeneratorPath
$filters = $config.AssemblyFilters
$coverageResult = Join-Path $workingDirectory "codecoverage.xml"
& $codeCoverageTool -target:"""$testRunner""" `
-targetargs:"""$testRunnerArgs --inprocess $("-result","test_result.xml")""" `
-register:Administrator `
-mergebyhash `
-skipautoprops `
-output:"""$coverageResult""" `
-filter:"""$filters""" `
-returntargetcode
if($LASTEXITCODE -ne 0){
exit $LASTEXITCODE
}
$targetDir = Join-Path $workingDirectory "CodeCoverage"
$historyDir = Join-Path $workingDirectory "CoverageHistory"
& $reportGenerator `
-reports:$coverageResult `
-targetDir:"""$targetDir""" `
-historydir:"""$historyDir"""
function GetTestProjects
{
param (
[Parameter(Mandatory=$true)]
[string]$SolutionFile,
[Parameter(Mandatory=$true)]
[string]$BuildConfiguration
)
$BaseDir = (get-item $solutionFile).Directory
$Projects = #()
Get-Content -Path $SolutionFile | % {
if ($_ -match '\s*Project.+=\s*.*,\s*\"\s*(.*Tests\.Unit.*proj)\s*\"\s*,\s*') {
$currentName = $matches[1].Split("\")[0]
$currentDll = $matches[1].Split("\")[1].Replace(".csproj",".dll")
#Write-Host "current $currentName"
$Projects += "`"", $(Join-Path -Path $BaseDir $currentName), "\bin\$BuildConfiguration\$currentDll" ,"`"" -join ""
}
}
return $Projects
}

I need a way to authenticate sharepointonline api connection without user consent using ARM or any powershell

I want automation to authenticate sharepoint online api connection without user consent in Azure as I want to run the code in azuredveops pipeline and the code which I got got does open a custom form and ask for user consent.It is good if I don't have to run it through devops pipeline but in my case yes I need to run authorization through code without user/graphical intervention
I have tried below code which works fine on my local but as I explained,it needs user consent which won't work in azuredevops pipeline world
[string] $ResourceGroupName = '*****',
[string] $ResourceLocation = '******',
[string] $api = 'office365',
[string] $ConnectionName = 'SharepointOnline',
[string] $subscriptionId = '*****'
)
#OAuth window for user consent
Function Show-OAuthWindow {
Add-Type -AssemblyName System.Windows.Forms
$form = New-Object -TypeName System.Windows.Forms.Form -Property #{Width=600;Height=800}
$web = New-Object -TypeName System.Windows.Forms.WebBrowser -Property #{Width=580;Height=780;Url=($url -f ($Scope -join "%20")) }
$DocComp = {
$Global:uri = $web.Url.AbsoluteUri
if ($Global:Uri -match "error=[^&]*|code=[^&]*") {$form.Close() }
}
$web.ScriptErrorsSuppressed = $true
$web.Add_DocumentCompleted($DocComp)
$form.Controls.Add($web)
$form.Add_Shown({$form.Activate()})
$form.ShowDialog() | Out-Null
}
#login to get an access code
#Login-AzureRmAccount
#select the subscription
$ResourceLocation = (Get-AzureRmResource -ResourceGroupName CI | Select-Object Location)[0].Location
$subscription = Select-AzureRmSubscription -SubscriptionId $subscriptionId
#Get the connection and create if wasn't already created
$connection = Get-AzureRmResource -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -ResourceName $ConnectionName -ErrorAction SilentlyContinue
if(-not $connection) {
$connection = New-AzureRmResource -Properties #{"api" = #{"id" = "subscriptions/" + $subscriptionId + "/providers/Microsoft.Web/locations/" + $ResourceLocation + "/managedApis/" + $api}; "displayName" = $ConnectionName; } -ResourceName $ConnectionName -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -Location $ResourceLocation -Force
}
#else get the connection
else{
$connection = Get-AzureRmResource -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -ResourceName $ConnectionName
}
Write-Host "connection status: " $connection.Properties.Statuses[0]
$parameters = #{
"parameters" = ,#{
"parameterName"= "token";
"redirectUrl"= "https://online.microsoft.com/default/authredirect"
}
}
#get the links needed for consent
$consentResponse = Invoke-AzureRmResourceAction -Action "listConsentLinks" -ResourceId $connection.ResourceId -Parameters $parameters -Force
$url = $consentResponse.Value.Link
#prompt user to login and grab the code after auth
Show-OAuthWindow -URL $url
$regex = '(code=)(.*)$'
$code = ($uri | Select-string -pattern $regex).Matches[0].Groups[2].Value
Write-output "Received an accessCode: $code"
if (-Not [string]::IsNullOrEmpty($code)) {
$parameters = #{ }
$parameters.Add("code", $code)
# NOTE: errors ignored as this appears to error due to a null response
#confirm the consent code
Invoke-AzureRmResourceAction -Action "confirmConsentCode" -ResourceId $connection.ResourceId -Parameters $parameters -Force -ErrorAction Ignore
}
#retrieve the connection
$connection = Get-AzureRmResource -ResourceType "Microsoft.Web/connections" -ResourceGroupName $ResourceGroupName -ResourceName $ConnectionName
Write-Host "connection status now: " $connection.Properties.Statuses[0]
You must first create a Automation account with AzureRunAs credentials. Then create your Runbook inside your automation account.
About AzureRunAs account - docs
My first Runbook - docs
From Azure Devops i found this blog which can be of help

How to post a message to Slack from Powershell

I'm looking for a simple example of PowerShell code that uses HttpClient to post to a Slack channel.
Add-Type -AssemblyName System.Net.Http
$http = New-Object -TypeName System.Net.Http.Httpclient
$message = "Hello world."
$httpMessage = "{""text"": """ + $message + """}";
$content = New-Object -TypeName System.Net.Http.StringContent($httpMessage)
$httpResult = $http.PostAsync("https://hooks.slack.com/services/your_channel_url_here", $content).Result

Resources