I’ll show how to configure TFS2015 Release Management to be able to deploy to another (untrusted) domain by having the deployment agent run under a shadow account.
Introduction
The Release Management functionality in TFS2015 update 2 allows for automated deployment of software in one or more environments. The idea is that you configure a deployment agent in every environment that you want to deploy to (such as test, user acceptance or production) and register it with your TFS server so that it will listen for new releases to be deployed to that environment.
While definitely a big improvement over the VS2013 Release Management product, the downside to the deployment agent is that it needs to run under the same account as the account used to communicate with TFS with. This poses a problem when the environments to deploy to live in different domains from the TFS server (without trusts): you can’t run the agent as a TFS user because it doesn’t exist in the target environment. Conversely, if you run the agent as a user from the target environment there’s no way to grant that user permissions within TFS.
Until Microsoft provides a way to specify an extra set of credentials for this, we’ll have to resort to using a shadow account: By creating a local user in the target environment that has the same login and password as the TFS user, Windows will treat both as the same user.
Even then it requires a bit of trickery though, which is what I’m going to show next.
Our setup
For the purposes of this post, I have a TFS2015 Server with update 2 at https://mytfs2015/tfs
, which is located in my development domain called DevEnv
. I want to install an agent on the WebSrv
machine inside the domain TestEnv
. The DevEnv
and TestEnv
domains don’t trust eachother, but the https://mytfs2015/tfs
url must be accessible from the WebSrv
machine without a firewall intervening.
In TFS, I have an Agent Pool (configurable via Control Panel, Agent Pools), and my own account is part of its Agent Pool Administrators role. I have created a user DevEnv\svcTstDeploymentAgnt
and made him member of the Agent Pool Service Accounts role; this will be the user under which the agent will run.
Creating the shadow account
- Sign in to the
TestEnv\WebSrv
machine using any administrator account and use Computer Management to create a local user namedsvcTstDeploymentAgnt
. Give it the same password as theDevEnv\svcTstDeploymentAgnt
user, so that it can be used as a shadow account. - For the duration of this installation,
WebSrv\svcTstDeploymentAgnt
needs administrator permissions, so add it to the local Administrators group.
Installing the agent – part 1
- Now, sign in to the
WebSrv
machine using theWebSrv\svcTstDeploymentAgnt
we just created. - Open up
https://mytfs2015/tfs
(using your regular user account) and download the agent (via Control Panel, Agent Pools). - Extract the
agent.zip
, e.g. toC:TfsDataAgentsAgent-WebSrv
- Open an elevated command prompt, navigate to
C:TfsDataAgentsAgent-WebSrv
and runConfigureAgent.cmd
. - Specify the Name, TFS URL and agent path as requested, and choose to install the agent as a windows service
- For “the name of the user account to use for the service”, specify
svcTstDeploymentAgnt
, followed by its password - Next, the installer will try to connect to the TFS instance and should ask you for your credentials (if not, there are already cached credentials which should first be cleared via the Windows Credential Manager, see below). Specify your own user account.
The installer will run, but will terminate with an error:
Installing service vsoagent.tfs.Agent-WebSrv... Service vsoagent.tfs.Agent-WebSrv has been successfully installed. Creating EventLog source vsoagent.tfs.Agent-WebSrv in log Application... TF14045: The identity with type 'System.Security.Principal.WindowsIdentity' and identifier 'S-1-5-21-2986214872-1000940727-4115246995-1004' could not be found.
Also, the agent will be listed in red under the Agents pool:
At this point the agent is registered succesfully with TFS, but refuses to run. This can also be seen in the logfile (inside the agent’s _diag
folder), which should contain:
08:47:34.856145 Authenticating to the server https://mytfs2015/tfs 08:47:35.043644 Failed to create session. Sleeping for 10 seconds before next retry. Attempts=1/10.
Installing the agent – part 2
To fix this, we need to reinstall the agent, this time using the DevEnv\svcTstDeploymentAgnt
to authenticate with to TFS.
- Go to the windows credential manager and remove the Windows credentials for your own account (that you used to sign in with to TFS), so that the installer will ask for your credentials again.
- Now run
ConfigureAgent.cmd
again, and specify the same values as before for the Name, TFS URL, Agent path and Windows Service credentials. - This time, specify the
DevEnv\svcTstDeploymentAgnt
credentials when connecting to TFS.
Again the installer will end in an error:
Access denied. svcTSTDeploymentAgnt needs Manage permissions for pool MyAgentPool to perform the action. For more information, contact the Team Foundation Server administrator.
However, the agent should now be listed as green in the Agent Pool overview (you might need to refresh the page) and running correctly.
Also, the logfile in the _diag
folder should report something like:
09:01:27.158926 Authenticating to the server https://mytfs2015/tfs 09:01:27.346417 Created Session: 83b37942-d0be-44b0-85a0-00ae147271cc 09:01:27.362042 MessageQueueListener.DispatchAsync - starting loop 09:01:27.362042 MessageQueueListener.DispatchAsync - Getting message from Session: 83b37942-d0be-44b0-85a0-00ae147271cc
Despite the last error message, the Agent is now ready to receive deployments.
Conclusion
As you can see from the steps involved and the number of error messages, this isn’t the most elegant solution, but hey, at least it works… Cheers!
5 comments
Leon, great blogpost. Really helped us to setup the environment. We now have a green agent in the tfs admin section.
But when we run the release pipeline the agent won’t start with the real work. Do you have experience with that as well?
Pieter Versteijnen
Seems to be that for some reason we get a server name without the full FQDN. When we add the name to the hosts file the problem is gone. So we now have to figure out where the name is returned without the FQDN. The agent is configured using FQDN names.
Pieter Versteijnen
Hi Pieter, glad to hear this article was of help to you, and good luck with the FQDN thing 😉
Léon Bouquiet
I suspect that the TFS Server’s Notification Uri is setup to be the server name and not its external DNS name. Change it from the TFS Admin Console.
Jesse Houwing
Hi Leon,
Very helpful post, and we will definitely follow this in our environment. However, 1 question prior to testing on our side:
I see you are using “local” accounts within the target web servers. Must these accounts be local?In your example, would it work if we try the above process with a TestEnv domain user account with the same username and password as the account on the untrusted DevEnv domain?
Thanks!
Ben
Ben Wong