InfoGrab Docs

셀프 매니지드 러너의 보안

요약

GitLab CI/CD 파이프라인은 단순하거나 복잡한 DevOps 자동화 작업에 사용되는 워크플로우 자동화 엔진입니다. GitLab CI/CD 잡을 셀프 매니지드 러너에서 실행할 계획이라면, 컴퓨팅 인프라와 네트워크에 보안 위험이 존재합니다.

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

  • 전체 기술 스택의 보안을 체계적으로 구성하는 접근 방식
  • 플랫폼의 구성과 사용에 대한 지속적이고 엄격한 검토

GitLab CI/CD 잡을 셀프 매니지드 러너에서 실행할 계획이라면, 컴퓨팅 인프라와 네트워크에 보안 위험이 존재합니다.

러너는 CI/CD 잡에 정의된 코드를 실행합니다. 프로젝트 리포지터리에 대한 Developer 권한을 가진 사용자는 의도적이든 아니든 러너를 호스팅하는 환경의 보안을 침해할 수 있습니다.

셀프 매니지드 러너가 비에페머럴(non-ephemeral)하고 여러 프로젝트에 사용되는 경우 이 위험은 더욱 심각합니다.

  • 악성 코드가 포함된 리포지터리의 잡은 비에페머럴 러너가 서비스하는 다른 리포지터리의 보안을 침해할 수 있습니다.
  • Executor에 따라 잡은 러너가 호스팅된 가상 머신에 악성 코드를 설치할 수 있습니다.
  • 침해된 환경에서 실행되는 잡에 노출된 시크릿 변수(CI_JOB_TOKEN 포함)는 탈취될 수 있습니다.
  • Developer 권한을 가진 사용자는 업스트림 프로젝트에 대한 접근 권한 없이도 프로젝트와 관련된 서브모듈에 접근할 수 있습니다.

Executor별 보안 위험#

사용하는 Executor에 따라 다른 보안 위험에 직면할 수 있습니다.

Shell executor 사용#

shell executor로 빌드를 실행할 때 러너 호스트와 네트워크에 높은 보안 위험이 존재합니다. 잡은 GitLab Runner 사용자의 권한으로 실행되며, 해당 서버에서 실행되는 다른 프로젝트의 코드를 탈취할 수 있습니다. 신뢰할 수 있는 빌드 실행에만 사용하십시오.

Docker executor 사용#

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

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

Warning

Docker의 특권 컨테이너는 호스트 VM의 모든 루트 권한을 가집니다. 자세한 내용은 런타임 권한 및 Linux 기능에 관한 공식 Docker 문서를 참조하십시오.

컨테이너를 특권 모드로 실행하는 것은 권장하지 않습니다.

특권 모드를 활성화하면 CI/CD 잡을 실행하는 사용자가 러너의 호스트 시스템에 대한 완전한 루트 접근 권한, 볼륨 마운트 및 분리 권한, 중첩 컨테이너 실행 권한을 얻을 수 있습니다.

특권 모드를 활성화하면 컨테이너의 모든 보안 메커니즘을 사실상 비활성화하고 호스트를 권한 상승에 노출시키며, 이는 컨테이너 탈출로 이어질 수 있습니다.

Docker Machine executor를 사용하는 경우, 단일 자동 스케일링된 VM(특권 모드로 인해 도입된 보안 취약점으로 인해 침해될 가능성이 있음)이 하나의 잡만 처리하도록 보장하는 MaxBuilds = 1 설정을 강력히 권장합니다.

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

고급 구성: 비공개 컨테이너 레지스트리 사용에 설명된 비공개 Docker 이미지 지원을 사용할 때는 pull_policy 값으로 always를 사용해야 합니다. 특히 Docker 또는 Kubernetes executor를 사용하는 공개 인스턴스 러너를 호스팅하는 경우 always 풀 정책을 사용해야 합니다.

풀 정책이 if-not-present로 설정된 경우의 예시를 살펴보겠습니다:

  1. 사용자 A는 registry.example.com/image/name에 비공개 이미지를 보유하고 있습니다.
  2. 사용자 A가 인스턴스 러너에서 빌드를 시작합니다: 빌드가 레지스트리 자격 증명을 받아 레지스트리에서 인증 후 이미지를 풀합니다.
  3. 이미지가 인스턴스 러너의 호스트에 저장됩니다.
  4. 사용자 B는 registry.example.com/image/name의 비공개 이미지에 대한 접근 권한이 없습니다.
  5. 사용자 B가 사용자 A와 동일한 인스턴스 러너에서 이 이미지를 사용하는 빌드를 시작합니다: 러너가 로컬 버전의 이미지를 찾아 자격 증명 누락으로 이미지를 풀할 수 없더라도 이를 사용합니다.

따라서 다양한 사용자와 프로젝트(공개 및 비공개 접근 수준이 혼합된)가 사용할 수 있는 러너를 호스팅하는 경우 풀 정책 값으로 if-not-present를 절대 사용하지 말고 다음을 사용하십시오:

  • never - 사용자가 사전에 다운로드한 이미지만 사용하도록 제한하려는 경우
  • always - 사용자가 모든 레지스트리에서 이미지를 다운로드할 수 있도록 하려는 경우

if-not-present 풀 정책은 신뢰할 수 있는 빌드와 사용자가 사용하는 특정 러너에 한해서만 사용해야 합니다.

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

SSH executor 사용#

SSH executor는 StrictHostKeyChecking 옵션이 없어 MITM 공격(중간자 공격)에 취약합니다. 이 문제는 향후 릴리스 중 하나에서 수정될 예정입니다.

Parallels executor 사용#

Parallels executor는 가장 안전한 옵션입니다. 전체 시스템 가상화를 사용하며, 격리된 가상화 모드로 실행되도록 구성된 VM 머신을 사용합니다. 모든 주변 장치와 공유 폴더에 대한 접근을 차단합니다.

러너 복제#

러너는 토큰을 사용하여 GitLab 서버에 자신을 식별합니다. 러너를 복제하면 복제된 러너가 해당 토큰에 대한 동일한 잡을 처리할 수 있습니다. 이는 러너 잡을 "탈취"하는 잠재적인 공격 벡터입니다.

공유 환경에서 GIT_STRATEGY: fetch 사용 시 보안 위험#

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

로컬 복사본을 사용하면 CI/CD 잡의 성능을 향상시킬 수 있습니다. 그러나 재사용 가능한 복사본에 접근할 수 있는 모든 사용자가 다른 사용자의 파이프라인에서 실행되는 코드를 추가할 수 있습니다.

Git은 서브모듈(다른 리포지터리 안에 내장된 리포지터리)의 내용을 상위 리포지터리의 Git reflog에 저장합니다. 따라서 프로젝트의 서브모듈이 처음 클론된 후에는 후속 잡이 스크립트에서 git submodule update를 실행하여 서브모듈의 내용에 접근할 수 있습니다. 이는 서브모듈이 삭제되었거나 잡을 시작한 사용자가 서브모듈 프로젝트에 대한 접근 권한이 없는 경우에도 적용됩니다.

공유 환경에 접근할 수 있는 모든 사용자를 신뢰하는 경우에만 GIT_STRATEGY: fetch를 사용하십시오.

보안 강화 옵션#

특권 컨테이너 사용의 보안 위험 감소#

Docker의 --privileged 플래그 사용이 필요한 CI/CD 잡을 실행해야 하는 경우, 다음 단계를 통해 보안 위험을 줄일 수 있습니다:

  • --privileged 플래그가 활성화된 Docker 컨테이너를 격리되고 에페머럴(ephemeral)한 가상 머신에서만 실행합니다.
  • Docker의 --privileged 플래그 사용이 필요한 잡을 실행하도록 전용 러너를 구성합니다. 그런 다음 이 러너가 보호된 브랜치에서만 잡을 실행하도록 구성합니다.

네트워크 분리#

GitLab Runner는 사용자 제어 스크립트를 실행하도록 설계되어 있습니다. 잡이 악성인 경우 공격 범위를 줄이기 위해 자체 네트워크 세그먼트에서 실행하는 것을 고려할 수 있습니다. 이를 통해 다른 인프라 및 서비스로부터 네트워크를 분리할 수 있습니다.

모든 요구 사항은 고유하지만 클라우드 환경에서는 다음을 포함할 수 있습니다:

  • 자체 네트워크 세그먼트에서 러너 가상 머신 구성
  • 인터넷에서 러너 가상 머신으로의 SSH 접근 차단
  • 러너 가상 머신 간의 트래픽 제한
  • 클라우드 공급자 메타데이터 엔드포인트에 대한 접근 필터링
Note

모든 러너는 GitLab.com 또는 GitLab 인스턴스에 대한 아웃바운드 네트워크 연결이 필요합니다. 대부분의 잡은 의존성 풀링 등을 위해 인터넷에 대한 아웃바운드 네트워크 연결도 필요합니다.

러너 호스트 보안 강화#

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

CI 잡 컨텍스트에서 실행된 악성 코드는 호스트를 침해할 수 있으므로 보안 프로토콜이 영향을 완화하는 데 도움이 될 수 있습니다. 호스트 시스템에서 SSH 키와 같이 공격자가 환경의 다른 엔드포인트에 접근할 수 있게 하는 파일을 보안하거나 제거하는 것도 염두에 두어야 합니다.

각 빌드 후 .git 폴더 정리#

러너에 정적 호스트를 사용하는 경우 FF_ENABLE_JOB_CLEANUP 기능 플래그를 활성화하여 추가 보안 레이어를 구현할 수 있습니다.

FF_ENABLE_JOB_CLEANUP을 활성화하면 각 빌드 후 러너가 호스트에서 사용하는 빌드 디렉토리가 정리됩니다.

셀프 매니지드 러너의 보안

Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기
요약

GitLab CI/CD 파이프라인은 단순하거나 복잡한 DevOps 자동화 작업에 사용되는 워크플로우 자동화 엔진입니다. GitLab CI/CD 잡을 셀프 매니지드 러너에서 실행할 계획이라면, 컴퓨팅 인프라와 네트워크에 보안 위험이 존재합니다.

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

  • 전체 기술 스택의 보안을 체계적으로 구성하는 접근 방식
  • 플랫폼의 구성과 사용에 대한 지속적이고 엄격한 검토

GitLab CI/CD 잡을 셀프 매니지드 러너에서 실행할 계획이라면, 컴퓨팅 인프라와 네트워크에 보안 위험이 존재합니다.

러너는 CI/CD 잡에 정의된 코드를 실행합니다. 프로젝트 리포지터리에 대한 Developer 권한을 가진 사용자는 의도적이든 아니든 러너를 호스팅하는 환경의 보안을 침해할 수 있습니다.

셀프 매니지드 러너가 비에페머럴(non-ephemeral)하고 여러 프로젝트에 사용되는 경우 이 위험은 더욱 심각합니다.

  • 악성 코드가 포함된 리포지터리의 잡은 비에페머럴 러너가 서비스하는 다른 리포지터리의 보안을 침해할 수 있습니다.
  • Executor에 따라 잡은 러너가 호스팅된 가상 머신에 악성 코드를 설치할 수 있습니다.
  • 침해된 환경에서 실행되는 잡에 노출된 시크릿 변수(CI_JOB_TOKEN 포함)는 탈취될 수 있습니다.
  • Developer 권한을 가진 사용자는 업스트림 프로젝트에 대한 접근 권한 없이도 프로젝트와 관련된 서브모듈에 접근할 수 있습니다.

Executor별 보안 위험#

사용하는 Executor에 따라 다른 보안 위험에 직면할 수 있습니다.

Shell executor 사용#

shell executor로 빌드를 실행할 때 러너 호스트와 네트워크에 높은 보안 위험이 존재합니다. 잡은 GitLab Runner 사용자의 권한으로 실행되며, 해당 서버에서 실행되는 다른 프로젝트의 코드를 탈취할 수 있습니다. 신뢰할 수 있는 빌드 실행에만 사용하십시오.

Docker executor 사용#

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

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

Warning

Docker의 특권 컨테이너는 호스트 VM의 모든 루트 권한을 가집니다. 자세한 내용은 런타임 권한 및 Linux 기능에 관한 공식 Docker 문서를 참조하십시오.

컨테이너를 특권 모드로 실행하는 것은 권장하지 않습니다.

특권 모드를 활성화하면 CI/CD 잡을 실행하는 사용자가 러너의 호스트 시스템에 대한 완전한 루트 접근 권한, 볼륨 마운트 및 분리 권한, 중첩 컨테이너 실행 권한을 얻을 수 있습니다.

특권 모드를 활성화하면 컨테이너의 모든 보안 메커니즘을 사실상 비활성화하고 호스트를 권한 상승에 노출시키며, 이는 컨테이너 탈출로 이어질 수 있습니다.

Docker Machine executor를 사용하는 경우, 단일 자동 스케일링된 VM(특권 모드로 인해 도입된 보안 취약점으로 인해 침해될 가능성이 있음)이 하나의 잡만 처리하도록 보장하는 MaxBuilds = 1 설정을 강력히 권장합니다.

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

고급 구성: 비공개 컨테이너 레지스트리 사용에 설명된 비공개 Docker 이미지 지원을 사용할 때는 pull_policy 값으로 always를 사용해야 합니다. 특히 Docker 또는 Kubernetes executor를 사용하는 공개 인스턴스 러너를 호스팅하는 경우 always 풀 정책을 사용해야 합니다.

풀 정책이 if-not-present로 설정된 경우의 예시를 살펴보겠습니다:

  1. 사용자 A는 registry.example.com/image/name에 비공개 이미지를 보유하고 있습니다.
  2. 사용자 A가 인스턴스 러너에서 빌드를 시작합니다: 빌드가 레지스트리 자격 증명을 받아 레지스트리에서 인증 후 이미지를 풀합니다.
  3. 이미지가 인스턴스 러너의 호스트에 저장됩니다.
  4. 사용자 B는 registry.example.com/image/name의 비공개 이미지에 대한 접근 권한이 없습니다.
  5. 사용자 B가 사용자 A와 동일한 인스턴스 러너에서 이 이미지를 사용하는 빌드를 시작합니다: 러너가 로컬 버전의 이미지를 찾아 자격 증명 누락으로 이미지를 풀할 수 없더라도 이를 사용합니다.

따라서 다양한 사용자와 프로젝트(공개 및 비공개 접근 수준이 혼합된)가 사용할 수 있는 러너를 호스팅하는 경우 풀 정책 값으로 if-not-present를 절대 사용하지 말고 다음을 사용하십시오:

  • never - 사용자가 사전에 다운로드한 이미지만 사용하도록 제한하려는 경우
  • always - 사용자가 모든 레지스트리에서 이미지를 다운로드할 수 있도록 하려는 경우

if-not-present 풀 정책은 신뢰할 수 있는 빌드와 사용자가 사용하는 특정 러너에 한해서만 사용해야 합니다.

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

SSH executor 사용#

SSH executor는 StrictHostKeyChecking 옵션이 없어 MITM 공격(중간자 공격)에 취약합니다. 이 문제는 향후 릴리스 중 하나에서 수정될 예정입니다.

Parallels executor 사용#

Parallels executor는 가장 안전한 옵션입니다. 전체 시스템 가상화를 사용하며, 격리된 가상화 모드로 실행되도록 구성된 VM 머신을 사용합니다. 모든 주변 장치와 공유 폴더에 대한 접근을 차단합니다.

러너 복제#

러너는 토큰을 사용하여 GitLab 서버에 자신을 식별합니다. 러너를 복제하면 복제된 러너가 해당 토큰에 대한 동일한 잡을 처리할 수 있습니다. 이는 러너 잡을 "탈취"하는 잠재적인 공격 벡터입니다.

공유 환경에서 GIT_STRATEGY: fetch 사용 시 보안 위험#

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

로컬 복사본을 사용하면 CI/CD 잡의 성능을 향상시킬 수 있습니다. 그러나 재사용 가능한 복사본에 접근할 수 있는 모든 사용자가 다른 사용자의 파이프라인에서 실행되는 코드를 추가할 수 있습니다.

Git은 서브모듈(다른 리포지터리 안에 내장된 리포지터리)의 내용을 상위 리포지터리의 Git reflog에 저장합니다. 따라서 프로젝트의 서브모듈이 처음 클론된 후에는 후속 잡이 스크립트에서 git submodule update를 실행하여 서브모듈의 내용에 접근할 수 있습니다. 이는 서브모듈이 삭제되었거나 잡을 시작한 사용자가 서브모듈 프로젝트에 대한 접근 권한이 없는 경우에도 적용됩니다.

공유 환경에 접근할 수 있는 모든 사용자를 신뢰하는 경우에만 GIT_STRATEGY: fetch를 사용하십시오.

보안 강화 옵션#

특권 컨테이너 사용의 보안 위험 감소#

Docker의 --privileged 플래그 사용이 필요한 CI/CD 잡을 실행해야 하는 경우, 다음 단계를 통해 보안 위험을 줄일 수 있습니다:

  • --privileged 플래그가 활성화된 Docker 컨테이너를 격리되고 에페머럴(ephemeral)한 가상 머신에서만 실행합니다.
  • Docker의 --privileged 플래그 사용이 필요한 잡을 실행하도록 전용 러너를 구성합니다. 그런 다음 이 러너가 보호된 브랜치에서만 잡을 실행하도록 구성합니다.

네트워크 분리#

GitLab Runner는 사용자 제어 스크립트를 실행하도록 설계되어 있습니다. 잡이 악성인 경우 공격 범위를 줄이기 위해 자체 네트워크 세그먼트에서 실행하는 것을 고려할 수 있습니다. 이를 통해 다른 인프라 및 서비스로부터 네트워크를 분리할 수 있습니다.

모든 요구 사항은 고유하지만 클라우드 환경에서는 다음을 포함할 수 있습니다:

  • 자체 네트워크 세그먼트에서 러너 가상 머신 구성
  • 인터넷에서 러너 가상 머신으로의 SSH 접근 차단
  • 러너 가상 머신 간의 트래픽 제한
  • 클라우드 공급자 메타데이터 엔드포인트에 대한 접근 필터링
Note

모든 러너는 GitLab.com 또는 GitLab 인스턴스에 대한 아웃바운드 네트워크 연결이 필요합니다. 대부분의 잡은 의존성 풀링 등을 위해 인터넷에 대한 아웃바운드 네트워크 연결도 필요합니다.

러너 호스트 보안 강화#

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

CI 잡 컨텍스트에서 실행된 악성 코드는 호스트를 침해할 수 있으므로 보안 프로토콜이 영향을 완화하는 데 도움이 될 수 있습니다. 호스트 시스템에서 SSH 키와 같이 공격자가 환경의 다른 엔드포인트에 접근할 수 있게 하는 파일을 보안하거나 제거하는 것도 염두에 두어야 합니다.

각 빌드 후 .git 폴더 정리#

러너에 정적 호스트를 사용하는 경우 FF_ENABLE_JOB_CLEANUP 기능 플래그를 활성화하여 추가 보안 레이어를 구현할 수 있습니다.

FF_ENABLE_JOB_CLEANUP을 활성화하면 각 빌드 후 러너가 호스트에서 사용하는 빌드 디렉토리가 정리됩니다.