보안 섹션 분석기 개발
분석기는 CI 파이프라인 컨텍스트 내에서 실행되는 Docker 이미지로 제공됩니다. 이 가이드에서는 분석기 간의 개발 및 테스트 관행을 설명합니다.
공유 모듈
공통 동작 및 인터페이스를 위해 여러 공유 Go 모듈이 분석기 간에 공유됩니다:
-
command
Go 패키지는 CLI 인터페이스를 구현합니다. -
common
프로젝트는 로깅, 인증서 처리 및 디렉터리 검색 기능에 대한 여러 공유 모듈을 제공합니다. -
report
Go 패키지의Report
와Finding
구조체는 JSON 보고서를 marshal합니다. -
template
프로젝트는 새로운 분석기의 템플릿을 구성합니다.
분석기 사용 방법
분석기는 Docker 이미지로 제공됩니다. 예를 들어, 작업 디렉터리를 스캔하기 위해 Semgrep Docker 이미지를 실행하려면:
- 스캔하려는 소스 코드의 디렉터리로 이동합니다.
-
docker login registry.gitlab.com
을 실행하고 사용자 이름과 적어도read_registry
스코프를 가진 개인 또는 프로젝트 액세스 토큰을 제공합니다. -
Docker 이미지를 실행합니다:
docker run \ --interactive --tty --rm \ --volume "$PWD":/tmp/app \ --env CI_PROJECT_DIR=/tmp/app \ -w /tmp/app \ registry.gitlab.com/gitlab-org/security-products/analyzers/semgrep:latest /analyzer run
- Docker 컨테이너는 분석기 범주에 해당하는 보고서 파일과 함께 마운트된 프로젝트 디렉터리에 보고서를 생성합니다. 예를 들어, SAST는
gl-sast-report.json
이라는 파일을 생성합니다.
분석기 개발
분석기를 업데이트하려면:
- Go 소스 코드를 수정합니다.
- 새로운 Docker 이미지를 빌드합니다.
- 분석기를 해당 테스트 프로젝트에 대해 실행합니다.
- 생성된 보고서를 기대치와 비교합니다.
analyzer
라는 이름의 Docker 이미지를 만드는 방법은 다음과 같습니다:
docker build -t analyzer .
예를 들어, Secret Detection을 테스트하려면 다음을 실행합니다:
wget https://gitlab.com/gitlab-org/security-products/ci-templates/-/raw/master/scripts/compare_reports.sh
sh ./compare_reports.sh sd test/fixtures/gl-secret-detection-report.json test/expect/gl-secret-detection-report.json \
| patch -Np1 test/expect/gl-secret-detection-report.json && Git commit -m 'Update expectation' test/expect/gl-secret-detection-report.json
rm compare_reports.sh
또한 자체 환경에 바이너리를 컴파일하고 로컬로 실행할 수 있지만 analyze
와 run
은 아마도 작동하지 않을 것입니다. 왜냐하면 분석기의 런타임 의존성이 없기 때문입니다.
SpotBugs를 기반으로 한 예시는 다음과 같습니다:
go build -o analyzer
./analyzer search test/fixtures
./analyzer convert test/fixtures/app/spotbugsXml.Xml > ./gl-sast-report.json
실행 기준
SAST 활성화에는 GitLab CI/CD 구성에 미리 정의된 템플릿을 포함해야 합니다.
프로젝트에서 실행해야 하는 분석기를 결정하는 다음 독립적인 기준이 있습니다:
- SAST 템플릿은 특정 파일의 존재 여부에 따라 실행할 분석기를 결정하기 위해
rules:exists
를 사용합니다. 예를 들어, Brakeman 분석기는 .rb 파일들과 Gemfile이 존재할 때 실행됩니다. - 각 분석기는 실제 분석을 수행하기 전에 사용자 정의 가능한 match 인터페이스를 실행합니다. 예를 들어: Flawfinder는 C/C++ 파일을 확인합니다.
- 일반 파일 확장자에서 실행되는 분석기 중 일부의 경우 CI/CD 변수를 기반으로 확인이 있습니다. 예를 들어 Kubernetes 마니페스트는 YAML로 작성되므로, Kubesec는
SCAN_KUBERNETES_MANIFESTS
가 true로 설정될 때 실행됩니다.
단계 1은 프로젝트에 적합하지 않은 분석기를 실행하여 컴퓨팅 할당량을 낭비하지 않도록 합니다. 그러나 기술적인 제약으로 인해 대규모 프로젝트에 사용할 수 없습니다. 따라서 단계 2는 일치하지 않는 분석기가 조기에 종료될 수 있도록 최종 확인 역할을 합니다.
분석기 테스트 방법
의존성 스캐닝 분석기가 하류 파이프라인 기능을 활용하여 테스트 프로젝트로 분석기를 테스트하는 영상 안내:
로컬 변경 사항 테스트
공유 모듈(예: command
또는 report
)에서의 로컬 변경을 테스트하려면 분석기용으로
go mod replace
지시문을 사용하여 원격으로 태그가 지정된 command 버전 대신 로컬 변경이 적용된 command를 로드할 수 있습니다. 예를 들어:
go mod edit -replace gitlab.com/gitlab-org/security-products/analyzers/command/v3=/local/path/to/command
또는 go.mod
파일을 매뉴얼으로 업데이트하여 동일한 결과를 얻을 수 있습니다:
module gitlab.com/gitlab-org/security-products/analyzers/awesome-analyzer/v2
replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /path/to/command
require (
...
gitlab.com/gitlab-org/security-products/analyzers/command/v3 v2.19.0
)
Docker에서의 로컬 변경 사항 테스트
go.mod
파일에서 replace
를 사용하여 Docker가 replace
를 사용하도록하려면:
-
command
의 내용을 분석기 디렉터리에 복사합니다.cp -r /path/to/command path/to/analyzer/command
. - 분석기의
Dockerfile
에 복사 문을 추가합니다:COPY command /command
. - 위 단계의
COPY
문의 대상과 일치하도록replace
문을 업데이트합니다:replace gitlab.com/gitlab-org/security-products/analyzers/command/v3 => /command
분석기 스크립트
analyzer-scripts 리포지터리에는 대부분의 분석기와 상호 작용하는 데 사용할 수 있는 스크립트가 포함되어 있습니다. 이를 사용하면 GitLab CI와 유사한 환경에서 분석기를 빌드, 실행 및 디버깅할 수 있으며, 분석기에 대한 변경 사항을 로컬에서 유효성을 검사하는 데 특히 유용합니다.
자세한 내용은 프로젝트 README를 참조하십시오.
버전 및 릴리스 프로세스
GitLab 보안 제품은 GitLab Rails의 MAJOR.MINOR
와는 독립적인 버전 관리 시스템을 사용합니다. 모든 제품은 Semantic Versioning의 변형을 사용하며 Docker 이미지로 제공됩니다.
Patch
버전 번호는 일반적으로 밑바닥 도구의 Minor
버전 번호의 Minor
버전 번호에 해당하는 경향이 있어 우리에게는 Minor
번호를 스캐너에 대한 중요한 변경 사항으로 적용하기 위한 더 큰 유연성을 제공합니다. 포장된 스캐너로 인한 중단 사항이 있을 경우 별도 리포지터리에 새 분석기를 만드는 것이 고려되어야 합니다.
분석기는 다음 방식으로 Docker 이미지로 릴리스됩니다:
- 기본 브랜치로의 각 푸시는
edge
이미지 태그를 덮어씁니다. -
awesome-feature
브랜치로의 각 푸시는 해당awesome-feature
이미지 태그를 생성합니다. - 각 Git 태그는 해당
Major.Minor.Patch
이미지 태그를 생성합니다. 매뉴얼 작업을 통해 해당Major
및latest
이미지 태그를 이Major.Minor.Patch
에 대한 포인터로 재지정할 수 있습니다.
대부분의 경우 최신 공지 사항 또는 도구의 패치와 자동으로 최신 상태를 유지하도록하는 MAJOR
이미지에 의존하는 것이 좋습니다. 우리의 포함된 CI 템플릿은 주 버전에 고정되어 있지만 사용자는 기본적으로 버전을 재정의할 수 있습니다.
새로운 분석기 Docker 이미지를 릴리스하려면 다음 두 가지 옵션이 있습니다:
다음 다이어그램은 새 분석기 버전이 릴리스될 때 생성되는 Docker 태그를 설명합니다:
저희의 지속적인 배포 흐름에 따라, GitLab Rails 앱에 상응하는 새로운 컴포넌트의 경우, 해당 컴포넌트는 언제든지 릴리스할 수 있습니다. 기존 응용 프로그램과 통합되지 않은 상태에서는 표준 릴리스 주기 및 프로세스에 의한 반복이 차단되지 않도록 해야 합니다.
매뉴얼 릴리스 프로세스
- 새로운 분석기에 대한
CHANGELOG.md
항목이 정확한지 확인합니다. - 릴리스 소스(일반적으로
master
또는main
브랜치)에 통과하는 파이프라인이 있는지 확인합니다. - 분석기 프로젝트에 대한 새 릴리스를 만들기 위해 프로젝트 창의 왼쪽에있는 배포 메뉴를 선택한 다음 릴리스 하위메뉴를 선택합니다.
-
새 릴리스를 선택하여 새 릴리스 페이지를 엽니다.
-
태그 이름 드롭다운에서
CHANGELOG.md
에서 사용된 동일한 버전(예:v2.4.2
)을 입력하고 태그 생성 옵션(Create tag v2.4.2
여기에서)을 선택합니다. -
릴리스 제목 텍스트 상자에 위에서 사용된 동일한 버전(예:
v2.4.2
)을 입력합니다. -
릴리스 노트
텍스트 상자에CHANGELOG.md
의 해당 버전의 노트를 복사하여 붙여넣습니다. - 모든 다른 설정은 기본값으로 남깁니다.
- 릴리스 생성을 선택합니다.
-
태그 이름 드롭다운에서
위 프로세스를 따라 새 릴리스를 만든 후, 지정한 태그 이름
으로 새로운 Git 태그가 생성됩니다. 이로 인해 주어진 태그 버전과 새로운 분석기 Docker 이미지가 빌드됩니다.
분석기가 analyzer.yml
템플릿을 사용하는 경우 새 릴리스 프로세스의 일환으로 트리거된 파이프라인은 분석기 Docker 이미지의 새 버전을 자동으로 태그하고 배포합니다.
analyzer.yml
템플릿을 사용하지 않는 경우, 분석기 Docker 이미지의 새 버전을 매뉴얼으로 태그하고 배포해야 합니다.
- 프로젝트 창의 왼쪽에있는 CI/CD 메뉴를 선택하고 파이프라인 하위메뉴를 선택합니다.
- 현재와 동일한 태그를 사용하여 새 파이프라인이 실행 중인 것을 볼 수 있어야 합니다(예:
v2.4.2
). - 파이프라인이 완료되면
blocked
상태가 됩니다. - 창 오른쪽에있는
매뉴얼 작업
재생 버튼을 선택하고tag version
을 선택하여 새 분석기 Docker 이미지 버전을 태그하고 배포합니다.
태그를 만들어 릴리스 작업을 트리거할 때 가장 좋은 결정을 내리십시오. 결정을 내릴 수 없는 경우 타인의 의견을 구하세요.
자동 릴리스 프로세스
자동 릴리스 프로세스를 사용하기 전에 다음 작업을 수행해야 합니다:
-
CI/CD
환경 변수로CREATE_GIT_TAG: true
을 구성합니다. - CI/CD 프로젝트 설정의
Variables
를 확인합니다. 프로젝트가 이미 프로젝트 그룹에서GITLAB_TOKEN
환경 변수를 상속받지 않은 경우,API에 대한 완전한 읽기/쓰기 액세스
를 갖는 프로젝트 액세스 토큰을 만들고, 이 토큰을 참조하는CI/CD
환경 변수로GITLAB_TOKEN
을 구성합니다.
위 단계를 완료한 후, 자동 릴리스 프로세스는 다음과 같이 실행됩니다:
- 프로젝트 유지자가 MR을 기본 브랜치로 머지합니다.
- 기본 파이프라인이 트리거되고,
upsert git tag
작업이 실행됩니다.-
CHANGELOG.md
의 가장 최근 버전이 Git 태그 중 하나와 일치하는 경우, 작업은 무시됩니다. - 그렇지 않은 경우, 이 작업은 프로젝트의
CHANGELOG.md
파일의 가장 최근 항목에서 버전과 메시지를 자동으로 사용하여 새 릴리스와 Git 태그를 생성합니다.
-
- 새로운 Git 태그에 대해 파이프라인이 자동으로 트리거됩니다. 이 파이프라인은 분석기의
latest
,major
,minor
및patch
Docker 이미지를 릴리스합니다.
분석기 릴리스 후 수행하는 단계
- 분석기 Docker 이미지의 새 버전이 태그되고 배포된 후, 해당 테스트 프로젝트를 사용하여 테스트합니다.
-
관련 그룹 Slack 채널에서 릴리스를 발표합니다. 예시 메시지:
FYI, 방금
ANALYZER_NAME
ANALYZER_VERSION
을(를) 릴리스했습니다.LINK_TO_RELEASE
이미 푸시된 Git 태그를 삭제하지 마십시오. 해당 태그가 사용될 수 있거나 Go 패키지 레지스트리에서 캐시될 가능성이 높습니다.
새로운 분석기 개발
가끔씩 새로운 프레임워크와 도구를 지원하기 위해 새 분석기 프로젝트를 개발해야 할 때가 있습니다. 이를 위해 우리는 우리의 엔지니어링 오픈 소스 지침을 따라야 하며, 라이선스 및 코드 기준을 포함해야 합니다.
또한, GitLab 응용 프로그램에 통합될 사용자 정의 분석기를 작성하려면 최소한의 기능 집합이 필요합니다:
체크리스트
기본 도구
- [ ] 허용되는 소프트웨어 라이선스를 갖고 있습니다.
- [ ] 헤드리스 실행 (CLI 도구)
- [ ] Docker 이미지로 패키징될 수 있는 의존성이 있어야 합니다. GitLab Runner의 Linux 또는 Windows Docker 실행기를 사용하여 실행할 수 있어야 합니다.
- [ ] 파일 이름 또는 확장자를 기준으로 호환 가능한 프로젝트를 감지할 수 있어야 합니다.
- [ ] 오프라인 실행 (인터넷 액세스 없음) 또는 사용자 정의 프록시 및/또는 CA 인증서를 사용할 수 있도록 구성할 수 있어야 합니다.
Dockerfile
Dockerfile
은 관리자(루트) 사용자로 컨테이너를 실행하는 것을 허용하지 않는 Red Hat OpenShift 인스턴스와 호환성을 제공하기 위해 GitLab
이라는 비 권한 있는 사용자를 사용해야 합니다. 비 권한 있는 사용자로 컨테이너를 실행하는 경우 특정 제한 사항이 있으며, Docker 파일 시스템에 쓰여야 하는 파일은 GitLab
사용자의 적절한 권한이 필요합니다. 자세한 내용은 다음 Merge Request을 참조하십시오: Use GitLab user instead of root in Docker image.
최소한의 취약성 데이터
자세한 필수 필드 디렉터리은 our security-report-schemas를 참조하십시오.
security-report-schema 리포지터리에는 각 보고서 유형에 대해 필요한 필수 필드를 나열하는 JSON 스키마가 포함되어 있습니다:
컨테이너 이미지 위치
컨테이너 레지스트리에 쓰기 액세스를 갖는 사람 수를 제한하기 위해 모든 이미지는 아래 위치에 발행되어야 합니다.
- 그룹:
https://gitlab.com/security-products/
- 프로젝트 경로:
https://gitlab.com/security-products/<NAME>
(예시) - 레지스트리 주소:
registry.gitlab.com/security-products/<NAME>[/<IMAGE_NAME>]:[TAG]
- 권한
- 최상위 그룹
- Maintainer:
@gitlab-org/secure/managers
,@gitlab-org/govern/managers
- Maintainer:
- 프로젝트 레벨
-
read_registry
및write_registry
액세스가 있는 배포 토큰을 사용하여 이미지를 푸시합니다. - 토큰은 프로젝트에 보호 및 마스크된 변수로 생성자에 의해 입력됩니다.
-
- 최상위 그룹
- 프로젝트 설정
- 가시성, 프로젝트 기능, 권한
- 프로젝트 가시성: 공개. “사용자가 액세스 요청을 할 수 없음” 선택 해제.
- 이슈: 비활성화.
- 리포지터리: “프로젝트 멤버만”. 사용 안 함: Merge Request, 포크, Git LFS, 패키지, CI/CD.
- 나머지 항목 비활성화: 분석, 요구 사항, 위키, 스니펫, 페이지, 작업.
- 서비스 데스크: 비활성화
- 가시성, 프로젝트 기능, 권한
Sec 섹션의 각 그룹은 다음을 담당합니다:
- 아티팩트의 폐기 및 제거 일정을 관리하고 이를 위한 이슈를 생성합니다.
- 새 위치에 프로젝트를 생성하고 구성합니다.
- 릴리스 아티팩트를 새 위치로 푸시하기 위한 빌드를 구성합니다.
- 자체 지원 계약에 따라 이전 위치의 이미지를 유지하거나 제거합니다.
Go의 보안 및 빌드 수정
Go로 구현된 안전 분석기의 Dockerfile
은 MINOR
리비전이 아닌 MAJOR
릴리스를 참조해야 합니다.
이를 통해 분석기를 컴파일하는 데 사용되는 Go 버전에는 특정 시간에 사용 가능한 모든 보안 수정이 포함됩니다.
예를 들어, 분석기의 다중 단계 Dockerfile은 golang:1.15-alpine
이미지를 사용하여 분석기 CLI를 빌드해야 하며, golang:1.15.4-alpine
을 사용해서는 안 됩니다.
MINOR
리비전의 Go가 출시되고 보안 수정이 포함된 경우 프로젝트 유지 보수자는 안전 분석기가 다시 빌드해야 하는지 확인해야 합니다.
빌드에 사용된 Go의 버전은 해당 릴리스에 해당하는 build
작업 로그에 표시되어야 하며, 또한 strings 명령을 사용하여 Go 이진 파일에서 추출할 수도 있습니다.
분석기의 최신 이미지가 해당 버전의 Go로 빌드되었다면 다시 빌드해야 합니다. 이미지를 다시 빌드하려면 유지 보수자는 다음 중 하나를 수행할 수 있습니다:
- 안정적인 릴리스에 해당하는 Git 태그에 대한 새로운 파이프라인을 트리거합니다.
-
BUILD
번호가 증가된 새로운 Git 태그를 생성합니다. - 기본 브랜치에 대한 파이프라인을 트리거하고
PUBLISH_IMAGES
변수를 비어 있지 않은 값으로 설정합니다.
어느 쪽이든 새로운 Docker 이미지가 빌드되며, 이미지 태그가 MAJOR.MINOR.PATCH
및 MAJOR
와 동일하게 게시됩니다.
이러한 작업 흐름은 동일한 MAJOR
릴리스의 MINOR
리비전 간의 완전한 호환을 전제로 합니다.
호환성 문제가 있는 경우 프로젝트 파이프라인이 테스트를 실행하는 동안 실패할 수 있습니다.
이런 경우 Dockerfile에 Go의 MINOR
리비전을 참조하고 호환성 이슈가 해결될 때까지 해당 예외를 문서화해야 할 수도 있습니다.
Dockerfile
에 참조되지 않았기 때문에 MINOR
Go 리비전은 프로젝트 변경 로그에 언급되지 않습니다.
빌드 관련 변경 사항으로 인해 변경 사항 항목이 필요하지 않을 때 적절한 경우 빌드 태그를 사용하는 것이 합리적일 수 있습니다. 예를 들어 새로운 레지스트리 위치에 Docker 이미지를 푸시하는 경우입니다.
다시 빌드하기 위한 Git 태그
분석기를 다시 빌드하기 위해 새로운 Git 태그를 생성할 때 새 태그는 이전과 동일한 MAJOR.MINOR.PATCH
버전을 가지나, BUILD
번호( semver의 정의에 따라)가 증가됩니다.
예를 들어, 분석기의 최신 릴리스가 v1.2.3
이고 해당 Docker 이미지가 영향받은 Go 버전을 사용하여 빌드되었다면 유지 보수자는 이미지를 다시 빌드하기 위해 v1.2.3+1
Git 태그를 생성합니다.
최신 릴리스가 v1.2.3+1
인 경우 v1.2.3+2
를 생성합니다.
빌드 번호는 이미지 태그에서 자동으로 제거됩니다.
예를 들어, gemnasium
프로젝트에서 v1.2.3+1
Git 태그를 만드는 것은 파이프라인이 이미지를 다시 빌드하고 gemnasium:1.2.3
로 푸시합니다.
다시 빌드를 위해 생성된 Git 태그에는 새 빌드가 필요한 이유를 설명하는 간단한 메시지가 포함됩니다.
예: Go 1.15.6으로 다시 빌드
.
태그에는 릴리스 노트가 없으며 릴리스가 생성되지 않습니다.
분석기를 다시 빌드하기 위해 새로운 Git 태그를 생성하려면 다음 단계를 따르세요:
-
새로운 Git 태그를 생성하고 메시지를 제공합니다
git tag -a v1.2.3+1 -m "Go 1.15.6으로 다시 빌드"
-
태그를 리포지터리에 푸시합니다
git push origin --tags
- Git 태그에 대한 새로운 파이프라인이 트리거되어 새 이미지가 빌드되고 태깅됩니다.
-
3.
단계에서 트리거된 릴리스 파이프라인은 일부 테스트만 실행하므로master
브랜치에 대한 새 파이프라인을 실행하여 새로 태그가 지정된 이미지에 대한 전체 테스트 스위트를 실행하고 새 취약성 보고서가 생성됩니다. 이는 예를 들어Container Scanning
분석을 수행하지 않습니다.
월간 릴리스 프로세스
이 작업은 매월 18일에 수행해야 합니다. 그러나 이는 유연한 마감일이며 몇 일 후에도 수행해도 문제가 되지 않습니다.
먼저, 이 리포지터리에서 스크립트를 사용하여 릴리스용 새 이슈를 생성하세요: ./scripts/release_issue.rb MAJOR.MINOR
.
이 이슈는 전체 릴리스 프로세스를 안내합니다. 일반적으로 다음 작업을 수행해야 합니다:
- GitLab 문서에서 지원되는 기술 디렉터리을 확인합니다.
-
vendored CI/CD 템플릿의 현재
job
정의 및 모든ENV vars
가docker run
시 도커 컨테이너로 전파되는지 확인합니다.- SAST vendored CI/CD template
- Dependency Scanning vendored CI/CD template
- License Scanning vendored CI/CD template
- Container Scanning CI/CD template
필요한 경우, 마지막 Git 태그에 해당하는 파이프라인으로 이동하여 빌드를 제어하는 매뉴얼 작업을 트리거합니다.
- 파이프라인에서 사용되는 현재 봇 계정
- 계정 이름:
@group_2452873_bot
- 사용: 릴리스/태그 생성에 사용
- 멤버: 그룹
gitlab-org/security-products
- 최고 역할:
Developer
- 연관된
GITLAB_TOKEN
범위: - 연관된
GITLAB_TOKEN
만료일:
- 계정 이름:
의존성 업데이트
분석기 소스에 사용된 모든 종속 항목 및 상위 스캐너(있는 경우)는 주로 보안 수정과 호환되지 않는 변경 사항을 포함하는 월간 주기로 업데이트됩니다.
- 정적 분석 팀은 SastBot이라는 사용자 정의 내부 도구를 사용하여 SAST 분석기의 모든 종속 항목을 자동으로 관리합니다. SastBot은 매월 8일에 MR을 생성하고 이를 정적 분석 팀 구성원들에게 배포하여 검토 진행을 담당하도록 지시합니다. 프로세스에 대한 자세한 내용은 의존성 업데이트 자동화를 참조하십시오.