← 학습 카테고리

Learn

Airflow

151개 모듈 · 현재 104번째

Airflow 모듈 104/151 airflow-learn-104

Dag Author의 Dag 접근 범위와 격리 한계 (multi-team, Per-Dag 소스 조회)

Apache Airflow Official Documentation (in-repo snapshot) — Apache Software Foundation security/security_model.rst - "Capabilities of Dag authors" ~ "Per-Dag read access and source-code retrieval" 섹션 (약 188-264행)

이 모듈을 다 읽으면

  • Dag Author가 기본적으로 모든 Dag에 접근할 수 있고 별도의 세분화된 접근 제어가 없다는 원칙을 설명할 수 있다
  • 실험적 multi_team 기능이 어떤 수준까지 격리를 제공하고 어떤 수준에서는 제공하지 못하는지 구분할 수 있다
  • dagSources 엔드포인트의 per-Dag read scoping이 '현재' 파일-Dag 매핑을 기준으로 동작하기 때문에 생기는 과거 버전 조회의 함정을 설명할 수 있다

Airflow는 아직 Dag Author 간의 완전한 태스크 레벨 격리를 제공하지 않는다. Dag Author는 기본적으로 모든 Dag에 접근해 수정할 수 있고, 실험적 multi_team 기능도 UI/REST API 레벨의 RBAC 격리만 제공할 뿐 태스크 실행 레벨의 격리는 보장하지 않는다. 소스 코드 조회 엔드포인트의 per-Dag 스코핑 방식도 파일 단위로 동작하기 때문에 버전 이력 조회 시 예상치 못한 결과를 낳을 수 있다.

Dag Author 코드는 검증되지 않는다

Dag Author는 Dag 번들에 놓인 파이썬 파일을 통해 여러 상황에서 실행될 코드를 자유롭게 작성/수정할 수 있다. Airflow는 이 코드를 검증하거나 확인하거나 샌드박싱하지 않는다 - 그렇게 하는 것 자체가 사실상 불가능에 가깝기 때문이다. 따라서 Dag Author는 워커(Celery Executor의 Celery Worker, Local Executor의 로컬 프로세스, Kubernetes Executor의 태스크 Pod), Dag Processor, Triggerer에서 임의 코드를 실행할 수 있는 것으로 취급된다.

Dag Author는 자신이 작성한 코드가 안전하며 보안 취약점을 열지 않는다는 것을 스스로 검증할 책임이 있다. 예를 들어 UI 사용자 입력(파라미터, Variable, Connection 설정)을 검증 없이 Operator/Hook이나 서드파티 라이브러리에 그대로 전달하는 코드는 원격 코드 실행이나 서비스 거부로 이어질 수 있다.

핵심 포인트

  • Airflow는 Dag 코드를 검증/샌드박싱하지 않으므로 Dag Author는 사실상 임의 코드 실행 권한을 가진 것으로 취급된다
  • Dag Author 코드는 워커, Dag File Processor, Triggerer에서 실행된다
  • 비검증 입력을 Operator/Hook에 그대로 전달하는 코드는 RCE/DoS로 이어질 수 있으며 이는 Dag Author의 책임이다

모든 Dag에 대한 기본 접근권과 실험적 multi_team 기능

Airflow는 아직 태스크 실행에 있어 서로 다른 사용자 그룹 간의 완전한 태스크 레벨 격리를 제공하지 않는다. Airflow 3.0 이후 워커의 태스크 코드는 메타데이터 DB에 직접 접근할 수 없고 Execution API를 통해서만 통신하지만, Dag File Processor와 Triggerer에서 실행되는 Dag Author 코드는 여전히 직접 DB 접근을 가질 수 있다. 실행 컨텍스트와 무관하게 Dag Author는 설치된 모든 Dag에 접근할 수 있고 이를 수정할 수 있다 - 이를 제한하는 세분화된 접근 제어는 없다.

이 원칙은 워커가 Task SDK를 통해 사용하는 Execution API에도 그대로 적용된다. 실행 중인 태스크에 발급된 Execution JWT는 Dag별 인가 정보를 담지 않는다 - 유효한 토큰을 가진 태스크는 설치된 어떤 Dag에 대해서도 상태 변경형 Execution API 엔드포인트(Dag 실행 트리거/삭제, Variable/Connection/XCom 읽기·쓰기 등)를 호출할 수 있다. ``ti:self`` 토큰 스코프는 서로 다른 태스크 인스턴스 간의 상태 변경만 제한할 뿐 Dag별 접근 제어가 아니다.

Airflow에는 UI/REST API 레벨의 RBAC 팀 간 격리를 제공하는 실험적 multi-team 기능(``[core] multi_team``)이 있다. 이 모드에서는 Execution API를 통해 접근 가능한 팀-스코프 자원도 격리된다: 태스크는 자신이 속한 팀 소유의 Variable/Connection만 접근할 수 있고(전역 값으로 폴백 가능), 자신이 속한 팀의 Dag가 가진 XCom만 접근할 수 있다(읽기는 전역 Dag까지 추가로 가능하지만, 쓰기/삭제는 불가능).

그러나 이 기능은 아직 태스크 레벨 격리를 보장하지 않는다. 태스크 실행 레벨에서는 서로 다른 팀의 워크로드가 여전히 동일한 Execution API, 서명 키, Connection, Variable을 공유한다. 한 팀의 태스크가 다른 팀의 태스크와 동일한 공유 자원에 접근할 수 있다. multi-team 기능은 아직 개발 중이며, 태스크 레벨 격리와 Execution API의 팀 경계 강제는 향후 버전에서 개선될 예정이다.

핵심 포인트

  • Dag Author는 실행 컨텍스트와 무관하게 설치된 모든 Dag에 접근·수정할 수 있고, 이를 제한하는 세분화된 접근 제어는 없다
  • Execution JWT는 Dag별 인가 정보를 담지 않으며, ti:self 스코프는 태스크 인스턴스 간 상태 변경만 제한할 뿐 Dag별 접근 제어가 아니다
  • 실험적 multi_team 기능은 UI/REST API 레벨 RBAC 격리와 팀-스코프 Variable/Connection/XCom 접근 제한을 제공한다
  • multi_team은 아직 태스크 레벨 격리를 보장하지 않는다 - 서로 다른 팀의 워크로드가 동일한 Execution API, 서명 키, Connection/Variable을 공유한다

Per-Dag 소스 코드 조회와 버전 이력의 함정

Dag 소스 조회 엔드포인트(``GET /api/v2/dagSources/{dag_id}``)는 '현재' Dag-파일 매핑을 기준으로 Dag별 읽기 스코핑을 존중한다. 요청한 Dag를 담고 있는 파일이 호출자가 읽을 권한이 없는 다른 Dag도 함께 정의하고 있다면, 이 엔드포인트는 원본 소스 대신 마스킹된 placeholder를 반환한다.

이 엔드포인트는 선택적 ``version_number`` 쿼리 파라미터로 과거 버전 소스도 조회할 수 있게 지원한다. 그런데 과거 버전을 조회할 때도 Dag별 스코프는 '현재' 파일 멤버십을 기준으로 적용되며, 이는 요청된 버전이 저장되던 시점의 실제 파일 내용과 다를 수 있다. 그 결과, 오래된 버전을 요청했을 때 그 사이 파일에서 제거된 Dag가 포함된 소스가 반환될 수 있다 - 호출자가 그 제거된 Dag에 대한 읽기 권한이 현재 없더라도 그렇다. 반대로, 나중에 추가된 co-located Dag가 호출자의 읽기 가능 집합에 없다면, 요청한 과거 소스가 실제로는 그 추가 이전 시점이었음에도 마스킹된 placeholder가 반환될 수 있다.

Per-Dag 읽기 스코핑을 소스 격리 수단으로 신뢰하는 배포에서는 파일당 Dag 1개를 유지하거나, ``DagAccessEntity.CODE`` 권한을 그 파일에 한 번이라도 공존했던 모든 Dag를 신뢰할 수 있는 역할로만 제한해야 한다.

핵심 포인트

  • dagSources 엔드포인트는 요청 Dag가 속한 파일에 읽기 권한 없는 다른 Dag가 있으면 소스 대신 redacted placeholder를 반환한다
  • version_number로 과거 버전을 조회해도 Dag별 스코프 판단은 '현재' 파일 멤버십 기준으로 이루어진다
  • 이 때문에 과거엔 있었지만 지금은 삭제된 Dag의 소스가 노출되거나, 반대로 나중에 추가된 Dag 때문에 과거 버전이 부당하게 마스킹될 수 있다
  • 소스 격리를 신뢰하려면 파일당 Dag 1개를 유지하거나 CODE 권한 부여 대상을 엄격히 제한해야 한다