AuthorizationFailed 와 403 권한 오류 (증상, 원인, 해결)
Azure 에서 만나는 권한 오류(AuthorizationFailed, LinkedAuthorizationFailed, RequestDisallowedByPolicy, ScopeLocked, 데이터 평면 403)를 증상, 원인, 해결 순서로 정리합니다. 에러 메시지에서 누가, 무엇을, 어디서를 읽는 법과 역할 반영 지연, 잘못된 ID, 데이터 평면 역할 누락을 다룹니다.
증상
배포 파이프라인이나 CLI 에서 이런 메시지가 나옵니다.
(AuthorizationFailed) The client 'a1b2c3d4-...' with object id 'a1b2c3d4-...' does not have authorization
to perform action 'Microsoft.Network/virtualNetworks/subnets/join/action' over scope
'/subscriptions/<sub>/resourceGroups/rg-conn-prod/providers/Microsoft.Network/virtualNetworks/vnet-hub/subnets/snet-pe'
or the scope is invalid. If access was recently granted, please refresh your credentials.비슷하지만 원인이 다른 오류들이 있습니다. 먼저 오류 코드로 갈래를 나눕니다.
| 오류 코드 | 누가 막았나 | 이 문서의 해결 |
|---|---|---|
AuthorizationFailed | Azure RBAC (제어 평면) | 원인 1~4 |
LinkedAuthorizationFailed | 연결된 다른 리소스에 대한 권한 부족 | 원인 3 |
RequestDisallowedByPolicy | Azure Policy | 원인 5 |
ScopeLocked | 리소스 잠금 | 원인 6 |
403 AuthorizationPermissionMismatch, ForbiddenByRbac | 데이터 평면 권한 | 원인 7 |
403 AuthorizationFailure (네트워크) | 방화벽, 공용 액세스 차단 | Private Endpoint DNS |
메시지에서 세 가지 읽기
AuthorizationFailed 메시지에는 답이 거의 다 들어 있습니다.
- 누가:
client와object id. 사람인지, 서비스 주체인지, 관리 ID 인지 확인합니다. - 무엇을:
action. 필요한 정확한 권한 이름입니다. - 어디서:
scope. 그 권한이 필요한 리소스입니다. 내가 배포하는 리소스 그룹이 아닐 수 있습니다.
# object id 가 누구인지
az ad sp show --id a1b2c3d4-... --query "{name:displayName, type:servicePrincipalType}" 2>/dev/null \
|| az ad user show --id a1b2c3d4-... --query userPrincipalName
# 그 주체가 그 범위에 가진 역할 (상속 포함)
az role assignment list --assignee a1b2c3d4-... --all --include-inherited -o table
원인과 해결
원인 1. 역할이 정말 없음
역할이 없거나, 범위가 좁거나(다른 리소스 그룹에만 있음), 역할에 그 action 이 없습니다.
해결: 메시지의 action 을 포함하는 가장 좁은 기본 제공 역할을 그 scope 에 줍니다. 역할에 어떤 action 이 있는지는 아래처럼 찾습니다.
az role definition list --query "[?contains(to_string(permissions[0].actions), 'Microsoft.Network/virtualNetworks/subnets/join/action')].roleName" -o tsv
원인 2. 역할을 줬는데 아직 안 됨
역할 할당은 보통 몇 분 안에 반영되지만, 이미 받아 둔 토큰에는 반영되지 않습니다. 메시지 끝의 "If access was recently granted, please refresh your credentials" 가 이 경우입니다.
해결: CLI 는 az account clear 후 다시 az login, 앱은 재시작해 새 토큰을 받습니다. 그룹 멤버십으로 받은 권한은 토큰 갱신까지 더 걸릴 수 있습니다. PIM 적격 역할이면 활성화했는지 확인합니다.
원인 3. 다른 리소스에 대한 권한 (Linked)
VM 이나 Private Endpoint 를 내 리소스 그룹에 만들면서 다른 리소스 그룹의 서브넷을 쓰면, 그 서브넷에 subnets/join/action 권한이 필요합니다. Key Vault 의 키로 디스크를 암호화하거나, 다른 구독의 공용 IP, 이미지, 사용자 할당 관리 ID 를 붙일 때도 같습니다. 이때 LinkedAuthorizationFailed 나 위 예시처럼 scope 가 다른 리소스를 가리킵니다.
해결: 허브 서브넷에는 Network Contributor 를 통째로 주기보다 subnets/join/action 과 read 만 담은 사용자 지정 역할을 서브넷 범위로 줍니다. 관리 ID 를 붙일 때는 Managed Identity Operator 역할이 필요합니다.
원인 4. 엉뚱한 ID 로 로그인
- CLI 가 다른 테넌트나 구독에 로그인되어 있음:
az account show로 확인. - 파이프라인의 서비스 연결이 다른 서비스 주체를 씀.
- 앱이 시스템 할당 관리 ID 가 아니라 사용자 할당 ID 로 토큰을 받는데, 권한은 다른 쪽에 줌.
DefaultAzureCredential은 사용자 할당 ID 가 여러 개면AZURE_CLIENT_ID로 지정해야 합니다. - 리소스를 다시 만들어서 시스템 할당 관리 ID 의 object id 가 바뀌었는데 예전 ID 에 준 역할이 남아 있음.
원인 5. 정책 거부 (RequestDisallowedByPolicy)
권한은 있지만 Azure Policy가 막은 것입니다. 메시지에 정책 할당 이름과 정의가 나옵니다.
az policy assignment show --name <assignment-name> --scope <scope> --query "{name:displayName, params:parameters}"해결: 템플릿을 정책에 맞게 고치는 것이 먼저입니다(허용 리전, 필수 태그, 공용 액세스 끄기). 정당한 예외면 만료일을 둔 정책 예외를 만듭니다. Owner 라도 정책은 우회하지 못합니다.
원인 6. 잠금 (ScopeLocked)
CanNotDelete 나 ReadOnly 잠금이 리소스나 상위 범위에 걸려 있습니다. ReadOnly 잠금은 스토리지 계정 키 나열처럼 POST 로 처리되는 읽기 작업도 막아서 엉뚱한 곳에서 실패합니다.
해결: az lock list --resource-group <rg> 로 확인하고, 변경 작업 동안만 잠금을 풀었다가 다시 겁니다.
원인 7. 데이터 평면 권한 (403 인데 Owner 임)
Owner, Contributor 는 제어 평면 역할이라 Blob 내용, Key Vault 비밀, Cosmos DB 문서를 Entra 인증으로 읽을 권한(dataActions)이 없습니다.
| 서비스 | 오류 예 | 필요한 역할 예 |
|---|---|---|
| Blob, ADLS Gen2 | AuthorizationPermissionMismatch | Storage Blob Data Reader, Contributor |
| Key Vault (RBAC 금고) | ForbiddenByRbac | Key Vault Secrets User, Secrets Officer |
| Cosmos DB | 403 Request blocked by Auth | Cosmos DB 기본 제공 데이터 역할 (SQL 역할 할당) |
| Azure SQL, PostgreSQL | 로그인 실패 | DB 안에서 Entra 사용자 만들기 |
Key Vault 는 2026-02-01 API 부터 새 금고의 기본이 RBAC 이므로, 예전 액세스 정책 방식 앱이 새 금고에서 갑자기 ForbiddenByRbac 를 받는 일이 늘었습니다 (보안 운영). Cosmos DB 의 데이터 역할은 Azure RBAC 역할 할당이 아니라 az cosmosdb sql role assignment create 로 따로 줍니다.
한도: RoleAssignmentLimitExceeded
역할을 주려는데 이 오류가 나면 구독의 역할 할당이 5,000 개 한도에 닿은 것입니다. 개인 할당을 그룹으로 바꾸고, 하위 범위의 중복 할당을 지우고, PIM 적격 할당으로 바꿉니다(적격 할당은 한도에 세지 않음).
예방
- 배포 ID 에 필요한 권한 목록(특히 다른 리소스 그룹의 서브넷, DNS 영역, Key Vault)을 설계 문서에 적습니다.
- 앱에는 데이터 평면 역할을 리소스 범위로 주는 것을 템플릿에 포함합니다.
- 활동 로그에서
Microsoft.Authorization/roleAssignments/write경고를 걸어 권한 변화를 추적합니다.