问题
I created a service account to impersonate users in my organization in order to make changes to work items in the users’ name. I already added that service account to the group “Project Collection Service Accounts”, which has “Make requests on behalf of others” set to “Allow”. The service account has Visual Studio Subscription.
I then used my code, which is working with our on-premise TFS, to execute the impersonation and I got an error 500 saying that “Access Denied: X needs the following permission(s) to perform this action: Make requests on behalf of others”
What should I do to make it works? Here the code I’m using:
var credential = new VssAadCredential("X@myoganization", "password");
var collection = new TfsTeamProjectCollection(new Uri("my_devops_uri"), credential);
MyTfsConnection.ProjectCollection = collection;
MyTfsConnection.IdentityService = collection.GetService<IIdentityManagementService>();
MyTfsConnection.WIStore = collection.GetService<WorkItemStore>();
var adAccount = "someone@myoganization";
var identity = MyTfsConnection.IdentityService.ReadIdentity(IdentitySearchFactor.AccountName, adAccount, MembershipQuery.None, ReadIdentityOptions.None);
using (var impersonatedCollection = new TfsTeamProjectCollection(new Uri("my_devops_uri"), credential, identity.Descriptor))
{
var impersonatedWIStore = impersonatedCollection.GetService<WorkItemStore>();
}
回答1:
It's not able to do this, Service account is not intended to connect the client with server either check in code or change work items.
Service account is used to run various services related to TFS. It should have the minimum privileges possible on the machine.
The client should not connect to the server with a service account, they should be using their own account which you grant access to the relevant repositories in TFS. For example, if you connect all clients with the service account, how will you know who checked in each changeset, who should assign work items to?
You will also not able to assign work items to a service account.
回答2:
I've been attempting to migrate code to DevOps Services that uses impersonation to alter work items in another users name as well. Uncanny how similar it is to yours. It's almost like we all grabbed it from this old post on TFS impersonation. Like yours, this code works with on-premises DevOps Server 2019.1.1 but I ran into the same issue trying to get it working with DevOps Services.
During my search for an answer that works with the TFS / DevOps (SOAP) client API and DevOps Services, I ran across this SO question where the question quotes the following.
"For security reasons (and compliance and a number of other reasons), the impersonation header isn't supported on Visual Studio Online"
I've yet to find this same information anywhere in the documentation. However, it appears to be true. Impersonation is disabled in Azure DevOps Services. Drat!
Not giving up, my search also turned up the following from the November 2017 release notes, which appears promising.
Grant the bypassrule permission to specific users
Often, when migrating work items from another source, organizations want to retain all the original properties of the work item. For example, you may want to create a bug that retains the original created date and created by values from the system where it originated.
The API to update a work item has a bypassrule flag to enable that scenario. Previously the identity who made that API request had to be member of the Project Collection Administrators group. With this deployment we have added a permission at the project level to execute the API with the bypassrule flag.
However, I find no such permission in the collection / organization or project permissions on either DevOps Server or DevOps Services. Drat again! That led me to this SO answer where a work item update is crafted in JSON using the REST API directly. So the bypass rule option must still be valid, just not exposed as a settable permission.
So I started looking at the TFS / DevOps (SOAP) client API again and found the WorkItemStoreFlags.BypassRules
flag to pass to the WorkItemStore
when it is created. The following should provide the basic mechanics.
// Use a personal access token with Work Items scope
var credentials = new VssBasicCredential(String.Empty, "Your PAT");
// Connect with TFS / DevOps client libs.
// Older SOAP based client but still works with DevOps Services.
var teamProjectCollection = new TfsTeamProjectCollection(new Uri("https://dev.azure.com/your-org"), credentials);
// Don't use teamProjectCollection.GetService<WorkItemStore>().
// New up WorkItemStore using the collection and explicitly specify the BypassRules flag.
// This allows you to set the CreatedBy field later.
var workItemStore = new WorkItemStore(teamProjectCollection, WorkItemStoreFlags.BypassRules);
// Get the project, work item type, and create the new work item.
var project = workItemStore.Projects["YourProject"];
var workItemType = project.WorkItemTypes["Product Backlog Item"];
var workItem = new WorkItem(workItemType);
// Set the work item fields
workItem.Title = "The Title";
// Without the BypassRules flag the CreatedBy value set here will be ignored on
// Save() and replaced with the user account attached to the PAT used to authenticate.
workItem.Fields[CoreField.CreatedBy].Value = "NotYourUser@yourdomain.com";
workItem.Fields[CoreField.AssignedTo].Value = "NotYourUser@yourdomain.com";
workItem.Save();
来源:https://stackoverflow.com/questions/57918502/how-to-use-service-account-to-impersonate-users-in-azure-devops