1

We provide a library of custom Azure DevOps tasks (Azure DevOps extensions provided through a private Visual Studio Marketplace) to our stakeholders in order to provision resources to Azure. Many times we need to switch an elevated service account to perform operations that are not allowed by the service principal of the Azure service connection, e.g. adding users to groups, or reading secrets from a central key vault.

What is the best way to establish this security context securely? Currently we have the credentials of this elevation service principal hard coded in our task code. Unfortunately this is easily retrieved by our stakeholders because the code is readable within the same Azure DevOps job context, so it is not safe.

Does Azure DevOps provide a special task context that we can utilize to encrypt the service principal credentials somehow? Are there any other routes to securily perform operations from a centralized security principal from within these custom tasks of ours?

Carl in 't Veld
  • 1,363
  • 2
  • 14
  • 29
  • https://learn.microsoft.com/en-us/azure/key-vault/secrets/quick-create-portal – Alexan May 12 '20 at 16:52
  • 1
    The problem is: the service principal of the service connection is not allowed to read from the central key vault. We have set up a central "elevation" service principal that is granted this access. We need to find a way to establish this security context from within the custom task without the user being able to reproduce it themselves. If I were to design this, I would add a mechanism to the marketplace in order to share a private token to the scope of the task. – Carl in 't Veld May 12 '20 at 19:30

2 Answers2

0

If you're using classic Releases you can define variables that you can reference in your steps with the syntax $(variableName). Variables can be made secret, so it's not possible to retrieve them.

enter image description here

Alternatively, if you're using yaml multi-stage pipelines then variables can be defined directly in the yaml. In this case you'll probably what to use a variable group so that you define the secrets either directly in the variable group or link to a key vault.

For the requirement of not allowing new pipelines to be set up to use variable groups you could investigate the Library assets security roles and / or putting your pipelines in a separate Azure Devops project within your organisation.

Depending on what your tasks are doing you might be able to rewrite them to use a task that makes use of the built in Azure Resource Manager service connection, for example the AzurePowerShell@4 task, rather than using your own service principal credentials, as another solution entirely.

Simon Ness
  • 2,272
  • 22
  • 28
  • The credentials should only be accessible in the custom task's context. I believe when you provide the credentials through a variable group the users can then apply the credentials in their own pipeline scripts. It is not allowed for users to utilize these credentials themselves. So I think variable groups are not sufficiently protecting the credentials. – Carl in 't Veld May 13 '20 at 06:31
  • Hi @Carlin'tVeld, I've updated the answer with a pointer. Hope this helps. – Simon Ness May 13 '20 at 07:20
  • Thanks for pointing towards Library assets security roles I will look into it. First thought is that as soon as pipelines are capable of accessing the secrets then we are bad. We are already using the ARM service connection. This is the foundational level of authorization towards the users. On top of that our custom tasks need to have additional elevated priviliges. – Carl in 't Veld May 13 '20 at 07:41
0

First thought is that as soon as pipelines are capable of accessing the secrets then we are bad.

Not sure if I understand you well. But if you don't want those stakeholders to access the secrets in your task context within some specific pipelines, you can consider combining the Variable Group and Pipeline Security.

1.For Library(Variable Group): Store the secrets here and enable Change variable type to secret. Then manage its security here:

enter image description here

Normally the stackholders can't access the variable group unless you grant access to them. I suggest you create a group to manage the permissions of those stackholders.

2.For pipelines: You can limit the view/edit related permissions in pipelines' security:

For all pipelines: enter image description here

For one specific pipeline: enter image description here

You can deny the View/Edit related permissions and only allow Queue build permission so that the stackholders can run your build but not see details about how you define the task context:

enter image description here

Hope it helps :)

LoLance
  • 25,666
  • 1
  • 39
  • 73
  • Our current setup enforces the users being able themselves to set up new pipelines using our custom tasks. I believe even when you prohibit the users read access to the variable group they can still run a pipeline that is able to read the variable group. They can just store the result in an artifact and there is your security breach. The easiest would be if there were a private key mechanism in the marketplace. The other option I see is to set up a separate Azure DevOps project with a range of pipelines for the elevated operations that can be called from the pipelines of our users. – Carl in 't Veld May 14 '20 at 21:00
  • Sorry but I have no idea about whether there's one third-party extension for this. If you want to set up a separate project which the stackholders can call, which way do you want to use? Rest api [queue build](https://learn.microsoft.com/en-us/rest/api/azure/devops/build/builds/queue?view=azure-devops-rest-5.1) ? You should be careful with the usage of PAT. – LoLance May 15 '20 at 06:01
  • Yes I was thinking of the queue build REST API. With regards to PAT, are you expecting soon delivery Azure Active Directory identities? What is the risk of using a PAT? – Carl in 't Veld May 15 '20 at 13:35
  • When creating the PAT, we should avoid giving it too many accesses, cause anyone randomly gets your PAT can manage your organization easily. – LoLance May 18 '20 at 09:40
  • I am thinking of using the $(System.AccessToken) predefined variable in order to trigger pipelines in another project with only read access to these pipelines. Would that be something? – Carl in 't Veld May 27 '20 at 20:08
  • It's possible but I haven't tested in such scenario. I assume you can use something like `echo $(System.AccessToken)>a.txt` to check the content. Also here's [one example](https://stackoverflow.com/a/62045367/10910450) about how to use system.accesstoken to call the rest api. – LoLance May 29 '20 at 09:22
  • I have tested with $(System.AccessToken). I am able to trigger builds in another project. But the unfortunate thing is that the builds are then run by the original build principal, and there is no trace of the original process or user that kicked of the original build. Not ideal. – Carl in 't Veld Jun 04 '20 at 14:27