Wednesday, February 14, 2024

Mother of AzureDevops repository policy - Create custom policy to monitor recommended repository policies are enabled

Branch policy are always an important factor in protecting your branch and deciding the work flow. Enabling certain branch policies help you always to protect from others being contributing.

As part of quality and to protect your branches, stakeholders always recommend to align with certain git repo policies in Azure Devops. In addition to quality, it helps keep your repos from changing the code from your default branches. By default, ADO has Require a minimum number of reviewers, Check for linked work items, Check for comment resolution, Limit merge types, Build Validation, Status checks..

Why we need Custom policy?

Generally, when a PR is raised if the default polices are enabled then it will be auto applied to a PR. But the users who have permission to alter with polices can alter them and complete the PR which can have serious security and quality impacts. So there is always a question, how to make sure/monitor that all the polices are enabled.

To overcome this, we can create a custom policy which will act as policy to monitor other policies. The advantage of custom policy is even if the custom policy is not added to repo policy as required, it will evaluate the policies applied over a repo and respond against PR as optional policy. This is because the service hook gets triggered when the PR is PR created and left part all happens in Azure and not in ADO. When the custom policy executes we can insert the repo evaluation details to a data base which can be in turn used for reporting on repo compliances.

What does Custom Policy do?

As mentioned, custom policy will be utilized to evaluate whether we have all recommended policies enabled over the repo. If all the policies are enabled, then custom policy will respond back to PR as passed else if will be failed. Also if the custom policy is enabled as required policy in repo settings then the user will not be able to complete the PR unless the custom policy passes based on the evaluation – result of evaluation whether we all policies enabled.

How it works:

Here, I am going to discuss on creating a custom policy which will make sure that all these policies are enabled for Pull request, unless the custom policy passes the developer will not be able to merge the code. The custom policy will act as mother of all policies.

There are 2 parts for the custom policy to work. I would recommend Azure function and Queue Storage to implement custom policies. First part is you need service hook which triggers when a pull request is created and add the request JSON from service hook to Queue Storage using a http trigger azure function. 


Second part is a Queue triggered azure function which will trigger when an JSON reaches the Queue Storage.

When the Queue triggered Azure function runs, it fetches the JSON from Queue storage which was send from service hooks. The JSON will have details like project id, repository id and PR id. Using these data we can use PR evaluation API to get the polices applied over that PR: Evaluations PR .Once the evaluation is completed, we can respond back to PR as Custom Policy : Creating Custom Policy.

Hope this idea helps in monitoring the repository policies and protect your branch!

Wednesday, January 5, 2022

How to Get Notified when a Azure DevOps Project is Created or Deleted!

Lets discuss how we can monitor the Azure DevOps project creation and deletion as part of administering the ADO.

We have been working with Azure DevOps to get notifications and found no ways to get info of the projects getting deleted and created(by some other collection admins!!).Main reason to get the notifications was as the project admins have the privilege to delete their project, so monitoring of the deletion in an automated way was necessary. Apart from this if we have multiple collection admins then, it is suggested all to be aware of what is happening in an ADO at collection level. I would always recommend the collection level admins to be maintained as low number as 2-4 people.

To monitor this, the only way was read the audit from ADO audit Logs. So the best way we found was to write a timer triggered job which runs on a daily basis and reads the audit for project created and deleted, then notifies the collection admins through Email or through the Teams Channel.


Response:









The decoratedAuditLogEntries contains all the log details. We just need to read each attributes of the depending on the length of the decoratedAuditLogEntries. For example here the lenth of decoratedAuditLogEntries is 94. So we may need to check all the 94 entries inside it.All the actions perfromed in Azure DevOps is logged in decoratedAuditLogEntries with an action id. So we can easily get the action id for project created and deleted.

Now for project creation ,decoratedAuditLogEntries will have its actionId as Project.CreateCompleted.















If you can get the action Id  "Project.CreateCompleted" from response json, then you can read the project name, Id and other details.

Similarly for Project deletion , decoratedAuditLogEntries will have its actionId as Project.SoftDeleteCompleted.














If you can get the action Id  "Project.SoftDeleteCompleted" from response json, then you can read the project name, operation time and other details.

Once you get all the details from Project.SoftDeleteCompleted and Project.CreateCompleted for deleted and created projects, you can use some notification method via email or to your organisation Teams channel.

The important thing to note here at times the log could be large, so we may have to use the continuation token and hasMore property from the API response.

Here we need to check whether "hasMore" property is true or not, if its true then we need to check for the continuationToken and the pass it with the API each time.

Enjoy!

Friday, May 7, 2021

Build your Azure DevOps extensions with Azure Pipelines

In this blog I will be discussing about building azuredevops extension using an azure pipeline.

Whenever we lack some out of the box functionality in ADO, we might need to develop an ADO extension and deploy them using CI-CD. 

In order to build and deploy them we have some useful extension available in marketplace. These extension tasks helps in smoothly building and deploying an extension. They are:
  1. Azure DevOps Extension Tasks : This extension helps in building and publishing your extension. This is developed my Microsoft DevLabs
  2. Version Number Counter : This task helps in incrementing the version number of the extension. 
Create your build pipeline:

1.Use the classic editor pipeline and select your repository:


















2.For building the extension I am going to use the below tasks:
























  • Use Node CLI for ADO(tfx-cli) : This will download and install the Node CLI for Azure Devops

















  • Version Number Counter: This is used to automatically update the version number. This extension will increment the minor of build version for each build execution. In this task we have mention couple of variable: version and PAT. Version should be in x.x.x  format and PAT should be your ADO pat. Here I have provided version as 1.0.0 with variable name as version itself and variable name for Pat is PAT



















Variables can be added under variable section inside the pipeline as shown below:






  • Package Extension: This will build and package the extension to VSIX format.
Here the first thing that we need to provide is manifest root folder. Since my manifest file is inside $(Build.SourcesDirectory), I have provided the same. For other it could be $(Build.SourcesDirectory)\some folder name\home as well.Next thing to provide is publisher name and extension version. Publisher name should be the name of the publisher who is publishing the extension and version can be provided as the same variable that was provided earlier as $(version).


































  • Copy files: This task can be used to copy the output's to the artifact's folder





















  • Publish Artifact : This task is used to publish the artifact to the Build Pipeline





















Once you run the pipeline successfully, you can see the build artifacts .vsix as the inside the build artifacts:






Now you can publish this artifact to market place using another build tasks using release pipeline or extending the same pipeline, about which I will be covering in my next blog. Manual way to publish this would be download the .vsix from the artifact and manually upload and publish it to the market place.

Reference:  


 






Monday, July 13, 2020

Packages for using Azure DevOps Rest Clients

Today, I am going to discuss about the ADOAdmin.AzureDevOps.Clients  which can be used to call, patch and post any of the ADO API.

ADOAdmin.AzureDevOps.Clients, as the name suggests it has been aimed for ADO admins who use the ADO api's extensively. This package has got modules for working Azure DevOps  API operations as GET,PATCH and POST. This can be further extended, based on the suggestions.

This package gives facility to avoid the repetition of codes that is being used for API calls.

How to Install it?

1. Click on "Manage Nuget Package" for your solution/project
2. Search for "ADOAdmin.AzureDevOps.Clients"
3. Install it.









How to use it?

1.Once you install it, in namespace as

using ADOAdmin.AzureDevOps.Clients;

2.Once you add it in the package list, create an object for RestAPIClients:

 RestAPIClient adoClient = new RestAPIClient();       

3. To use it for GET operations:

string _jResponse=adoClient.AzureDevOpsGet(string devOpsPat, string apiUrl)

Sample:

string auditRepsonse = adoClient.AzureDevOpsGet(adoPat, adoApiUrl = string.Format(
             @"https://auditservice.dev.azure.com/{0}/_apis/audit/auditlog?startTime={1}&endTime={2}&continuationToken={3}&batchSize=1000&skipAggregation=true&api-version=5.1-preview.1",
               accountName, auditReadStartTime, auditReadEnddate, continuationToken));

4.To use it for POST operations:

string _jResponse=adoClient.AzureDevOpsPost(string devOpsPat, string apiUrl, string jsonData)

5.To use it for PATCH operations:

string _jResponse=adoClient.AzureDevOpsPost(string devOpsPat, string apiUrl, string jsonData)

Without much complications and googling for how you can use httpclients to call ADO API's use can directly use these packages.

The source code for these packages can be found here: Ado_api_Usage

Hope this helps!!!




                

Sunday, May 17, 2020

Manage Azure DevOps License


In this blog, I am going to explain how we can manage the licenses in Azure DevOps in a better way.

We have different type of licenses that are being provided by Microsoft to access Azure DevOps at different price levels and privileges.






















Most widely used licenses to access the ADO are Basic and Basic+Test Plan which costs to $5 and $52 user/month. Allocation of these licenses are pretty easy and can be done seamlessly. But the monitoring of these licenses, whether the people are using these licenses appropriately is very difficult. At times we might have allocated some folks Basic+Test Plans license and he might have moved to some other project with another tool, but still exists in ADO without accessing ADO and wasting the license. Especially during these times when companies are planning about cost-cutting, this document might help them.

The steps to monitor the usage of ADO by users using ADO rest API can be done as below:
1.First get the list of all users with their licenses and last Access date using the User Entitlements - List API:


Example:
  
From the response collect all the users Id, licenses and last access date:




























Now check whether the user’s last access date is more than 30 or not. 30 is a random number which we decided, so that those who have not used ADO for last 30 days, we will send a warning message to use ADO or else the license will be downgraded to stakeholder one.
Now if you want to downgrade directly the license of those users who have not used the ADO from last 30 days you can use API Update user entitlements:
















Once we patch and update the license, we can see in ADO UI as below:






API response:


























We can execute these API’s as a scheduled job which might execute twice a month to monitor the licenses. The entire source will be uploaded to my git repository soon.

Tuesday, May 12, 2020

Create common group which can access all team projects in Azure DevOps


Depending on organizational structure and security, some of the organisations would need a common security group with atleast read access to all projects. This might be for management monitoring or for some secutiry purpose.
So for creating such groups, first of all you need need to collection admin of the organization. Now create a new group in Azure devops at collection level with the basic inherited permissons. Here I have created a goup with name “Allprojectaccessgroup”.


























Now add people to this group who needs read permission to all the projects of your organisation.

Next step would be to create a group a group rule. For this you need to go to Users tab at organizational level.





Select add group rule and add the collection level group to it.

















From the projects dropdown select the required projects in which you need to add this group. If you want add to all projects select “All”.
Once select the projects, save it. Now wait for a moment and check for the group rule being listed under the group rule tab. Select “Manage group rule” from the menu options. 







While managing group rule you can assign to required group and assign the access level:















You can select for all the projects as “Project Readers” and save it.

If we go inside projects “Readers” security group, we would be able to see this collection group being added to the project.











From here on for all the projects we create, we have to either go manually select from manage rules at group rule level or we can do some automation to update the group rule. The easiest way would be creating automated scripts using API’s to update the group rule. We can automate this using some scheduling approach. We have scheduled our script to execute once every day, so that any project created will have the new group added on the same day. I will put the code soon in my github repository.

Hope this works for you!

Thursday, April 2, 2020

Azure DevOps : Creation of custom security groups using ADO Rest API


Depending on organizational structure and security requirements, there can be a need for custom security group(s) at the project level. For example, a project level group that has access only to repos. Now this can be a standard requirement as well, where all projects getting created in the org should have this custom security group created as part of it – this post will focus on explaining how custom security groups can be created using Azure DevOps rest apis.

If you are looking to create a custom security group in all your projects,(existing and the ones getting created) please take a look at this public git repository. This repository consists of an azure function, the way which we used to automate the creation of custom security group. The azure function which  runs daily to check for new projects and created the security group.

Pre-requisites:
  1.       Collection admin privileges on Azure DevOps org.
  2.       Knowledge on ADO Rest APIs and Access Control Entries.

Create the security group

         Create the security group using the ADO rest API.
For this we need:
Ø  the project id and
Ø  the scope descriptor.
To get the project id use the Projects – List API:


Response:


Once you get the project id, use it to find the scope descriptor using Descriptors - Get:


Example: From the above response my project id is 123456789. Use this as storage key:


Response:


Here storageKey refers to the project Id.

Once you get the descriptor create the security group in the project using Groups - Create, by providing the group name and group description in the request body.



Use the below json as body for post:




Response:

















Here display name is the group name, I have given it as “MyGroup” - once you post this you will find a new group getting  created in this project.









The group being created will have the below permissions:





















Make sure that view project-level information is enabled. Else you will have to follow the below same steps to enable the “view project-level information”. Here for me view project -level information is enabled. So below I am going to explain how you can enable the view for repos for this group.

Assign permissions to the newly created security group

Once you create the group you need to set the permissions for this group. For this we should get the list of Namespace IDs, with Security Namespaces – Query :



You will find around 50 plus namespaces with its key permission and bit value as shown below. For example, if you take repo level namespace, it may look like as shown below. Here the namespace id for repo level permissions is 2e9eb7ed-3c0a-47d4-87c1-0ffdd275fd87. In order to set the permissions for the group, we should identify:
  • the correct namespace
  • the actions to allow/deny





















Now here we must understand that the permissions/ Access control entries in ADO are controlled by its bit value. For example at repo level if you want to give only Generic Read permission then the “allow” bit value for ACE should be 2 and if you want to give Both Generic read and contribute permission then we have to take sum of both the bits i.e. 2+4=6. In case you need to deny permissions, add up the “deny” bit values for the namespace. Once you get the required, set the group’s permissions using  Access Control Entries - Set Access Control Entries:









Here one tricky thing could be that, we may have to decode the base descriptor using base64.We get the base descriptor in create group step.

Separate the descriptor from vssgp and decode it. Once decoded use this to append with descriptor using in namespace update/ACE update. Here Uy0xLTktMTU1MTM3NDI0NS0zNzMyNDgwMzkxLTIwOTQzODAzNTQtMjkwMjExNjYwMy00NzQwMjk2OTAtMS0zNzI1Njg1NDI4LTI5ODA4NTQ4NTgtMjE3MjE5MTIzNS0zMzMzODgxMDg4, can be decoded to S-1-9-1551374245-3732480391-2094380354-2902116603-474029690-1-3725685428-2980854858-2172191235-3333881088.

Important thing to note here is we need to validate that the descriptor length can be divided by 4.If its length is not divided by four then add “=” at the end of the descriptor until the length becomes divided by 4.

So, the whole body for POST request should look like below:







Now if you check the permissions at the repo level, you will be able to see that both GenericContribute and GenericRead add will be enabled for MyGroup, since allow bit is 6.

GenericContribute=4 + GenericRead=2 = 6

Once POST is successful navigate to ADO repository permissions to see the access to MyGroup:





Hope this helps!