Features FYI How-To's Tips & Tricks

TeamCity Plugin for HashiCorp Vault

When performing integration tests and deployments, build scripts need credentials to access external servers and services. Traditionally passwords are stored on the TeamCity server as secure parameters. But although secrets are masked in the UI, encrypted at rest, and protected from being exposed in the build log as plain text, this often does not provide a high enough level of security.

HashiCorp Vault offers a unified approach to managing secrets and credentials, allows auditing access, and helps with password rotation.

Integration with Vault

Today we are presenting a new plugin to help build scripts interact with Vault and obtain credentials dynamically.

The plugin allows connecting TeamCity to Vault, requesting new credentials when a build starts, passing them to the build script, and revoking them immediately when the build finishes.

Usage

We expect you have installed and configured:

  • a Vault server. Refer to the Getting Started guide to learn how to launch a testing Vault instance.
  • A TeamCity server. Refer to the Getting Started guide for details.

Perform the following:

  • Download the plugin from the plugin repository, and install it to TeamCity server.
  • Configure secret backends in Vault to obtain secrets, for example AWS credentials, or generic secrets.
  • Create an AppRole in Vault for the TeamCity server to access these backends.
  • Create a connection to Vault in your TeamCity project:1
  • Next, in your build configuration declare new build parameters which refer to the Vault secrets to be used in this build:

screenshot_17334

The parameter value has a special syntax:%vault:PATH!KEY% where PATH is the secret name, and KEY is the specific value inside. If you use version 2 kv, make sure to adjust the path value to %vault:aws/data/creds/deploy!/access_key%.
At the moment these values can be used in the build parameter declaration only, and cannot be specified in build steps.

  • Run a build step. Deployment scripts can read credentials from environment variables, and do not need to perform any Vault-related actions:3

Besides AWS, any other Vault backends can be used. In this case:

  • Declare a configuration parameter with a value from generic backend. If you use version 2 kv, make sure to adjust the path value to %vault:secret/data/foo!/password%.4
  • In a build step, refer to this parameter explicitly:5

How It Works

  • The TeamCity server stores the AppRole ID and secret, and keeps the secret encrypted at rest. When required, it can be rotated manually in the UI, or via the REST API.
  • When a new build is started, the TeamCity server requests a one-time response wrappingtoken in Vault, and sends it to a build agent.
    The AppRole secret never leaves the TeamCity server machine.
  • The build agent requests the actual secrets from Vault.
    The actual credentials are obtained from Vault by a build agent machine directly, and never transferred to the TeamCity server.
  • The build parameters are resolved and the secrets are passed to environment variables and system properties.
  • The build steps are started, and they refer to these environment variables and system properties.
  • If secret values appear in a build log, they are automatically replaced by asterisks.
  • Right after the build finish, the credentials are explicitly revoked in Vault.

Security Considerations

It is advised that you limit access to TeamCity project settings. If a person can modify build configuration settings in a TeamCity project, they can get access to the secrets. Dynamic credentials are revoked after a build, but for generic secrets this may cause more risks. To minimize the risks, split build configurations for CI and deployments into separate projects with different permissions.

Make sure build agent machines are connected to the TeamCity server via HTTPS. Only one-time tokens are transferred over network, and if they are stolen, credentials will be immediately revoked. However, it is a good practice to encrypt all traffic between the server and agents.

Feedback Wanted

This is an initial release, and we continue to improve features and user experience, and encourage you to give it a try and tell us what do you think!

The plugin is open-sourced, and published on GitHub.

If you are attending HashiConf in Austin, TX, USA next week, visit the JetBrains sponsor booth for the demonstration of this plugin and our other plugins for integrating Packer and Terraform with TeamCity and IntelliJ-based IDEs.

image description