As many as 99% of security failures in the cloud through 2025 will be the customer’s fault. That’s right, ninety-nine percent. While that may imply cloud vendors are doing a good job keeping up their end of the bargain, it also suggests users of cloud services — DevOps teams included — can greatly mitigate risk by focusing on what they can control.
With Azure DevOps Services continuing to grow in popularity, there are plenty of teams looking to get up to speed on securing the platform without creating bottlenecks in their pipelines. While there’s never a one-size-fits-all infallible fix for everything “security”, we’ve put together a comprehensive Azure DevOps Security Checklist that will help you address many of the security issues you’ll face when using Azure DevOps Services.
We’ll explore the why and the how of Azure DevOps Security. There’s a lot of ground to cover, so let’s dive in.
Microsoft provides security of the cloud, it’s up to you to configure security in the cloud.
In other words, you’re responsible for that part responsible for 99% of the security failures… but what exactly does that mean?
Like other cloud service providers, Microsoft uses a shared responsibility model with Azure. Microsoft is responsible for keeping the underlying cloud infrastructure secure. This means Microsoft takes care of security when it comes to computing, storage, and networking resources that enable cloud workloads. Additionally, Microsoft handles the security configuration for managed services like Azure Kubernetes (AKS), Cosmos DB, and Azure SQL.
However, it’s up to the customer to harden their specific instances in the Azure cloud, and that holds true for Azure DevOps Services as well. That’s the crux of the “security of the cloud vs security in the cloud” model.
For example, consider the threat posed by compromised credentials, which is one of the most common attack vectors used by hackers as attacks involving compromised credentials almost tripled between 2018 and 2020. One of the best ways to mitigate the threat of compromised credentials being exploited is by implementing multi-factor authentication (MFA). Azure provides you with the ability to activate MFA, but it’s your responsibility to implement and enforce it across all accounts.
While there are many baked-in tools to help you harden your Azure DevOps Services, you’ll often need to complement them with 3rd party tools for true end-to-end security across your pipeline. For example, third-party tools can help identify misconfigurations, security issues in source code, and exposed secrets before they reach production.
As evidenced by Microsoft’s own blog being compromised due to misconfigured Azure Blob Storage (which Azure DevOps uses for large binary objects), it’s important to take a proactive and holistic approach to security.
With the why out of the way, we can jump into the how. While we’ll use the Azure portal in many of our examples, keep in mind that Azure DevOps Services expose a RESTful API and the Azure CLI has an Azure DevOps extension that can help with programmatic configuration.
Here we’ll look at specific steps you can take related to four key aspects of Azure DevOps Services security.
With any IT infrastructure, strong security posture starts with authentication and access control.
Azure DevOps uses Microsoft accounts and Azure Active Directory (AD) for authentication.
Whether you decide to create policies at the individual user level or integrate your own AD domain with Azure AD will depend on the size and complexity of your organization. In either case, here are some of the most important tips to keep in mind as you go.
Only give users and services the minimum amount of access to perform their business functions.
Regardless of the system, users and services should be provisioned with the principle of least privilege in mind. In fact, you’ll find that many of the items in our Azure DevOps Services security checklist are rooted in the principle of least privilege.
As you’d expect, user accounts and security groups are a big part of implementing effective security. At a high level, using the Azure DevOps platform you can restrict access in two ways:\
Let’s take a look at an example of using each method to restrict user access to a subset of Azure DevOps features.
When you create an Azure DevOps project, a default set of security groups are also created. These security groups have default permissions that cover many basic use cases. You can also create custom security groups with access controls optimized for your team’s workflows.
Here, we’ll create a custom “Business Analysts” group. Members of this group should be allowed to view project information and view, edit, and delete analytics information.
That’s it! Members of the newly created security group will have access to Azure DevOps resources based on the permissions we defined. You can edit existing security groups or create new ones to optimize the access controls for your infrastructure.
💡A permission that is “Not set” is effectively an implicit deny. That means users with a “Not set” permission don’t have access by default, but may be granted access by inheriting it from another group.
Access levels provide a simple way to restrict access for newly created users. There are 3 access levels available, they are:
For a breakdown of the specific permissions granted at each access level, check out the Azure docs.
You can assign an access level to a new user at the organization level (e.g. from https://dev.azure.com/<yourorg>). Here’s how:
Multi-factor authentication greatly reduces the threats posed by credential leaks and improves security posture.
We won’t mince words on this one: in 2021, no users should be accessing critical infrastructure without MFA enabled. Azure makes it easy to enforce MFA and you should do it for your Azure DevOps Services. You can create an MFA policy from the Azure portal (e.g. https://portal.azure.com – NOT the Azure DevOps portal) using the Azure AD Conditional Access service.
For a step-by-step breakdown of MFA configuration, check out the Azure Conditional Access: Require MFA for all users Microsoft documentation.
💡Pro-tip: To further enhance security, you leave “remember multi-factor authentication on trusted devices” disabled.
Of course, in some instances (e.g. applications and service accounts), implementing MFA may be impractical. For those cases, location conditions and app passwords can help you strike a balance between security and usability.
Limiting access to Azure DevOps projects and repos reduces the risk of leaking sensitive information and deploying insecure code to production.
Individual projects and repos are where the bulk of the work gets done in the Azure DevOps platform. Code tampering and leaking of sensitive information are both real threats you’ll need to account for. We’ve already seen how security groups and access levels can help limit access, additional steps we recommend to further secure your repos and projects we recommend:
Let’s take a closer look at each of those items.
Repo-level policies allow you to fine tune permissions on repositories within a project and limit the threat of code tampering.
Setting explicit policies at the repo-level allows you to add an additional layer of security to your Azure DevOps infrastructure. For example, you may want to restrict commits to a given repo based on email address. You can do just that with a repository policy.
Policies for all repositories in a project can be configured within the Azure DevOps portal at Project Settings → Repositories → Policies
You can configure policies for specific repos by navigating to Project Settings → Repositories → <your repo> → Policies
Set branch policies
Branch policies help ensure only valid and reviewed code is committed.
In addition to repo-level policies, you can configure specific branch-level policies to ensure only valid commits make it into your pipeline. In addition to improving security, branch policies can have a positive impact on quality by making code review a requirement. You can configure branch policies at Project Settings → Repositories → <your repo> → Policies → Branch Policies → <your branch>
Requiring at least 2 reviewers on each commit is generally good practice. Not only does it help ensure team reviews are occurring, but it also limits the risk if a single developer’s account is compromised.
You can also use branch policies to require specific users to review commits to a given branch.
Controlling who can and cannot view source code is an important aspect of many commercial software projects.
For many teams, limiting project visibility is an important aspect of keeping confidential information secure. To help ensure your confidential information stays private, you can restrict project visibility and disable forking for your Azure DevOps projects.
Restricting project visibility can help reduce leaking sensitive or proprietary information.
By default, project visibility in Azure DevOps is set to private meaning anonymous access is not allowed. However, the setting can be adjusted.
You can prevent users from making any project in your organization public with a setting at the organization level. You can change that setting at Organization Settings → Policies → Security Policies → Allow public projects.
Disabling forking limits project sprawl and the risk of leaking information.
Forking poses two separate but important threat vectors to consider:
A simple solution to both of these problems is to disable forking. You can disable forking within the Azure DevOps portal by navigating to Project Settings → Repositories → <your repo> → Repository Settings
Logging and auditing allow you to detect and react to suspicious logins and activity.
Monitoring what actually occurs in your Azure DevOps environment is a critical part of maintaining security. After all, there’s no such thing as a flawless set of security policies and breaches occurring or even malicious users compromising your project are real threats. Azure DevOps audit logs allow you to review the last 90 days of activity at a granular level. Additionally, audit streaming — a relatively new feature still in public preview — allows you to send audit logs to Security Information and Event Management (SIEM) tools to help automate your detection and reaction to threats.
Audit logs allow you to manually review activity over the last 90 days.
You can view, filter, and download (as a .csv or .json file) your Azure DevOps audit logs at the organization level (e.g. from https://dev.azure.com/<yourorg>) at Organization Settings → General → Auditing.
If you see suspicious behavior, like a user making apparently malicious changes, you can take action. For example, by disabling that account.
Audit streaming enables Azure DevOps users to export logs to a SIEM to scale and improve threat detection capabilities.
Of course, manual review of logs isn’t scalable, robust, or consistent with the level of automation DevOps platforms normally offer. Fortunately, Azure DevOps users can now export audit logs to a SIEM for analysis. Today, supported export targets include Splunk, Azure Monitor Log, and Azure Event Grid. Audit streaming can be configured at the organization level (e.g. from https://dev.azure.com/<yourorg>) at Organization Settings → General → Auditing → Streams → New stream.
As we’ve seen, a big part of getting Azure DevOps Security right entails knowing how to implement the principle of least privilege in the cloud along with some defense-in-depth for good measure. Microsoft takes care of security of the cloud for you, but it’s up to you to get things like access controls, policy creation, and threat detection right.
The practices we’ve covered here will help you mitigate risk in your Azure DevOps Services instance and our complete security checklist allows you to drill down even further.