Compose 파일의 신뢰 모델

Compose 파일의 신뢰 모델 (Trust model)

Docker Compose는 모든 Compose 파일을 신뢰된 입력 으로 취급해요. 파일이 상승된 권한이나 호스트 파일시스템 접근을 요청하면 Compose는 적힌 그대로 적용해요. 이건 docker run에 플래그를 직접 넘기는 것과 같은 동작이에요.

출처: Trust model for Compose files

본문

실행하는 어떤 Compose 파일이든 — 로컬 파일시스템에 있든, Git 리포지토리에 있든, OCI 레지스트리에 있든 — 컨테이너가 호스트와 어떻게 상호작용할지 완전히 제어해요. 보안 경계는 파일이 어디서 왔는지가 아니라 작성자를 신뢰하느냐 에 있어요.

신뢰를 평가한다는 건 이런 질문을 하는 거예요. 누가 이 파일을 작성했나? 마지막으로 검토한 이후로 바뀌었나? 요청하는 모든 권한을 이해하고 있나?

의존성 체인 (dependency chain)

Compose 애플리케이션은 여러 소스에서 조합될 수 있어요. include 지시어는 전체 Compose 파일을 가져오고, extends는 다른 파일의 특정 서비스에서 설정을 상속받아요. 둘 다 원격 참조를 지원하고 체인처럼 연결될 수 있어요.

Your command
  └─ compose.yaml                                    (local or remote)
       ├─ services, volumes, networks                (direct config)
       ├─ include:
       │    └─ oci://registry.example.com/base:v2   (remote dependency)
       │         └─ services, volumes, networks      (indirect config)
       └─ services:
            └─ app:
                 └─ extends:
                      └─ file: oci://registry.example.com/templates:v1
                           └─ service: webapp        (inherited config)

각 단계는 같은 능력을 가져요. 최상위 파일은 안전해 보여도, 중첩된 includeextends가 상승된 권한을 가진 서비스, 호스트 바인드 마운트, 검증되지 않은 이미지를 들여올 수 있어요. 이런 의존성은 각각 독립적으로 바뀔 수도 있어요. 완전히 해석된(resolved) 출력을 직접 확인하지 않으면 보지 못하는 중첩 의존성에 의해 위험한 설정이 들어올 수 있어요.

중요: 설정이 원격 소스를 참조하면 Compose가 경고해요. 체인에 있는 모든 참조를 이해하기 전에는 이 경고를 무시하고 수락하지 마세요.

모범 사례: 전체 설정 확인하기

Compose가 실제로 적용하는 내용 — 해석된 모든 include, extends, 병합된 오버라이드, 보간된 변수 — 을 정확히 보려면 다음을 써요.

$ docker compose config

원격 참조의 경우:

$ docker compose -f oci://registry.example.com/myapp:latest config

up이나 create를 실행하기 전에, 특히 감사하지 않은 소스에서 온 설정이라면 이 출력을 꼭 검토해야 해요.

주의해야 할 필드

Compose 설정은 컨테이너가 호스트와 상호작용하는 방식을 넓게 제어해요. 신뢰하지 않는 작성자가 설정할 때 보안 영향을 주는 필드 목록(비완전)이에요.

필드 효과
privileged 컨테이너에 호스트에 대한 완전한 접근을 부여
cap_add SYS_ADMIN, NET_RAW 같은 Linux capabilities 추가
security_opt seccomp, AppArmor 등 보안 프로파일 설정
volumes / bind mounts 호스트 디렉터리를 컨테이너에 마운트
network_mode: host 호스트 네트워크 스택 공유
pid: host 호스트 PID 네임스페이스 공유
devices 호스트 장치를 컨테이너에 노출
image 임의의 컨테이너 이미지를 pull해서 실행
env_file, label_file, secrets/configs(file:), include, extends 호스트에서 파일을 읽고, 원격 체크아웃의 심볼릭 링크를 통해 해석된 내용을 설정 로딩 중 노출시킬 수 있음
provider up, down, stop을 실행할 때 provider.type이 지정한 바이너리를 컨테이너 밖, 호스트에서 실행

잘 모르는 필드가 있으면 실행하기 전에 그 효과를 찾아보는 게 좋아요. volumes처럼 파일 참조 필드도 Compose를 실행하는 사용자가 접근할 수 있는 파일을 읽어요. 원격 체크아웃에서 해석된 심볼릭 링크를 통해서도요. 그 내용은 컨테이너가 시작되기 전에 docker compose config 출력에 나타날 수 있어요. Compose는 읽기를 프로젝트 디렉터리로 제한하지 않아요. Compose 프로젝트는 검사하는 데이터가 아니라 실행하는 코드 로 취급해야 해요.

CI/CD 환경

자동화 파이프라인은 종종 자격 증명, 클라우드 제공자 토큰, Docker 소켓에 접근해서 실행되기 때문에 특히 민감해요.

  • 자동화 파이프라인에서 공개되거나 검증되지 않은 Compose 설정을 참조하지 마세요.
  • 업데이트는 평소 코드 리뷰 프로세스 뒤에 게이트(gate)를 두세요.
  • 가능하면 읽기 전용 Docker 소켓 마운트를 사용해 위험을 줄이세요.

원격 참조를 digest로 고정 (pin)

태그(tag)는 변경 가능해서, 레지스트리에 푸시 권한이 있는 사람은 태그를 조용히 덮어쓸 수 있어요. 지난주에 검토한 참조가 오늘은 다른 내용을 가리킬 수 있다는 뜻이에요. 반면 digest는 불변(immutable) 이에요. 태그로 참조하지 말고 digest로 고정하세요.

include:
  - oci://registry.example.com/base@sha256:a1b2c3d4...

고정된 digest에 대한 업데이트는 코드 변경으로 취급해야 해요. 참조를 갱신하기 전에 새 내용을 검토하세요.

기타 권장 사항

  • 비공개 레지스트리 사용: 조직이 통제하는 레지스트리에 OCI 아티팩트를 두고, 푸시할 수 있는 사람을 제한하세요.
  • 전이 의존성 감사: 최상위 파일뿐 아니라 체인에 있는 모든 원격 include, extends 참조를 확인하세요.
  • 모든 Compose 확인 프롬프트 검토: 원격 Compose 파일을 로딩할 때 Compose는 보간 변수, 환경 값, 원격 include에 대한 확인 프롬프트를 보여줘요. 수락하기 전에 검토하세요.

더 알아보기