컨테이너 스캔
GitLab v19.5Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
요약
컨테이너 이미지의 보안 취약점은 애플리케이션 라이프사이클 전반에 걸쳐 위험을 초래합니다. 컨테이너 스캔은 흔히 소프트웨어 구성 분석(SCA)의 일부로 간주됩니다. GitLab은 이러한 모든 의존성 유형을 포괄하기 위해 컨테이너 스캔과 의존성 스캐닝을 모두 제공합니다.
컨테이너 이미지의 보안 취약점은 애플리케이션 라이프사이클 전반에 걸쳐 위험을 초래합니다. 컨테이너 스캔은 이러한 위험이 프로덕션 환경에 도달하기 전에 조기에 탐지합니다. 베이스 이미지나 운영 체제 패키지에 취약점이 나타나면 컨테이너 스캔이 이를 식별하고, 가능한 경우 수정 경로를 제공합니다.
- 개요는 컨테이너 스캔 - 고급 보안 테스트를 참고합니다.
- 동영상 안내는 GitLab을 사용한 컨테이너 스캔 설정 방법을 참고합니다.
- 입문 튜토리얼은 Docker 컨테이너의 취약점 스캔을 참고합니다.
컨테이너 스캔은 흔히 소프트웨어 구성 분석(SCA)의 일부로 간주됩니다. SCA에는 코드가 사용하는 항목을 검사하는 측면이 포함될 수 있습니다. 이러한 항목에는 일반적으로 직접 작성한 것이 아니라 외부 소스에서 가져오는 애플리케이션 및 시스템 의존성이 거의 항상 포함됩니다.
GitLab은 이러한 모든 의존성 유형을 포괄하기 위해 컨테이너 스캔과 의존성 스캐닝을 모두 제공합니다. 위험 영역을 최대한 커버하려면 모든 보안 스캐너를 사용합니다. 이러한 기능의 비교는 의존성 스캐닝과 컨테이너 스캔 비교를 참고합니다.
GitLab은 Trivy 보안 스캐너와 통합하여 컨테이너에서 취약점 정적 분석을 수행합니다.
Grype 분석기는 GitLab 지원 정책에서 설명하는 제한적인 수정을 제외하고 더 이상 유지 관리되지 않습니다. Grype 분석기 이미지의 현재 주요 버전은 GitLab 19.0까지 최신 어드바이저리 데이터베이스와 운영 체제 패키지로 계속 업데이트되며, 이 시점 이후에는 분석기가 작동을 멈춥니다.
기능#
| 기능 | Free 및 Premium | Ultimate |
|---|---|---|
| 설정 커스터마이즈(변수, 재정의, 오프라인 환경 지원 등) | ✅ | ✅ |
| CI job 아티팩트로 JSON 보고서 보기 | ✅ | ✅ |
| CI job 아티팩트로 CycloneDX SBOM JSON 보고서 생성 | ✅ | ✅ |
| GitLab UI에서 MR을 통해 컨테이너 스캔을 활성화하는 기능 | ✅ | ✅ |
| UBI 이미지 지원 | ✅ | ✅ |
| Trivy 지원 | ✅ | ✅ |
| 수명 종료(EOL) 운영 체제 탐지 | ✅ | ✅ |
| GitLab 어드바이저리 데이터베이스 포함 | GitLab advisories-community 프로젝트의 시간 지연 콘텐츠로 제한됨 | 예 - Gemnasium DB의 모든 최신 콘텐츠 |
| 머지 리퀘스트 및 CI 파이프라인 job의 보안 탭에 보고서 데이터 표시 | ❌ | ✅ |
| 취약점 해결책(자동 수정) | ❌ | ✅ |
| 취약점 허용 목록 지원 | ❌ | ✅ |
| 의존성 목록 페이지 접근 | ❌ | ✅ |
시작하기#
CI/CD 파이프라인에서 컨테이너 스캔 분석기를 활성화합니다. 파이프라인이 실행되면 애플리케이션이 의존하는 이미지에서 취약점을 스캔합니다. CI/CD 변수를 사용하여 컨테이너 스캔을 커스터마이즈할 수 있습니다.
사전 요구 사항:
.gitlab-ci.yml파일에 test stage가 필요합니다.- Self-managed 러너를 사용하는 경우 Linux/amd64에서
docker또는kubernetesexecutor가 있는 러너가 필요합니다. GitLab.com의 인스턴스 러너를 사용하는 경우 기본적으로 활성화되어 있습니다. - 지원되는 배포판과 일치하는 이미지.
- Docker 이미지를 프로젝트의 컨테이너 레지스트리에 빌드하고 푸시합니다.
- 서드파티 컨테이너 레지스트리를 사용하는 경우 CI/CD 변수
CS_REGISTRY_USER및CS_REGISTRY_PASSWORD를 사용하여 인증 자격 증명을 제공해야 할 수 있습니다. 이러한 변수 사용 방법에 대한 자세한 내용은 프라이빗 외부 레지스트리 인증을 참고합니다.
분석기를 활성화하려면 다음 중 하나를 수행합니다:
- 의존성 스캐닝이 포함된 Auto DevOps를 활성화합니다.
- 미리 구성된 머지 리퀘스트를 사용합니다.
- 컨테이너 스캔을 강제하는 스캔 실행 정책을 생성합니다.
.gitlab-ci.yml파일을 수동으로 편집합니다.
미리 구성된 머지 리퀘스트 사용#
이 방법은 .gitlab-ci.yml 파일에 컨테이너 스캔 템플릿을 포함하는 머지 리퀘스트를
자동으로 준비합니다. 이 머지 리퀘스트를 머지하면 컨테이너 스캔이 활성화됩니다.
이 방법은 기존 .gitlab-ci.yml 파일이 없거나 최소한의 구성 파일만 있을 때 가장 잘
작동합니다. 복잡한 GitLab 구성 파일이 있으면 파일이 제대로 파싱되지 않아 오류가
발생할 수 있습니다. 이 경우에는 수동 방법을 사용합니다.
사전 요구 사항:
- 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
.gitlab-ci.yml파일에teststage가 있어야 합니다.- Self-managed 러너를 사용하는 경우 Linux/amd64에서
docker또는kubernetesexecutor가 있는 러너가 필요합니다. GitLab.com의 인스턴스 러너를 사용하는 경우 기본적으로 활성화되어 있습니다. - 지원되는 배포판과 일치하는 이미지.
- Docker 이미지가 프로젝트의 컨테이너 레지스트리에 빌드 및 푸시되어 있어야 합니다.
- 서드파티 컨테이너 레지스트리를 사용하는 경우 CI/CD 변수
CS_REGISTRY_USER및CS_REGISTRY_PASSWORD를 사용하여 인증 자격 증명을 제공해야 할 수 있습니다. 자세한 내용은 프라이빗 외부 레지스트리 인증을 참고합니다.
컨테이너 스캔을 활성화하려면 다음을 수행합니다:
- 상단 메뉴바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
- 왼쪽 사이드바에서 Secure > Security configuration을 선택합니다.
- Container Scanning 행에서 Configure with a merge request를 선택합니다.
- Create merge request를 선택합니다.
- 머지 리퀘스트를 검토한 다음 Merge를 선택합니다.
이제 파이프라인에 컨테이너 스캔 job이 포함됩니다.
.gitlab-ci.yml 파일 수동 편집#
이 방법에서는 기존 .gitlab-ci.yml 파일을 직접 수정해야 합니다. GitLab 구성 파일이
복잡하거나 기본값이 아닌 옵션을 사용해야 하는 경우 이 방법을 사용합니다.
사전 요구 사항:
- 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
.gitlab-ci.yml파일에teststage가 있어야 합니다.- Self-managed 러너를 사용하는 경우 Linux/amd64에서
docker또는kubernetesexecutor가 있는 러너가 필요합니다. GitLab.com의 인스턴스 러너를 사용하는 경우 기본적으로 활성화되어 있습니다. - 지원되는 배포판과 일치하는 이미지.
- Docker 이미지가 프로젝트의 컨테이너 레지스트리에 빌드 및 푸시되어 있어야 합니다.
- 서드파티 컨테이너 레지스트리를 사용하는 경우 CI/CD 변수
CS_REGISTRY_USER및CS_REGISTRY_PASSWORD를 사용하여 인증 자격 증명을 제공해야 할 수 있습니다. 자세한 내용은 프라이빗 외부 레지스트리 인증을 참고합니다.
컨테이너 스캔을 활성화하려면 다음을 수행합니다:
-
상단 메뉴바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
-
왼쪽 사이드바에서 Build > Pipeline editor를 선택합니다.
-
.gitlab-ci.yml파일이 없으면 Configure pipeline을 선택한 다음 예제 내용을 삭제합니다. -
다음을
.gitlab-ci.yml파일 하단에 복사하여 붙여넣습니다.include줄이 이미 있으면 그 아래에template줄만 추가합니다.include: - template: Jobs/Container-Scanning.gitlab-ci.yml -
Validate 탭을 선택한 다음 Validate pipeline을 선택합니다.
Simulation completed successfully 메시지가 표시되면 파일이 유효하다는 뜻입니다.
-
Edit 탭을 선택합니다.
-
필드를 완성합니다. Branch 필드에는 기본 브랜치를 사용하지 않습니다.
-
Start a new merge request with these changes 체크박스를 선택한 다음 Commit changes를 선택합니다.
-
표준 워크플로에 따라 필드를 완성한 다음 Create merge request를 선택합니다.
-
표준 워크플로에 따라 머지 리퀘스트를 검토하고 편집한 다음 파이프라인이 통과할 때까지 기다린 후 Merge를 선택합니다.
이제 파이프라인에 컨테이너 스캔 job이 포함됩니다.
결과 이해하기#
사전 요구 사항:
- 프로젝트에 대한 Security Manager, Developer, Maintainer 또는 Owner 권한.
파이프라인에서 취약점을 검토할 수 있습니다:
- 상단 메뉴바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
- 왼쪽 사이드바에서 Build > Pipelines를 선택합니다.
- 파이프라인을 선택합니다.
- Security 탭을 선택합니다.
- 취약점을 선택하여 다음을 포함한 세부 정보를 확인합니다:
- Description: 취약점의 원인, 잠재적 영향, 권장 수정 단계를 설명합니다.
- Status: 취약점이 검토되었는지 또는 해결되었는지를 나타냅니다.
- Severity: 영향도에 따라 6개 수준으로 분류됩니다. 심각도 수준에 대해 자세히 알아보기.
- CVSS score: 심각도에 대응하는 숫자 값을 제공합니다.
- EPSS: 취약점이 실제로 악용될 가능성을 나타냅니다.
- Has Known Exploit (KEV): 해당 취약점이 악용된 적이 있음을 나타냅니다.
- Project: 취약점이 발견된 프로젝트를 표시합니다.
- Report type: 출력 유형을 설명합니다.
- Scanner: 취약점을 탐지한 분석기를 식별합니다.
- Image: 취약점이 귀속된 이미지를 제공합니다.
- Namespace: 취약점이 귀속된 워크스페이스를 식별합니다.
- Links: 다양한 어드바이저리 데이터베이스에 등재된 취약점의 증거입니다.
- Identifiers: CVE 식별자 등 취약점을 분류하는 데 사용되는 참조 목록입니다.
자세한 내용은 파이프라인 보안 보고서를 참고합니다.
컨테이너 스캔 결과를 확인하는 추가 방법:
- 취약점 보고서: 기본 브랜치에서 확인된 취약점을 표시합니다.
- 컨테이너 스캔 보고서 아티팩트
최적화#
GitLab은 컨테이너 스캔에 대해 두 가지 접근 방식을 제공합니다:
- 표준 컨테이너 스캔: job당 단일 컨테이너 이미지를 스캔합니다. 단순하고 분산된 워크플로에 적합합니다.
- 멀티 컨테이너 스캔: 하나의 구성 파일로 여러 이미지를 병렬로 스캔합니다. 여러 이미지를 효율적으로 스캔하는 데 적합합니다.
배포#
단일 프로젝트에서 컨테이너 스캔 결과에 대한 확신이 생기면 다른 프로젝트로 구현을 확장할 수 있습니다:
지원되는 배포판#
다음 Linux 배포판이 지원됩니다:
- Alma Linux
- Alpine Linux
- Amazon Linux
- CentOS
- CBL-Mariner
- Debian
- Distroless
- Oracle Linux
- Photon OS
- Red Hat (RHEL)
- Rocky Linux
- SUSE
- Ubuntu
FIPS 지원 이미지#
GitLab은 컨테이너 스캔 이미지의 FIPS 지원 Red Hat UBI
버전도 제공합니다. 따라서 표준 이미지를 FIPS 지원 이미지로 교체할 수 있습니다. 이미지를
구성하려면 CS_IMAGE_SUFFIX를 -fips로 설정하거나 CS_ANALYZER_IMAGE 변수를 표준
태그에 -fips 확장자를 붙인 값으로 수정합니다.
GitLab 인스턴스에서 FIPS 모드가 활성화되면 CS_ANALYZER_IMAGE에 -fips 플래그가 자동으로 추가됩니다.
FIPS 모드가 활성화된 경우 인증이 필요한 레지스트리에 있는 이미지의 컨테이너 스캔은
지원되지 않습니다. CI_GITLAB_FIPS_MODE가 "true"이고 CS_REGISTRY_USER 또는
CS_REGISTRY_PASSWORD가 설정되어 있으면 분석기가 오류와 함께 종료되고 스캔을 수행하지 않습니다.
구성#
분석기 동작 커스터마이즈#
컨테이너 스캔을 커스터마이즈하려면 CI/CD 변수를 사용합니다.
자세한 출력 활성화#
문제 해결 시와 같이 의존성 스캐닝 job이 수행하는 작업을 자세히 확인해야 할 때 자세한 출력을 활성화합니다.
다음 예시에서는 컨테이너 스캔 템플릿을 포함하고 자세한 출력을 활성화합니다.
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
variables:
SECURE_LOG_LEVEL: 'debug'
언어별 결과 보고#
CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN CI/CD 변수는 스캔이 프로그래밍 언어와 관련된
결과를 보고할지 여부를 제어합니다. 지원되는 언어에 대한 자세한 내용은 Trivy 문서의 언어별 패키지를 참고합니다.
기본적으로 보고서에는 운영 체제(OS) 패키지 관리자가 관리하는 패키지만 포함됩니다
(예: yum, apt, apk, tdnf). OS가 아닌 패키지의 보안 결과를 보고하려면
CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN을 "false"로 설정합니다:
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN: "false"
이 기능을 활성화하면 프로젝트에서 의존성 스캐닝이 활성화되어 있는 경우 취약점 보고서에 중복 결과가 나타날 수 있습니다. 이는 GitLab이 서로 다른 유형의 스캔 도구 간에 결과를 자동으로 중복 제거할 수 없기 때문입니다. 어떤 유형의 의존성이 중복될 가능성이 높은지 알아보려면 의존성 스캐닝과 컨테이너 스캔 비교를 참고합니다.
머지 리퀘스트 파이프라인에서 job 실행#
머지 리퀘스트 파이프라인에서 보안 스캔 도구 사용을 참고합니다.
사용 가능한 CI/CD 변수#
컨테이너 스캔을 커스터마이즈하려면 CI/CD 변수를 사용합니다. 다음 표는 컨테이너 스캔에 특정한 CI/CD 변수를 나열합니다. 미리 정의된 CI/CD 변수도 사용할 수 있습니다.
GitLab 분석기의 커스터마이즈는 기본 브랜치에 병합하기 전에 머지 리퀘스트에서 테스트합니다. 그렇게 하지 않으면 대량의 오탐을 포함해 예상치 못한 결과가 발생할 수 있습니다.
| CI/CD 변수 | 기본값 | 설명 |
|---|---|---|
ADDITIONAL_CA_CERT_BUNDLE |
"" |
신뢰할 CA 인증서 묶음입니다. 자세한 내용은 커스텀 SSL CA 인증 기관 사용을 참고합니다. |
CI_APPLICATION_REPOSITORY |
$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG |
스캔할 이미지의 Docker 리포지터리 URL입니다. |
CI_APPLICATION_TAG |
$CI_COMMIT_SHA |
스캔할 이미지의 Docker 리포지터리 태그입니다. |
CS_ANALYZER_IMAGE |
registry.gitlab.com/security-products/container-scanning:8 |
분석기의 Docker 이미지입니다. GitLab이 제공하는 분석기 이미지에는 :latest 태그를 사용하지 않습니다. |
CS_DEFAULT_BRANCH_IMAGE |
"" |
기본 브랜치에서 CS_IMAGE의 이름입니다. 자세한 내용은 기본 브랜치 이미지 설정을 참고합니다. |
CS_DISABLE_DEPENDENCY_LIST |
"false" |
⚠️ GitLab 17.0에서 제거됨. |
CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN |
"true" |
스캔된 이미지에 설치된 언어별 패키지의 스캔을 비활성화합니다. |
CS_DOCKER_INSECURE |
"false" |
인증서를 검증하지 않고 HTTPS를 사용하는 보안 Docker 레지스트리에 대한 접근을 허용합니다. |
CS_DOCKERFILE_PATH |
Dockerfile |
수정을 생성하는 데 사용할 Dockerfile의 경로입니다. 기본적으로 스캐너는 프로젝트의 루트 디렉터리에서 Dockerfile이라는 이름의 파일을 찾습니다. Dockerfile이 하위 디렉터리 등 비표준 위치에 있는 경우에만 이 변수를 구성합니다. 자세한 내용은 취약점 해결책을 참고합니다. |
CS_INCLUDE_LICENSES |
"" |
설정하면 각 구성 요소의 라이선스를 포함합니다. cyclonedx 보고서에만 적용되며, 해당 라이선스는 trivy에서 제공됩니다. |
CS_IGNORE_STATUSES |
"" |
분석기가 쉼표로 구분된 목록에 지정된 상태의 결과를 무시하도록 강제합니다. 허용되는 값은 다음과 같습니다: unknown,not_affected,affected,fixed,under_investigation,will_not_fix,fix_deferred,end_of_life.1 |
CS_IGNORE_UNFIXED |
"false" |
수정되지 않은 결과를 무시합니다. 무시된 결과는 보고서에 포함되지 않습니다. |
CS_IMAGE |
$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG |
스캔할 Docker 이미지입니다. 설정하면 이 변수가 $CI_APPLICATION_REPOSITORY 및 $CI_APPLICATION_TAG 변수를 재정의합니다. |
CS_IMAGE_SUFFIX |
"" |
CS_ANALYZER_IMAGE에 추가되는 접미사입니다. -fips로 설정하면 스캔에 FIPS-enabled 이미지가 사용됩니다. 자세한 내용은 FIPS 지원 이미지를 참고합니다. |
CS_QUIET |
"" |
설정하면 job 로그에서 취약점 표 출력을 비활성화합니다. |
CS_REGISTRY_INSECURE |
"false" |
안전하지 않은 레지스트리(HTTP만)에 대한 접근을 허용합니다. 로컬에서 이미지를 테스트할 때만 true로 설정해야 합니다. 모든 스캐너에서 작동하지만, Trivy가 동작하려면 레지스트리가 80/tcp 포트에서 리슨해야 합니다. |
CS_REGISTRY_PASSWORD |
$CI_REGISTRY_PASSWORD |
인증이 필요한 Docker 레지스트리에 접근하기 위한 비밀번호입니다. 기본값은 $CS_IMAGE가 $CI_REGISTRY에 있는 경우에만 설정됩니다. FIPS 모드가 활성화된 경우에는 지원되지 않습니다. |
CS_REGISTRY_USER |
$CI_REGISTRY_USER |
인증이 필요한 Docker 레지스트리에 접근하기 위한 사용자 이름입니다. 기본값은 $CS_IMAGE가 $CI_REGISTRY에 있는 경우에만 설정됩니다. FIPS 모드가 활성화된 경우에는 지원되지 않습니다. |
CS_REPORT_OS_EOL |
"false" |
EOL 탐지를 활성화합니다. |
CS_REPORT_OS_EOL_SEVERITY |
"Medium" |
CS_REPORT_OS_EOL이 활성화된 경우 EOL OS 결과에 지정되는 심각도 수준입니다. EOL 결과는 CS_SEVERITY_THRESHOLD와 무관하게 항상 보고됩니다. 지원되는 수준은 UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL입니다. |
CS_SEVERITY_THRESHOLD |
UNKNOWN |
심각도 수준 기준값입니다. 스캐너는 이 기준값보다 높거나 같은 심각도 수준의 취약점을 출력합니다. 지원되는 수준은 UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL입니다. |
CS_TRIVY_JAVA_DB |
"registry.gitlab.com/gitlab-org/security-products/dependencies/trivy-java-db" |
trivy-java-db 취약점 데이터베이스의 대체 위치를 지정합니다. |
CS_TRIVY_DETECTION_PRIORITY |
"precise" |
정의된 Trivy 탐지 우선순위를 사용하여 스캔합니다. 허용되는 값은 precise 또는 comprehensive입니다. |
SECURE_LOG_LEVEL |
info |
최소 로깅 수준을 설정합니다. 이 로깅 수준 이상의 메시지가 출력됩니다. 심각도가 높은 순서부터 낮은 순서로 로깅 수준은 다음과 같습니다: fatal, error, warn, info, debug. |
TRIVY_TIMEOUT |
5m0s |
스캔 제한 시간을 설정합니다. |
TRIVY_PLATFORM |
linux/amd64 |
이미지가 멀티 플랫폼을 지원하는 경우 os/arch 형식으로 플랫폼을 설정합니다. |
기본 환경 변수로 Trivy 직접 구성#
위에 나열된 GitLab 전용 CS_* 변수 외에도 container_scanning job에서
기본 환경 변수 중 하나를
설정하여 Trivy를 직접 구성할 수 있습니다. GitLab 컨테이너 스캔 분석기는 모든 환경
변수를 Trivy로 자동으로 전달합니다.
예를 들어 Trivy가 자동으로 감지할 수 없는 컨테이너 이미지(예: 커스터마이즈된 베이스 이미지)의 OS 배포판을 수동으로 지정하려면 다음을 사용합니다:
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
GIT_STRATEGY: fetch
TRIVY_DISTRO: "alma/10"
TRIVY_DISTRO가 사용하는 --distro 플래그는 Trivy의 실험 기능입니다.
결과는 Trivy 버전과 지정한 배포판에 따라 달라질 수 있습니다.
GitLab 래퍼에서 관리하는 변수#
다음 TRIVY_* 변수는 GitLab 컨테이너 스캔 분석기 내부에서 설정됩니다.
해당하는 GitLab CI/CD 변수로 제어되며 직접 재정의할 수 없습니다:
| Trivy 변수 | GitLab CI/CD 변수 |
|---|---|
TRIVY_CACHE_DIR |
(내부용, 노출되지 않음) |
TRIVY_USERNAME |
CS_REGISTRY_USER |
TRIVY_PASSWORD |
CS_REGISTRY_PASSWORD |
TRIVY_DEBUG |
SECURE_LOG_LEVEL |
TRIVY_INSECURE |
CS_DOCKER_INSECURE |
TRIVY_NON_SSL |
CS_REGISTRY_INSECURE |
TRIVY_DB_REPOSITORY의 알려진 문제#
TRIVY_DB_REPOSITORY를 설정하여 Trivy가 커스텀 취약점 데이터베이스를 가리키도록 해도
효과가 없습니다. GitLab 컨테이너 스캔 분석기는 취약점 데이터베이스를 분석기 이미지
내부에 포함하고, 런타임에 --skip-db-update를 Trivy에 전달하므로 이 변수와
무관하게 Trivy는 데이터베이스를 다운로드하지 않습니다. 커스텀 데이터베이스 위치를
사용하려면 Java 데이터베이스는 Trivy Java 데이터베이스 미러 사용을,
일반적인 오프라인 설정은 오프라인 환경을 참고합니다.
컨테이너 스캔 템플릿 재정의#
job 정의를 재정의하려는 경우(예: variables 같은 속성을 변경하는 경우), 템플릿을
포함한 뒤에 job을 선언하고 재정의한 다음 추가 키를 지정해야
합니다.
이 예시는 GIT_STRATEGY를 fetch로 설정합니다:
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
GIT_STRATEGY: fetch
외부 레지스트리의 이미지 스캔#
기본적으로 컨테이너 스캔은 GitLab 컨테이너 레지스트리에 있는 이미지를 스캔합니다. 외부 레지스트리에 있는 이미지도 스캔할 수 있습니다.
외부 레지스트리에 있는 이미지를 스캔하려면 이미지의 전체 경로로
CS_IMAGE 변수를 구성합니다.
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
CS_IMAGE: <example.com>/<user>/<image>:<tag>
프라이빗 외부 레지스트리 인증#
외부 레지스트리에 인증이 필요한 경우 CS_REGISTRY_USER 및
CS_REGISTRY_PASSWORD CI/CD 변수를 사용하여 자격 증명을 제공합니다.
FIPS 모드가 활성화된 경우 외부 프라이빗 레지스트리에 있는 이미지의 스캔은 지원되지 않습니다.
예를 들어 Google Container Registry에 있는 이미지를 스캔하려면 다음과 같이 합니다:
-
Google Cloud Platform Container Registry 문서에 설명된 대로 JSON 키가 포함된
GCP_CREDENTIALSCI/CD 변수를 추가합니다.- 이 변수의 값은 마스킹 변수 옵션의 마스킹 요구 사항에 맞지 않을 수 있으므로 job 로그에 값이 노출될 수 있습니다.
- 보호 변수 옵션을 선택하면 보호되지 않은 기능 브랜치에서 스캔이 실행되지 않을 수 있습니다.
- 이러한 옵션을 선택하지 않는 경우 읽기 전용 권한으로 자격 증명을 생성하고 정기적으로 교체하는 것을 고려합니다.
-
.gitlab-ci.yml파일에 다음을 추가합니다.include: - template: Jobs/Container-Scanning.gitlab-ci.yml container_scanning: variables: CS_REGISTRY_USER: _json_key CS_REGISTRY_PASSWORD: "$GCP_CREDENTIALS" CS_IMAGE: "gcr.io/<path-to-your-registry>/<image>:<tag>"
예를 들어 AWS Elastic Container Registry에 있는 이미지를 스캔하려면 다음과 같이 합니다:
-
.gitlab-ci.yml파일에 다음을 추가합니다:container_scanning: before_script: - ruby -r open-uri -e "IO.copy_stream(URI.open('https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip'), 'awscliv2.zip')" - unzip awscliv2.zip - sudo ./aws/install - export AWS_ECR_PASSWORD=$(aws ecr get-login-password --region <region>) include: - template: Jobs/Container-Scanning.gitlab-ci.yml variables: CS_IMAGE: <aws_account_id>.dkr.ecr.<region>.amazonaws.com/<image>:<tag> CS_REGISTRY_USER: AWS CS_REGISTRY_PASSWORD: "$AWS_ECR_PASSWORD" AWS_DEFAULT_REGION: <region>
Trivy Java 데이터베이스 미러 사용#
trivy 스캐너를 사용하고 스캔 대상 컨테이너 이미지에서 jar 파일이 발견되면,
trivy는 추가로 trivy-java-db 취약점 데이터베이스를 다운로드합니다. 기본적으로
trivy-java-db 데이터베이스는 ghcr.io/aquasecurity/trivy-java-db:1에 OCI 아티팩트로
호스팅됩니다. 이 레지스트리에
접근할 수 없거나
TOOMANYREQUESTS 응답이 발생하는 경우, 더 접근하기 쉬운 컨테이너 레지스트리로
trivy-java-db를 미러링하는 것이 하나의 해결책입니다:
mirror trivy java db:
image:
name: ghcr.io/oras-project/oras:v1.1.0
entrypoint: [""]
script:
- oras login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- oras pull ghcr.io/aquasecurity/trivy-java-db:1
- oras push $CI_REGISTRY_IMAGE:1 --config /dev/null:application/vnd.aquasec.trivy.config.v1+json javadb.tar.gz:application/vnd.aquasec.trivy.javadb.layer.v1.tar+gzip
취약점 데이터베이스는 일반적인 Docker 이미지가 아니므로 docker pull으로
가져올 수 없습니다. GitLab UI에서 확인하면 이미지에 오류가 표시됩니다.
컨테이너 레지스트리가 gitlab.example.com/trivy-java-db-mirror인 경우, 컨테이너 스캔
job을 다음과 같이 구성해야 합니다. 끝에 태그 :1은 추가하지 않으며, 이는
trivy가 추가합니다:
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
CS_TRIVY_JAVA_DB: gitlab.example.com/trivy-java-db-mirror
기본 브랜치 이미지 설정#
기본적으로 컨테이너 스캔은 이미지 이름 지정 규칙이 브랜치별 식별자를 이미지 이름이 아니라 이미지 태그에 저장한다고 가정합니다. 기본 브랜치와 기본이 아닌 브랜치 사이에 이미지 이름이 다른 경우, 이전에 탐지된 취약점이 머지 리퀘스트에서 새로 탐지된 것처럼 표시됩니다.
기본 브랜치와 기본이 아닌 브랜치에서 동일한 이미지가 다른 이름을 사용하는 경우
CS_DEFAULT_BRANCH_IMAGE 변수를 사용하여 기본 브랜치에서 해당 이미지의 이름을 지정할 수 있습니다.
그러면 GitLab이 기본이 아닌 브랜치에서 스캔을 실행할 때 취약점이 이미 존재하는지
올바르게 판단합니다.
예를 들어 다음과 같은 상황을 가정해 보겠습니다:
- 기본이 아닌 브랜치는
$CI_REGISTRY_IMAGE/$CI_COMMIT_BRANCH:$CI_COMMIT_SHA이름 지정 규칙으로 이미지를 게시합니다. - 기본 브랜치는
$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA이름 지정 규칙으로 이미지를 게시합니다.
이 경우 다음 CI/CD 구성을 사용하여 취약점이 중복되지 않도록 할 수 있습니다:
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
before_script:
- export CS_IMAGE="$CI_REGISTRY_IMAGE/$CI_COMMIT_BRANCH:$CI_COMMIT_SHA"
- |
if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
export CS_IMAGE="$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
fi
CS_DEFAULT_BRANCH_IMAGE는 특정 CS_IMAGE에 대해 항상 동일한 값을 유지해야 합니다.
값이 바뀌면 취약점 집합이 중복 생성되며, 이는 직접 해제해야 합니다.
Auto DevOps를 사용하는 경우 CS_DEFAULT_BRANCH_IMAGE는
$CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_APPLICATION_TAG로 자동 설정됩니다.
커스텀 SSL CA 인증 기관 사용#
ADDITIONAL_CA_CERT_BUNDLE CI/CD 변수를 사용하여 커스텀 SSL CA 인증 기관을 구성할 수 있습니다. 이 인증 기관은 HTTPS를 사용하는 레지스트리에서 Docker 이미지를 가져올 때 피어를 확인하는 데 사용됩니다. ADDITIONAL_CA_CERT_BUNDLE 값에는 X.509 PEM 공개 키 인증서의 텍스트 표현이 포함되어야 합니다. 예를 들어 .gitlab-ci.yml 파일에서 이 값을 구성하려면 다음을 사용합니다:
container_scanning:
variables:
ADDITIONAL_CA_CERT_BUNDLE: |
-----BEGIN CERTIFICATE-----
MIIGqTCCBJGgAwIBAgIQI7AVxxVwg2kch4d56XNdDjANBgkqhkiG9w0BAQsFADCB
...
jWgmPqF3vUbZE0EyScetPJquRFRKIesyJuBFMAs=
-----END CERTIFICATE-----
ADDITIONAL_CA_CERT_BUNDLE 값은 UI에서 커스텀 변수로 구성할 수도 있으며, 인증서 경로가
필요한 file 형식이나 인증서의 텍스트 표현이 필요한 변수 형식 중 하나로
구성합니다.
멀티 아키텍처 이미지 스캔#
TRIVY_PLATFORM CI/CD 변수를 사용하여 특정 운영 체제 및 아키텍처에 대해 컨테이너 스캔을 실행하도록
구성할 수 있습니다. 예를 들어 .gitlab-ci.yml 파일에서 이 값을 구성하려면
다음을 사용합니다:
container_scanning:
# Use an arm64 SaaS runner to scan this natively
tags: ["saas-linux-small-arm64"]
variables:
TRIVY_PLATFORM: "linux/arm64"
취약점 허용 목록#
사전 요구 사항:
- 프로젝트에 대한 Developer, Maintainer 또는 Owner 권한.
특정 취약점을 허용 목록에 추가하려면 다음 단계를 따릅니다:
- 컨테이너 스캔 템플릿 재정의의 안내에 따라
.gitlab-ci.yml파일에서GIT_STRATEGY: fetch를 설정합니다. - 허용 목록에 추가할 취약점을
vulnerability-allowlist.yml이라는 YAML 파일에 정의합니다. 이때vulnerability-allowlist.yml데이터 형식에 설명된 형식을 사용해야 합니다. vulnerability-allowlist.yml파일을 프로젝트의 Git 리포지터리 루트 폴더에 추가합니다.
vulnerability-allowlist.yml 데이터 형식#
vulnerability-allowlist.yml 파일은 오탐이거나 적용되지 않아 존재해도 되는 취약점의 CVE ID 목록을 지정하는 YAML 파일입니다.
vulnerability-allowlist.yml 파일에서 일치하는 항목이 발견되면 다음과 같이 처리됩니다:
- 분석기가
gl-container-scanning-report.json파일을 생성할 때 해당 취약점이 포함되지 않습니다. - 파이프라인의 보안 탭에 해당 취약점이 표시되지 않습니다. 보안 탭의 소스 오브 트루스인 JSON 파일에 포함되지 않기 때문입니다.
vulnerability-allowlist.yml 파일 예시:
generalallowlist:
CVE-2019-8696:
CVE-2014-8166: cups
CVE-2017-18248:
images:
registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:
CVE-2018-4180:
your.private.registry:5000/centos:
CVE-2015-1419: libxml2
CVE-2015-1447:
이 예시는 gl-container-scanning-report.json에서 다음을 제외합니다:
- CVE ID가
CVE-2019-8696,CVE-2014-8166,CVE-2017-18248인 모든 취약점. registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256컨테이너 이미지에서 발견된 CVE IDCVE-2018-4180의 모든 취약점.your.private.registry:5000/centos컨테이너에서 발견된 CVE IDCVE-2015-1419,CVE-2015-1447의 모든 취약점.
파일 형식#
-
generalallowlist블록은 CVE ID를 전역으로 지정할 수 있습니다. 일치하는 CVE ID를 가진 모든 취약점이 스캔 보고서에서 제외됩니다. -
images블록은 각 컨테이너 이미지별로 독립적으로 CVE ID를 지정할 수 있습니다. 일치하는 CVE ID를 가진 해당 이미지의 모든 취약점이 스캔 보고서에서 제외됩니다. 이미지 이름은 스캔할 Docker 이미지를 지정하는 데 사용되는 환경 변수(예:$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG또는CS_IMAGE) 중 하나에서 가져옵니다. 이 블록에 지정하는 이미지는 이 값과 일치해야 하며 태그 값을 포함해서는 안 됩니다. 예를 들어CS_IMAGE=alpine:3.7을 사용하여 스캔할 이미지를 지정한 경우,images블록에는alpine을 사용해야 하며alpine:3.7은 사용할 수 없습니다.컨테이너 이미지는 여러 방식으로 지정할 수 있습니다:
- 이미지 이름만 지정(예:
centos). - 레지스트리 호스트명을 포함한 전체 이미지 이름으로 지정(예:
your.private.registry:5000/centos). - 레지스트리 호스트명과 sha256 레이블을 포함한 전체 이미지 이름으로 지정(예:
registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256).
- 이미지 이름만 지정(예:
CVE ID 뒤의 문자열(앞의 예시에서 cups와 libxml2)은 선택적인 주석 형식입니다. 취약점 처리에는 영향을 주지 않습니다. 취약점을 설명하는 주석을 포함할 수 있습니다.
컨테이너 스캔 job 로그 형식#
container_scanning job 세부 정보에서 컨테이너 스캔 분석기가 생성하는 로그를 확인하면
스캔 결과와 vulnerability-allowlist.yml 파일의 정확성을 검증할 수 있습니다.
로그에는 발견된 취약점이 다음과 같이 표 형태로 나열됩니다:
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
| STATUS | CVE SEVERITY | PACKAGE NAME | PACKAGE VERSION | CVE DESCRIPTION |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
| Approved | High CVE-2019-3462 | apt | 1.4.8 | Incorrect sanitation of the 302 redirect field in HTTP transport metho |
| | | | | d of apt versions 1.4.8 and earlier can lead to content injection by a |
| | | | | MITM attacker, potentially leading to remote code execution on the ta |
| | | | | rget machine. |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
| Unapproved | Medium CVE-2020-27350 | apt | 1.4.8 | APT had several integer overflows and underflows while parsing .deb pa |
| | | | | ckages, aka GHSL-2020-168 GHSL-2020-169, in files apt-pkg/contrib/extr |
| | | | | acttar.cc, apt-pkg/deb/debfile.cc, and apt-pkg/contrib/arfile.cc. This |
| | | | | issue affects: apt 1.2.32ubuntu0 versions prior to 1.2.32ubuntu0.2; 1 |
| | | | | .6.12ubuntu0 versions prior to 1.6.12ubuntu0.2; 2.0.2ubuntu0 versions |
| | | | | prior to 2.0.2ubuntu0.2; 2.1.10ubuntu0 versions prior to 2.1.10ubuntu0 |
| | | | | .1; |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
| Unapproved | Medium CVE-2020-3810 | apt | 1.4.8 | Missing input validation in the ar/tar implementations of APT before v |
| | | | | ersion 2.1.2 could result in denial of service when processing special |
| | | | | ly crafted deb files. |
+------------+-------------------------+------------------------+-----------------------+------------------------------------------------------------------------+
로그에서 해당 CVE ID가 vulnerability-allowlist.yml 파일에 추가되면 취약점이 Approved로 표시됩니다.
오프라인 환경#
오프라인 환경에서 컨테이너 스캔을 실행하려면 초기 설정을 수행하고 지속적으로 유지 관리해야 합니다.
초기 설정:
- 러너를 구성합니다(
docker또는kubernetesexecutor를 사용할 수 있는지 확인). - 로컬 컨테이너 레지스트리를 설정합니다. 자세한 내용은 GitLab 컨테이너 레지스트리를 참고합니다.
- 이미지를 로컬 컨테이너 레지스트리에 복사합니다.
- 컨테이너 스캔을 사용하는 각 프로젝트의 CI/CD를 구성합니다.
- 필요에 따라 다음을 선택적으로 구성할 수 있습니다:
지속적인 유지 관리:
- 새 버전이 릴리스될 때마다 로컬 컨테이너 스캔 이미지를 업데이트합니다.
러너 구성#
러너를 구성합니다(docker 또는 kubernetes executor를 사용할 수 있는지 확인). 자세한 내용은
시작하기를 참고합니다.
기본적으로 러너는 로컬 사본이 있어도 GitLab 컨테이너 레지스트리에서 컨테이너 이미지를
가져옵니다. 로컬 컨테이너 이미지만 사용하려면
pull_policy를 if-not-present로 설정할 수 있습니다.
하지만 특별한 이유가 없다면 pull_policy 설정은 기본값을 유지해야
합니다.
컨테이너 이미지 복사#
GitLab.com 컨테이너 레지스트리에서 다음 이미지를 로컬 컨테이너 레지스트리로 가져옵니다. 이 이미지는 오프라인 GitLab 인스턴스에서 접근할 수 있어야 합니다.
registry.gitlab.com/security-products/container-scanning:8
로컬 컨테이너 레지스트리로 이미지를 가져오는 과정은 네트워크 보안 정책에 따라 다릅니다. 외부 리소스를 가져오거나 일시적으로 접근하는 승인된 절차는 IT 담당자에게 문의합니다.
각 프로젝트의 CI/CD 구성#
이러한 구성 변경 사항은 레지스트리에 대한 컨테이너 스캔에는
적용되지 않습니다. 이는 .gitlab-ci.yml 파일을 참조하지 않기 때문입니다.
오프라인 환경에서 레지스트리에 대한 컨테이너 스캔을 자동으로 구성하려면
GitLab UI에서 CS_ANALYZER_IMAGE 변수를 정의
합니다.
컨테이너 스캔을 사용하는 모든 프로젝트에 대해, 적용되는 모든 위치에서 CI/CD 구성을 편집합니다. 다음이 포함될 수 있습니다:
- 개별 프로젝트의
.gitlab-ci.yml파일 - 파이프라인 실행 정책
- 스캔 실행 정책
다음 변수로 컨테이너 스캔 구성을 업데이트합니다:
- 선택 사항. 컨테이너 스캔 템플릿이 아직 포함되어 있지 않으면 추가합니다.
CS_ANALYZER_IMAGE를 로컬 컨테이너 레지스트리의 컨테이너 스캔 이미지로 설정합니다.- 선택 사항. GitLab이 아닌 컨테이너 레지스트리를 사용하는 경우
CS_REGISTRY_USER및CS_REGISTRY_PASSWORD를 레지스트리 자격 증명에 맞게 설정합니다. - 선택 사항. 로컬 컨테이너 레지스트리에 자체 서명 인증서를 사용하는 경우
CS_DOCKER_INSECURE: "true"를 설정합니다.
오프라인 환경용 .gitlab-ci.yml 구성 예시:
include:
- template: Jobs/Container-Scanning.gitlab-ci.yml
container_scanning:
variables:
# Container scanning-specific variables
CS_ANALYZER_IMAGE: <hostname>:<port>/analyzers/container-scanning:8
CS_REGISTRY_USER: <username>
CS_REGISTRY_PASSWORD: <password>
CS_DOCKER_INSECURE: "true"
로컬 컨테이너 이미지 업데이트#
컨테이너 스캔 이미지는 주기적으로 업데이트되어 GitLab.com 레지스트리에 게시됩니다. 오프라인 환경에서는 로컬 컨테이너 레지스트리의 컨테이너 스캔 이미지를 자동으로(권장) 또는 수동으로 업데이트해야 합니다.
- 수동 방법: 네트워크를 통해 GitLab.com 레지스트리에 접근할 수 없는 경우 로컬 레지스트리에서 컨테이너 스캔 이미지를 수동으로 업데이트합니다. 초기 설정 시 이미지를 복사했던 방법과 동일한 방법을 사용합니다.
- 자동 방법: 오프라인 GitLab 인스턴스가 GitLab.com에 대한 읽기 접근 권한이 있는 경우 사전 설정된 일정에 따라 이미지를 자동으로 업데이트하는 예약된 파이프라인을 설정합니다.
자동 이미지 업데이트 방법#
다음 .gitlab-ci.yml 예시는 로컬 레지스트리에서 컨테이너 스캔 이미지를 자동으로
업데이트하는 방법을 보여줍니다. 이 방법은 소스 이미지와 대상
이미지를 위한 변수를 정의한 다음, Docker CLI를 사용하여 GitLab.com 레지스트리에서 이미지를 가져와 로컬
레지스트리로 푸시합니다.
GitLab이 아닌 레지스트리를 사용하는 경우 CI_REGISTRY 값을 업데이트하고, CI_REGISTRY_USER 및
CI_REGISTRY_PASSWORD 변수를 로컬 레지스트리 자격 증명에 맞게 설정하여 인증을
구성합니다.
variables:
SOURCE_IMAGE: registry.gitlab.com/security-products/container-scanning:8
TARGET_IMAGE: $CI_REGISTRY/namespace/container-scanning
image: docker:cli
update-scanner-image:
services:
- docker:dind
script:
- docker pull $SOURCE_IMAGE
- docker tag $SOURCE_IMAGE $TARGET_IMAGE
- echo "$CI_REGISTRY_PASSWORD" | docker login $CI_REGISTRY --username $CI_REGISTRY_USER --password-stdin
- docker push $TARGET_IMAGE
아카이브 형식 스캔#
히스토리
- tar 파일 스캔이 GitLab 18.0에서 도입되었습니다.
컨테이너 스캔은 아카이브 형식(.tar, .tar.gz)의 이미지를 지원합니다.
이러한 이미지는 예를 들어 docker save 또는 docker buildx build로 생성할 수 있습니다.
아카이브 파일을 스캔하려면 환경 변수 CS_IMAGE를 archive://path/to/archive 형식으로 설정합니다:
archive://스킴 접두사는 분석기가 아카이브를 스캔하도록 지정합니다.path/to/archive는 스캔할 아카이브의 경로를 지정하며, 절대 경로 또는 상대 경로 모두 가능합니다.
컨테이너 스캔은 Docker Image Specification을 따르는 tar 이미지 파일을 지원합니다. OCI tarball은 지원되지 않습니다. 지원되는 형식에 대한 자세한 내용은 Trivy의 tar 파일 지원을 참고합니다.
지원되는 tar 파일 빌드#
컨테이너 스캔은 이미지 이름을 지정하는 데 tar 파일의 메타데이터를 사용합니다. tar 이미지 파일을 빌드할 때는 이미지에 태그가 지정되어 있는지 확인합니다:
# Pull or build an image with a name and a tag
docker pull image:latest
# OR
docker build . -t image:latest
# Then export to tar using docker save
docker save image:latest -o image-latest.tar
# Or build an image with a tag using buildx build
docker buildx create --name container --driver=docker-container
docker buildx build -t image:latest --builder=container -o type=docker,dest=- . > image-latest.tar
# With podman
podman build -t image:latest .
podman save -o image-latest.tar image:latest
이미지 이름#
컨테이너 스캔은 먼저 아카이브의 manifest.json을 확인하고 RepoTags의 첫 번째 항목을 사용하여 이미지 이름을 결정합니다.
이것이 발견되지 않으면 index.json을 사용하여 io.containerd.image.name 애노테이션을 가져옵니다. 이것도 발견되지 않으면 아카이브 파일 이름이
대신 사용됩니다.
manifest.json은 Docker Image Specification v1.1.0에 정의되어 있으며docker save명령으로 생성됩니다.index.json형식은 OCI image specification v1.1.1에 정의되어 있습니다.io.containerd.image.name은 containerd v1.3.0 이상에서 사용할 수 있으며ctr image export를 사용할 때 적용됩니다.
이전 job에서 빌드된 아카이브 스캔#
CI/CD job에서 빌드된 아카이브를 스캔하려면 빌드 job에서 컨테이너 스캔 job으로 아카이브 아티팩트를 전달해야 합니다.
artifacts:paths 및 dependencies 키워드를 사용하여 한 job에서 다음 job으로 아티팩트를 전달합니다:
build_job:
script:
- docker build . -t image:latest
- docker save image:latest -o image-latest.tar
artifacts:
paths:
- "image-latest.tar"
container_scanning:
variables:
CS_IMAGE: "archive://image-latest.tar"
dependencies:
- build_job
프로젝트 리포지터리의 아카이브 스캔#
프로젝트 리포지터리에서 발견된 아카이브를 스캔하려면 Git 전략이 리포지터리에 대한 접근을 허용하는지 확인합니다.
container_scanning job에서 GIT_STRATEGY 키워드는 기본값이 none이므로 clone 또는 fetch로 설정합니다.
container_scanning:
variables:
GIT_STRATEGY: fetch
독립형 컨테이너 스캔 도구 실행#
CI job의 맥락 안에서 실행하지 않고도 Docker 컨테이너에 대해 GitLab 컨테이너 스캔 도구를 실행할 수 있습니다. 이미지를 직접 스캔하려면 다음 단계를 따릅니다:
-
Docker Desktop 또는 Docker Machine을 실행합니다.
-
분석하려는 이미지와 태그를
CI_APPLICATION_REPOSITORY및CI_APPLICATION_TAG변수로 전달하여 분석기의 Docker 이미지를 실행합니다:docker run \ --interactive --rm \ --volume "$PWD":/tmp/app \ -e CI_PROJECT_DIR=/tmp/app \ -e CI_APPLICATION_REPOSITORY=registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256 \ -e CI_APPLICATION_TAG=bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e \ registry.gitlab.com/security-products/container-scanning
결과는 gl-container-scanning-report.json에 저장됩니다.
보고서 JSON 형식#
컨테이너 스캔 도구는 CI/CD 구성 파일의 artifacts:reports 키워드를 통해 GitLab Runner가 인식하는
JSON 보고서를 생성합니다.
CI/CD job이 완료되면 러너가 이러한 보고서를 GitLab에 업로드하며, 이는 CI/CD job 아티팩트에서 확인할 수 있습니다. GitLab Ultimate에서는 이러한 보고서를 해당 파이프라인 및 취약점 보고서에서 볼 수 있습니다.
이러한 보고서는 컨테이너 스캔 보고서 스키마를 준수해야 합니다.
CycloneDX 소프트웨어 명세서(SBOM)#
JSON 보고서 파일 외에도 컨테이너 스캔 도구는 스캔된 이미지에 대해
CycloneDX 소프트웨어 명세서(SBOM)를 출력합니다. 이
CycloneDX SBOM은 gl-sbom-report.cdx.json으로 명명되어 JSON report file과 동일한 디렉터리에 저장됩니다. 이 기능은 Trivy 분석기를 사용할 때만 지원됩니다.
이 보고서는 의존성 목록에서 확인할 수 있습니다.
CycloneDX SBOM은 다른 job 아티팩트와 동일한 방법으로 다운로드할 수 있습니다.
CycloneDX 보고서의 라이선스 정보#
히스토리
- GitLab 18.0에서 도입되었습니다.
컨테이너 스캔은 CycloneDX 보고서에 라이선스 정보를 포함할 수 있습니다. 이 기능은 이전 버전과의 호환성을 유지하기 위해 기본적으로 비활성화되어 있습니다.
컨테이너 스캔 결과에서 라이선스 스캔을 활성화하려면:
.gitlab-ci.yml파일에서CS_INCLUDE_LICENSES변수를 설정합니다:
container_scanning:
variables:
CS_INCLUDE_LICENSES: "true"
- 이 기능을 활성화하면 생성된 CycloneDX 보고서에 컨테이너 이미지에서 탐지된 구성 요소의 라이선스 정보가 포함됩니다.
- 이 라이선스 정보는 의존성 목록 페이지 또는 다운로드 가능한 CycloneDX job 아티팩트의 일부로 확인할 수 있습니다.
SPDX 라이선스만 지원된다는 점에 유의해야 합니다. 그러나 SPDX를 준수하지 않는 라이선스도 사용자에게 오류를 표시하지 않고 수집됩니다.
수명 종료(EOL) 운영 체제 탐지#
컨테이너 스캔에는 컨테이너 이미지가 수명 종료(EOL)에 도달한 운영 체제를 사용하는 경우 이를 탐지하고 보고하는 기능이 포함되어 있습니다. EOL에 도달한 운영 체제는 더 이상 보안 업데이트를 받지 않아 새로 발견되는 보안 문제에 취약합니다.
EOL 탐지 기능은 Trivy를 사용하여 해당 배포판에서 더 이상 지원하지 않는 운영 체제를 식별합니다. EOL 운영 체제가 탐지되면 다른 보안 결과와 함께 컨테이너 스캔 보고서에 취약점으로 보고됩니다.
EOL 탐지를 활성화하려면 CS_REPORT_OS_EOL을 "true"로 설정합니다.
레지스트리에 대한 컨테이너 스캔#
히스토리
- GitLab 17.1에서
enable_container_scanning_for_registry라는 기능 플래그와 함께 도입되었습니다. 기본적으로 비활성화되어 있습니다. - GitLab 17.2에서 GitLab Self-Managed 및 GitLab Dedicated에서 활성화되었습니다.
- GitLab 17.2에서 일반적으로 사용 가능해졌습니다.
enable_container_scanning_for_registry기능 플래그가 제거되었습니다.
latest 태그로 컨테이너 이미지가 푸시되면 보안 정책 봇이 기본 브랜치에 대한 새 파이프라인에서 컨테이너 스캔 job을 자동으로 트리거합니다.
일반 컨테이너 스캔과 달리 이 스캔 결과에는 보안 보고서가 포함되지 않습니다. 대신 레지스트리에 대한 컨테이너 스캔은 지속적 취약점 스캐닝에 의존하여 스캔에서 탐지된 구성 요소를 검사합니다.
보안 결과가 식별되면 GitLab은 해당 결과로 취약점 보고서를 채웁니다. 취약점은 취약점 보고서 페이지의 Container registry vulnerabilities 탭에서 확인할 수 있습니다.
레지스트리에 대한 컨테이너 스캔은 GitLab 어드바이저리 데이터베이스에 새 어드바이저리가 게시될 때만 취약점 보고서를 채웁니다. 새로 탐지된 데이터만이 아니라 현재 존재하는 모든 어드바이저리 데이터로 취약점 보고서를 채우는 기능은 에픽 11219에서 제안되어 있습니다.
레지스트리에 대한 컨테이너 스캔으로 탐지된 취약점은 취약한 구성 요소를 업데이트하거나 제거해도 자동으로 해결됨으로 표시될 수 없습니다. 이 기능은 취약점 해결에 필요한 보안 보고서가 아니라 SBOM만 생성하기 때문에, 이러한 취약점은 무기한으로 표시된 상태로 남습니다.
레지스트리에 대한 컨테이너 스캔 활성화#
사전 요구 사항:
- 프로젝트에 대한 Security Manager, Maintainer 또는 Owner 권한.
- 프로젝트가 비어 있지 않아야 합니다. 컨테이너 이미지 저장만을 위해 빈 프로젝트를 사용하는 경우 이 기능이 의도한 대로 작동하지 않습니다. 해결 방법으로 프로젝트의 기본 브랜치에 초기 커밋이 있는지 확인합니다.
- 기본적으로 프로젝트당 하루에
50건의 스캔 제한이 있습니다. - 컨테이너 레지스트리 알림을 구성해야 합니다.
- 패키지 메타데이터 데이터베이스를 구성해야 합니다. GitLab.com에서는 기본적으로 구성되어 있습니다.
GitLab 컨테이너 레지스트리에 대한 컨테이너 스캔을 활성화하려면 다음을 수행합니다:
- 상단 메뉴바에서 Search or go to를 선택하고 프로젝트를 찾습니다.
- 왼쪽 사이드바에서 Secure > Security configuration을 선택합니다.
- Container Scanning For Registry 섹션으로 스크롤하여 토글을 켭니다.
오프라인 또는 에어 갭 환경에서 사용#
인터넷을 통한 외부 리소스 접근이 제한적이거나 불안정한 환경의 인스턴스에서 레지스트리에 대한 컨테이너 스캔을 성공적으로 실행하려면 몇 가지 조정이 필요합니다. 자세한 내용은 오프라인 환경을 참고합니다.
레지스트리에 대한 컨테이너 스캔은 GitLab Security Policy Bot이 관리하므로,
.gitlab-ci.yml 파일을 편집하여 분석기 이미지를 구성할 수 없습니다. 대신
GitLab UI에서 CS_ANALYZER_IMAGE CI/CD 변수를 설정하여 기본 스캐너 이미지를 재정의합니다. 동적으로 생성되는 스캔 job은
UI에 정의된 변수를 상속합니다. 프로젝트, 그룹 또는 인스턴스 CI/CD 변수를 사용할 수 있습니다.
사전 요구 사항:
-
프로젝트 또는 그룹에 대한 Maintainer 또는 Owner 권한.
-
Docker 또는 Kubernetes executor가 있는 GitLab Runner.
-
컨테이너 스캔 분석기 이미지의 로컬 사본.
-
패키지 메타데이터 데이터베이스(PMDB)에 대한 접근 권한.
컨테이너 이미지에서 탐지된 구성 요소에 대한 어드바이저리 데이터를 확보하는 데 필요합니다. 레지스트리에 대한 컨테이너 스캔은 지속적 취약점 스캐닝에 의존하여 취약점을 채우며, 이를 위해서는 동기화된 어드바이저리 데이터가 필요합니다. PMDB 동기화가 없으면 스캔이 성공적으로 완료되어도 레지스트리에 대한 컨테이너 스캔이 취약점 보고서를 채우지 않습니다.
오프라인 환경에서 컨테이너 스캔 분석기를 사용하려면 다음을 수행합니다:
-
컨테이너 이미지 복사에 설명된 대로
registry.gitlab.com에서 로컬 컨테이너 레지스트리로 컨테이너 스캔 이미지를 가져옵니다.로컬 컨테이너 레지스트리로 이미지를 가져오는 과정은 네트워크 보안 정책에 따라 다릅니다. 외부 리소스를 가져오거나 일시적으로 접근할 수 있는 승인된 절차는 IT 팀에 문의합니다.
-
CS_ANALYZER_IMAGECI/CD 변수를 설정하여 로컬 분석기 이미지를 사용하도록 GitLab Security Policy Bot을 구성합니다:- 상단 메뉴바에서 Search or go to를 선택하고 프로젝트 또는 그룹을 찾습니다.
- 왼쪽 사이드바에서 Settings > CI/CD를 선택합니다.
- Variables 섹션을 확장합니다.
- Add variable을 선택하고 세부 정보를 입력합니다:
- Key:
CS_ANALYZER_IMAGE - Value: 미러링된 컨테이너 스캔 이미지의 전체 URL. 예를 들어,
my.local.registry:5000/analyzers/container-scanning:8.
- Key:
- Add variable을 선택합니다.
GitLab Security Policy Bot은 스캔을 트리거할 때 지정된 이미지를 사용합니다.
취약점 데이터베이스#
모든 분석기 이미지는 매일 업데이트됩니다.
이 이미지는 업스트림 어드바이저리 데이터베이스의 데이터를 사용합니다:
- AlmaLinux Security Advisory
- Amazon Linux Security Center
- Arch Linux Security Tracker
- SUSE CVRF
- CWE Advisories
- Debian Security Bug Tracker
- GitHub Security Advisory
- Go Vulnerability Database
- CBL-Mariner Vulnerability Data
- NVD
- OSV
- Red Hat OVAL v2
- Red Hat Security Data API
- Photon Security Advisories
- Rocky Linux UpdateInfo
- Ubuntu CVE Tracker(2021년 중반 이후의 데이터 소스만 해당)
이러한 스캐너가 제공하는 소스 외에도 GitLab은 다음 취약점 데이터베이스를 유지 관리합니다:
GitLab Ultimate 티어에서는 GitLab 어드바이저리 데이터베이스의 데이터가 외부 소스의 데이터를 보강하기 위해 병합됩니다. GitLab Premium 및 Free 티어에서는 GitLab 어드바이저리 데이터베이스(오픈 소스 에디션)의 데이터가 외부 소스의 데이터를 보강하기 위해 병합됩니다. 이 보강은 Trivy 스캐너의 분석기 이미지에만 적용됩니다.
다른 분석기의 데이터베이스 업데이트 정보는 유지 관리 표에서 확인할 수 있습니다.
취약점 해결책(자동 수정)#
일부 취약점은 GitLab이 자동으로 생성하는 해결책을 적용하여 수정할 수 있습니다.
수정 지원을 활성화하려면 스캔 도구가 CI/CD 변수 CS_DOCKERFILE_PATH로 지정된
Dockerfile에 접근할 수 있어야 합니다. 스캔 도구가 이
파일에 접근할 수 있도록 하려면 이 문서의
컨테이너 스캔 템플릿 재정의 섹션에 설명된 안내에 따라 .gitlab-ci.yml 파일에서
GIT_STRATEGY: fetch를 설정해야 합니다.
취약점 해결책에 대해 자세히 알아봅니다.
Footnotes
-
수정 상태 정보는 소프트웨어 공급업체 및 컨테이너 이미지 운영 체제 패키지 메타데이터의 정확한 수정 가능 여부 데이터에 크게 의존합니다. 또한 개별 컨테이너 스캐너의 해석에 따라서도 달라질 수 있습니다. 컨테이너 스캐너가 취약점에 대한 수정된 패키지의 가용성을 잘못 보고하는 경우, 이 설정이 활성화된 상태에서
CS_IGNORE_STATUSES를 사용하면 결과의 오탐 또는 미탐 필터링이 발생할 수 있습니다. ↩