Self-Managed 러너의 보안

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed

GitLab CI/CD 파이프라인은 간단하거나 복잡한 DevOps 자동화 작업에 사용되는 워크플로우 자동화 엔진입니다. 이러한 파이프라인은 원격 코드 실행 서비스를 가능하게 하기 때문에 보안 리스크를 줄이기 위해 다음 프로세스를 구현해야 합니다:

  • 전체 기술 스택의 보안 구성에 대한 체계적인 접근 방식.
  • 구성 및 플랫폼 사용의 지속적이고 엄격한 검토.

GitLab CI/CD 작업을 Self-Managed형 러너에서 실행할 계획이 있다면, 컴퓨팅 인프라 및 네트워크에 보안 리스크가 존재합니다.

러너는 CI/CD 작업에서 정의된 코드를 실행합니다. 프로젝트 리포지터리에 대한 Developer 역할을 가진 사용자라면 의도적인 경우든 그렇지 않은 경우든 러너를 호스팅하는 환경의 보안을 compromise시킬 수 있습니다.

특히 Self-Managed형 러너가 일회성이 아니고 여러 프로젝트에 사용되는 경우, 이러한 리스크는 더욱 심각해집니다.

  • 악성 코드가 포함된 리포지터리에서의 작업은 일회성이 아닌 러너를 사용하는 다른 리포지터리의 보안을 compromise할 수 있습니다.
  • 실행자에 따라, 작업은 러너가 호스팅된 가상 머신에 악성 코드를 설치할 수 있습니다.
  • compromise된 환경에서 실행되는 작업에 노출된 비밀 변수는 CI_JOB_TOKEN을 비롯한 것으로 제한되지 않고 도난당할 수 있습니다.
  • Developer 역할을 가진 사용자는 해당 프로젝트와 관련된 서브모듈에 액세스할 수 있습니다. 해당 서브모듈의 상위 프로젝트에 액세스할 수 없더라도요.

다른 실행자의 보안 리스크

사용 중인 실행자에 따라 다른 보안 리스크를 마주할 수 있습니다.

Shell 실행자 사용

shell 실행자로 빌드를 실행할 때 러너 호스트 및 네트워크에 높은 보안 리스크가 존재합니다. 작업은 GitLab 러너 사용자의 권한으로 실행되며, 이로써 다른 프로젝트에서 코드를 도용할 수 있습니다. 신뢰할 수 있는 빌드에만 사용하십시오.

Docker 실행자 사용

Docker는 비특권 모드에서 실행할 때 안전하다고 간주될 수 있습니다. 이러한 구성을 더 안전하게 만들려면 Docker 컨테이너에서 sudo를 비활성화하거나 SETUIDSETGID 권한을 해제한 상태의 비루트 사용자로 작업을 실행하십시오.

비특권 모드에서 더 상세한 권한 설정을 cap_add/cap_drop 설정을 통해 구성할 수 있습니다.

caution
Docker의 특권 컨테이너는 호스트 VM의 모든 루트 권한을 갖습니다. 자세한 내용은 런타임 특권 및 리눅스 권한 공식 Docker 문서를 확인하십시오

특권 모드를 활성화하면 CI/CD 작업을 실행하는 사용자가 러너 호스트 시스템에 대한 완전한 루트 액세스 권한을 얻고, 볼륨을 마운트하고 마운트를 해제하며 중첩된 컨테이너를 실행할 수 있습니다.

특권 모드를 활성화하면 모든 컨테이너의 보안 메커니즘을 비활성화하고 권한 상승을 노출시켜 컨테이너 탈출로 이어질 수 있습니다.

특히 여러 조직 간에 러너를 공유하는 경우에는 특히 리스크가 있습니다. 예를 들어, GitLab.com과 같은 서비스의 인스턴스 전역 러너에서 여러 독립적인 조직이 동시에 작업할 수 있는 경우입니다.

Docker Machine 실행자를 사용하는 경우, MaxBuilds = 1 설정을 권장합니다. 이를 통해 특권 모드로 인한 보안 취약점 때문에 잠재적으로 compromise될 수 있는 단일 autoscaled VM이 한 번에 하나의 작업을 처리하도록 보장할 수 있습니다.

if-not-present 풀 정책으로 개인 Docker 이미지 사용

고급 구성: 개인 컨테이너 레지스트리 사용 에서 설명된 개인 Docker 이미지 지원을 사용할 때, pull_policy 값으로 always를 사용해야 합니다. 특히 Docker 또는 Kubernetes 실행자를 사용하는 공용 공유 러너에서 always 풀 정책을 사용해야 합니다.

if-not-present 풀 정책이 설정된 예시를 고려해 보겠습니다:

  1. 사용자 A는 registry.example.com/image/name에서 개인 이미지를 갖고 있습니다.
  2. 사용자 A는 공유 러너에서 빌드를 시작합니다: 빌드는 명시된 권한으로 인증 후 이미지를 받습니다.
  3. 이미지가 공유 러너의 호스트에 저장됩니다.
  4. 사용자 B는 registry.example.com/image/name에서의 개인 이미지에 액세스할 수 없습니다.
  5. 사용자 B는 동일한 공유 러너에서 이 이미지를 사용하는 빌드를 시작합니다. 사용자 A와 마찬가지로 이미지를 가져올 수 없더라도, 러너는 로컬 버전의 이미지를 찾고 사용합니다.

따라서 여러 사용자와 다른 프로젝트 (혼합된 비공개 및 공개 액세스 수준)에서 사용할 수 있는 러너를 호스팅하는 경우 never - 다운로드할 수 있는 이미지를 사용자가 제한하려는 경우 또는 always - 모든 레지스트리에서 어떤 이미지라도 다운로드할 수 있는 옵션을 사용해야 합니다.

if-not-present 풀 정책은 신뢰할 수 있는 빌드 및 사용자에게만 사용해야 합니다.

자세한 내용은 풀 정책 문서를 참조하십시오.

Docker 설치된 시스템

note
0.5.0 미만의 설치 또는 새로운 버전으로 업그레이드된 설치에 해당됩니다.

Linux 시스템에 Docker가 설치된 경우, gitlab-runnerDocker에 액세스할 수 있는 권한을 갖는 사용자를 생성합니다. 이는 shell 실행자로 실행되는 작업이 docker에 전체 권한으로 액세스할 수 있게 합니다.

SSH 실행자 사용

SSH 실행자는 StrictHostKeyChecking 옵션이 누락되어 MITM 공격에 취약합니다. 이 문제는 향후 릴리스 중에 수정될 것입니다.

Parallels 실행자 사용

Parallels 실행자는 가장 안전한 옵션입니다 전체 시스템 가상화를 사용하며 완전히 격리된 가상화 모드에서 구성된 VM 머신을 사용합니다. 모든 주변 기기 및 공유 폴더에 대한 액세스를 차단합니다.

러너 클론

러너는 GitLab 서버를 식별하기 위한 토큰을 사용합니다. 따라서 러너를 복제하면 복제된 러너가 해당 토큰의 작업을 선택할 수 있습니다. 이것은 “러너 작업을 도용”하는 가능한 공격 벡터입니다.

사용자환경에서 GIT_STRATEGY: fetch 사용 시의 보안 리스크

GIT_STRATEGYfetch로 설정하면, 러너는 Git 리포지터리의 로컬 작업 복사본을 재사용하려고 시도합니다.

로컬 복사본 사용은 CI/CD 작업의 성능을 향상시킬 수 있습니다. 그러나 재사용 가능한 복사본에 액세스 권한이 있는 모든 사용자는 다른 사용자의 파이프라인에서 실행될 수 있는 코드를 추가할 수 있습니다.

Git은 서브모듈 (다른 리포지터리 내에 포함된 리포지터리)의 내용을 부모 리포지터리의 Git reflog에 저장합니다. 결과적으로 프로젝트의 서브모듈이 초기에 복제된 후에 스스로를 삭제하고 서브모듈 프로젝트에 액세스할 수 없더라도 다음 작업에서 스크립트에서 git submodule update를 실행하여 서브모듈의 내용에 액세스할 수 있습니다.

GIT_STRATEGY: fetch를 사용할 때에는 공유 환경에 액세스 자체를 신뢰할 수 있는 모든 사용자에게만 사용하십시오.

보안 강화 옵션

특권 컨테이너 사용 보안 리스크 줄이기

Docker의 --privileged 플래그가 필요한 CI/CD 작업을 실행해야 하는 경우, 다음과 같은 단계를 거쳐 보안 리스크를 줄일 수 있습니다:

  • Docker 컨테이너를 --privileged 플래그가 활성화된 상태에서 오직 격리되고 일회성인 가상 머신에서만 실행합니다.
  • Docker의 --privileged 플래그가 필요한 작업을 실행하기 위해 구성된 전용 러너를 구성하고 해당 러너가 보호된 브랜치에서만 작업을 실행하도록 설정합니다.

네트워크 분할

GitLab Runner는 사용자가 제어하는 스크립트를 실행하는 데 설계되었습니다. 작업이 악의적인 경우 공격 표면을 줄이기 위해 해당 작업을 고유한 네트워크 세그먼트에서 실행하는 것을 고려할 수 있습니다. 이는 인프라 및 서비스로부터 네트워크 분리를 제공할 것입니다.

모든 요구 사항은 고유합니다. 그러나 클라우드 환경의 경우 다음을 포함할 수 있습니다:

  • 러너 가상 머신을 고유한 네트워크 세그먼트에 구성
  • 인터넷에서 러너 가상 머신으로의 SSH 액세스 차단
  • 러너 가상 머신 간의 트래픽 제한
  • 클라우드 제공업체 메타데이터 엔드포인트의 액세스 필터링
note
모든 러너가 GitLab.com 또는 GitLab 인스턴스로의 외부 네트워크 연결이 필요합니다. 대부분의 작업은 의존성 풀링 등을 위해 인터넷으로의 외부 네트워크 연결도 필요할 것입니다.

러너 호스트의 보안 강화

러너(runner)에 대한 정적 호스트(베어 메탈 또는 가상 머신)를 사용하는 경우 호스트 운영 체제에 대한 보안 모범 사례를 구현해야 합니다.

CI 작업의 컨텍스트에서 악성 코드가 실행될 경우 호스트가 compromise될 수 있으므로 보안 프로토콜은 영향을 완화하는 데 도움이 될 수 있습니다. 고려해야 할 다른 사항으로는 환경의 다른 엔드포인트에 액세스할 수 있게 하는 SSH 키와 같은 파일을 보안화하거나 제거하는 것이 있습니다.