Azure DevOps + Entra tenant move: interní migration playbook

[!IMPORTANT] Původní zadání uživatele: Move Azure DevOps connected to Entra to another tenant and Entra. Zaměřit se na remapping users, groups, approvals, permissions a repair scripts/runbook. Oddělit supportované vs. nesupportované kroky, přidat migration playbook, repair checklist a validační smoke testy, zachovat oficiální zdroje a community zdroje jasně označit jako neoficiální.

Datum publikace: 2026-06-23
Viditelnost: interní Hermes WWW
Výstup navazuje na researcher/analyst tasky t_febef00e, t_68dfda16, t_f8066492 a syntézu t_551d512d.

1. Executive summary

Doporučený default pro scénář „stávající Azure DevOps organizace je připojená na Microsoft Entra tenant a má se přesunout na jiný Entra tenant“ je oficiální Azure DevOps Switch directory pro existující organizaci, ne zakládání nové Azure DevOps organizace.

Důvod: Microsoft dokumentuje změnu Azure DevOps organization connection to a different Microsoft Entra ID a uvádí, že projektové zdroje zůstávají zachované. To typicky znamená zachování organizace, projektů, work items, repos, pipelines, artifacts a historie. Neznamená to ale, že se automaticky a bezpečně přemapují všechny identitní a tenant-specific vazby.

Největší riziko je identitní vrstva:

Produkční move nedělat bez sandboxu, read-only inventory snapshotu, identity mapy, group mapy, Microsoft Support plánu pro větší/komplexní organizace a předem připraveného P0 repair runbooku.

2. Co přesně se migruje

V praxi se často míchají tři různé věci. Je nutné je oddělit.

A. Azure DevOps organization Entra directory switch

Cíl: existující Azure DevOps organizace se přepojí ze source Entra tenant na target Entra tenant.

Typicky zachovává:

Vyžaduje repair:

B. Azure subscription tenant transfer

Cíl: Azure subscription/resource ownership se přesune do jiného Entra tenant.

Toto není totéž jako Azure DevOps directory switch. Dopady:

Pokud se dělá zároveň s Azure DevOps switchem, je to mnohem rizikovější cutover a musí mít samostatný rollback a smoke test plán.

C. Nová paralelní Azure DevOps organizace

Cíl: založit novou Azure DevOps org v target tenantovi a přesouvat obsah.

Použít jen pokud se zároveň mění operating model nebo governance a akceptuje se nižší věrnost migrace. Microsoft Azure DevOps Data Migration Tool není určený pro Azure DevOps Services org-to-org project migration. Git mirror/import zachová repo historii, ale není full-fidelity migrace Boards, Pipelines, Policies, Artifacts, permissions ani audit historie.

3. Podporované vs. workaround vs. nepodporované

Oficiálně podporované / doložené Microsoft dokumentací

Praktické repair/workaround kroky

Tyto kroky jsou v enterprise realitě často nutné, ale nejsou „jedno tlačítko“:

Nepodporované / nedoporučené / nutné ověřit v sandboxu

4. Identitní model a remapping pravidla

User mapping

Cílový výstup před cutoverem: identity-map.csv nebo identity-map.json.

Doporučené sloupce:

Pole Popis
oldAdoDescriptor Azure DevOps Graph descriptor ve source stavu
oldStorageKey / VSID stabilnější ADO identifikátor tam, kde je dostupný
oldOrigin / oldOriginId původ identity a source Entra objectId/MSA vazba
oldPrincipalName původní UPN/login
oldMailAddress e-mail jako kandidátní signál
oldTenantId source tenant
newEntraObjectId target user objectId
newPrincipalName target UPN/login
newMailAddress target mail/proxy
mappingStatus confirmed / conflict / missing / exclude
ownerApproval kdo mapping schválil

Pravidla:

  1. Nemapovat podle displayName.
  2. UPN/mail použít jen jako kandidátní signál.
  3. Preferovat kombinaci: old Entra objectId, old UPN/mail/proxyAddresses, ADO descriptor/storageKey/originId, new Entra objectId, new UPN/mail/proxyAddresses, userType.
  4. Konflikty řešit ručně: duplicate mail, změněná doména, guest/member mismatch, MSA vs work/school account, chybějící target account.
  5. Kritické role potvrdit ručně: PCA/admin, release approvers, endpoint admins, build/release admins, feed owners, environment admins.

Group mapping

Cílový výstup: group-map.csv nebo group-map.json.

Doporučené sloupce:

Pole Popis
oldEntraGroupObjectId source group objectId
oldDisplayName původní group name
oldMembersHash hash membership snapshotu
targetEntraGroupObjectId target group objectId
targetDisplayName cílová group name
targetOwners owners v target tenantovi
intendedAdoGroup Azure DevOps group, kam se má přidat
intendedAccessLevel Basic/Stakeholder/VS/subscription rule
permissionsScope org/project/repo/environment/feed
repairStatus planned/applied/validated

Důležité: Entra groups nepovažovat za přenositelný objekt. Počítat s jejich rekonstrukcí a explicitním znovunapojením do Azure DevOps.

Service principal / managed identity mapping

Cílový výstup: service-principal-map.csv nebo service-principal-map.json.

Doporučené sloupce:

Pole Popis
oldClientId / appId původní application clientId
oldServicePrincipalObjectId source SP objectId
oldTenantId source tenant
targetClientId / appId target app/SP/MI
targetServicePrincipalObjectId target SP objectId
authMode secret / cert / workload identity federation / managed identity
adoServiceConnectionId Azure DevOps endpoint id
azureScope subscription/RG/resource scope
rbacStatus missing/applied/validated
smokeTest passed/failed/not-run

5. Phased migration playbook

Fáze 0 — Governance a rozhodovací brána

Výstupy:

No-go:

Fáze 1 — Read-only inventory snapshot

Vytvořit neměnný baseline před změnou.

Inventarizovat:

Exit criteria:

Fáze 2 — Pre-migration cleanup

Cíl: snížit počet problémů přenášených do cutoveru.

Kroky:

Exit criteria:

Fáze 3 — Identity mapping approval

Cíl: schválit identity-map, group-map, service-principal-map.

No-go:

Fáze 4 — Cutover

Doporučený průběh:

  1. Aktivovat freeze pro P0 pipelines/deployments.
  2. Ověřit operátorský přístup: ADO PCA + target tenant membership.
  3. Provést Microsoft documented Switch directory.
  4. Odhlásit/přihlásit operátorské účty v čisté/private session.
  5. Použít Resolve disconnected users / Support-assisted mapping.
  6. Ověřit, že PCA/admin přístup stále funguje.
  7. Znovu vytvořit/přidat target Entra groups do ADO podle group-map.
  8. Regrantovat ADO group memberships, access levels, group rules/licensing.
  9. Přepnout/ověřit billing subscription, pokud je ve scope.

Poznámka: cutover není konec migrace. Je to začátek repair fáze.

Fáze 5 — P0/P1/P2 repair

P0 jako první:

P1:

P2:

Fáze 6 — Stabilizace a acceptance

Stabilizace končí až když:

6. Repair runbook a skriptovací kostra

6.1 Inventory export — Azure DevOps Graph/IMS

Oficiální API endpointy:

Kostra Bash/curl:

#!/usr/bin/env bash
set -euo pipefail

org="${ADO_ORG:?set ADO_ORG}"
out="snapshot-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$out"

# Předpoklad: az devops/az account login nebo PAT v env podle interního standardu.
# Token handling nenechávat v historii shellu.
# Ukázka záměrně nepředepisuje konkrétní secret management.
auth_header="<AUTH_HEADER>"

curl -fsS \
  -H "$auth_header" \
  "https://vssps.dev.azure.com/${org}/_apis/graph/users?api-version=7.1-preview.1" \
  > "$out/graph-users.json"

curl -fsS \
  -H "$auth_header" \
  "https://vssps.dev.azure.com/${org}/_apis/graph/groups?api-version=7.1-preview.1" \
  > "$out/graph-groups.json"

curl -fsS \
  -H "$auth_header" \
  "https://dev.azure.com/${org}/_apis/identities?api-version=7.1-preview.1" \
  > "$out/ims-identities.json"

6.2 Service connections inventory

#!/usr/bin/env bash
set -euo pipefail

org="${ADO_ORG:?}"
project="${ADO_PROJECT:?}"
out="${OUT_DIR:-snapshot}"
mkdir -p "$out/service-endpoints"

auth_header="<AUTH_HEADER>"

curl -fsS \
  -H "$auth_header" \
  "https://dev.azure.com/${org}/${project}/_apis/serviceendpoint/endpoints?api-version=7.1" \
  > "$out/service-endpoints/${project}.json"

jq -r '.value[] | [.id,.name,.type,.authorization.scheme, (.data.subscriptionId // ""), (.authorization.parameters.tenantid // .data.tenantid // "")] | @csv' \
  "$out/service-endpoints/${project}.json" \
  > "$out/service-endpoints/${project}.csv"

Co hledat:

6.3 Pipeline/YAML scan

#!/usr/bin/env bash
set -euo pipefail

repo_root="${REPO_ROOT:?}"
old_tenant="${OLD_TENANT_ID:?}"
old_subscription="${OLD_SUBSCRIPTION_ID:-}"
old_client="${OLD_CLIENT_ID:-}"

rg -n --hidden --glob '!**/.git/**' \
  -e "$old_tenant" \
  ${old_subscription:+-e "$old_subscription"} \
  ${old_client:+-e "$old_client"} \
  -e 'login.microsoftonline.com/' \
  -e 'serviceConnection|azureSubscription|connectedServiceName|environment:' \
  "$repo_root" \
  > tenant-reference-scan.txt || true

Klasifikace hitů:

6.4 ACL repair princip

Bezpečný princip:

  1. Exportovat security namespaces a ACLs před switchem.
  2. Přeložit old descriptor → new descriptor přes schválenou identity-map/group-map.
  3. Nikdy automaticky neměnit explicit Deny bez review.
  4. Reaplikovat pouze scope/tokeny, které jsou v approved repair listu.
  5. Po každé dávce spustit access smoke test.

Pseudo workflow:

for each acl in exported_acls:
  for each ace in acl.acesDictionary:
    old_descriptor = ace.descriptor
    new_descriptor = identity_map.get(old_descriptor) or group_map.get(old_descriptor)
    if not new_descriptor:
      record orphan
      continue
    if ace.deny != 0:
      require manual approval
    emit patch for token/securityNamespaceId/new_descriptor/allow/deny

6.5 Approvals/checks/policies repair

Opravit a validovat:

Smoke test:

7. Repair checklist

P0 — obnovit provoz a bezpečný deployment

P1 — governance a runtime kontroly

P2 — cleanup a dlouhodobá stabilizace

8. Validační smoke testy

Identity/access

Repos/PR

Pipelines/service connections

Environments/checks/agents

Boards/artifacts/integrace

9. Produkční go/no-go

No-go, dokud platí něco z toho:

10. Rollback posture

Rollback neplánovat jako „one-click undo“. Bezpečný rollback posture znamená:

Rollback blockery:

11. Oficiální zdroje

Microsoft Learn / oficiální dokumentace:

12. Neoficiální/community zdroje

V tomto finálním interním markdownu nejsou použité žádné konkrétní community návody jako autoritativní zdroj. Pokud se v implementaci použijí blogy, GitHub gisty nebo StackOverflow odpovědi pro skripty, musí být označené jako neoficiální/community a ověřené v sandboxu proti oficiálním API a dokumentaci.

13. Doporučený minimální balíček artefaktů před produkcí