Security – How to secure TeamCity deployment via Web Deploy service

deploymentSecurityteamcity

My team uses TeamCity for continuous integration. It will build, test and deploy web applications via Web Deploy to dev and qa web servers. The tricky part is deploying to a production web server – our policy dictates that developers cannot deploy to production, only a system administrator can.

Our current approach is to have TeamCity build a web deployment package, which the administrator can download and install on the production web server. However, we'd like to allow them to simply click "Run" on a build configuration, but we're not sure how to secure that button.

We could create a TeamCity project that only administrators have access to, but we also have to address Web Deploy security. The Web Deploy service needs to be authenticated with a local admin account on the production server. We don't want developers having access to the username/password in a build script, nor do we want every build agent running as this account since developers could create a build that uses it to deploy to production.

I've haven't had much luck finding resources on TeamCity security/deployment best practices, but I can't imagine we're the only company in this situation. How do others manage automated deployment security?

Best Answer

Using the roles and permissions in Teamcity, you can have a project that only your deployment team has access to. It can have an artifact dependency on the main build, and you can even have it used "last pinned build" so developers can control what's even available.

I would install a build agent that is able to deploy to the target system(s), and then use the "compatible builds" feature of that agent in the TeamCity UI to make it only compatible with your production deployment build. (Of course you'll also want to ensure your developers don't have permissions to modify agent configuration.)

This is one downside of Teamcity using Agent compatible configurations options: if you leave your other build agent(s) as compatible with all builds, then the production deployment may be attempted from one of them if free. The only workaround I know of is to set them all to only run "specified builds" and add all other builds to the other agent(s). The pain is if you add a new build, it won't be able to run anywhere until you specifically add it as compatible.


There are another couple ways to restrict the build to only run on specific agents using Agent Requirements in the build configuration.

One is to add a requirement that teamcity.agent.name equals the agent name you want it to run on. (or conversely, Does Not Equal the one you don't want it to run on).

Another is to add a requirement for an environment variable (exists, or with a specific value) and then only set that environment variable on the agent(s) you want to be able to run that build.


Another possible solution is to have two installs of Teamcity, since you effectively have two different sets of users. You obviously can't use an artifact dependency, but you can always get to the latest artifacts of a given build using a url like: * http://teamcity.server/repository/download/bt41/latest.lastSuccessful/setupfile.exe

where:

  • bt41 is the build id in Teamcity (you can find it in the URL when you navigate to any build)
  • latest.lastSuccessful can also be lastest.lastPinned, `latest.lastFinished, or the exact build number
  • setupfile.exe is the file you want to grab from the artifacts output (this can also be a path, if it's not published in the top-level)
Related Topic