How to safely put credentials in a custom Azure DevOps task? - azure

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?

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.
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.

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:
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:
For one specific pipeline:
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:
Hope it helps :)

Related

Azure DevOps agent pool creating using Terraform

I need to create Azure DevOps agent pool using Terraform.
In Terraform I'm using microsoft/azuredevops provider. And resource azuredevops_agent_pool
In conclusion, I have an error Error creating agent pool in Azure DevOps: Access denied. user needs Manage permissions to perform the action. For more information, contact the Azure DevOps Server administrator.
I have Administrator permissions in Azure Devops.
What can I try with this error?
UPD. I can create agent pool from Web UI azuredevops.
I am using authentication with PAT. PAT configured for FULL access.
UPD2. I understood that access on Project Level is other than access on Organization Level. So I have full access on Project Level but terraform is trying to create agent pull on Organization Level.
It's not possible at the moment. I face the same issue.
The issue is still opened since 2020.
https://github.com/Azure/terraform-azurerm-aci-devops-agent/issues/4
As mentioned on the README.md
Before running this module, you need to create an agent pool in your
Azure DevOps organization and a personal access token that it
authorized to manage this agent pool.
So it's not possible to automatically create an agent pool from the official Terraform azure DevOps provider
You might try to find a way through Azure DevOPS REST API:
https://learn.microsoft.com/en-us/rest/api/azure/devops/distributedtask/elasticpools/create?view=azure-devops-rest-7.1
You might also find this GitHub issue comment useful:
https://github.com/microsoft/terraform-provider-azuredevops/issues/204#issuecomment-962504540
Someone has already developed a way to do with Terraform using local-exec combined with azure cli/PowerShell/rest api

GitOps & Infrastrucute as a Code - secrets storing

Just conceptual questions because I apparently doesn't feel the articles already available #google in this topic.
The story:
I have 2 git projects for IaC which create and configure network and create and configure projects. Both of those projects use different service accounts to perform operation on the cloud (different permissions are needed by them and I don't want to have one super account with all permissions). I would like to perform CICD pipeline which will allow to perform in general teraform apply.
The question:
I would like to not store keys for such accounts at GitLab (gitlab variables - I would like to store them in Hashicorp Vault - The goal is to make sure that it will only be avaliable for CICD. No human should be allowed to access those keys. How to make it work? To cloud access keys stored at vault I still need vault key to be stored on runner machine or in gitlab variables both not considered as safe for me, if anyone will get access to vault key it is really easy to access service account keys by Vault Rest API
One way we solve this is by leveraging Gitlab’s identities and Vault’s JWT authentication method.
You can read more about this here: https://docs.gitlab.com/ee/ci/examples/authenticating-with-hashicorp-vault/ for Gitlab and https://www.vaultproject.io/docs/auth/jwt for the Vault auth method.
Why would this solve the issue (if I understood your challenge correctly)?
Once you have this setup, you can
create an identity entity in Vault to represent your CI service account
create an alias to bind this identity entity to the identity Gitlab will provide in CI_JOB_JWT
create a policy to allow this identity entity (directly or via a group) to read the secrets)
Hence anyone running the pipeline from another identity won’t be able to read the secrets (because it would map to another identity entity in Vault, so they won’t get a token with that policy)

How to manually create the required Azure API token for deploying to Azure Static Web Apps (Preview)?

We're trying to setup a Github Action that will deploy our software to Azure. Our software is not multi-tenant-aware, so we deploy a replica of the software into a fresh Azure Resource Group for each tenant. So far this has been no problem. Our Github Action has an event input into which we can provide the resource group name and from there it can deploy to that resource group.
With Static Web Apps, though, the Azure API token is generated behind a black box, as is the deployment process. I don't want to have a Github Action workflow and repository secret for each tenant that we want to deploy to.
It looks to me like the auto-generated secret likely somehow specifies which resource group to deploy to, since I see no other way for the "Azure/static-web-apps-deploy#v0.0.1-preview" Github Action to know where it is to be deploying to.
The Azure Portal automatically creates this secret token and adds it with a name like: AZURE_STATIC_WEB_APPS_API_TOKEN_LEMON_WAVE_00AD12A10
Obviously there is a way to create this token, but has that been discussed or outlined anywhere?
Ideally, I'd be able to create that token as-needed and perform a manual deploy using the Azure Static Web Apps Deploy Github Action into any resource group that I need, without duplicating workflows and github secrets.
The service itself seems great and like a clear upgrade over Azure Storage static web apps. The current deployment options are terrible though - why only from a specific github repo and to a specific Azure Resource Group? Why not expose the ability to deploy to anywhere as needed?
Any ideas?
The API token is not tied to a specific repo or branch, but is the permission to deploy to a particular Static Web App. Likewise, it has no tie to a particular resource group, it has a 1-1 relationship with a particular Static Web app.
It sounds like you want to have a single API token that can deploy to all of your Static Web Apps? This is not a good security model and is not recommended.
You can call an API today to retrieve a new API token and invalidate the old one.
To benefit the community posting the answer from our discussion on Microsoft Q&A thread.

Azure Devops: securing deployments to on-premise servers at webapp level

It's clear that you can set which roles can deploy to a certain on-premise server thanks to the security settings in Deployment Groups and Agent pools. But, any way of restrict access at webapp level?
The only ways I found are:
Creating a specific account, giving it deploying permissions in target server's IIS in required webapps only and provide this credentials to developers on charge of creating the pipelines for deploying those webapps (they will put them as custom environment vars or similar in pipelines)
Same than 1 but using the created account as a service account for an agent. Access to this agent will be restricted to developers on charge of creating the pipelines for deploying those webapps.
Both cases require to create new accounts and to give permissions on server's IIS. No way of doing this from Azure DevOps on the same way that access to whole servers can be restricted?
Regards.
It's clear that you can set which roles can deploy to a certain
on-premise server thanks to the security settings in Deployment Groups
and Agent pools. But, any way of restrict access at webapp level?
Sorry but as I know Azure Devops Service doesn't support such out-of-box feature.
We can manage the access in Organization level(Organization settings), Project Level(Project settings), Feature Level(Security of Pipelines/Deployment Groups feature...) and even the 'instance Level' (Set security for one specific pipeline/deployment group/one specific git repo).
But the 'instance level' is the lowest level, we can only manage the access in specific pipeline or specific deployment group but not one webapp which will be deployed by pipeline/deploymentGroup.
The webapp is not an option hosted by Azure Devops Service, it's just something to be deployed by pipelines(hosted by Azure Devops Service). So Azure Devops Service avtually have no knowledge about the webapp(it also won't have UI that represents one webapp), that's why we can manage the access in pipeline but not webapp in that pipeline...
Update 1
Once you have only one deployment group for the specific target server, you can determine who can access the deployment group here:
The person who is assigned with reader permission can't use the deployment group to do the deploy.
Ok, following the suggestion from #Lance and after some research, this is what I´m planning to do:
Creating a custom service connection where following fields can be set: IIS Server where the WebApp is, Webapp name, User (with permissions to deployment) and Password.
Together with the Custom Service connection I will provide a custom task where developer team can select the service connection against they want to do the deployment (obviously, server admins will only configure service connections to webapps which this team is allowed to deploy).
Agent will run with a low-privileged account (no way of affecting any app) and the custom task will use internally the creds provided on service connection to perform the deploying.
I think that approach is the best workaround to the initial problem and can be extensible to fix the granularity problem in other kinds of resources (like DB´s, Shared Folders, ...) just simply adding another specific custom service connection (to specify the resource and the deployment credentials) and a linked Custom task which allows deployments only against that resource.
The only drawback is the fact that, if you want to set a deployment approval, you have to do it at resource level (for every webapp, for every DB, ...) and that means that approvers will have to approve resource by resource when deploying also (instead of a single approval for the whole application deployment as, in my understanding, should be)
What do you think guys? Any remark before start coding this?
Regards.

Architecture Resources in Azure Resource Manager

We are developing applications in .Net and deploying them to Azure app services. We currently have a multi-tier environment (QA/STG/PROD). In order to replicate the same environments we are using slots. However, the issue with slots is all developers who has access to QA slot are able to view/modify STG / PROD slot settings. We want to segregate this with authorization where-in users should only be able to publish apps on QA. Should we still use slots or we go with separate web apps?
As suggested in one of the comments you can use RBAC (Role Based Access Control) to control the user permissions on the web app/slots.
Azure RBAC has three basic roles that apply to all resource types:
Owner has full access to all resources including the right to delegate access to others.
Contributor can create and manage all types of Azure resources but can’t grant access to others.
Reader can view existing Azure resources.
So, you could add the developers as a READER to the webapp and as a CONTRIBUTOR to one of the slots. This will prevent the web app changes
Further, you can customize the RBAC to suit your requirements.
You can create a role with custom
Refer this article:
https://azure.microsoft.com/en-us/documentation/articles/role-based-access-control-custom-roles/
You can go with slots. Each slot creates a separate URL and you could control access to the slots by Authenticating using AD.
https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-how-to-configure-active-directory-authentication/

Resources