Con risposta TFS version control inheritance modifications via API

  • mercoledì 7 marzo 2012 21:28
     
      Contiene codice

    Our branching scheme puts significant security around the $/Main trunk, such that when developers create a branch, someone with project admin auth (aka me) needs to manually go in and reset permissions. 

    I have this down to a science now - I simply open up the branch properties, go to permissions, highlight the "[project]\Contributors" and remove inheritenace, click ok, then go back and re-add the inheritance so that it picks up the permissions from the folder that the branch lives in.

    But its a manual process.  And I dont want to be the choke point for any development efforts.

    Our Source heirarchy looks like this:

    Project
      $/Main
      Branches
         $/Main/Branch1
         $/Main/Branch2
         ...etc

    So I want to write code to allow the devs to do this on their own... using a svc account with sufficient privs.  What I have found after scouring the various blogs isnt doing what I want, so I'm stumped..

    This is the latest incarnation of my effort showing the working guts

                  TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(TFSCollUri, CredentialCache.DefaultCredentials);
    
                    VersionControlServer vcs = tfs.GetService(typeof(VersionControlServer)) as VersionControlServer;
    
                    // duplicate what I do when new branches are created
                    // 1. Break the Inherited Permissions
    
                    changes.Add(new InheritanceChange(SourceBranchSelector.SelectedValue.ToString(), false));
                                    
                    actualChanges = vcs.SetPermissions(changes.ToArray());
                         
    
                    // 2 Re-add the Inerhitance
                    changes.Clear();
                    changes.Add(new InheritanceChange(SourceBranchSelector.SelectedValue.ToString(), true));
    
                    actualChanges = vcs.SetPermissions(changes.ToArray());
                    
    

    I see two problems when I execute this...

    1. I see no way of working against only the "[Project]\Contributors" within this method (worse yet when I look at the permission set after the first vcs.SetPermissions, there are NO permissions in the list).. kinda scary (and lucky I'm working on a test instance of TFS)

    2. When I execute the re-add, the permissions are not being reset to the folder level that these branches live at, but at the main project level (what they were originally)..

    So, in a nutshell, how do I replicate what the TFS Version Control UI is doing? 

    Thanks in advance

Tutte le risposte

  • giovedì 8 marzo 2012 13:49
     
     

    It has been a while since I worked on this, but I believe the UI is doing some additional work here on each of the two different inheritance transitions, which may be misleading you.

    Inherit -> No inherit: Take the effective permissions that applied to the item and turn these all into "real" access control entries on the item.

    No inherit -> Inherit: I believe we take this opportunity to wipe the access control list of the item completely. So all you are left with are inherited permissions from the parent.

    Looking at your scenario more closely: When you branch an item in TFS, we branch the access control entries with it. It sounds like that for your particular scenario this is not what you want. So your app doesn't need to toggle inheritance at all. After you create the new branch, you just need to clear the access control list for the root item of the branch of all explicit ACEs. The inherit bit would remain on, meaning the effective permissions continue to propagate down from its parents.

    You can do this through the API or you can use the "Tf perm" command. (Again I haven't done this in a while so my syntax might be slightly off.)

    tf perm $/My/New/Branch /remove:*

    Hope this helps

  • giovedì 8 marzo 2012 17:28
     
      Contiene codice

    Thank you for the info -- The Devs wont be able to play with the permissions on the version control tree... so the "TF perm.. " option is a non starter (though admittedly, it would be a lot easier for me)

    However, the API calls seem simple enough.  I havent done extensive testing on this yet, but what I have done seems promising so far... it does a Permission removal rather than ACL removal (nomenclature difference??  The only ACL references I found were relating to workspaces, not VCS branches)

                    string[] removeperms = PermissionChange.AllItemPermissions;
    
                    creds = CredentialCache.DefaultNetworkCredentials;
    
                    TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(TFSCollUri, creds);
    
                    VersionControlServer vcs = tfs.GetService(typeof(VersionControlServer)) as VersionControlServer;
    
                    string projectGroup = string.Format("[{0}]\\Contributors",ProjectSelector.SelectedValue.ToString());
    
                    changes.Add(new PermissionChange(SourceBranchSelector.SelectedValue.ToString(), // File Path
                                                    projectGroup,                            		// Group affected
                                                    null,                                           	// perms to allow
                                                    null,                                           	// perms to deny
                                                    removeperms));         			// perms to remove
    
                    actualChanges = vcs.SetPermissions(changes.ToArray());

    I have observed (in my limited tests) that the resulting permissions seem to be matching the folder that these branches live in, rather than the source trunk, as desired, so thats a huge step forward... now I just need to confirm that I'm not messing something else up by referencing PermissionChange.AllItemPermissions.

    thanks again.

  • venerdì 9 marzo 2012 00:12
     
     Con risposta Contiene codice

    If you are using TFS 2010 and Visual Studio 2010 then you can use the following code block which goes directly to the security service (it's a cleaner API to program against than the older version control client object model methods for playing with security).

    using Microsoft.TeamFoundation;
    using Microsoft.TeamFoundation.Common;
    using Microsoft.TeamFoundation.Client;
    using Microsoft.TeamFoundation.Framework.Common;
    using Microsoft.TeamFoundation.Framework.Client;
    
    TfsTeamProjectCollection tpc = new TfsTeamProjectCollection(new Uri("http://myserver:8080/tfs"));
    
    // Get the security service for the TPC and use it to get the repository security namespace.
    ISecurityService security = tpc.GetService<ISecurityService>();
    SecurityNamespace vcSecurityNamespace = security.GetSecurityNamespace(SecurityConstants.RepositorySecurityNamespaceGuid);
    
    // Remove any permissions on this item and below.
    // As a result everything will be inherited from the parent.
    bool wasSomethingRemoved = vcSecurityNamespace.RemoveAccessControlLists("$/Proj/My/New/Branch", true /* recurse */);
    
    if (wasSomethingRemoved)
    {
        System.Windows.Forms.MessageBox("access control list(s) removed!");
    }

    • Contrassegnato come risposta JScottBrown venerdì 9 marzo 2012 16:44
    •  
  • venerdì 9 marzo 2012 16:46
     
     

    Thank you - yes, we do use TFS2010/VS2010, and that does indeed replicate the behaviour of the GUI.

    Scott

  • venerdì 30 novembre 2012 18:42
     
     

    Check out the link below. We had the same issue that you detailed above. I really like the solution below because it's fully automatated on the Server side. This solution doesn't depend on some person taking the action of removing the explicit permissions after they do a branch. Let me know what you think.

    TFS Branch Permission Removal Event Subscriber


    Jason Camp, MCSE, MCSD, MCDBA, MCPD: Web, MCAD, MCSA, CISSP, SCSA