Security best practices

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

When you're working with information and data, particularly in a cloud-based solution like Azure DevOps Services, prioritizing security should always be your primary concern. While Microsoft maintains the security of the underlying cloud infrastructure, it's your responsibility to configure security in Azure DevOps.

Although it's not mandatory, incorporating best practices while using Azure DevOps can enhance your experience and make it more secure. We've compiled the following best practices that aim to keep your Azure DevOps environment secure:

Secure Azure DevOps environment

Removing users

  • If your organization uses MSA accounts, then remove inactive users directly from the organization, as you have no other way to prevent access. When you do so, you can't create a query for work items assigned to the removed user account. For more information, see Delete users from Azure DevOps.
  • If your organization is connected to Microsoft Entra ID, then you can disable or delete the Microsoft Entra user account and leave your Azure DevOps user account active. In this way, you can continue to query work item history using your Azure DevOps user ID.
  • Revoke user PATs.
  • Revoke any special permissions that may have been granted to individual user accounts.
  • Reassign work from users you’re removing to current team members.

Use Microsoft Entra ID

Integrate Azure DevOps with Microsoft Entra ID to have a single plane for identity. Consistency and a single authoritative source increases clarity and reduces security risks from human errors and configuration complexity. The key to end governance is to have multiple role assignments (with different role definitions and different resource scopes to the same Microsoft Entra groups). Without Microsoft Entra ID, you're solely responsible for controlling organization access.

Using Microsoft Entra ID also allows you to access other security features, like multi-factor authentication or other conditional access policies.

For more information, see the following articles:

Review auditing events

Once you have a Microsoft Entra backed organization, you can turn on Auditing in your Security policies. Periodically review audit events to monitor and react to unexpected usage patterns by administrators and other users.

Secure your network

A few ways to do so might include:

  • Set up an allowlist to restrict specific IPs.
  • Always use encryption.
  • Validate certificates.
  • Implement Web application firewalls (WAFs), so they can filter, monitor, and block any malicious web-based traffic to and from Azure DevOps.
  • For more information, see this guidance on application management best practices

Scoped permissions

The system manages permissions at different levels - individual, collection, project, and object - and assigns them to one or more built-in groups by default.

Project-level permissions

  • Limit access to projects and repos to reduce the risk of leaking sensitive information and deploying insecure code to production.
  • Use either the built-in security groups or custom security groups to manage permissions. For more information, see Grant or restrict permissions to select tasks.
  • Disable "Allow public projects" in your organization's policy settings to prevent every organization user from creating a public project. Azure DevOps Services allows you to change the visibility of your projects from public to private, and vice-versa. If users haven't signed into your organization, they have read-only access to your public projects. If users have signed in, they can be granted access to private projects and make any permitted changes to them.
  • Don’t allow users to create new projects.

External guest access

  • Block external guest access entirely by disabling the "Allow invitations to be sent to any domain" policy. It's a good idea to do so if there's no business need for it.
  • Use a different email or user principal name (UPN) for your personal and business accounts, even though it's allowed. This action eliminates the challenge of disambiguating between your business and personal accounts when the email/UPN is the same.
  • Put all the external guest users in a single Microsoft Entra group and manage the permissions of that group appropriately. You can easily manage and audit this way.
    • Remove direct assignments so the group rules apply to those users. For more information, see Add a group rule to assign access levels.
    • Reevaluate rules regularly on the Group rules tab of the Users page. Clarify whether any group membership changes in Microsoft Entra ID might affect your organization. Microsoft Entra ID can take up to 24 hours to update dynamic group membership. Every 24 hours and anytime a group rule changes, rules get automatically reevaluated in the system.
  • For more information, see B2B guests in the Microsoft Entra ID.

Manage security groups

Security and user groups

See the following recommendations for assigning permissions to security groups and users groups.

Do Don't
Use Microsoft Entra ID, Active Directory, or Windows security groups when you're managing lots of users. Don’t change the default permissions for the Project Valid Users group. This group can access and view project information.
When you're adding teams, consider what permissions you want to assign to team members who need to create and modify area paths, iteration paths, and queries. Don't add users to multiple security groups that contain different permission levels. In certain cases, a Deny permission level may override an Allow permission level.
When you're adding many teams, consider creating a Team Administrators custom group where you allocate a subset of the permissions available to Project Administrators. Don't change the default assignments made to the Project Valid Users groups. If you remove or set View instance-level information to Deny for one of the Project Valid Users groups, no users in the group can access whatever project, collection, or deployment you set the permission on.
Consider granting the work item query folders Contribute permission to users or groups who require the ability to create and share work item queries for the project. Don't assign permissions that are noted as Assign only to service accounts to user accounts.
Keep groups as small as possible. Access should be restricted, and the groups should be frequently audited.
Take advantage of built-in roles and default to Contributor for developers. Admins get assigned to the Project Administrator security group for elevated permissions, allowing them to configure security permissions.

For more information, see Valid user groups.

Just-in-time access for admin groups

You can change the configuration of your organization or project if you have Project Collection Administrator and Project Administrator access. To protect access to these built-in administrator groups, require just-in-time access using a Microsoft Entra Privileged Identity Management (PIM) group.

Configure access

  1. Create a role-assignable group in Microsoft Entra ID.
  2. Add your Microsoft Entra group to the Azure DevOps group.

Note

Make sure any user with elevated access using a PIM group also has standard access to the organization, so they can view the page to refresh their permissions.

Use access

  1. Activate your access.
  2. Refresh your permissions in Azure DevOps.
  3. Take the action requiring administrator access.

Note

Users have elevated access in Azure DevOps for up to 1 hour after their PIM group access gets deactivated.

Scope service accounts

  • Ensure service accounts have zero interactive sign-in rights.
  • Restrict service account privileges to the bare minimum necessary.
  • Use a different identity for the report reader account, if you use domain accounts for your service accounts. For more information, see Service accounts and dependencies.
  • Use local accounts for user accounts, if you're installing a component in a workgroup. For more information, see Service account requirements.
  • Use service connections when possible. Service connections provide a secure mechanism to connect to assorted services without the need to pass in secret variables to the build directly. - Restrict these connections to the specific place they should be used and nothing more.
  • Monitor service account activity and create audit streaming. Auditing allows you to detect and react to suspicious sign-ins and activity.
  • For more information, see Common service connection types.

Scope service connections

  • Scope Azure Resource Manager, and other service connections, only to the resources and groups to which they need access. Service connections shouldn't have broad contributor rights on the entire Azure subscription.
  • Use workload identity federation for your Azure Resource Manager (ARM) service connections. Workload identity federation allows you to create secret-free service connections in Azure Pipelines to Azure.
  • Don’t give users generic or broad contributor rights on the Azure subscription.
  • Don’t use Azure Classic service connections, as there’s no way to scope the permissions.
  • Make sure the resource group only contains Virtual Machines (VMs) or resources that the build needs access to.
  • Use a purpose-specific team service account to authenticate a service connection.
  • For more information, see Common service connection types.

Choose the right authentication method

Select your authentication methods from the following sources:

Consider service principals

Explore alternatives like service principals and managed identities that enable you to use Microsoft Entra tokens to access Azure DevOps resources. Such tokens carry less risk when leaked compared to PATs and contain benefits like easy credential management.

Use PATs sparingly

If possible, we recommended to always use identity services for authentication instead of cryptographic keys since managing keys securely with application code is challenging and can lead to mistakes like accidentally publishing sensitive access keys to public code repositories like GitHub. However, if you must use personal access tokens (PATs), consider the following guidelines:

  • PATs should always be scoped to specific roles.

  • PATs shouldn't provide global access to multiple organizations.

  • PATs shouldn't grant write or manage permissions on builds or releases.

  • PATs should have an expiration date and be kept secret since they're as critical as passwords.

  • PATs should never be hardcoded in the application code, even if it's tempting to do so to simplify the code.

  • Administrators should regularly audit all PATs using the REST APIs and revoke any that don't meet the above criteria.

  • Keep your PATs a secret. Your tokens are as critical as passwords.

  • Store your tokens in a safe place.

  • Don’t hard code tokens in applications. It can be tempting to simplify code to obtain a token for a long period of time and store it in your application, but don’t do that.

  • Give tokens an expiration date.

  • For more information, check out the following articles:


Secure Azure Artifacts

Secure Azure Boards

Secure Azure Pipelines

Policies

  • Require at least one reviewer outside of the original requester. The approver shares coownership of the changes and should be held equally accountable for any potential impact.
  • Require CI build to pass. This requirement is useful for establishing baseline code quality, through code linting, unit tests, and security checks, like virus and credential scans.
  • Ensure that the original pull requester can’t approve the change.
  • Disallow completion of a PR (Pull Request), even if some reviewers vote to wait or reject.
  • Reset code reviewer votes when recent changes get pushed.
  • Lock down release pipelines by running them only on specific production branches.
  • Enable “Enforce settable at queue time for variables” in your organization’s pipeline settings.
  • Don’t allow “Let users override this value when running this pipeline,” for variables set in the editor.

Agents

  • Grant permissions to the smallest possible number of accounts.
  • Have the most restrictive firewall that leaves your agents usable.
  • Update pools regularly to ensure the build fleet isn’t running vulnerable code that a malicious actor can exploit.
  • Use a separate agent pool for build artifacts that get shipped or deployed to production.
  • Segment “sensitive” pool from nonsensitive pools, and only allow the use of credentials in build definitions that are locked to that pool.

Definitions

  • Manage pipeline definitions with YAML (Yet Another Markup Language). YAML is the preferred method for managing pipeline definitions, as it provides traceability for changes and can follow approval guidelines.
  • Secure the pipeline definition Edit access to the minimum number of accounts.

Input

  • Include sanity checks for variables in build scripts. A sanity check can mitigate a command injection attack through the settable variables.
  • Set as few build variables as possible to “Settable at release time.”

Tasks

  • Avoid remotely fetched resources, but, if necessary, use versioning and hash checking.
  • Don’t log secrets.
  • Don’t store secrets in pipeline variables, use Azure Key Vault. Regularly scan your build pipelines to ensure secrets aren’t being stored in build pipeline variables.
  • Don’t let users run builds against arbitrary branches or tags on security-critical pipelines.
  • Disable inheritance on the pipeline, as inherited permissions are broad and don’t accurately reflect your needs for permissions.
  • Limit job authorization scopes in all cases.

Repositories and branches

  • Set the “Require a minimum number of reviewers,” policy to on, so that every pull request gets reviewed by at least two approvers.
  • Configure security policies specific to each repository or branch, instead of project wide. Security policies reduce risk, enforce change management standards, and improve your team’s quality of code.
  • Store production secrets in a separate Key Vault and ensure that access is only granted on a need-to-know basis to keep nonproduction builds separate.
  • Don’t mix test environments with production, including use of credentials.
  • Disable forking. The more forks there are, the harder it's to keep track of each fork’s security. Also, a user can easily fork a copy of a repository to their own private account.
  • Don't provide secrets to fork builds.
  • Consider manually triggering fork builds.
  • Use Microsoft-hosted agents for fork builds.
  • For Git, check your production build definitions in the project’s git repository, so they can be scanned for credentials.
  • Configure a branch control check so that only pipelines running in the context of the production branch may use the prod-connection.
  • For more information, see Other security considerations.

Secure Azure Repos

Secure Azure Test Plans

Secure GitHub Integrations

  • Disable Personal Access Token (PAT)-based authentication, so the OAuth flow gets used with the GitHub service connection.
  • Never authenticate GitHub service connections as an identity that's an administrator or owner of any repositories.
  • Never use a full-scope GitHub PAT (Personal Access Token) to authenticate GitHub service connections.
  • Don't use a personal GitHub account as a service connection with Azure DevOps.