.NET · .net-core · AzureDevOps · C# · CI-CD · Command · docker · IAC · Infrastructure As Code

Azure DevOps security as Code

Accompanied source code can be found here.

A while ago, I have written an application that could simplify managing Azure DevOps security. The idea was that one could define bunch of YAML file that describes numerous security aspect for an Azure DevOps project (for example, security for teams, build and release folders, repositories etc.) and a pipeline that could sync or apply those security settings to Azure DevOps. Essentially doing GitOps for Azure DevOps and getting a nice readable security documentation as byproduct.

Quite some people have used this, and I was reached out by many to add few more support – specially for Area Paths and iteration paths. This week, I have spent a bit more time – adding these features into the code. Here’s the quick update and instructions how to use it (as of now):

Security as code Samples

Let’s begin seeing some example YAML that the application currently supports:

Project

Here’s the project manifest (YAML) looks like (project.yaml):

apiVersion: apps/v1
kind: Project
metadata:
  name: Platform
  description: Project for platform team
template:
  name: Agile
  sourceControlType: Git

The project manifest is required, without it the application will not process any other files.

AAD Groups

The application can support both AAD groups and Azure DevOps groups to be materialized or created respectively. Let’s start with defining an AAD group:

apiVersion: apps/v1
kind: Group
metadata:
  name: K8s-Operators
  description: An AAD Group that needs to be materialized
properties:
  origin: Aad
  aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6

The above manifest will “materialize” the AAD group K8s-Operator if not already done before, so later we can use this group in other manifests. For AAD group we must set origin: Aad and provide the Azure AD group object ID as aadObjectId.

Azure DevOps Groups

Next to AAD group the application supports creating native Azure DevOps groups too:

apiVersion: apps/v1
kind: Group
metadata:
  name: SRE-Project-Scoped-Group-001
  description: A Group that is project scoped
properties:
  origin: Vsts
  scope: Project
membership:
  groups:
  - name: 'IoT-Developers'
    origin: Aad
    aadObjectId: 00238ebc-66c1-4220-a859-ed0a00243f27
  - name: 'K8s-Operators'
    origin: Aad
    aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6
  users:
  - name: Timothy Green
    principal: timothy@cloudoven.net
  - name: Linda
    principal: Linda@cloudoven.net

In order to create Azure DevOps native groups, we must provide origin: Vsts and an appropriate value for scope. Scope can be Project scoped or Organization scoped. A native Azure DevOps group can have members that are AAD group or another AzDO native group, and of course direct members that are described by their principals.

Area Paths

We can define Area Paths and their permissions using an Area Path manifest like below:

apiVersion: apps/v1
kind: AreaPathSecurity
metadata:
  name: AreaPathSecurity
  description: Sample that applies permissions across multiple area paths
permissions:
  - paths:
    - Platform/Marketing/Frontdesk
    - Platform/Finance
    - Platform/Finance/LoanSector
    allowed:
    - GENERIC_READ
    - GENERIC_WRITE
    - CREATE_CHILDREN
    - DELETE
    - WORK_ITEM_READ
    - WORK_ITEM_WRITE
    - MANAGE_TEST_PLANS
    - MANAGE_TEST_SUITES
    groups: 
    - group: 'K8s-Operators'
      origin: Aad
      aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6
    users:
    - name: Timothy
      principal: timothy@cloudoven.net

You can allow permissions for a certain number of groups (can be both AAD groups or Azure DevOps groups) or users.

Iteration Path

Like Area Path we can also define Iteration Paths and their permissions:

apiVersion: apps/v1
kind: IterationPathSecurity
metadata:
  name: IterationPathSecurity
  description: Sample that applies permissions across multiple Iteration paths
permissions:
  - paths:
    - Platform/GA
    - Platform/GA/CommunityRelease
    - Platform/GA/CTP1
    allowed:
    - GENERIC_READ
    - GENERIC_WRITE
    - CREATE_CHILDREN
    - DELETE
    groups: 
    - group: 'K8s-Operators'
      origin: Aad
      aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6
    users:
    - name: Timothy
      principal: timothy@cloudoven.net
Teams

We can define Teams, along with the administrators of the team, members and map them to a certain Area path.

apiVersion: apps/v1
kind: Team
metadata:
  name: PO-TEAM
  description: A team for Product owners
admins:
  - name: Timothy Green
    principal: timothy@cloudoven.net
  - name: Moim
    principal: moim@cloudoven.net
membership:
  groups:
    - name: 'K8s-Operators'
      origin: Aad
      aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6
  users:
    - name: Timothy Green
      principal: timothy@cloudoven.net
    - name: Linda
      principal: Linda@cloudoven.net
    - name: Scrum
      principal: Scrum@cloudoven.net
config:
  defaultPath: Platform/Marketing/Frontdesk
  areaPaths:
    - path: 'Platform/Finance/South Americas'
      includeSubAreas: true
    - path: 'Platform/Marketing/Frontdesk'
      includeSubAreas: true
    - path: 'Platform/HR/Internal'
      includeSubAreas: true

As we can see the team manifest is quite richer than earlier version. It now allows you to define admins, members but also allows mapping multiple area paths (including their sub areas).

Repository

We can define permissions for repositories (one or more repositories in a single manifest file):

apiVersion: apps/v1
kind: RepositorySecurity
metadata:
  name: RepositorySecurity
  description: Sample that applies permissions across multiple repositories.
permissions:
  - names:
    - React-JS
    - Mobile-App 
    allowed:
    - GenericRead
    - GenericContribute
    - CreateBranch
    - PullRequestContribute
    groups: 
    - group: 'K8s-Operators'
      origin: Aad
      aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6
    users:
    - name: Timothy
      principal: timothy@cloudoven.net

One thing to note, if the repository doesn’t exist the application will NOT create one.

Build Folders

YAML pipeline folders or classic build folders can be managed with following example manifest.

apiVersion: apps/v1
kind: PipelineFolderSecurity
metadata:
  name: PipelineFolderSecurity
  description: Sample that applies permissions across multiple pipeline folders
permissions:
  - paths:
    - \Demo-Folder\Child-Folder\X86
    - \Demo-Folder\Child-Folder\X64
    allowed:
    - ViewBuilds
    - QueueBuilds
    - StopBuilds
    - ViewBuildDefinition
    - EditBuildDefinition
    groups: 
    - group: 'K8s-Operators'
      origin: Aad
      aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6
    users:
    - name: Timothy
      principal: cloudoven.net
Release folders

Classic release folders can be managed as below:

apiVersion: apps/v1
kind: ReleaseFolderSecurity
metadata:
  name: ReleaseFolderSecurity
  description: Sample that applies permissions across multiple release folders
permissions:
  - paths:
    - \Demo-Folder\Child-Folder\X86
    - \Demo-Folder\Child-Folder\X64
    allowed:
    - ViewReleaseDefinition
    - EditReleaseDefinition
    - ViewReleases
    - CreateReleases
    - EditReleaseEnvironment
    - DeleteReleaseEnvironment
    - ManageDeployments 
    groups: 
    - group: 'K8s-Operators'
      origin: Aad
      aadObjectId: eb2a16c0-401a-4fc8-beb4-02fe3e6f25b6
    users:
    - name: Timothy
      principal: timothy@cloudoven.net

Run it!

Let’s say we have bunch of these manifest files into a directory, then we can lunch the application to process all of these one after another.

docker run --rm \
            -v "/mnt/c/Git/Manifests:/home/payload" \
             moimhossain/azdoctl:gama apply -d "/home/payload" \
             -u "https://dev.azure.com/<ORG NAME>" \
             -p "<YOUR PAT>" \
             -k "APP INSIGHT CONNECTION STRING"

Alternatively, you can run a single manifest file – specifically:

docker run --rm \
               -v "/mnt/c/Git/Manifests:/home/payload" 
               moimhossain/azdoctl:gama apply \
               -f "/home/payload/Project.yml" \
               -u "https://dev.azure.com/<ORG NAME>" \
               -p "<YOUR PAT>" \
               -k "APP INSIGHT CONNECTION STRING"

This produces the logs into the console as it processes the manifests:

Conclusion

Azure DevOps security is crucial for businesses that want to stay ahead of the game in terms of security standards. In recent years, the importance of security in the DevOps process has skyrocketed, and there is no doubt that security has become essential for businesses of all sizes. However, most businesses still view security as a separate task and often fail to integrate it into their development process. That’s where Azure DevOps security as Code comes to the rescue.

Azure DevOps security as Code allows businesses to incorporate security into their development process by automating security testing and ensuring that the security aspect of their code is in line with their requirements. With Azure DevOps security, businesses can create automated security testing pipelines that can help detect and prevent any security issues before they become an issue in production.

By adopting Infrastructure As Code (IAC) and Docker-based operations, businesses can quickly deploy infrastructure and applications with Azure DevOps, reducing errors in manual processes and increasing agility. Furthermore, with the Azure DevOps security features, businesses can take control of security with command-line management, enhancing interactions between teams, enabling better testing and deployment practices, and helping adopt and optimize continuous integration and delivery (CI/CD) pipelines.

In conclusion, Azure DevOps security as Code is an essential tool that can help businesses secure their code, ensure that their development process is in line with their security requirements, and mitigate any security threats in a fast and convenient manner. With technology trends evolving and security threats becoming more significant, businesses must be proactive in their approach to security, and Azure DevOps security as Code is the way to go.

Hope you find this useful. Thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s