Sharing secrets among Team Build and/or Release Management definitions
When creating a team build 2015 (often called build v.next) or a release management definition, you can store secrets in variable (for example for passing a password or a token to a task).
Secret variables cannot be seen when viewing/editing a build definition (hence the name secret), only changed.
Secret variables have some disadvantages
- Their scope is limited to the build/release definition, if you want to use the same secret among several definitions you have to replicate them among the definitions
- You can’t apply security to variables, if a user has permission to edit a build definition he can change the secret.
In order to overcome these two disadvantages I have created a build/release task that can be used to have a single instance of a secret (per team project) and that can be used to pass secrets to tasks.
The task is called Set Variables with Credential and it’s part of a bigger package called Variable Tasks Pack which contains other tasks that deals with variables, it contains the following tasks
- Set Variable Set a variable value and optionally apply a transformation to it.
- Set Variables with Credential Sets the username/password from an existing service endpoint
- Set Variable from JSON Extracts a value from JSON using JSONPath
- Set Variable from XML Extracts a value from XML using XPath
- Update Build Number Allows you to change a build number
- Increment Version Increments a semver version number
But the topic of this post is how to share secrets among multiple definitions.
When you install the Variable Tasks Pack in your VSTS account from the marketplace, the extension will also configure a new Service Endpoint type, called Credential
This will allow you to store on your team project a username and a password (don’t worry password it’s just a name you can use it to store any secret, for example I used it to store a Personal Access token to publish extensions on the Visual Studio Marketplace). The connection name it’s just a label you can use to give it a meaningful name.
Using a Service endpoint gives you the possibility to define permissions (per credential) by adding users/groups to the Endpoint Readers
This will allow you to define which users have permission to use a given credential in a build/release definition. This means people with permissions to edit build/release definitions are not able to change secrets and only use the ones they are allowed to (you can also add users to Endpoint administrator to define who can edit the credential endpoint).
After you have defined your credential(s) you can use then on your build/release definitions, the provided task has three parameters.
- The name of the connection
- The name of the variable where the username will be stored (optional)
- The name of the variable where the password will be stored (optional).
This will set the value of a regular variable, that can be used in other tasks like if it was a defined variable.
For example, if you set in the “Password variable name” the value MyVar
You can use it on subsequent task, like any other variable (Eg: $(MyVar) )
With this task not only you can control who can change/use a given secret, it is also possible to have a central place where the secret is stored and if you update it all definitions that use it will pick up the change immediately and you don’t have to update all tasks manually as if you used a secret variable.