Setting "Allow all pipelines" when creating a service endpoint through DevOps API Create Endpoint - azure

I am attempting to create a service endpoint through the Azure DevOps Rest API but cannot set the "Allow all pipelines to use this service connection" option. I cannot find documentation on the json structure to accomplish this.
https://learn.microsoft.com/en-us/rest/api/azure/devops/serviceendpoint/endpoints/create?view=azure-devops-rest-5.0#endpointauthorization
Current snippet for creating the connection:
$baseUri = "https://dev.azure.com/org/proj/";
$createEndpointUri = "$($baseUri)_apis/serviceendpoint/endpoints?api-version=5.0-preview.2";
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("token:{0}" -f $devOpsPAT)))
$DevOpsHeaders = #{Authorization = ("Basic {0}" -f $base64AuthInfo)};
$AzureSubscriptionData = New-Object PSObject -Property #{
authorizationType = "AzureSubscription"
azureSubscriptionId = $SubscriptionId
azureSubscriptionName = $subscriptionName
clusterId = $clusterId
};
$Authorization = New-Object PSObject -Property #{
parameters = New-Object PSObject -Property #{
azureEnvironment = "AzureCloud"
azureTenantId = "$tenantID"
};
scheme = "Kubernetes"
};
$ServiceEndpointBody = New-Object PSObject -Property #{
authorization =$Authorization
data = $AzureSubscriptionData
name = $serviceConnectionName
type = "kubernetes"
url = $k8sUrl
isReady = "true"
};
$jsonbody = $ServiceEndpointBody | ConvertTo-Json -Depth 100
Invoke-RestMethod -UseBasicParsing -Uri $createEndpointUri -Method Post -ContentType "application/json" -Headers $DevOpsHeaders -Body $jsonbody;

You can usually figure this stuff out by doing the operation in the Azure DevOps UI and inspecting the HTTP requests it makes using (for example) Chrome debugging tools.
In this case, I think you first need to create the service connection and then make a PATCH request to the pipelinePermissions endpoint, setting the allPipelines.authorized flag to true.
URI
PATCH https://dev.azure.com/{organisation}/{project}/_apis/pipelines/pipelinePermissions/endpoint/{endpointId}?api-version=5.1-preview.1
Patch Request Body
{
"allPipelines": {
"authorized": true,
"authorizedBy": null,
"authorizedOn": null
},
"pipelines": null,
"resource": {
"id": "{endpointid}",
"type": "endpoint"
}
}
Powershell
Invoke-RestMethod -Method PATCH -Uri "{uriasabove}" -Headers $headers -Body "{patchbodyasabove}" -ContentType "application/json"

Thanks for the above help, however I wanted to do all of this using bash script.
patch.json
{
"allPipelines": {
"authorized": true,
"authorizedBy": null,
"authorizedOn": null
},
"pipelines": null,
"resource": {
"id": "test-service-endpoint-id",
"type": "endpoint"
}
}
A simple Bash Script to achieve the same.
#!/bin/bash
token=test-token
organization_name=your-azuredevops-organisation
project=test-project
user=your-user-name
connection_name=test-connection
#Get Request for endpoint ID
connection_id=$(curl -X GET \
-H "Content-Type: application/json" \
-u $user:$token \
https://dev.azure.com/$organization_name/$project/_apis/serviceendpoint/endpoints\?endpointNames\=$connection_name\&api-version\=5.1-preview.2 | jq '.value[].id' | tr -d "\"" )
#Creating newpatch.json with connection_id
cat patch.json | jq --arg conn_id "$connection_id" -r '.resource.id = $conn_id' > newpatch.json
curl --request PATCH \
-H "Content-Type: application/json" \
-u $user:$token \
-d "#newpatch.json" https://dev.azure.com/$organization_name/$project/_apis/pipelines/pipelinePermissions/endpoint/$connection_id\?api-version\=5.1-preview.1

Related

Export all API names Azure APIM

I am trying to export all the url endpoints of my APIs which are stored in Azure APIM.
I need them listed in the format [POST]: https://apim-resource-name.azure-api.net/api-name/api-function, or something similar, so I am trying to enumerate all the endpoints first and the VERB that can be used much like what SwaggerUI or one of the OpenAPI docs might show.
I have this code so far but cannot get the output I would like, am I on the right track or is there any easier way to do this even via UI? I have also tried exporting the template and parsing the script, but it seemed overly complicated for this task.
#az login
$token = az account get-access-token | ConvertFrom-Json
$token = $token.accessToken -replace "`n","" -replace "`r",""
$headers = #{Authorization="Bearer $token.accessToken"}
$subscriptionId = 'subscriptionid'
$resourceGroupName = 'resourcegroupname'
$resourceName = 'resourcename'
$apiName = 'apiname'
$url_getapiexport = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$resourceName/apis/$apiName`?format=swagger-link&export=true&api-version=2021-08-01" #GET
$url_getapiexport
#Invoke-RestMethod -Uri $url_getapiexport -Method GET -Headers #{Authorization="Bearer $token"} -ContentType "application/json"
$url_getapibytags = "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$resourceName/apisByTags?&includeNotTaggedApis=true&api-version=2021-08-01" #GET
$url_getapibytags
$api_tags = Invoke-RestMethod -Uri $url_getapibytags -Method GET -Headers #{Authorization="Bearer $token"} -ContentType "application/json"
$api_tags
foreach ($api in $api_tags) {
write-host API: $api.value.api.name
}
So if you want to export all APIM APIs and their service URLs you can do like this (replace xxx with correct values). Example in PHP
<?php
echo "[INFO] API Names and Service Urls \n\n";
$apiList = shell_exec('az apim api list --resource-group "xxx" --service-name "xxx" ');
$apis = json_decode($apiList, true);
$cli = "az rest --method get --url";
foreach ($apis as $api)
{
$name = $api["name"];
$apiRequest = "$cli " . "\"https://management.azure.com/subscriptions/xxx/resourceGroups/xxx/providers/Microsoft.ApiManagement/service/xxx/apis/$name?api-version=2021-08-01\"";
$json = shell_exec($apiRequest);
$apiInfo = json_decode($json, true);
$displayName = $apiInfo["properties"]["displayName"];
$serviceUrl = $apiInfo["properties"]["serviceUrl"];
printf("%s: %s \n", $displayName, $serviceUrl);
}
?>

Getting 'Bad Request' and 'Invalid query definition' when calling Azure REST API

I'm trying to call an Azure REST API endpoint to get information my daily usage cost.
I'm using Powershell 7.2 and here's my code:
$uri = 'https://management.azure.com/subscriptions/{subscription id}/providers/Microsoft.CostManagement/query?api-version=2021-10-01'
$token = '{generated bearer token string}'
$securetoken = ConvertTo-SecureString $token -AsPlainText -Force
$body = #{
type = 'Usage'
timeframe = 'MonthToDate'
dataset = #{
granularity = 'Daily'
aggregation = #{
totalCost = #{
name = 'PreTaxCost'
function = 'Sum'
}
}
grouping = #(
#{
type = 'Dimension'
name = 'ServiceName'
}
)
}
}
$costresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication Bearer -Token $securetoken -Body $body
Write-Host $costresponse
Here's the request body example from the Microsoft documentation I'm trying to emulate:
{
"type": "Usage",
"timeframe": "TheLastMonth",
"dataset": {
"granularity": "None",
"aggregation": {
"totalCost": {
"name": "PreTaxCost",
"function": "Sum"
}
},
"grouping": [
{
"type": "Dimension",
"name": "ResourceGroup"
}
]
}
}
When I run the code I get this error message:
Line |
27 | … tresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"error":{"code":"BadRequest","message":"Invalid query definition: Missing dataset granularity; valid
| values: 'Daily'.\r\n\r\n (Request ID: c6ead005-85b3-4ebe-9b46-........)"}}
I think the error has to do with the body syntax but I can't figure out what is the issue. I'm following this Microsoft documentation: https://learn.microsoft.com/en-us/rest/api/cost-management/query/usage
EDIT:
I tried converting the body to JSON and adding a depth parameter like this:
$costresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication Bearer -Token $securetoken -Body ($body|ConvertTo-Json -Depth 5)
And now I get a slightly different error message:
Line |
26 | … tresponse = Invoke-WebRequest -Uri $uri -Method Post -Authentication …
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| {"error":{"code":"BadRequest","message":"Invalid query definition, Dataset is invalid or not supplied.
| (Request ID: cf6a4b8f-88e8-4037-aa33-904......)"}}
I needed to add -ContentType 'application/json' to my Invoke-WebRequest function to get it to work. Thanks to #bluuf for the suggestion.

Azure Devops REST API SendMail

I'm trying to send mail after the successful stage on my release definition.
Following the docs
OAuth box is checked in my stage
Project Collection Service Account is added to Build Administrators and Release Administrators.
But the response from REST API is "Azure DevOps Login Page"
Here is my script:
$OrganizationName = "myorg"
$ProjectName = "myproj"
$sendmailto = "example#mail.com"
$mysubject = "Test Mail Subjcet"
$mailbody = "Mail body to test it works with azure rest api"
$PAT="MYPAT"
$Token = "$(System.AccessToken)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$Token"))
$HeaderMail = #{
Authorization = "Bearer $encodedCreds"
}
##send mail
$urimail = "https://${OrganizationName}.vsrm.visualstudio.com/${ProjectName}/_apis/Release/sendmail/$($env:RELEASE_RELEASEID)?api-version=3.2-preview.1"
$requestBody =
#"
{
"senderType":1,
"to":{"tfsIds":[$sendmailto]},
"body":"${mailbody}",
"subject":"${mysubject}"
}
"#
Try {
Invoke-RestMethod -Uri $urimail -Body $requestBody -Method POST -ContentType "application/json" -Headers $HeaderMail
}
Catch {
$_.Exception
}
Tested with:
Tried with 3.2 version and 7.1
PAT Token and authorization to Basic return 400 with Bearer return 401.
Switch $(System.AccessToken) to $($env:System_AccessToken) trygin to convert to base64 and without.
What I'm missing?
Response from
ConsoleLog
It's caused by the $requestBody. The request body requires valid Azure DevOps users referenced by their tfsIds.
Below PS script works for me, if your are running it in pipeline, then please use the $(System.AccessToken) instead of $PAT.
Running locally and authenticate with PAT:
$OrganizationName = "organization"
$ProjectName = "Project"
$sendmailto = "xxx#microsoft.com"
$mysubject = "Test Mail Subjcet"
$PAT="xxx"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$PAT"))
$HeaderMail = #{
Authorization = "Basic $encodedCreds"
}
#Get the tfsid
$userentitlementurl = "https://vsaex.dev.azure.com/${OrganizationName}/_apis/userentitlements?api-version=7.1-preview.1"
$response = Invoke-RestMethod -Uri $userentitlementurl -Method Get -Headers $HeaderMail
#Filter by sendmailto
$tfsid = ($response.value| where {$_.user.mailAddress -eq $sendmailto}).id
Write-Host $tfsid
##send mail
$urimail = "https://vsrm.dev.azure.com/${OrganizationName}/${ProjectName}/_apis/Release/sendmail/168?api-version=7.1-preview.1"
$requestBody =
#"
{
"senderType": 1,
"to": {
"tfsIds": [
"$tfsid"
],
"emailAddresses": []
},
"subject": "$mysubject",
"sections": [
5,
0,
1,
2,
4
]
}
"#
Try {
Invoke-RestMethod -Uri $urimail -Body $requestBody -Method POST -ContentType "application/json" -Headers $HeaderMail
}
Catch {
$_.Exception
}
Running in release pipeline and authenticate with $(System.AccessToken): (Please note that, because this script is being run during the release, the summary email will show the environment as IN PROGRESS even if it is run as the last step in the Release.)
$OrganizationName = "organization"
$ProjectName = "project"
$sendmailto = "xxx#microsoft.com"
$mysubject = "Test Mail Subjcet"
$HeaderMail = #{
Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}
#Get the tfsid
$userentitlementurl = "https://vsaex.dev.azure.com/${OrganizationName}/_apis/userentitlements?api-version=7.1-preview.1"
$response = Invoke-RestMethod -Uri $userentitlementurl -Method Get -Headers $HeaderMail
#Filter by sendmailto
$tfsid = ($response.value| where {$_.user.mailAddress -eq $sendmailto}).id
Write-Host $tfsid
##send mail
$urimail = "$env:SYSTEM_TEAMFOUNDATIONSERVERURI$env:SYSTEM_TEAMPROJECT/_apis/Release/sendmail/$($env:RELEASE_RELEASEID)?api-version=7.1-preview.1"
$requestBody =
#"
{
"senderType": 1,
"to": {
"tfsIds": [
"$tfsid"
],
"emailAddresses": []
},
"subject": "$mysubject",
"sections": [
5,
0,
1,
2,
4
]
}
"#
Try {
Invoke-RestMethod -Uri $urimail -Body $requestBody -Method POST -ContentType "application/json" -Headers $HeaderMail
}
Catch {
$_.Exception
}

Azure DevOps REST API returns a 403 when using the system OAuth token during a build

I'm running a script:
# Variables
$organization = "****"
$project = "****"
$repositoryId = "****"
$pullRequestId = $env:BUILD_PULLREQUEST_ID
$pat = "Bearer $env:System_AccessToken"
$featureReleaseUrl = "http://" + $env:prSourceBranchName + ".azurewebsites.net"
$body = #"
{
"comments": [
{
"content": "Link naar feature release $featureReleaseUrl"
}
]
}
"#
$createThreadInPRUrl = "https://dev.azure.com/$organization/$project/_apis/git/repositories/$repositoryId/pullRequests/$pullRequestId/threads?api-version=5.0"
if ($pullRequestId) {
Invoke-RestMethod -Uri $createThreadInPRUrl -Headers #{Authorization = $pat} -Body $body -Method Post -ContentType 'application/json'
}
When it runs it returns a:
##[error]The remote server returned an error: (403) Forbidden.
I've created a Personal Access Tokens in my personal settings.
I've also created this script:
# Variables
$organization = "****"
$project = "****"
$buildId = $****
$pat = "Bearer $env:System_AccessToken"
if (!$env:Build_PullRequest_SourceBranchName) {
$retrieveSourceBranchFromBuildURL = "https://dev.azure.com/$organization/$project/_apis/build/builds/$buildId" + "?api-version=5.0"
$buildInformation = Invoke-RestMethod -Uri $retrieveSourceBranchFromBuildURL -Headers #{Authorization = $pat } -Method Get -ContentType 'application/json'
$SourceBranchFromBuild = $buildInformation.sourceBranch.split('/')[-1]
Write-Host "### no Build PullRequest SourceBranchName available ###"
Write-Host "##vso[task.setvariable variable=prSourceBranchName;]"$SourceBranchFromBuild
}
And this runs fine. The difference between the first and second script is that the first is a POST and the second a GET. But they both use the $pat token.
Even though the token you used is System.AccessToken, if you don't have access permission of Pull Request, you will also could not operate it.
Go Project Setting--> Repositories--> Repository you want to access, locate your account or the group you are in. Check the permission state of Contribute to pull requests.
You must have this Contribute to pull requests permission allowed, so that you can add the comment to PR.

Function Level Authorization Authorize keys in Azure can we manage these keys through CICD

Can we managae keys through CICD?
Means i need to manage these through CICD not portal or Rest Srevice is it possible?
everything is being managed through rest api (ultimately) so this ask makes very little sense. you can manage those only using the rest calls (as far as I know).
function Add-AzureFunctionKey {
Param(
[string]$appName,
[string]$resourceGroup,
[string]$funcKeyName,
[string]$funcKeyValue
)
$AzureContext = Get-AzureRmContext
if(!$AzureContext){
Write-Output "Please login to your Azure Account"
Login-AzureRmAccount
}
$SubscriptionId = (Get-AzureRmSubscription | select Name, State, SubscriptionId, TenantId | Out-GridView -Title "Azure Subscription Selector" -PassThru).SubscriptionId
Get-AzureRmSubscription -SubscriptionId $SubscriptionId | Select-AzureRmSubscription
$PublishingProfile = (Get-AzureRmWebAppPublishingProfile -ResourceGroupName $resourceGroup -Name $appName)
$user = (Select-Xml -Xml $PublishingProfile -XPath "//publishData/publishProfile[contains(#profileName,'Web Deploy')]/#userName").Node.Value
$pass = (Select-Xml -Xml $PublishingProfile -XPath "//publishData/publishProfile[contains(#profileName,'Web Deploy')]/#userPWD").Node.Value
$pair = "$($user):$($pass)"
$kuduCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair))
$authToken = Invoke-RestMethod -Uri "https://$appName.scm.azurewebsites.net/api/functions/admin/token" -Headers #{Authorization = ("Basic {0}" -f $kuduCredentials)} -Method GET
$Functions = Invoke-RestMethod -Method GET -Headers #{Authorization = ("Bearer {0}" -f $authToken)} -Uri "https://$appName.azurewebsites.net/admin/functions"
$Functions = $Functions.Name
ForEach ($functionName in $Functions) {
$data = #{
"name" = "$funcKeyName"
"value" = "$funcKeyValue"
}
$json = $data | ConvertTo-Json;
$keys = Invoke-RestMethod -Method PUT -Headers #{Authorization = ("Bearer {0}" -f $authToken)} -ContentType "application/json" -Uri "https://$appName.azurewebsites.net/admin/functions/$functionName/keys/$funcKeyName" -body $json
Write-Output "Function $FunctionName Key updated $keys"
}
}
here's a sample found online, i didnt test it. there are a few examples online more or less like the one above.
Source: https://www.powershellbros.com/add-azure-function-key/

Resources