TFS 2010 - Build Security API

I had a request recently on how to “Secure” a build from code. While I am still not sure there is a great way to do that. What I found is that there is next to no information on the TFS Security API. So, I thought I would post this code here as an example of using the Security API. Note that this example is specific to Build, but the security API is for TFS in general.

So, in this example we want to “deny” contributors from being able to Edit builds for a particular definition. In the UI, you would simply right click the definition, choose Security, select the Contributors group, and click the checkbox in the Deny column for the “Edit build quality” permission.

In code this looks like this:

 using System;
using Microsoft.TeamFoundation;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Build.Common;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Server;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Remove the ability for a user to modify a build
            TfsTeamProjectCollection collection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
                new Uri("https://jpricket-test:8080/tfs/defaultcollection"));
            IBuildServer buildServer = collection.GetService<IBuildServer>();
            ISecurityService securityService = collection.GetService<ISecurityService>();
            ICommonStructureService cssService = collection.GetService<ICommonStructureService>();
            IIdentityManagementService imService = collection.GetService<IIdentityManagementService>();  

            String teamProject = "jpricket-071410";
            String definitionName = "New Build Definition 1";
            String buildNumber = "New Build Definition 1_20100714.3";
            String groupName = @"[jpricket-071410]\Contributors";

            IBuildDetail build = buildServer.GetBuild(
                buildServer.CreateBuildDefinitionSpec(teamProject, definitionName), 
                buildNumber, null, QueryOptions.Definitions);

            // Read the group represnting the root node  
            TeamFoundationIdentity groupIdentity = imService.ReadIdentity(
                IdentitySearchFactor.AccountName,  groupName, 
                MembershipQuery.Direct, ReadIdentityOptions.None);

            SecureBuild(build, groupIdentity, securityService, cssService);

            Console.WriteLine("Build {0} secured.", build.BuildNumber);
        }

        static void SecureBuild(IBuildDetail build, TeamFoundationIdentity groupIdentity, 
            ISecurityService securityService, ICommonStructureService cssService)
        {
            SecurityNamespace buildSecurity = securityService.GetSecurityNamespace(
                BuildSecurity.BuildNamespaceId);

            // Check for null 
            // (build security would only be null if we are talking to an older server)
            if (buildSecurity != null)
            {
                // Team project level permissions use this token 
                // (these permissions are found on the Security menu off the Builds node in Team Explorer)
                String tokenTeamProject = LinkingUtilities.DecodeUri(
                    cssService.GetProjectFromName(build.TeamProject).Uri).ToolSpecificId;

                // Definition level permissions use this token (Security menu on a BuildDefinition in Team Explorer)
                String tokenDefinition = 
                    tokenTeamProject + 
                    BuildSecurity.NamespaceSeparator + 
                    LinkingUtilities.DecodeUri(build.BuildDefinition.Uri.AbsoluteUri).ToolSpecificId;

                buildSecurity.SetPermissions(
                    tokenDefinition, groupIdentity.Descriptor, 0, 
                    BuildPermissions.EditBuildQuality, true);
            }
        }
    }
}

I hope this sample leads to more samples – Code On!