Managing whether an identity has access to a given service, feature, function, object, or method in Azure DevOps comes down to authorisation. Fortunately, by default, the permissions are set in such a way to enable you to focus on the job at hand, DevOps. Loosely translated this means 'don't get in my way'. My experience is that the Microsoft #AzureDevOps team have done a really good job at this, enabling you to crack on developing, building, testing and releasing without much hindrance.
Working with relaxed permissions is great when you are the owner and possibly either a one man band or small team but as soon as we need to consider larger teams, varying roles with approvals and degrees of access, authorisation becomes a real concern.
I recently designed a pipeline for a project utilising offshore and onshore collaboration where security and access levels were a primary consideration within the teams where specific teams handling dev|build|release|SecOps|snr mgt|owners| and so on needed to come together as one seemless workflow to approve a set of pipelines with all the gated test, code coverage and confidence checklist provided with a zero downtime production release being the end product.
This article is a condensed version of the larger article i wrote back in May 2019 which can be found here and serves as a pick of findings and a memory jogger for me of some of the touch points encountered. There is quite a bit of detail but when you are at the implementation phase, you will hopefully appreciate the granularity.
This assumes the connection has already been authenticated, more detail on authentication can be found under the references section below.
Authorisation is based on users and groups.
On top of this comes another layer of abstraction that of Azure DevOps security groups. Security groups assign a set of permissions to the members of the group. The members are either individuals or user groups, such as Active Directory, more on that later.
Azure DevOps comes pre-configured with default (built-in) security groups. Some thought has gone into the way different types of users (roles) will interact with Repos, Builds, Releases and much finer granularity but the out of the box groups are ready to be populated with members.
The groups are applied at three levels:
- Server (TFS and Azure DevOps Server)
- Organisation (also known as collection level)
The levels are detailed below along with examples of the default security groups created for you out of the box.
We can ignore Server for this discussion as it is essentially an on prem install and we are focusing on a purely cloud based solution. Links in the references section below provide more info about Azure DevOps Server or Team Foundation Server (TFS).
Organisation-level (Also referred to as Collection Level)
The default organisational security groups are shown below:
Default Permissions and Groups
Note* In order to create projects and add users to projects, you need to be added as a project administrator
Essentially, when working in an Azure cloud only model, you are either dealing with an Organisational group or a Project level group.
Note** Avoid changing the permissions of the default groups and instead, create custom security groups
Custom Security Groups
When a scenario develops which requires finer granularity or a subset of another group, creating a custom group is the solution. For example, you may want a specific set of Team Admins that do not require all the project or organisational administrator permissions applied to a default administrator group but just a subset.
Note*** Whether creating a security group at the organisation or project level, the result is the same.
Adding Users and Groups to Azure DevOps can can be achieved via Active Directory (AD), Azure Active Directory (AAD), Individual Microsoft Accounts (MSA) or for on-premises deployments, local Windows users and groups.
Our discussion focuses on a the DevOps portal and Azure only so we can narrow that down further to AAD and MSA.
Using MSA works great for projects with limited users but as soon as you start dealing with teams, AAD is the way to go.
You can add individual users or AAD groups to either the default or custom security groups. When you do so, an entry automatically gets added to the Valid Users group (default) as this is required to connect to a project and is primarily limited to read access, such as view build, project and organisational information.
As a starting point, users that are required to 'get stuff done' will usually require access to the Contributors security group. For those only required to approve and review information, this may not be required.
Members can be individual users or more commonly AAD groups. This will lead to creating AAD groups for the types of roles within the organisation but targeted towards DevOps. Some examples might be 'Developers', 'Business Stakeholders', 'Build Admins' 'Release Admins' and at least one group which may act as a more general group with common permissions shared by other groups. Another tip I can recommend is to find a naming convention for the AAD groups which distinguishes them from other Azure DevOps groups, particularly when attempting to gain insight into who is a member of what further down the road.
Linking DevOps Organisation to AAD
Linking your DevOps organisation to AAD is a straight forward process using the link button in the portal, as shown below.
As well as the default groups created, you can also see above a default team has been created with the same name as the project.
Teams can drastically help the organisation of the development work underway. You can create 'feature' teams and add those as members of the Azure security groups. Work items and sprint planning can then be linked to specific teams. For the sake of brevity, we will not be going any deeper with teams in this article but bear in mind you will need to touch on them to group and get an overview of work at a team level.
Also be mindful that users and groups are assigned to your teams. Teams can then be added as members of the default or custom security groups, which are then impacted by the default or custom level of permissions assigned.
By default, the default team group and all other teams added to the project are included as members of the Contributors group. So adding new users to a team, automatically inherit Contributor permissions.
Note* In order to create teams and manage users, you need to be added as a project administrator or team administrator.
The way to visualise permissions is that they are also applied at either the Organisational or Project level. Basically, does it affect the Organisation, which includes all projects within or does it only affect a specific project. Some permissions are only applicable to an Organisation or Project.
Each of the default groups comes pre-defined with a set of default permissions.
Permission controls access to specific functional tasks at different levels within the system.
The levels that permissions are applied to are identified below:
- Collection-level (Also known as Organisational level)
- Object-level - set permissions on a file, folder, build pipeline, or a shared query.
Object level permissions are what they say on the tin. But it took me a while for the penny to drop. Each and every 'thing' we create in the portal is mostly defined as an object. For example, a build pipeline, a code branch, a release pipeline, file, folder etc. Each of these objects contain a more granular permission level by accessing the ellipses menu while the object is selected, which loads the familiar permissions dialog.
Object-level permissions can be seen below, highlighting specific permissions applied to a selected build pipeline.
Once again, the same set of security groups determine what permissions are allowed, which as stated previously will cover most scenarios 99% of the time.
Also bear in mind many of the object-level permissions follow a hierarchical model. In the above release pipeline scenario, the same set of permissions can be set for all release pipelines as shown below:
The above highlights that for the area of interest, it is first worth checking whether object-level permissions apply to ensure you are setting the permission at the right level for your requirements. (see scopes below)
At the other end of the spectrum, below highlights the same permissions being applied to a stage within the same release pipeline:
Another example is Git Repos, which also have a set of Object-level permissions, accessed via the project settings action bar.
There are also
- Role - managed through a security role
- Team - managed by an administrator team
The above release-pipeline scenario highlights another level, that of scopes. When reading the documentation for a permission, take note of the scope column, which identifies at what scope a permission can be applied i.e project | release | pipeline or project | release | pipeline | stage. This will aid in confirming the level applied is the correct one for your given requirement/s.
Note* Project Collection Administrators are granted all collection-level permissions. Other collection-level groups have select permission assignments.
Permission settings correspond to Allow, Deny, Inherited allow, Inherited deny, and Not set.
Allow or Deny explicitly grants or restricts users from performing specific tasks, and are usually inherited from group membership.
Not set implicitly denies users the ability to perform tasks that require that permission, but allows membership in a group that does have that permission set to take precedence, also known as Allow (inherited) or Inherited allow and Deny (inherited) or Inherited deny.
On most groups and almost all permissions, Deny overrides Allow. If a user belongs to two groups, and one of them has a specific permission set to Deny, that user is not able to perform tasks that require that permission even if they belong to a group that has that permission set to Allow.
For members of the Project Collection Administrators or Team Foundation Administrators groups, Deny doesn't trump Allow. Permissions assigned to these groups take precedence over any Deny set within any other group to which that member might belong.
Changing permission for a group changes that permission for all users who are members of that group. In other words, depending on the size of the group, you might affect the ability of hundreds of users to do their jobs by changing just one permission. So make sure you understand the impact before you make a change.
One feature of interest in tracking down how, or more precisely where, a permission has been applied is to use the 'Why?' link that is available when hovering over a given permission that is inherited. The trace permission feature gives an insight into where the permission is applied as shown:
Note* When navigating Groups at the Organisational level, ensure you use double click to move between groups resulting in an updated view of members and permissions. Single select, at the time of writing does not always update the details, which can lead to some confusion.
The most time consuming part of changing permissions in my experience has been finding the correct permission to apply. The reference section contains a handy Permissions lookup guide for Azure DevOps link which is essentially an index for specific permissions, grouped by Organisation | Project | Object | Role | Team
In order to access certain features of the Azure DevOps portal, users also need to be assigned an access level. The ones of interest are currently:
- VS Enterprise
By default, an organisation has 5 Basic licenses and unlimited Stakeholders. A license is assigned to a user by selecting the access level, as shown below. Additional licenses need to be purchased via the Azure Marketplace.
o do anything meaningful, other than read and comment, at least the Basic access level is required. A basic access level enables code, build, test, release and most of what is required to be productive.
Note* Applying access levels alone does not grant access to the project in the portal. Users still need to be added to a security group or team which is a member of an existing group.
There is a fair bit to comprehend with Azure DevOps authorisation as it inherits much from TFS. Hopefully the areas covered in this article will get you up to speed as soon as possible by highlighting the touch points you will need to be aware of.
Also bear in mind there are a number of ways to skin a solution to your organisational needs. Once defined, it is important to remain consistent to keep a high degree of clarity.
During investigation, within a sandbox environment, the creation of AAD groups and MSA users with a specific goal in mind helped. I would encourage you to do the same and learn from doing across Repos, Builds and Release Pipelines.
If you would like some hands on expertise for your business feel free to reach out via my company assemblysoft
Thanks for sharing. Very informative and well explained.