0
votes

I've created a powershell script that does some updating of taskgroups that we need in our company. I do this by calling the route "/_apis/distributedtask/taskgroups".

This script works well when I use a personal access token from myself. However, I need it to be run by a build agent as part of a release process.

To manage this I have enabled "Allow scripts to access OAuth token" as outlined in

VSTS - allow Scripts to Access OAuth Token in Release Managment

I have then in my powershell script used the logic outlined here

https://docs.microsoft.com/sv-se/vsts/build-release/actions/scripts/powershell#oauth

to gain access to the token and include it in my api calls to the TFS api. I am successfull in retrieving the taskgroups this way, but when I try to update one I get

[error]Invoke-RestMethod : TF400813: Resource not available for anonymous access. Client authentication required.

To exclude permisson problems I have given the build agent account "Project administrator" persmissions as well as "Build administrator" and "Release administrator". Any suggestions?

2
Could you please share your PS script for troubleshooting? - Andy Li-MSFT
I don't think the script would make much sense to you. But basicly what we do is find a specific taskgroup from one collection A, then we find one taskgroup in collection B and update it so that it looks like the taskgroup from collection A. We want to copy all taskgroups from our collection since we're an infrastructure developing department, and copy it to all other collections. This works when I use my own personal access token. But of course we dont want to have scripts with a token hard coded in them :( - ds99jove
I've managed to create a simple powershell script after all. It first gets all taskgroups, then takes the first one and tries to update it using a PUT. - ds99jove
$url="url/collection/name/_apis/distributedtask/taskgroups" $auth = "Bearer $env:SYSTEM_ACCESSTOKEN" $def=Invoke-RestMethod -Uri $url -Headers @{"Authorization" = $auth} write-host $def $json = ConvertTo-Json $def.value[0] -Depth 10 $enc = [System.Text.Encoding]::UTF8 $encjson= $enc.GetBytes($json) $response = Invoke-RestMethod -Method Put -Body ($encjson) -Uri "$($url)?api-version=4.0-preview.1" -headers @{ "Authorization" = $auth "Content-Type" = "application/json; charset=utf-8" } - ds99jove

2 Answers

0
votes

It appears that OAuth token is not registered for the server.

Please refer to slautebach's solution in this thread for troubleshooting:

It appears that during our upgrade TFS did not register a OAuth token for the server.

The SQL recommend to execute was: using the FQDN (ie tfs-server.doman.com)

EXEC prc_SetRegistryValue 1,'#\Configuration\OAuth\TrustedIssuers\tfs-sever.domain.com\','Microsoft.TeamFoundation.Framework.Server.OAuth.ClientAuthTokenValidator'

This prevented all users from logging in after a TFS server reboot. We then tried with just the server name (ie tfs-server)

EXEC prc_SetRegistryValue 1,'#\Configuration\OAuth\TrustedIssuers\tfs-server\','Microsoft.TeamFoundation.Framework.Server.OAuth.ClientAuthTokenValidator'

This than allowed normal user login and the builds to finally work after a server reboot and re-registering all the build agent.

If that still not work, as a workaround you can use basic authorization to do that:

Below PowerShell script works for me:

Param(
   [string]$baseurl = "http://server:8080/tfs/DefaultCollection",  
   [string]$projectName = "ProjectName",
   [string]$keepForever = "true",
   [string]$user = "username",
   [string]$token = "password"
)

# Base64-encodes the Personal Access Token (PAT) appropriately
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token)))

#Need to change revision every time

function CreateJsonBody
{

    $value = @"
        {
            "tasks": [
                {
                    "displayName": "PowerShell Script",
                    "alwaysRun": false,
                    "continueOnError": false,
                    "condition": "succeeded()",
                    "enabled": true,
                    "timeoutInMinutes": 0,
                    "inputs": {
                        "scriptType": "filePath",
                        "scriptName": "$/TFVC-Scrum2018/ConsoleApp1/PS/0129-GetIISsites.ps1",
                        "arguments": "",
                        "workingFolder": "",
                        "inlineScript": "# You can write your powershell scripts inline here. \n# You can also pass predefined and custom variables to this scripts using arguments\n\n Write-Host \"Hello World\"",
                        "failOnStandardError": "true"
                    },
                    "task": {
                        "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1",
                        "versionSpec": "1.*",
                        "definitionType": "task"
                    }
                },
                {
                    "displayName": "PowerShell Script",
                    "alwaysRun": false,
                    "continueOnError": false,
                    "condition": "succeeded()",
                    "enabled": true,
                    "timeoutInMinutes": 0,
                    "inputs": {
                        "scriptType": "filePath",
                        "scriptName": "$/TFVC-Scrum2018/ConsoleApp1/PS/0129.ps1",
                        "arguments": "",
                        "workingFolder": "",
                        "inlineScript": "# You can write your powershell scripts inline here. \n# You can also pass predefined and custom variables to this scripts using arguments\n\n Write-Host \"Hello World\"",
                        "failOnStandardError": "true"
                    },
                    "task": {
                        "id": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1",
                        "versionSpec": "1.*",
                        "definitionType": "task"
                    }
                }
            ],
            "visibility": [
                "Build",
                "Release"
            ],
            "runsOn": [
                "Agent",
                "DeploymentGroup"
            ],
            "owner": "d122de31-36a7-415c-aa42-b6d09295d5a0",
            "revision": 2,
            "createdBy": {
                "id": "d122de31-36a7-415c-aa42-b6d09295d5a0",
                "displayName": "xxx",
                "uniqueName": "xxx"
            },
            "createdOn": "2018-02-02T07:17:45.25Z",
            "modifiedBy": {
                "id": "d122de31-36a7-415c-aa42-b6d09295d5a0",
                "displayName": "xxx",
                "uniqueName": "xxx"
            },
            "modifiedOn": "2018-02-02T07:17:45.25Z",
            "id": "4c8c1d32-52bc-492e-ba4d-c9b1b363bcdf",
            "name": "0203",
            "version": {
                "major": 1,
                "minor": 0,
                "patch": 0,
                "isTest": false
            },
            "serverOwned": false,
            "contentsUploaded": true,
            "iconUrl": "/tfs/_static/tfs/Dev16.M122.5/_content/icon-meta-task.png",
            "hostType": null,
            "packageType": "",
            "packageLocation": "",
            "sourceLocation": "",
            "minimumAgentVersion": "*",
            "friendlyName": "0203",
            "description": "test0203",
            "category": "Build",
            "helpMarkDown": "",
            "definitionType": "metaTask",
            "author": "xxx",
            "demands": [],
            "groups": [
                {
                    "name": "PowerShell Script",
                    "displayName": "PowerShell Script",
                    "isExpanded": true,
                    "visibleRule": ""
                },
                {
                    "name": "PowerShell Script",
                    "displayName": "PowerShell Script",
                    "isExpanded": true,
                    "visibleRule": ""
                }
            ],
            "inputs": [],
            "satisfies": [],
            "sourceDefinitions": [],
            "dataSourceBindings": [],
            "instanceNameFormat": "Task group: 0203 ",
            "execution": {}
        } 

"@

 return $value
}

$json = CreateJsonBody

$uri = "$baseurl/$($projectName)/_apis/distributedtask/taskgroups?api-version=4.0-preview.1"
Write-Host $uri
$result = Invoke-RestMethod -Uri $uri -Method Put -Body $json -ContentType "application/json" -Headers @{Authorization=("Basic {0}" -f $base64AuthInfo)}
0
votes

It was actually a permission issue. I was assuming that the OAuth token being used would be from the user that the build agent was running as, but this was not the case.

I resolved this by giving 'Project Collection Build Service' user "Edit task group" permissions on each collections task groups.