Force all source control folders to inherit security settings

While working on a code to set the security for source control using the TFS API, I came across a need to  force all children source control folders to inherit from their parent. All existing setting on the children had to be “cleaned up” so only inherited secutriy shows up.

var tfs = Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://223973regrtfsp1:8080/tfs/teamproject"));
tfs.EnsureAuthenticated();
var sec = tfs.GetService<ISecurityService>();
Microsoft.TeamFoundation.Framework.Client.SecurityNamespace vcSecurityNamespace = sec.GetSecurityNamespace(Microsoft.TeamFoundation.VersionControl.Common.SecurityConstants.RepositorySecurityNamespaceGuid);
vcSecurityNamespace.RemoveAccessControlLists("$/PathOfFolder", true);

The above code removed all security setting from the folder down to the last child. This is very useful when you know that security for all folders need to be reset.

Posted in Team Foundation Server | Tagged | Leave a comment

Update user permissions in source control using TFS API

Recently I had to make changes to our source control permissions, so that a specific group/user is just given read access and all other access is removed. We have used active directory for providing permissions and also given specific individuals permissions on different folders levels. Not an ideal way for giving access to user in TFS since it makes auditing and maintenance of user access very difficult. However this was the way the TS security turned out to be.

The Active directory groups were given different access (sometimes just read and sometimes all permissions) across folders. This made it very difficult to manually determine the group’s/user’s access in source control.

Hence I had to write code (using the TFS API) to grant/deny permissions to the group/user across all folders. The sample code is shown below.

using System;
using System.Collections.Generic;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
...
...

static void Main(string[] args)
{

    // Connect to TFS - VersioControlServer service
    var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("<TFS Collection URL>"));
    tfs.EnsureAuthenticated();

    // Get the identity management service
    IIdentityManagementService ims = tfs.GetService<IIdentityManagementService>();

    // Get the TFS security service.
    var sec = tfs.GetService<ISecurityService>();

    // Version control service exposes methods to work with TFS version control
    var vcs = tfs.GetService<VersionControlServer>();

    TeamFoundationIdentity identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, "<User> or <Group>", MembershipQuery.None, ReadIdentityOptions.None);
    SecurityNamespace vcSecurityNamespace = sec.GetSecurityNamespace(Microsoft.TeamFoundation.VersionControl.Common.SecurityConstants.RepositorySecurityNamespaceGuid);

    var teamProjects = vcs.GetAllTeamProjects(true);
    foreach (var teamProject in teamProjects)
    {
        System.Collections.ObjectModel.Collection<AccessControlList> accLst = vcSecurityNamespace.QueryAccessControlLists(teamProject.ServerItem, new List<IdentityDescriptor>() { identity.Descriptor }, true, true);
        int allow = (int)Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.Read;
        int deny = (int)(Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.AdminProjectRights |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.Checkin |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.CheckinOther |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.PendChange |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.Label |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.ReviseOther |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.LabelOther |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.Lock |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.ManageBranch |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.Merge |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.UndoOther |
                            Microsoft.TeamFoundation.VersionControl.Common.VersionedItemPermissions.UnlockOther);

        vcSecurityNamespace.SetPermissions(teamProject.ServerItem, identity.Descriptor, allow, deny, true);

        foreach (var accCtrl in accLst)
        {
            if (!accCtrl.InheritPermissions)
            {
                string[] perm = vcs.GetEffectivePermissions(identity.UniqueName, accCtrl.Token);
                if (perm.Length != 0)
                {
                    Console.WriteLine("Existing permissions at '{0}' are: '{1}'", accCtrl.Token, String.Join(", ", perm));
                    if (!(perm.Length == 1 && perm[0] == "Read"))
                    {
                        if (perm.Length != 0)
                        {
                            // ******
                            //  DO NOT SET PERMISSIONS USING THE ACCESS CONTROL. DOING SO WILL REMOVE ALL OTHER SECURITY
                            // SETTING ON THE SOURCE CONTROL FOLDER.
                            // ******
                            //accCtrl.SetPermissions(identity.Descriptor, allow, deny, true);

                            vcSecurityNamespace.SetPermissions(accCtrl.Token, identity.Descriptor, allow, deny, true);
                            string[] newPerm = vcs.GetEffectivePermissions(identity.UniqueName, accCtrl.Token);
                            Console.WriteLine("\t\tUpdated permissions to: '{0}'", String.Join(", ", newPerm));
                        }
                    }
                }
            }
        }
    }
}
Posted in Team Foundation Server | Tagged | 1 Comment

TFS 2013 Update 2 hangs during upgrade – .NET issue!

Earlier this week I was doing an upgrade of our Team Foundation Server  2013 instance to Update 2. The database and the application tier are installed on the same machine. The installation piece went through without any issue. However when I started the configuration part, in the Update section of the TFS administration console, the application kept hanging on the “Database” screen. It would display the configuration database in the list box, but then just hang.

On looking at the event viewer logs, there were two errors in the “Application Logs” sections (as shown below)

image

The .NET Runtime error logs provided further clues as to what could be wrong. On opening it I could see the stack trace that linked to a SQL connectivity issue. This seemed odd because I was doing an in-place upgrade and the existing TFS instance was not having any issues with database connectivity (before the update 2 was installed!).

Application: TfsMgmt.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
   at System.Data.SqlClient.SNIHandle.ReleaseHandle()
   at System.Runtime.InteropServices.SafeHandle.InternalDispose()
   at System.Data.SqlClient.TdsParserStateObject.Dispose()
   at System.Data.SqlClient.TdsParser.Disconnect()
   at System.Data.SqlClient.SqlInternalConnectionTds.LoginFailure()
   at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(System.Data.ProviderBase.TimeoutTimer, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.String, System.Security.SecureString, Boolean)
   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(System.Data.ProviderBase.DbConnectionPoolIdentity, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SqlCredential, System.Object, System.String, System.Security.SecureString, Boolean, System.Data.SqlClient.SqlConnectionString, System.Data.SqlClient.SessionData)
   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(System.Data.Common.DbConnectionOptions, System.Data.Common.DbConnectionPoolKey, System.Object, System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection, System.Data.Common.DbConnectionOptions, System.Data.Common.DbConnectionPoolKey, System.Data.Common.DbConnectionOptions)
   ...
   ...

On doing some more online searches it turns out that the above SQL error is caused because of .NET 4.5.1. More details of this issue seen in this KB article from Microsoft at http://support.microsoft.com/kb/2915689 (example 3 is close to the error we see in the event viewer). As suggested in the “Resolution” section, I went ahead and installed Microsoft .NET Framework 4.5.2 from http://support.microsoft.com/kb/2901954.

After restarting the machine I was able to successfully go ahead and  connect to the databases and finish the upgrade to TFS 2013 Update 2.

Posted in Team Foundation Server | Tagged , | Leave a comment

Report Builder icon missing in SQL Report Manager

Recently I was asked to look into an issue were users were not able to see either the Report Builder icon image or the My Reports folder on SQL 2012’s report manager page (default URL is http://<server name>/Reports). Most of the blogs (and the MSDN site) indicate that this feature is enabled by default, but I could not find it!


Enable the My Reports Folder

This option can be set using the SQL Management Studio (SSMS). Log into SSMS (select “Reporting Services” as server type) using a administrator account for the SQL server. Right click on the server node to open the drop down option and selected properties.

image

Note: I had to open the management studio using the Run as administrator option to be able to view the properties of the reporting server. Otherwise the properties option would be disabled (as shown below)!

image

On the General tab make sure that the Enable a My Reports folder for each user checkbox is checked. I selected the “My Reports” role (which is one of the default roles) to be associated with this option. Only users who have this role would be able to see the My Reports folder.

image

After this change was made the users  could now see the folder where they can save their own reports.

image

 

Show the Report Builder Icon on the Report Manager page

To enable/show this icon on the report manager page, open the Report Manager page, in your favorite browser, using the administrator account. On the right top corner of the page there will be a “Site Settings” link. Click the link to view and make modifications to the site settings.  image

Note you must open the browser using the “Run as administrator” option to see the “Site Settings” option.

Select the Security tab and on the page that shows up click the New Role Assignment button to add the user who would like to see the Report Builder icon.In the user name area provide the user’s ID and select the “System User” role. This is a default role that has the appropriate privileges set so that the report builder option is shown to the user.

image

 

System Roles

The System User and System Administrator roles are two default roles in SQL 2012. To view these roles, log into SSMS using the administrator id (just like in the above steps) and expand the Security–>Roles tree.

image

Here you can see all the roles that are defined for SSRS.  The default task permissions for System Administrator and System Users are shown below

image

image

Note that the “Execute Report Definition” task is the one that causes the report builder icon to show up.  As seen from above the “System User” role has that task selected and hence users with this role can view/use the report builder.

Posted in SSRS | Tagged | Leave a comment

Changing the default action on check-in

When a user associates their check-in with a work item, the default behavior is to “Resolve” the work item. Many times developers prefer not to have the work item change its state and rather just associate their check-in with the work item. In such a scenario they need to select the “Associate” option from the drop down (next to the work item being associated with).

Developers can change this default behavior on their local machine by changing the registry value “ResolveAsDefaultCheckinAction” to “False”at “HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0\TeamFoundation\SourceControl\Behavior”. The highlighted number “10.0” indicates the version of Visual Studio 2010. Change this to the version for which you want to change this default behavior. The version is 11.0 (for Visual Studio 2012), and 12.0 (for Visual Studio 2013).

Posted in Team Foundation Server | Leave a comment

Connect to SQL server when all system administrators passwords are lost!

Recently I was in a situation (on my local machine) where I could not create new users or do any admin related stuff on my SQLEXPRESS 2012 instance. After search around I came across this blog that showed how you can add an existing windows administrator to SQL and give it admin rights.

Microsoft also has a link about this process at http://msdn.microsoft.com/en-us/library/dd207004.aspx. However the blog (mentioned above) had pictures and seemed easier to follow! ;)

Posted in SQL Server | Leave a comment

Register TFS Check-in policy using command line

Recently I created a custom check-in policy that had to be distributed across all developers. There are multiple options of doing it (using an installer that all developers would use to install it, using TFS power tools or by using a “push” technique that would roll out the policies).  Here the company already had an infrastructure setup for pushing files to end user machines and executing remote commands (using Windows PowerShell or just the regular MSDOS command line). Weighing We decided to utilize this infrastructure to roll out our custom policy rather than ask every developer to install (or copy and register) the policy manually.

We started by staging the policy on a NAS location that can be accessed by all developer machines. Using the registry key values (as mentioned in this article), the version of Visual Studio was detected.

   1: reg query "HKEY_CLASSES_ROOT\VisualStudio.DTE.11.0"

   2: IF ERRORLEVEL 0 (

   3:     REM Visual Studio 2012 is installed. 

   4: )

Since the registry path for a check-in policy are different for a 64-bit machine, compared to a 32 bit machine, it was important to detect if the machine was a 64-bit or 32 bit. I have used the simple approach of checking if the “ProgramFiles(x86)” environment variable exists. If it does then the machine is a 64 bit, if not it is a 32 bit machine. Microsoft has another approach, if you prefer and it is shown here – http://support.microsoft.com/kb/556009

   1: IF DEFINED ProgramFiles(x86) (

   2:   REM This is a 64 bit machine

   3: )

Now using the “reg add” command the check-in policy is registered. More information on the reg command is located here

   1: reg add "%FullRegPath%" /v "%RegKey%" /t REG_SZ /d "%RegValue%" /f

The batch script is executed remotely on every developer machine any updates are pushed out using the existing infrastructure. Till now this process has worked for us. Hopefully Microsoft will come out with a easier, inbuilt approach to installing/registering check-in policies on  all developer machines.

Posted in Team Foundation Server | Tagged | Leave a comment