0
votes

We have an on-premise Azure DevOps Server that works with a corporate ActiveDirectory. When adding new users, Azure DevOps Server pulls their information from ActiveDirectory. But the user's information was later updated in ActiveDirectory to fix an issue - their email account was missing.

In the past, I have been able to remove and re-add the user to Azure DevOps Server to fix the problem, as my administrative account has access and can see the user's email in ActiveDirectory. But the users are not being picked up by the sync job in Azure DevOps Server anymore, so their email address continues to be blank. (Users have been added for weeks or months without the update being picked up.)

We have verified that the Azure DevOps Server service account can see the email address in ActiveDirectory when logged into the server. So it's not an access issue with the service account.

How do I manually force Azure DevOps Server to run an ActiveDirectory sync? There used to be a JobService web service that I could access for this in previous versions of TFS, but that service doesn't appear to be available anymore, or is no longer scheduled to run.

3
I'm still looking for a solution to this issue. So far nothing that has been tried has worked. And we now have other sections about a user, such as a last name change, that aren't being picked up either.Jeff

3 Answers

1
votes

Since no solution has worked, I decided to see what could be done from a coding perspective. The answer turned out to be straightforward. NOTE: Please make sure that you check the solutions provided below prior to the coding approach, as Azure DevOps Server is supposed to be refreshing identities automatically.

First, I found a Stack Overflow article about finding users by name:

TFS get user by name

This can be used to fetch a user or a group by its display name, among other attributes, using the ReadIdentity method.

This same IIDentityServiceProvider also has a method on it called RefreshIdentity. This method, when called with the IdentityDescriptor of the user, forces the identity to be immediately refreshed from its provider. See the documentation here:

https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2013/ff734945(v=vs.120)?redirectedfrom=MSDN

This method returns true if the refresh was successful, or false if the refresh failed. it is also possible for the refresh to throw an exception. For example, the Azure DevOps identity named "Project Collection Build Service" is listed as a user when retrieved, but this identity throws an exception when refreshed.

Using these methods, a complete tool was able to be constructed to repair the identities of individual users, or to scan through all users in the group "Project Collection Valid Users" and refresh the entire system. Using this tool, we were able to fix our synchronization issues between Azure DevOps Server and Active Directory.

Here's some sample code showing how to use these methods:

string rootSourceControlUrl = "TODO: Root URL of Azure DevOps";
string projectCollection = "TODO: Individual project collection within Azure DevOps";    

TfsTeamProjectCollection tfsCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri($"{rootSourceControlUrl}/{projectCollection}"));
IIdentityManagementService ims = (IIdentityManagementService)tfsCollection.GetService(typeof(IIdentityManagementService));
TeamFoundationIdentity foundUser = ims.ReadIdentity(IdentitySearchFactor.DisplayName, 
                                       "TODO: Display name of user", MembershipQuery.Direct, 
                                       ReadIdentityOptions.ExtendedProperties);
if(foundUser != null)
{
    try
    {
        if (ims.RefreshIdentity(foundUser.Descriptor))
        {
            // Find the user by its original IdentityDescriptor, which shouldn't change during the refresh
            TeamFoundationIdentity refreshedUser = ims.ReadIdentity(foundUser.Descriptor, 
                          MembershipQuery.Direct, ReadIdentityOptions.ExtendedProperties);

            // TODO : Display changes from foundUser to refreshedUser, using individual properties 
            //        and the method foundUser.GetProperties(), which returns an 
            //        IEnumerable<KeyValuePair<string, object>> collection.
        }
        else
        {
             // TODO : Notify that user failed to refresh
        }
    }
    catch(Exception exc)
    {
        // TODO : Notify that exception occurred
    }
}
else
{
    // TODO : Notify that user was not found
}
0
votes

TFS/Azure DevOps Server uses a background synchronization job, scheduled every hour, to look for changes in Active Directory. So changes you make to Active Directory groups do not get reflected in TFS immediately. Instead, TFS will synchronize those groups regularly (by default every hour).

You may try to restart TFS Job Agent service to see whether it helps.

-2
votes

I tried all of above recommendations and none of them works!

Finally, this code solved my problem:

update [Tfs_Configuration].dbo.tbl_Identity
set 
    AccountName = 'New Name', 
    DistinguishedName = 'CN=*New Name*, OU=..., OU= ... ,OU=... ,OU=...,OU=...,DC=...,DC=...',
    MailAddress = 'New eMail'
where *Your Condition*