레거시 권한 모듈 폐기와 API 엔드포인트 권한 참조
Apache Airflow Official Documentation (in-repo snapshot) — Apache Software Foundation security/deprecated_permissions.rst (전체), security/api_permissions_ref.rst (자동 생성 레퍼런스, 요약)
이 모듈을 다 읽으면
- airflow.security.permissions 모듈이 왜 폐기되었고 Airflow 4에서 제거되는지 설명할 수 있다
- DAG.access_control이 FAB 이외의 auth manager에서 어떻게 조용히 무력화되는지 판단할 수 있다
- API 엔드포인트 권한 참조표의 Resource/Method 규칙을 읽고 특정 엔드포인트에 필요한 권한을 판단할 수 있다
Airflow 3에서 Flask AppBuilder(FAB)가 core 의존성에서 빠지면서, 과거 권한 모델의 핵심이었던 airflow.security.permissions는 하위 호환용으로만 남아 Airflow 4에서 제거될 예정이다. 이 전환은 DAG.access_control처럼 FAB에 강하게 결합된 기능이 다른 auth manager에서 조용히 무력화되는 위험을 동반한다. 한편 api_permissions_ref.rst는 새 auth manager 체계에서 각 API 엔드포인트가 요구하는 Resource/Method를 자동 생성된 표로 제공한다.
airflow.security.permissions 폐기 배경
Airflow 3 릴리스 이후 Flask AppBuilder(FAB) 프로바이더는 더 이상 core Airflow 의존성이 아니다(AIP-79: Flask AppBuilder를 core 의존성에서 제거). 다만 FAB Auth Manager 전용으로 설계된 일부 모듈은 하위 호환을 위해 core 배포판에 그대로 남아 있으며, 그중 하나가 airflow.security.permissions다. 이 모듈은 Airflow 4에서 제거될 예정이다.
이 폐기가 실제로 영향을 미치는 경우는 두 가지다: 커스텀 RBAC 역할 정의를 위해 airflow.security.permissions에 의존하는 배포, 또는 커스텀 auth manager 로직 등 이 모듈에 의존하는 다른 커스텀 로직이 있는 배포. 반대로 수정되지 않은 FAB Auth Manager를 커스텀 역할 정의 없이 그대로 쓰거나, Simple Auth Manager나 다른 프로바이더 auth manager를 이 모듈에 의존하는 커스텀 코드 없이 쓰는 경우에는 이 폐기가 영향을 주지 않는다.
핵심 포인트
- airflow.security.permissions는 FAB이 core 의존성에서 빠진 Airflow 3에서도 하위호환을 위해 남아있을 뿐이며 Airflow 4에서 제거될 예정이다
- 커스텀 RBAC 역할 정의나 커스텀 auth manager 로직이 이 모듈에 의존하는 배포만 영향을 받는다
새 권한 표준으로의 마이그레이션
폐기된 모듈의 구성요소는 다음과 같이 새 표준으로 대체된다: airflow.security.permissions.ACTION_*는 airflow.api_fastapi.auth.managers.base_auth_manager.ResourceMethod로, airflow.security.permissions.RESOURCE_*는 airflow.api_fastapi.auth.managers.models.resource_details로 대체된다. 폐기된 모듈에 의존하는 커스텀 auth manager를 유지보수한다면, ResourceMethod와 resource_details 컴포넌트를 어떻게 활용할지 참고할 예시로 SimpleAuthManager의 소스 코드를 살펴볼 것을 권장한다. 커스텀 역할 정의에 의존하는 경우에는 사용 중인 auth manager의 문서를 참고해야 한다.
한편 DAG.access_control은 이들과 성격이 다르다 — 대체할 드롭인 컴포넌트가 없다. 이는 그 자체로 하나의 인가 메커니즘이 아니라 FAB auth manager에 대한 입력값이었다: DAG 파싱 시점에 그 내용이 FAB의 권한 테이블로 확장되고, 이후 인가는 DAG 인자가 아니라 그 권한 테이블을 읽어 이루어졌다.
핵심 포인트
- ACTION_*는 ResourceMethod로, RESOURCE_*는 resource_details로 대체되며, SimpleAuthManager 소스코드가 참고 예시로 제시된다
- DAG.access_control은 그 자체로 권한 메커니즘이 아니라 FAB auth manager가 파싱 시점에 권한 테이블로 변환해 소비하는 입력값이었다
DAG.access_control은 FAB 외 auth manager에서 조용히 무력화된다
공식 문서는 이 지점을 경고로 강조한다: Airflow는 설정된 auth manager가 FAB Auth Manager일 때만 DAG.access_control을 읽는다. 다른 어떤 auth manager 하에서도 이 인자는 파싱되고 직렬화될 뿐 인가 판단에 전혀 참조되지 않으므로, 권한을 부여하지도 거부하지도 않는다. FAB에서 다른 auth manager로 옮겨가면서 Dag에 access_control을 그대로 남겨둔 배포는 그 권한 부여가 에러 없이 조용히 더 이상 적용되지 않는 상태가 된다.
이는 실무에서 놓치기 쉬운 보안 회귀(regression) 위험이다 — 마이그레이션 후에도 코드상 access_control이 그대로 남아 있으면 여전히 작동한다고 착각하기 쉽지만 실제로는 아무 효과가 없다. 마이그레이션 시에는 그 권한 부여 내용을 새 auth manager가 참조하는 정책 소스로 직접 옮겨야 한다.
핵심 포인트
- FAB 외 auth manager로 전환하면 DAG.access_control은 파싱/직렬화만 되고 실제 권한 판단에는 전혀 반영되지 않는다
- 이 전환은 에러 없이 조용히 일어나므로, FAB에서 이관할 때 access_control에 의존하던 접근 제어가 여전히 유효하다고 착각하기 쉽다 — 새 auth manager의 정책 소스로 권한을 반드시 이전해야 한다
API 엔드포인트 권한 참조표 읽는 법
api_permissions_ref.rst는 stable REST API(/api/v2)의 모든 엔드포인트에 필요한 권한을 정리한 자동 생성 문서다. scripts/ci/prek/extract_permissions.py 스크립트가 소스 코드에서 직접 추출해 생성하며, prek run generate-api-permissions-doc 훅으로 재생성되므로 수동으로 편집해서는 안 된다. 각 행은 Method(HTTP 메서드), Endpoint path, Resource, Required permission 네 열로 구성된다.
Resource 열에는 DAG, DAG.RUN, DAG.TASK_INSTANCE, DAG.XCOM, DAG.CODE, DAG.WARNING, DAG.VERSION, DAG.HITL_DETAIL, DAG.TASK_LOGS, DAG.AUDIT_LOG처럼 점(.)으로 하위 범위를 표시하는 DAG 계열 리소스와, Connection/Variable/Pool/Asset/AssetAlias/Configuration 같은 독립 리소스, 그리고 View.IMPORT_ERRORS/View.JOBS/View.PLUGINS/View.PROVIDERS처럼 특정 객체가 아니라 읽기 전용 시스템 정보 페이지에 대응하는 singleton View.* 리소스가 함께 나타난다.
Method와 Required permission은 대개 GET→GET, POST→POST, DELETE→DELETE로 일치하지만, PATCH 메서드는 대체로 PUT 권한에 매핑된다(수정 작업이므로). 여러 항목을 한 번에 다루는 벌크 엔드포인트(bulk_variables류)는 Required permission이 multi로 표기된다. /auth/login, /auth/logout, /monitor/health, /version, POST /connections/enqueue-test처럼 Resource가 Public으로 표기된 엔드포인트는 Airflow 권한이 전혀 필요 없다.
일부 엔드포인트는 표에 두 번 나타나는데, 이는 하나의 엔드포인트가 서로 다른 두 리소스에 대한 권한을 동시에 요구하기 때문이다. 예를 들어 자산의 큐 이벤트를 삭제하는 DELETE /assets/{asset_id}/queuedEvents는 Asset에 대한 DELETE 권한과 DAG에 대한 PUT 권한을 모두 요구한다 — 자산 이벤트 삭제가 DAG 범위의 상태에도 영향을 주기 때문으로 볼 수 있다. 또한 GET /eventLogs(감사 로그 조회)에 필요한 권한은 이 표에서 DAG.AUDIT_LOG로 표기되는데, 이는 새 auth manager 체계의 리소스 명명 규칙이며 audit_logs.rst에서 언급된 FAB 시절의 권한명인 "Audit Logs.can_read"와는 이름이 다르다 — 앞서 다룬 RESOURCE_*/ACTION_* → resource_details/ResourceMethod 마이그레이션이 실제로 리소스 명명에 반영된 사례로 볼 수 있다.
핵심 포인트
- api_permissions_ref.rst는 소스코드에서 자동 생성되는 문서이며 prek 훅으로 재생성되므로 수동 편집 대상이 아니다
- Resource는 DAG/DAG.RUN/DAG.TASK_INSTANCE 같은 도메인 리소스와 View.IMPORT_ERRORS/JOBS/PLUGINS/PROVIDERS 같은 읽기전용 singleton 리소스로 나뉜다
- PATCH 메서드는 대개 PUT 권한에 매핑되고, 벌크 엔드포인트는 multi 권한을 요구한다
- 일부 엔드포인트는 두 리소스에 대한 권한을 동시에 요구해 표에 중복 행으로 나타난다(예: 자산 큐 이벤트 삭제는 Asset DELETE와 DAG PUT을 모두 요구)
- Public 리소스(예: /auth/login, /monitor/health, /version)는 Airflow 권한이 전혀 필요 없다
- eventLogs 엔드포인트의 권한은 새 체계에서 DAG.AUDIT_LOG로 표기되며, 이는 FAB 시절 권한명 'Audit Logs.can_read'와는 다른 새 명명 규칙이다