자가 관리형 러너의 보안
GitLab CI/CD 파이프라인은 간단하거나 복잡한 DevOps 자동화 작업을 위한 워크플로우 자동화 엔진입니다. 이러한 파이프라인은 원격 코드 실행 서비스를 가능하게 하므로 보안 위험을 줄이기 위해 다음 프로세스를 구현해야 합니다:
- 전체 기술 스택의 보안을 구성하는 체계적인 접근 방식.
- 플랫폼의 구성 및 사용에 대한 지속적인 철저한 검토.
자가 관리형 러너에서 GitLab CI/CD 작업을 실행할 계획이라면, 컴퓨팅 인프라 및 네트워크에 대한 보안 위험이 존재합니다.
러너는 CI/CD 작업에서 정의된 코드를 실행합니다. 프로젝트 리포지토리에 대한 Developer 역할을 가진 사용자는 의도적으로 또는 의도하지 않게 러너를 호스팅하는 환경의 보안을 위협할 수 있습니다.
이 위험은 자가 관리형 러너가 비일시적이며 여러 프로젝트에 사용될 경우 더욱 심각합니다.
- 악성 코드가 포함된 리포지토리에서의 작업은 비일시적 러너가 서비스하는 다른 리포지토리의 보안을 위협할 수 있습니다.
- 실행자에 따라, 작업은 러너가 호스팅되는 가상 머신에 악성 코드를 설치할 수 있습니다.
- 손상된 환경에서 실행되는 작업에 노출된 비밀 변수는 도난당할 수 있으며, CI_JOB_TOKEN을 포함하되 이에 한정되지 않습니다.
- Developer 역할을 가진 사용자는 서브모듈과 관련된 프로젝트에 접근할 수 있으며, 서브모듈의 상위 프로젝트에 대한 접근 권한이 없더라도 가능합니다.
다양한 실행자에 대한 보안 위험
사용하는 실행자에 따라 서로 다른 보안 위험에 직면할 수 있습니다.
Shell 실행자 사용
shell
실행자를 사용하여 빌드를 실행할 때 러너 호스트 및 네트워크에 대한 높은 보안 위험이 존재합니다. 작업은 GitLab 러너의 사용자의 권한으로 실행되며, 이 서버에서 실행되는 다른 프로젝트의 코드를 도난당할 수 있습니다. 신뢰할 수 있는 빌드 실행에만 사용해야 합니다.
Docker 실행자 사용
Docker는 비특권 모드에서 실행할 때 안전하다고 간주될 수 있습니다. 이러한 구성을 더 안전하게 만들려면, sudo
를 비활성화하거나 SETUID
및 SETGID
기능을 제외한 비루트 사용자로 Docker 컨테이너에서 작업을 실행하세요.
비특권 모드에서는 cap_add
/cap_drop
설정을 통해 더 세분화된 권한을 구성할 수 있습니다.
자세한 내용은 공식 Docker 문서의 Runtime privilege and Linux capabilities를 참조하세요.
특권 모드로 컨테이너를 실행하는 것은 권장되지 않습니다.
특권 모드가 활성화되면 CI/CD 작업을 실행하는 사용자가 러너 호스트 시스템에 대한 완전한 루트 접근 권한을 얻고, 볼륨을 마운트 및 언마운트할 권한을 얻으며, 중첩된 컨테이너를 실행할 수 있습니다.
특권 모드를 활성화하면 사실상 모든 컨테이너의 보안 메커니즘을 비활성화하고 호스트를 권한 상승에 노출시켜 컨테이너 탈출로 이어질 수 있습니다.
Docker Machine 실행자를 사용하는 경우, MaxBuilds = 1
설정을 사용하는 것이 좋습니다. 이 설정은 보안 약점으로 인해 잠재적으로 손상된 단일 자동 확장 VM을 사용하여 하나의 작업만 처리하도록 보장합니다.
if-not-present
풀 정책을 가진 개인 Docker 이미지 사용
고급 구성: 개인 컨테이너 레지스트리 사용에서 설명된 개인 Docker 이미지 지원을 사용할 때는 pull_policy
값을 always
로 설정해야 합니다. 특히 Docker 또는 Kubernetes 실행자를 사용하여 공용 공유 러너를 호스팅하고 있다면 always
풀 정책을 사용해야 합니다.
풀 정책이 if-not-present
로 설정된 예를 고려해 보겠습니다:
- 사용자 A는
registry.example.com/image/name
에 개인 이미지를 가지고 있습니다. - 사용자 A는 공유 러너에서 빌드를 시작합니다: 빌드는 레지스트리 자격 증명을 받고 레지스트리에서 승인 후 이미지를 가져옵니다.
- 이미지는 공유 러너의 호스트에 저장됩니다.
- 사용자 B는
registry.example.com/image/name
에 대한 개인 이미지에 접근할 수 없습니다. - 사용자 B는 사용자 A와 동일한 공유 러너에서 이 이미지를 사용하는 빌드를 시작합니다: 러너는 이미지를 локиᄉу 버전으로 찾고 사용합니다 자격 증명이 누락되어 이미지를 가져올 수 없더라도.
따라서 서로 다른 사용자 및 서로 다른 프로젝트(혼합된 개인 및 공개 접근 수준이 있는)에 의해 사용될 수 있는 러너를 호스팅하는 경우 if-not-present
를 풀 정책 값으로 사용하는 것은 절대적으로 금지되어야 하며, 대신 다음을 사용해야 합니다:
-
never
- 사전 다운로드된 이미지만 사용하도록 제한하려는 경우. -
always
- 사용자가 모든 레지스트리에서 모든 이미지를 다운로드할 수 있도록 하려는 경우.
if-not-present
풀 정책은 신뢰할 수 있는 빌드 및 사용자에 의해 사용되는 특정 러너에 대해서만 사용해야 합니다.
자세한 내용은 풀 정책 문서를 참조하세요.
도커가 설치된 시스템
참고:
이 내용은 0.5.0 이하의 설치 또는 최신 버전으로 업그레이드된 경우에 적용됩니다.
도커가 설치된 리눅스 시스템에 GitLab Runner 패키지를 설치할 때, gitlab-runner
는 Docker
데몬에 액세스할 수 있는 권한을 가진 사용자를 생성합니다. 이로 인해 shell
executor로 실행되는 작업들이 전체 권한으로 docker
에 접근할 수 있으며, 서버에 루트 접근을 허용할 수 있습니다.
SSH executor 사용
SSH executors는 MITM 공격(중간자 공격)에 취약합니다, StrictHostKeyChecking
옵션이 누락되었기 때문입니다. 이 문제는 향후 릴리스 중 하나에서 수정될 것입니다.
Parallels executor 사용
Parallels executor는 가능한 가장 안전한 옵션입니다. 전체 시스템 가상화를 사용하며, 격리된 가상화에서 실행되도록 구성된 VM 머신과 격리된 모드에서 실행되도록 구성된 VM 머신을 사용합니다. 모든 주변 장치와 공유 폴더에 대한 접근을 차단합니다.
러너 복제하기
러너는 GitLab 서버에 식별하기 위해 토큰을 사용합니다. 러너를 복제하면 복제된 러너가 해당 토큰에 대해 동일한 작업을 추출할 수 있습니다. 이는 러너 작업을 “훔치는” 가능한 공격 경로입니다.
공유 환경에서 GIT_STRATEGY: fetch
사용 시 보안 위험
GIT_STRATEGY
를 fetch
로 설정하면, 러너는 Git 리포지토리의 로컬 작업 복사를 재사용하려고 시도합니다.
로컬 복사를 사용하면 CI/CD 작업의 성능을 개선할 수 있습니다. 그러나 해당 재사용 가능한 복사본에 접근할 수 있는 모든 사용자는 다른 사용자의 파이프라인에서 실행되는 코드를 추가할 수 있습니다.
Git은 서브모듈(다른 리포지토리 내에 내장된 리포지토리)의 내용을 부모 리포지토리의 Git reflog에 저장합니다. 결과적으로 프로젝트의 서브모듈이 처음으로 복제된 후, 후속 작업은 스크립트에서 git submodule update
를 실행하여 서브모듈의 내용에 접근할 수 있습니다. 이는 서브모듈이 삭제되었고 작업을 시작한 사용자가 서브모듈 프로젝트에 접근할 수 없는 경우에도 적용됩니다.
공유 환경에 접근할 수 있는 모든 사용자를 신뢰할 때만 GIT_STRATEGY: fetch
를 사용하세요.
보안 강화 옵션
특권 있는 컨테이너 사용의 보안 위험 줄이기
Docker의 --privileged
플래그가 필요한 CI/CD 작업을 실행해야 하는 경우, 보안 위험을 줄이기 위해 다음 단계를 수행할 수 있습니다:
-
--privileged
플래그가 활성화된 Docker 컨테이너를 격리된 일회용 가상 머신에서만 실행하세요. - Docker의
--privileged
플래그를 사용하는 작업을 실행하도록 설정된 전용 러너를 구성합니다. 그런 다음 이러한 러너가 보호된 브랜치에서만 작업을 실행하도록 구성합니다.
네트워크 분할
GitLab Runner는 사용자 제어 스크립트를 실행하기 위해 설계되었습니다. 악의적인 작업의 공격 표면을 줄이기 위해, 이를 자체 네트워크 세그먼트에서 실행하는 것을 고려할 수 있습니다. 이는 다른 인프라 및 서비스로부터 네트워크 분리를 제공할 것입니다.
모든 요구 사항은 고유하지만, 클라우드 환경의 경우 다음을 포함할 수 있습니다:
- 자체 네트워크 세그먼트에서 러너 가상 머신 구성
- 인터넷에서 러너 가상 머신으로의 SSH 접근 차단
- 러너 가상 머신 간의 트래픽 제한
- 클라우드 공급자 메타데이터 엔드포인트에 대한 접근 필터링
참고:
모든 러너는 GitLab.com 또는 귀하의 GitLab 인스턴스에 대한 외부 네트워크 연결이 필요합니다. 대부분의 작업은 의존성 풀링 등을 위해 인터넷에 대한 외부 네트워크 연결이 필요합니다.
러너 호스트 보안
정적 호스트를 러너에 사용하는 경우, 베어메탈이든 가상 머신이든 관계없이 호스트 운영 체제에 대한 보안 최선의 관행을 구현해야 합니다.
CI 작업의 컨텍스트에서 실행된 악성 코드는 호스트를 위협할 수 있으므로, 보안 프로토콜이 영향을 완화하는 데 도움이 될 수 있습니다. 다른 고려 사항으로는 공격자가 환경의 다른 끝점에 접근할 수 있도록 할 수 있는 SSH 키와 같은 파일을 보호하거나 제거하는 것입니다.
빌드 후 .git
폴더 정리하기
러너에 대해 정적 호스트를 사용하는 경우,
FF_ENABLE_JOB_CLEANUP
기능 플래그를 활성화하여 추가적인 보안 계층을 구현할 수 있습니다.
FF_ENABLE_JOB_CLEANUP
을 활성화하면, 호스트에서 러너가 사용하는 빌드 디렉토리가 각 빌드 후에 정리됩니다.