'What kind of security context do custom TFS release tasks get?

TFS 2018u1. I have a custom Powershell task that calls TFS services via the VSSConnection object:

$VSS = Get-VssConnection -TaskContext $distributedTaskContext
$Client = $VSS.GetClient(...)

Question: what kind of security context does the task get? It's definitely not the agent account. To make sure, I've set up a temporary agent instance that runs as me, the TFS admin, and the custom task running on that agent doesn't have the full admin.

The underlying problem is - I'm trying to get the current agent record from a task, and the task only sees one pool, even though we have several. See this answer.



Solution 1:[1]

First off, the distributedTaskContext doesn't connect to TFS with NTLM, like Patrick Lu's answer suggests. It connects with Authorization:Bearer and a token. I've used the same token to invoke the /_api/_common/GetUserProfile endpoint, which returns the current user, and got back the following identity record:

{
    "IdentityType": "user",
    "FriendlyDisplayName": "Project Collection Build Service (TEAM FOUNDATION)",
    "DisplayName": "Project Collection Build Service (TEAM FOUNDATION)",
    "SubHeader": "Build\\233e4ccc-d129-4ba4-9c5b-ea82c7ae1d15",
    "TeamFoundationId": "7a3195ee-870e-4151-ba58-1e522732086c",
    "EntityId": "vss.ds.v1.ims.user.7a3195ee870e4151ba581e522732086c",
    "Errors": [],
    "Warnings": [],
    "Domain": "Build",
    "AccountName": "233e4ccc-d129-4ba4-9c5b-ea82c7ae1d15",
    "IsWindowsUser": false,
    "MailAddress": ""
}

It looks like some kind of artificial identity that TFS creates just for this purpose. Looking in the TFS database in the tbl_Identity table, there are numerous user records with names like that - one per collection, it seems, and also some that are project specific.

This user belongs to a server-level group called "Security Service Group" (and also to a collection level group with the same name). Those groups belong, respectively, to Team Foundation Valid Users and Project Collection Valid Users and nothing else.

At least on the collection level, the "Security Service Group" is visible and contains a lot of accounts.

All those "Build Service" users belong to the domain called "Build". A domain is not a security principal though, you can't grant rights to a domain.

Speaking of OAuth scopes. I've used the same token to invoke the homegrown "what are this token's scopes" page, and it turns out the distributedTaskContext token has exactly one - app_token. It's a valid scope that opens up all endpoints and all methods (see the dynamic scope list). The scopes parameter in the extension manifest has no bearing on that; it only affects the client-side contributions.


When it comes to pool visibility, though, the story is tricky. Seems like all the "Project Collection Build Service" accounts belong to Valid Users, but granting the Reader role on all pools to Valid Users doesn't open them up to the REST API in tasks. Granting Reader explicitly to "Project Collection Build Service" does. However, there are numerous accounts like this (one per collection, it seems) - and granting Reader only opens the pools up to release definitions in the collection where it resides. In order to let tasks in releases in all collections read the pools, you need to go through all collections and grant Reader to the "Project Collection Build Service" from each.

Solution 2:[2]

I'm trying to get the current agent record from a task, and the task only sees one pool, even though we have several.

There is a Agent pool security roles concept, for example with Administrator Role, you can:

Rregister or unregister agents from the pool and manage membership for all pools, as well as view and create pools. They can also use the agent pool when creating an agent queue in a team project. The system automatically adds the user that created the pool to the Administrator role for that pool.

The default rights of a build agent running a release task should be the same as build service account. Please add your build service account to Agent pool security roles to Administrator from the collection-level admin context, Agent Pools page. Then try it again.

Another possibility you are lacking of vso.agentpools scope in your customize release task.

Grants the ability to view tasks, pools, queues, agents, and currently running or recently completed jobs for agents

More details please take a look at Supported scopes

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2