Azure DevOps: Setup and Guiding Principles¶
Many workload teams build and deploy with Azure DevOps. The platform can create a repository and a service connection for your spoke (What you get), but the Azure DevOps organisation and its projects are your organisation's. This page collects recommended settings (guardrails) and a sensible project structure.
Recommendations, not platform features
The MCP product does not configure your Azure DevOps organisation. Treat the lists below as a baseline that your security officer and DevOps administrators adapt. Where your organisation has its own rules, those win.
Organisation, project, team¶
| Level | What it is | Advice |
|---|---|---|
| Organisation | Top-level container, linked to Microsoft Entra ID and billing | Few. Usually one per company. |
| Project | Repositories, pipelines, boards, test plans, with its own permissions | One project per product or application area. |
| Team | A group within a project with its own board and backlog | One per DevOps team. |
One project or several?
| Approach | Good for |
|---|---|
| Single project | Small and medium organisations, simple permissions, easy navigation across components of one product |
| Multiple projects | Large organisations with independent teams. Better isolation, and different security, build and release requirements per project |
Whichever you pick, keep it consistent. Moving repositories and pipelines between projects later is work.
Organisation level¶
| Guardrail | Why |
|---|---|
| A non-personal account owns the organisation, and access to it is only through escalation | People leave; a personal owner is a single point of failure |
| Access only with Entra ID identities, through groups | Joiners and leavers follow your identity process |
| Built-in groups stay empty, except their defaults. The non-personal account is in Project Collection Administrators. | No permissions through forgotten memberships |
| Privileged roles (for example Project Collection Administrators) only through PIM | Just-in-time access with an audit trail. See Access, groups and PIM. |
| Disable alternate authentication credentials | Smaller attack surface |
| Disable third-party application access through OAuth | Control over integrations |
| Allow SSH authentication | A secure alternative for Git |
| Enable audit log events | Audit trail and incident investigation |
| Disable public projects | No accidental exposure |
| Enable additional protections for public package registries | Protects against compromised or malicious packages |
| Enable IP conditional access validation on non-interactive flows | Also covers service connections |
| Disable external guest access | Collaboration stays internal |
| Do not let team and project administrators invite users | Central onboarding |
Pipelines¶
| Guardrail | Why |
|---|---|
| Nobody deletes builds, releases, projects or repositories | A complete, auditable history. Use retention policies instead. |
| Approval on the production stage is mandatory. Run release pipelines only from specific production branches. | Controlled, auditable production deployments |
| Define pipelines in YAML. Turn off classic build and classic release pipelines. | Changes are reviewed and traceable in version control |
| Enable Enforce settable at queue time for variables, limit the variables that can be set at queue time, and do not allow overriding variables set in the editor | Reproducible runs and fewer injection options |
| Do not let users run security-critical pipelines against arbitrary branches or tags | Only reviewed code reaches production |
| Disable inheritance on the pipeline and limit job authorisation scope in all cases | Least privilege |
| Avoid remotely fetched resources. If you need one, pin the version and check a hash. | Supply chain safety |
| Do not log secrets. Do not keep secrets in pipeline variables: use Azure Key Vault. When you cannot, use secret variables, limit who can read them, and do not store structured data (for example JSON) as a secret. | Secrets stay out of logs and pipeline definitions |
| Audit and rotate secrets | Limits the time a leaked secret is useful |
| Use service connections instead of passing credentials, scope them to the resources and resource groups they need, and do not use Azure Classic service connections | Least privilege, central management |
| Use PATs sparingly and rotate them. Consider service principals (or workload identity federation) instead. | PATs are powerful and personal |
| Do not build pull requests from GitHub forks. When you do, do not give them secrets and trigger them manually. | Untrusted code must not run with your credentials |
| Keep pipeline dependencies up to date with a tool such as Renovate | Fewer known vulnerabilities |
The service connection that the platform creates for your spoke can use federated credentials instead of a secret, see How to change and How to use.
Repositories and branches¶
| Guardrail | Why |
|---|---|
| Configure branch policies on the main branch and do not allow bypassing them | The rules apply to everyone |
| Require a minimum number of reviewers (two is a common choice) and at least one approval on the last iteration | Independent review of what is merged |
| The person who pushed last cannot approve their own change | Four-eyes principle |
| Link a work item to every pull request | Traceability |
| Resolve all comments before completing a pull request | Feedback is not lost |
| Require a successful build on the pull request | Catch errors before merging |
| Store production secrets in a separate Key Vault, with access on a need-to-know basis | Separation of production and non-production |
| Do not mix test environments and production, including their credentials | Prevents accidents and data leaks |
| Disable forking | Control over code and secrets |
Agents¶
| Guardrail | Why |
|---|---|
| Give permissions on agent pools to as few accounts as possible | Smaller attack surface |
| Use the most restrictive firewall that still leaves the agents usable | Limits what a compromised build can reach |
| Update the pools regularly so the build fleet does not run vulnerable software | See Build agents |
| Use a separate pool for builds that ship or deploy to production | Separation |
| Separate sensitive pools from the others, and only use credentials in pipelines that are locked to specific pools | Credentials do not spill to untrusted jobs |
Open the platform's project to workload teams (optional)¶
Some platform teams run their own Azure DevOps project, with a wiki, a board and repositories (for example the firewall rule definitions). Giving workload teams limited access there speeds up work:
| What | Access | Why |
|---|---|---|
| Wiki with platform documentation | Read, for every onboarded team | Teams find the concepts and how-tos themselves |
| Board | Read | Teams can follow their own requests when tickets are synchronised to the board |
| Repository with firewall rules | Read | Teams can see which rules apply to them and whether the firewall blocks their traffic |
| Pull requests on that repository | Per team, after agreement | A pull request is easier to validate than a written request. The platform team still approves and deploys, and a ticket is still required. |
Give access through one reader group in Microsoft Entra ID, to which you add the groups of each onboarded team, and not to people one by one. Keep the other repositories closed. Opening the configuration repository of the platform is a decision for the platform team: read Operating models and Firewall rules first.