TFS 2015 u2. Trying to write a TFS extension that would use JavaScript API to manipulate the security on a release definition. Security related APIs fail on me with error 401. T
Unfortunately, there isn’t any REST API to change permission of release definition or release environment.
There is a user voice that you can vote. REST API for release defintion or release enviornment TFS PM will kindly review your suggestion.
In TFS 2017 u2, finally, there's vso.security_manage.
In TFS 2017 u1, there is a scope vso.base
that covers this API endpoint, but only with GET. POST, which is required to change the descriptor, is still not covered by the scope.
In TFS 2015 u2, and presumably below, there's no scope that covers the ACL related endpoints.
I've found a very hackish way to enable those endpoints for OAuth in older versions of TFS. It's only applicable to on-premises TFS. The relationship between OAuth scopes and service endpoint URLs/methods is stored in a global, public, mutable singleton data structure that a piece of user code might just be able to alter. You can see it in your favorite MSIL disassembler (ILDASM, ILSpy, Reflector) if you poke around method CreateDefault
in class Microsoft.VisualStudio.Services.DelegatedAuthorization.AuthorizationScopeDefinitions
within Microsoft.TeamFoundation.Framework.Server.dll
.
The following Global.asax does the trick. You have to copy it to C:\Program Files\Microsoft Team Foundation Server 14.0\Application Tier\Web Services
(for TFS 2015).
<%@ Application Inherits="Microsoft.TeamFoundation.Server.Core.TeamFoundationApplication" %>
<%@ Import namespace="Microsoft.VisualStudio.Services.DelegatedAuthorization" %>
<%@ Import namespace="System.Collections.Generic" %>
<%@ Import namespace="System.Linq" %>
<script runat="server">
void Session_Start(object o, EventArgs a)
{
AuthorizationScopeDefinition Def = AuthorizationScopeDefinitions.Default.scopes
.FirstOrDefault(d => d.scope == "vso.identity");
if(Array.IndexOf(Def.patterns, "/_apis/SecurityNamespaces#GET") < 0)
{
List<string> l = Def.patterns.ToList();
l.Add("/_apis/SecurityNamespaces#GET");
l.Add("/_apis/AccessControlLists#GET+POST");
l.Add("/DefaultCollection/_apis/SecurityNamespaces#GET");
l.Add("/DefaultCollection/_apis/AccessControlLists#GET+POST");
Def.patterns = l.ToArray();
}
}
</script>
Hooking Application_Start would've made more sense, but the code-behind DLL already hooks it. Another handler in Global.asax doesn't override. I monkey-patch the vso.identity
scope, because my extension already claims that, but feel free to use any other one.
Introducing your own, brand new scope probably won't work.