How to add a user to Project Collection Service Account in TFS / VSO

VSO and TFS have a special group called: Project Collection Service Account that has really powerful permission, and usually no user should be part of that group. There are specific circumstances, like running TFS Integration platform to move code to TFS, where the account used to access VSO needs to be part of this group to temporary have special permission.

Sadly enough, the UI does not allow you to directly add a user to that group, because the add button is disabled if you select that group.


Figure 1: You cannot add users or group to Project Collection Service Account Users directly from the ui.

The reason behind this decition is security, adding a user to this group is not part of everyday operation, users in that groups has really powerful permissions and you should add users to Service Accounts only in really specific situations and only when really required. This is the reason why you need to resort to Command Line.

	"Project Collection Service Accounts" 

TfsSecurity.Exe command line utility can add whatever users to whatever group, bypassing limitation in the UI. Remember than to remove the user from that group when he does not need anymore special permission; the commandline is the same as previous one just change /g+ to /g-

As a rule of  thumb, users should only be added to Service Account group only if strictly required, and removed from that group immediately after the specific need ceased to exist.

In older version of VSO / TFS you could obtain the same result without command line in the UI. You just selected the user you want to add to Service Group, then go to the member of section and then, pressing plus button, add the user to the group, but this is actually disabled in actual version.


Figure 2: You cannot add anymore a user directly to a group.

If you really want to avoid command line, you can still use the UI. Just create a standard TFS Group and then add the group to the Project Collection Service Accounts. First step: create a group with a Really Explicit Name.


Figure 3: This group has a specific name that immediately tells to the reader that it is a special group.

Once the group is created, you can simply add it to the Project Collection Service Account group with few click.


Figure 4: Add new group to the Project Collection Service Accounts group

Now you can simply add and remove users to the “WARN – Service Account Users” group from the UI when you need to grant or remove Service Account Permission.

Gian Maria Ricci.

Make easy storing secure password in TFS Build with DPAPI

I’ve blogged some days ago on Securing the password in build definition. I want to make a disclaimer on this subject. The technique described in that article permits you to use encrypted password in a build definition, but this password cannot be decrypted only if you have no access to the build machine. If you are a malicious user and you can schedule a build, you can simply schedule a new build that launch a custom script that decrypts the password and sends clear password by email or dump to the build output.

The previous technique is based on encrypting with DPAPI, encrypted password can be decrypted only by TfsBuild user and only in the machine used to generate the password (build machine). Despite the technique you used to encrypt the password, the build process should be able to decrypt the password, so it is possible for another user to schedule another build running a script that decrypt the password.

Every user that knows the TfsBuild user password can also remote desktop to build machine, or using Powershell Remoting to decrypt the password from the build server. This means: the technique described is not 100% secure and you should be aware of limitation.

Apart from these discussions on the real security of this technique, one of the drawbacks of using DPAPI is you need to do some PowerShell scripting in the remote machine to encrypt the password. So you need to remote Desktop build machine or you need to do a remote session with PowerShell. A better solution is creating a super simple Site that will encrypt the password with a simple HTML page, then deploy that site on the Build Server.

The purpose is having a simple page running on build server with credentials of TfsBuild that simply encrypt a password using  DPAPI


Figure 1: Simple page to encrypt a string.

You can test locally this technique simply running the site in localhost using the same credentials of logged user, encrypting a password and then try to decrypt in powershell.


Figure 2: Decrypting a password encrypted with the helper site should work correctly.

The code of this page is really stupid, here is the controller.

public ActionResult Index(String pwd)
    var pbytes = Protect(Encoding.Unicode.GetBytes(pwd));
    ViewBag.Encrypted = BitConverter.ToString(pbytes).Replace("-", "");
    return View();

public static byte[] Protect(byte[] data)
        // Encrypt the data using DataProtectionScope.CurrentUser. The result can be decrypted 
        //  only by the same current user. 
        return ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser);
    catch (CryptographicException e)
        Console.WriteLine("Data was not encrypted. An error occurred.");
        return null;

And the related view.

    ViewBag.Title = "Index";

<h2>Simple Powershell Encryptor utils</h2>
<form method="post">

    Insert your string <input type="password" name="pwd" />
    <br />
    <input type="submit" value="Encrypt" />
    <br />
    <textarea cols="80
              " rows="10" >@ViewBag.Encrypted</textarea>


Thanks to this simple site encrypting the password is much more simpler than directly using powershell and you do not need to remote desktop to build machine. To have a slightly better security you can disable remote desktop and remote powershell in the Build Machine so noone will be able to directly use PowerShell to decrypt the password, even if they know the password of TfsBuild user.

Related Articles

Gian Maria.

Is there a reason to put restriction on password?

I’ve stumbled upon this funny comic


I usually use long Random generated password, that I store in KeePass for all services that I really care about, (home banking, amazon account that has my credit card, etc), and tend to use easy to remember password for services I do not care very much (stupid online games, or stuff like that).

This funny comics suggests that choosing some four random common words can be a viable solution (complex to guess, but easy to remember), but sadly enough some online services does not permits you to use long password, or password that use special chars etc. My online banks forced me to choose a 10 digit number as the password o_O, another online service told me to use a password between 6 and 18 chars, but only letters, numbers are allowed, Another one forced me to use at leas one uppersize, and one digit, but limits the length to 20 chars, etc etc. My question is “why in the hell a service should limit my possibilities to choose a password I like?”.

Having such restrictions is quite annoying, because if you have a mental scheme to choose passwords, password complexity rules quite often render this scheme not valid, forcing you to use a password that will be hard to remember (thanks to keepass this is much more easier) and not more secure. And what about a Chinese or Japanese user that want to choose a password composed of Kanji characters? Maybe he want to use Kanji of Spring, mountain, sky, because it is easy for her to remember a blue mountain sky on spring.

I’m not a cryptography expert, but usually password are stored in HASHED format with a SALT (beware of Italian Railway system, last year I clicked “lost my password” and they sent me the password in CLEAR format on my e-mail O_o), this means that the user could choose an arbitrary sequence of Unicode chars, because it is simply a stream of bytes that will be hashed producing another stream of bytes of Fixed Length that can be stored in a database without problems, even if the user choose a 100 character password, the hash length is always the same.

Given this, is there really a reason to impose restrictions on password complexity? In my opinion the only restriction should be in the length, prohibiting really short password to avoid really easy-to-guess password, but every Unicode charachter should be acceptable and there should be no maximum password length, no specific char requirements (es. at least one digit, at least one Uppercase char), if I trust my KeePass program to generate a cryptography random sequence of 32 chars, or if I want to use an Haiku I like, why you should limit my freedom in choosing my password?


How to check if a user belong to a certain role in ASP.Net

This question is really simple to answer… or no? Suppose you need to verify, in a service, if the user belongs to the xxxx group, and then take a different path of execution if the condition is true.

if (Roles.IsUserInRole("xxxx"))




Ok, this seems such a piece of innocent code, but actually it caused me a bad bug. The reason is really simple, the same service is called from a program written in windows forms, (a windows service) and a web site. The programmer that is developing the web site, took the service and add that checks in one function, and I begin to get exception from the code of the service. The reason is clear Asp.Net roles and Membership are not configured in the windows program, nor I want to configure it.

To fix this, and in general to verify roles of the current user, when you does not know in advance if the code would be called  outside the context of a web application, we need to create the group xxxx in windows, assign the user that run the service or the program to this group and add this line at the very beginning of the winform program to use windows authentication.


But this is not enough since the code in the service should not use the Roles.IsUserInRole() function because it needs to have membership configuration enabled. The solution is using this code instead of the above one.

var currentPrincipal = System.Threading.Thread.CurrentPrincipal;

if (currentPrincipal.IsInRole("xxxx")

This works because in windows forms the CurrentPrincipal is a WindowsPrincipal, and thus it checks if the current user belong to the group xxxx, but when it is run from a web site, with ASP.NEt membership configured, the principal is of type RolePrincipal as you can verify from Fgure1


Figure 1: the current principal of code running in sites with roles and membership configured is of type RolePrincipal.

and in this situation IsInRole() method verifies the user against ASP.Net roles.


Desiging a authentication layer with cryptoagility.

Today I was working a little bit on Dexter, and I’m trying to update the security system, the actual login system is based on a membership provider quite old, but I’d like to update it to be CryptoAgile. First of all here is the class UserDto (the name Dto should be changed because it is really a domain class but we are in the middle of a reorganization Smile so do not mind the name ) that has some methods to manage authentication.

To be flexible the class should support storing of the password in clear form (strongly discouraged) and in hashed form with salt (the default one). Here is the code of the ChangePassword function


The key factor is that the HashAlgorithm used is not hardcoded in source code, the trick is in the shared factory method HashAlgorithm.Create that permits to create a sha provider from a string code like: MD5, SHA1, etc. The user object stores used hash provider in a property called HashProvider and has a default value of SHA1 type.


This test verify that for a newly constructed User object the HashProvider is of SHA1 type, but since the HashProvider property is stored to database so we can apply a little bit of cryptoagility. Suppose that at a certain point in the future the SHA1 provider is broken. To solve this problem we can store a global application setting that tells the HashProvider to use, and when a specific algorithm is broken we can change it. I write a test to verify this.


This test uses a different VerifyPassword function, that pass both the password and the global Hash provider. In this test you can verify that the password is hashed with SHA1, but the software requires SHA512 to be used, so, after a successful login, the current password should change and the current HashProvider should be set to the default one.

The code to accomplish this is really simple.


If the password is good you can simply check if the required HashProvider is different from the current one, and if they are different you can change the HashProvider and recalculate the password using the current one. This is good because with this simple technique we are not bound to a specific hash provider and we can change the provider at any time.