I'm attempting to use the TFS event subscription service to dynamically create subscriptions through the web interface. The subscriptions are going to an intermediate account. For our purposes, we'll call the two accounts "non-admin user" and "subscription storage".
An administrator can create an alert for the "subscription storage" account, and the subscription storage account can create alerts for itself, but a non-admin user cannot create subscriptions in the storage account. I receive the following error message:
Access Denied: {user account name} needs the following permission(s) on the resource $SUBSCRIPTION: to perform this action: Edit
The code I'm using is:
IEventService eventService = (IEventService)this.tfsCollection.GetService(typeof(IEventService));
eventService.SubscribeEvent(userAccountIdentity.Sid, Strings.WorkItemChangedEvent, string.Format(Strings.Condition0, workItem.ToString(CultureInfo.InvariantCulture)), deliveryPreference, string.Format(Strings.AlertTag0, workItem.ToString(CultureInfo.InvariantCulture)));
Please take it on faith that all of the parameters are correct and that their values are irrelevant for this discussion. :) tfsCollection
is a TfsTeamProjectCollection
object that comes from the page's Connection.TeamProjectCollection
property.
My first thought was to break impersonation so that it uses the service account (in this case, NetworkService), so I made an extension method that takes an Action
and performs it without impersonation, as follows:
public static void WithoutImpersonation(this Action actionToPerform)
{
using (var ctx = WindowsIdentity.Impersonate(IntPtr.Zero))
{
try
{
actionToPerform();
}
finally
{
ctx.Undo();
}
}
}
This correctly breaks impersonation for the duration of the Action
(checking WindowsIdentity.GetCurrentUser()
returns the NetworkService account instead of the user account), but it still fails to create the event subscription with the same error. The authenticated user of the TfsTeamProjectCollection
is the NetworkService account, as well.