1
votes

I've been researching Azure DevOps and I've come across what looks like a pretty obvious security hole in Azure pipelines.

So, I'm creating my pipeline as YAML and defining 2 stages: a build stage, and a deployment stage. The deployment stage looks like this:

- stage: deployApiProdStage
  displayName: 'Deploy API to PROD'
  dependsOn: buildTestApiStage
  jobs:
  - deployment: deployApiProdJob
    displayName: 'Deploy API to PROD'
    timeoutInMinutes: 10
    condition: and(succeeded(), eq(variables.isRelease, true))
    environment: PROD
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebApp@1
            displayName: 'Deploy Azure web app'
            inputs:
              azureSubscription: '(service connection to production web app)'
              appType: 'webAppLinux'
              appName: 'my-web-app'
              package: '$(Pipeline.Workspace)/$(artifactName)/**/*.zip'
              runtimeStack: 'DOTNETCORE|3.1'
              startUpCommand: 'dotnet My.Api.dll'

The Microsoft documentation talks about securing this by adding approvals and checks to an environment; in the above case, the PROD environment. This would be fine if the protected resource here that allows publishing to my PROD web app - the service connection in azureSubscription - were pulled from the PROD environment. Unfortunately, as far as I can tell, it's not. It's associated instead with the pipeline itself.

This means that when the pipeline is first run, the Azure DevOps UI prompts me to permit the pipeline access to the service connection, which is needed for any deployment to happen. Once access is permitted, that pipeline has access to that service connection for evermore. This means that from then on, that service connection can be used no matter which environment is specified for the job. Worse still, any environment name specified that is not recognized does not cause an error, but causes a blank environment to be created by default!

So even if I setup a manual approval for the PROD environment, if someone in the organization manages to slip a change through our code review (which is possible, with regular large code reviews) that changes the environment name to 'NewPROD' in the azure-pipelines.yml file, the CI/CD will create that new environment, and go ahead and deploy immediately to PROD because the new environment has no checks or approvals!

Surely it would make sense for the service connection to be associated with the environment instead. It would also make sense to have an option to ban the auto-creation of new environments - I don't really see how that's particularly useful anyway. Right now, as far as I can tell, this is a huge security hole that could allow deployments to critical environments by anyone who has commit access to the repo or manages to slip a change to the azure-pipelines.yml file through the approval process, introducing a major single point of failure/weakness. What happened to the much-acclaimed incremental approach to securing your pipelines? Am I missing something here, or is this security hole as bad as I think it is?

1

1 Answers

1
votes

In your example, it seemed you created/used an empty environment, there is no deployment target. Currently, only the Kubernetes resource and virtual machine resource types are supported in an environment.

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/environments?view=azure-devops

The resource in your example is a service connection, so you need to go the service connection and define checks for this service connection.

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/approvals?view=azure-devops&tabs=check-pass

enter image description here