【问题标题】:Error managing taskgroups using the TFS api and builtin OAuth System.Accesstoken使用 TFS api 和内置 OAuth System.Accesstoken 管理任务组时出错
【发布时间】:2018-07-11 14:25:58
【问题描述】:

我创建了一个 powershell 脚本,用于更新我们公司需要的任务组。我通过调用路由“/_apis/distributedtask/taskgroups”来做到这一点。

当我使用自己的个人访问令牌时,此脚本运行良好。但是,我需要它在发布过程中由构建代理运行。

为了管理这一点,我启用了“允许脚本访问 OAuth 令牌”,如

中所述

VSTS - allow Scripts to Access OAuth Token in Release Managment

然后我在我的 powershell 脚本中使用了此处概述的逻辑

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

获取对令牌的访问权并将其包含在我对 TFS api 的 api 调用中。我以这种方式成功地检索了任务组,但是当我尝试更新一个时,我得到了

[错误]Invoke-RestMethod:TF400813:资源不可用于 匿名访问。需要客户端身份验证。

为了排除权限问题,我已授予构建代理帐户“项目管理员”权限以及“构建管理员”和“发布管理员”权限。有什么建议吗?

【问题讨论】:

  • 能否分享您的 PS 脚本以进行故障排除?
  • 我认为这个脚本对你没有多大意义。但基本上我们所做的是从一个集合 A 中找到一个特定的任务组,然后我们在集合 B 中找到一个任务组并对其进行更新,使其看起来像集合 A 中的任务组。我们想要从我们的集合中复制所有任务组,因为我们是基础设施开发部门,并将其复制到所有其他馆藏。这在我使用自己的个人访问令牌时有效。但是我们当然不希望脚本中有硬编码的令牌:(
  • 毕竟我已经设法创建了一个简单的 powershell 脚本。它首先获取所有任务组,然后获取第一个并尝试使用 PUT 对其进行更新。
  • $url="url/collection/name/_apis/distributedtask/taskgroups" $auth = "承载 $env:SYSTEM_ACCESSTOKEN" $def=Invoke-RestMethod -Uri $url -Headers @{"Authorization" = $auth} 写入主机$def $json = ConvertTo-Json $def.value[0] -Depth 10 $enc = [System.Text.Encoding]::UTF8 $encjson= $enc.GetBytes($json) $response = Invoke-RestMethod -Method把 -Body ($encjson) -Uri "$($url)?api-version=4.0-preview.1" -headers @{ "Authorization" = $auth "Content-Type" = "application/json; charset=utf -8" }

标签: powershell tfs oauth


【解决方案1】:

这实际上是一个权限问题。我假设正在使用的 OAuth 令牌来自运行构建代理的用户,但事实并非如此。

我通过授予“项目集合构建服务”用户对每个集合任务组的“编辑任务组”权限来解决此问题。

【讨论】:

    【解决方案2】:

    似乎没有为服务器注册 OAuth 令牌。

    请参考this thread slautebach的解决方案进行故障排除:

    在我们的升级过程中,TFS 似乎没有注册 OAuth 令牌 用于服务器。

    建议执行的 SQL 是:使用 FQDN(即 tfs-server.doman.com)

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

    这会阻止所有用户在 TFS 服务器重新启动后登录。我们 然后尝试仅使用服务器名称(即 tfs-server)

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

    这比允许普通用户登录和构建最终工作 在服务器重新启动并重新注册所有构建代理后。

    如果这仍然不起作用,作为一种解决方法,您可以使用基本授权来执行此操作:

    以下 PowerShell 脚本适用于我:

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

    【讨论】:

    • 我看看我能不能测试这个脚本,另一个部门负责。当我们设法测试它时会报告!
    • 当我等待的时候,你确定这是我们的问题吗?只是认为我可以使用 AccessToken 进行 GET。如果没有为服务器注册 OAuth 令牌,我应该能够这样做吗?所以重复我自己,这似乎只是我做 PUT 时的问题。
    • @ds99jove 是的,看起来有点奇怪,一般 Gets 工作 Put 也会工作。无论基本身份验证如何工作,它对你有用吗?有更新吗?
    • 由于各种原因,我转而使用 Powershell v2(预览版)的任务,并且由于某种原因似乎给了我更好的错误消息
    • "Invoke-RestMethod : {"$id":"1","innerException":null,"message":"访问被拒绝。项目集合构建服务(帐户)需要编辑任务组权限才能执行操作。有关详细信息,请联系 Team Foundation Server 管理员。","typeName":"Microsoft.TeamFoundation.DistributedTask.WebApi.AccessDeniedException, Microsoft.TeamFoundation.DistributedTask.WebApi","typeKey":"AccessDeniedException","errorCode":0 ,"eventId":3000}"
    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 2019-03-01
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    相关资源
    最近更新 更多