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