I have written an updated version of this application; you can read here.
Every Few months I notice the following Saga repeats. I face a challenge where I need to programmatically manage security aspects of Azure DevOps resources (like Repository, Pipeline, Environment etc.). I do lookup the Azure DevOps REST API documentation, realize that the Permissions & Security API’s are notoriously complicated and inadequately documented. So, I begin with F12 to kick off the Development tools for Browser and intercepting HTTP requests. Trying to guess what’s payloads are exchanged and try to come up with appropriate HTTP requests myself. However strange it might sound, usually this method works for me (actually worked almost all the time). But it’s a painful and time-consuming process. Recently I had to go through this process one more time and I promised to myself that once I am done, I will write a Blog post about it and put the code in a GitHub repository – so next time I will save myself some time & pain. That’s exactly what this post is all about.
Security & Permission REST API
As I have said, the security REST API is complicated and inadequately documented. Typically, each family of resources (work items, Git repositories, etc.) is secured using a different namespace. The first challenge is to find out the namespace IDs.
Then each security namespace contains zero or more access control lists (aka. ACLs). Each access control list contains a token, an inherit flag and a set of zero or more access control entries. Each access control entry contains an identity descriptor, an allowed permissions bitmask, and a denied permissions bitmask.
Tokens are arbitrary strings representing resources in Azure DevOps. Token format differs per resource type; however, hierarchy and separator characters are common between all tokens. Now, where do you find these tokens format? Well, I mostly find them by intercepting the Browser HTTP payloads. To save me from future efforts, I have created a .net Object model around the security namespace IDs, permissions and tokens – so when I consume those libraries, I can ignore these lower-level elements and have a higher order APIs to manage permissions. You can investigate the GitHub repository to learn about it. However, just to make it more fun to use, I have spent a bit time to create a Manifest file (Yes, stolen from Kubernetes world) where I can get my future job done only by writing YAML files – as oppose to .net/C# codes.
Instructions to use
The repository contains two projects (once is a Library – produced a DLL and another is the console executable application) and the console executable is named as azdoctl.exe
.
The idea is to create a manifest file (yaml format) and apply the changes via the azdoctl.exe
:
> azdoctl apply -f manifest.yaml
Manifest file
You need to create a manifest file to describe your Azure DevOps project and permissions. The format of the manifest file is in yaml (and idea is borrowed from Kubernetes manifest files.)
Schema
Here’s the schema of the manifest file:
apiVersion: apps/v1
kind: Project
metadata:
name: Bi-Team-Project
description: Project for BI Engineering team
template:
name: Agile
sourceControlType: Git
Manifest file starts with the team project name and description. Each manifest file can have only one team project definition.
Teams
Next, we can define teams for the project with following yaml block:
teams:
- name: Bi-Core-Team
description: The core team that run BI projects
admins:
- name: Timothy Green
id: 4ae3c851-6ef3-4748-bef9-4f809736d538
- name: Linda
id: 9c5918c7-ef03-4059-a49e-aa6e6d761423
membership:
groups:
- name: 'UX Specialists'
id: a2931c86-e975-4220-aa89-dc3f952290f4
users:
- name: Timothy Green
id: 4ae3c851-6ef3-4748-bef9-4f809736d538
- name: Linda
id: 9c5918c7-ef03-4059-a49e-aa6e6d761423
Here we can create teams and assign admins and members to them. All the references (name and ids) must be valid in Azure Active Directory. Ids are Object ID for group or users in Azure Active directory.
Repository
Next, we can define the repository – that must be created and assigned permissions to.
repositories:
- name: Sample-Git-Repository
permissions:
- group: 'Data-Scientists'
origin: aad
allowed:
- GenericRead
- GenericContribute
- CreateBranch
- PullRequestContribute
- group: 'BI-Scrum-masters'
origin: aad
allowed:
- GenericRead
- GenericContribute
- CreateBranch
- PullRequestContribute
- PolicyExempt
Again, you can apply an Azure AD group with very fine-grained permissions to each repository that you want to create.
List of all the allowed permissions:
Administer,
GenericRead,
GenericContribute,
ForcePush,
CreateBranch,
CreateTag,
ManageNote,
PolicyExempt,
CreateRepository,
DeleteRepository,
RenameRepository,
EditPolicies,
RemoveOthersLocks,
ManagePermissions,
PullRequestContribute,
PullRequestBypassPolicy
Environment
You can create environments and assign permissions to them with following yaml block.
environments:
- name: Development-Environment
description: 'Deployment environment for Developers'
permissions:
- group: 'Bi-Developers'
origin: aad
roles:
- Administrator
- name: Production-Environment
description: 'Deployment environment for Production'
permissions:
- group: 'Bi-Developers'
origin: aad
roles:
- User
Build and Release (pipeline) folders
You can also create Folders for build and release pipelines and apply specific permission during bootstrap. That way teams can have fine grained permissions into these folders.
Build Pipeline Folders
Here’s the snippet for creating build folders.
buildFolders:
- path: '/Bi-Application-Builds'
permissions:
- group: 'Bi-Developers'
origin: aad
allowed:
- ViewBuilds
- QueueBuilds
- StopBuilds
- ViewBuildDefinition
- EditBuildDefinition
- DeleteBuilds
And, for the release pipelines:
releaseFolders:
- path: '/Bi-Application-Relases'
permissions:
- group: 'Bi-Developers'
origin: aad
allowed:
- ViewReleaseDefinition
- EditReleaseDefinition
- ViewReleases
- CreateReleases
- EditReleaseEnvironment
- DeleteReleaseEnvironment
- ManageDeployments
Once you have the yaml file defined, you can apply it as described above.
Conclusion
That’s it for today. By the way,
The code is provided as-is, with MIT license. You can use it, replicate it, modify it as much as you wish. I would appreciate if you acknowledged the usefulness, but that’s not enforced. You are free to use it anyway you want.
And, that also means, the author is not taking any responsibility to provide any guarantee or such.
Thanks!
Really nice! I so totally relate to the “Saga experience” with ADO. Security is just overly complex and documentation just nonsense.
LikeLike
Agreed. It is definitely lacking and not enough documentation/examples. Typical Microsoft protected garden…
LikeLike