DEV Community

Cover image for Implement security through a pipeline using Azure DevOps. Part2
Emmanuel A. Anene
Emmanuel A. Anene

Posted on

Implement security through a pipeline using Azure DevOps. Part2

In Part 1 of this lab, we laid the foundation for building secure Azure DevOps pipelines by setting up protected repositories, managing identities, and enforcing least privilege access. Now, in Part 2, we take security to the next level focusing on safeguarding pipeline resources, securing access to Azure Repos, protecting sensitive variables, and introducing reusable templates for consistency and compliance.

By the end of this section, your pipelines won’t just deliver code they will enforce security at every stage, ensuring that deployments are both efficient and compliant with best practices.

Continuation

Step 4: Use Secure Variable Management

Secure variable management involves storing sensitive information (like passwords, tokens, or API keys) in Azure DevOps as secret variables or through Azure Key Vault. These secrets are encrypted, hidden from logs, and only accessible during pipeline runtime to protect against unauthorized access or exposure.

i. Go to ** Pipelines > Library >** and click + Variable Group to create a Variable Group.

ii. Add variables like dbPassword, apiKey and mark them as secrets.

iii. Reference the Variable Group in Your Pipeline YAML. Open your pipeline YAML file and click on Edit.

iv. Reference the variable group by adding👇🏻:
trigger:
main

variables:
group: SecureSecrets This is your variable group

trigger:
  - main

variables:
  - group: SecureSecrets  # 👈 This is your variable group

stages:
  - stage: Build
    jobs:
      - job: BuildJob
        steps:
          - script: |
              echo "This is your API key: $(apiKey)"
            displayName: Print API Key
Enter fullscreen mode Exit fullscreen mode


Save and commit your YAML changes

vii. When the pipeline runs, it will automatically pull values from the linked variable group—ensuring secrets are securely injected without hardcoding them in the file.

Step 5: Secure Pipeline Access to Azure Repos Using Personal Access Token (PAT) Authentication

In this step, We will configure the pipeline to use a Personal Access Token (PAT) stored securely as a secret variable, enabling secure authentication to Azure Repos without exposing credentials in the code. This ensures that only authorized builds and scripts can interact with your repository.

i. Click your user profile picture (top right). Click on User Settings and select Personal access tokens.

ii. Click + New Token.

iii. Fill out:

  1. Name → something descriptive, e.g., Pipeline-GitAccess

  2. Organization → select your Azure DevOps org

  3. Expiration → e.g., 30 or 90 days (shorter is safer)

  4. Scopes → pick only what’s needed: For Git repo access → Code: Read & Write. For REST API calls → add Build or Release scopes as needed

  5. Click on SAVE

Note: Copy the token right away and save it on your note, you won’t be able to see it again

iii. Store PAT in Azure DevOps Securely: Go to Pipelines → Library → + Variable group.

iv. Fill Out:

  1. Name it → e.g., AuthTokens.

  2. Add a variable → PAT_SECRET.

  3. Paste your PAT in the value field.

  4. Mark it as Keep this value secret.

  5. Click Save.

iv. Use the PAT in Your Pipeline: Example: Using PAT to access Azure Repos inside a pipeline job. Validate the below YAML and SAVE

variables:
- group: AuthTokens

steps:
- checkout: none
- script: |
    git config --global user.email "pipeline@devops"
    git config --global user.name "Azure DevOps Pipeline"
    git clone https://$(PAT_SECRET)@dev.azure.com/<org>/<project>/_git/<repo>
  displayName: "Clone repo using PAT"
Enter fullscreen mode Exit fullscreen mode

✅ Security Tips:

  • Keep PAT scopes minimal (e.g., Code:Read if you only need to read code).

  • Use short expiry and regenerate PATs periodically.

  • Never commit PATs to your repo always store as secret variables.

  • Remove unused PATs from User settings → Personal access tokens.

v. Audit Repository Permissions in Azure DevOps Go to Project Settings.

  • In the left-hand menu, under Repos, click Repositories. This will show a list of all repositories in the project. Click the repository you want to audit SecurePipelineRepo.

  • Inside the repository settings page, select Security. This will display a list of users and groups with access to the repository.

  • Review Permissions
    For each user or group, you can see permissions like:

    • Read
    • Contribute
    • Force Push
    • Manage Permissions

Check whether permissions are Allowed, Denied, or Not set.

vi. Identify Over-Privileged Accounts
Look for accounts with unnecessary Contribute or Manage Permissions rights. Pay attention to Project Collection Administrators or Build Service accounts. They often have high-level permissions by default.

Outcome: You now have a clear picture of who can read, modify, or manage your repository, ensuring you can enforce least privilege.

Step 6: Modularize Your Pipeline Using Templates

Breaking your pipeline into reusable YAML templates allows you to centralize common tasks, reduce duplication, and maintain consistency across projects, while securing access to shared logic.

i. Create a new repo (e.g.,pipeline-templates). Go to Project Settings. under Repos, click Repositories. And click on + Create.

ii. Give the repo a name e.g. pipeline-templates. Keep Add a README checked (optional but recommended). Keep Default branch as main and click on Create.

iii. Write a Reusable build.yml Template: Open your new pipeline-templates repository. Click on the three dots(...) in the front of the repo and select Browse.

iv. On the New Repository page:

  1. Click on the three dots(...) in the front of the Repo
  2. On the drop-down select NEW
  3. And click on FILE.

v. Give the File a name build.yml

vi. Paste the below example reusable build template and Commit the file to the main branch.

parameters:
  - name: buildConfiguration
    type: string
    default: 'Release'
  - name: vmImage
    type: string
    default: 'ubuntu-latest'

jobs:
  - job: Build
    displayName: 'Build Application'
    pool:
      vmImage: ${{ parameters.vmImage }}
    steps:
      - checkout: self

      - task: NodeTool@0
        inputs:
          versionSpec: '16.x'
        displayName: 'Install Node.js'

      - script: |
          npm install
          npm run build -- --configuration ${{ parameters.buildConfiguration }}
        displayName: 'Run build'
Enter fullscreen mode Exit fullscreen mode

What this template does:

  • Accepts parameters for build configuration (Release, Debug) and VM image type.

  • Checks out code.

  • Installs Node.js (can be changed to .NET, Python, etc.).

  • Runs the build script.

vii. Secure Access to the Templates Repo: Select your pipeline-templates repo:
Select your pipeline-templates repository.

Open Security tab.

Remove “Contribute” permissions for groups/users who do not need to edit templates.

Grant:

Read access to teams that only need to use templates.

Contribute access only to DevOps engineers responsible for maintaining templates.

Deny Force Push and Bypass Policies for everyone except admins.

And that’s a wrap for Part 2!
We’ve gone beyond just writing YAML and pushing code, we have built a pipeline that guards your resources, keeps secrets locked away, controls who can access what, and uses reusable templates to keep things both consistent and secure.

Security is not something you add at the end, it’s something you bake in from the start. With what you have set up here, every run of your pipeline is not just a deployment, it is a statement that you value stability, compliance, and trust.

This completes our lab on Implementing Security Through a Pipeline in Azure DevOps, giving you the skills and mindset to build pipelines that are as safe as they are efficient

If you have any question, insight, or your own tips on securing pipelines? Drop them in the comments, I’d love to hear from you.
Follow me for more hands-on DevOps, Azure, and Cloud Security labs and guides.

AzureDevOps #DevOps #Azure #Security #CloudSecurity #PipelineSecurity #AzurePipelines #CICD #CloudEngineering #AzureKeyVault #YAML #InfrastructureAsCode #MicrosoftAzure

Top comments (0)