InfoGrab DocsInfoGrab Docs

Advanced SAST C/C++ 구성

요약

프로젝트에서 GitLab Advanced SAST C/C++ 분석을 켜려면 다음을 수행합니다. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다. Build > Pipeline editor로 이동합니다.

히스토리

GitLab Advanced SAST C/C++ 분석 켜기#

사전 요구 사항:

프로젝트에서 GitLab Advanced SAST C/C++ 분석을 켜려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.

  2. Build > Pipeline editor로 이동합니다.

  3. SAST job 설정에 C/C++ 분석을 추가합니다. 여기의 안내는 컴파일 데이터베이스 이름이 compile_commands.json 이라고 가정합니다.

    • CI/CD 템플릿을 사용한다면 include: 구문 뒤에 다음 CI/CD 변수를 설정에 추가합니다.

      include:
        - template: Jobs/SAST.gitlab-ci.yml
      
      variables:
        GITLAB_ADVANCED_SAST_CPP_ENABLED: "true"
        SAST_COMPILATION_DATABASE: "compile_commands.json"
      
    • CI/CD 컴포넌트를 사용한다면 다음 입력 파라미터와 CI/CD 변수를 설정에 추가합니다.

      include:
      - component: gitlab.com/components/sast/sast@main
          inputs:
            run_advanced_sast_cpp: "true"
      
      variables:
        SAST_COMPILATION_DATABASE: "compile_commands.json"
      
  4. Validate 탭을 선택한 다음 Validate pipeline을 선택합니다.

    Simulation completed successfully 메시지가 나오면 파일이 유효한 것입니다.

  5. Edit 탭을 선택합니다.

  6. 다음 항목을 입력합니다.

    • 커밋 메시지입니다.
    • 브랜치입니다. 예를 들면 add-sast 입니다.
  7. Start a new merge request with these changes 체크박스를 선택한 다음 Commit changes를 선택합니다.

    머지 리퀘스트 페이지가 열립니다.

  8. 평소 워크플로에 맞게 항목을 입력한 다음 Create merge request를 선택합니다.

  9. 평소 워크플로에 맞게 머지 리퀘스트를 검토하고 수정한 다음 Merge를 선택합니다.

컴파일 데이터베이스#

GitLab Advanced SAST CPP 분석기는 소스 파일을 정확히 파싱하고 분석하기 위해 컴파일 데이터베이스(CDB)를 필요로 합니다.

CDB는 번역 단위마다 항목 하나를 담은 JSON 파일(compile_commands.json)입니다. 각 항목에는 보통 다음이 들어 있습니다.

  • 파일을 빌드할 때 사용한 컴파일러 명령
  • 컴파일러 플래그와 include 경로
  • 컴파일을 수행한 작업 디렉터리

CDB가 있으면 분석기가 빌드 환경을 그대로 재현할 수 있어 파싱과 의미 분석이 정확해집니다.

GitLab Advanced SAST CPP를 사용하려면 CDB를 만들어 분석기에 제공해야 합니다.

CDB 생성#

CDB를 생성하는 방법은 빌드 시스템에 따라 다릅니다. 아래는 흔히 쓰는 예시입니다.

예시: CMake#

CMake는 cmake 호출에 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 파라미터를 추가하면 CDB를 바로 생성할 수 있습니다.

cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

이 옵션은 프로젝트를 구성하고 build 폴더에 compile_commands.json 파일을 생성하며, 이 파일에는 소스 파일별 컴파일러 명령이 기록됩니다.

GitLab Advanced SAST CPP 분석기는 이 파일로 빌드 환경을 정확히 재현합니다.

다음 빌드 job 예시처럼 생성된 compile_commands.json 파일을 job 아티팩트로 내보냅니다.

:
  image: ubuntu:24.04
  before_script:
    - apt update -qq && apt install -y -qq cmake build-essential
  script:
    - mkdir -p build
    - cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
    - make -j$(nproc)
  artifacts:
    paths:
      - build/compile_commands.json # Pass the CDB file to the gitlab-advanced-sast-cpp job

여러 빌드 시스템 예시#

여러 빌드 시스템에서 CDB를 생성하고 GitLab Advanced SAST CPP를 실행하는 전체 예시도 확인할 수 있습니다.

분석기에 CDB 제공#

SAST_COMPILATION_DATABASE 변수로 GitLab Advanced SAST CPP 분석기에 CDB 위치를 알려 줍니다.

variables:
  SAST_COMPILATION_DATABASE: YOUR_COMPILATION_DATABASE.json

SAST_COMPILATION_DATABASE를 지정하지 않으면 GitLab Advanced SAST CPP 분석기는 프로젝트 루트 디렉터리의 compile_commands.json 파일을 기본값으로 사용합니다.

compile_commands.json 파일을 생성하는 빌드 job은 gitlab-advanced-sast-cpp job 이 사용할 수 있도록 그 파일을 job 아티팩트로 내보내야 합니다.

variables:
  SAST_COMPILATION_DATABASE: build/compile_commands.json

:
  image: ubuntu:24.04
  before_script:
    - apt update -qq && apt install -y -qq cmake build-essential
  script:
    - mkdir -p build
    - cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
    - make -j$(nproc)
  artifacts:
    paths:
      - build/compile_commands.json # Pass the CDB file to the gitlab-advanced-sast-cpp job

또는 CDB 캐싱을 참고합니다.

분석 실행 시간 최적화#

C/C++ 코드의 분석 실행 시간을 줄이려면 CDB를 여러 조각으로 나눠 분석을 병렬로 실행할 수 있습니다.

GitLab Advanced SAST CPP 리포지터리는 CDB를 나누고 병렬 분석을 실행하는 헬퍼 스크립트를 제공합니다.

C/C++ 코드 분석을 병렬로 실행하려면 다음을 수행합니다.

  1. 스크립트를 포함합니다.

    include:
      - project: "gitlab-org/security-products/demos/sast/gitlab-advanced-sast-cpp-templates"
        file: "templates/scripts.yml"
    
  2. 빌드 job에서 헬퍼 스크립트를 참조하고 CDB를 나눕니다.

    :
      script:
        - <your-script to generate the CDB>
        - !reference [.gitlab-advanced-sast-cpp-scripts]
        - split_cdb "${BUILD_DIR}" 1 4 # Split into 4 fragments
      artifacts:
        paths:
          - ${BUILD_DIR} # Pass the split CDB files to the parallelized gitlab-advanced-sast-cpp jobs
    

    [!note] split_cdb는 ${BUILD_DIR}/compile_commands.json을 읽도록 고정되어 있습니다. split_cdb를 호출하기 전에 빌드가 바로 이 위치에 CDB를 생성해야 합니다.

  3. 병렬 분석기 job을 실행합니다.

    gitlab-advanced-sast-cpp:
      parallel: 4
      variables:
        SAST_COMPILATION_DATABASE: "${BUILD_DIR}/compile_commands${CI_NODE_INDEX}.json"
      needs:
        - job: 
          artifacts: true
    
    • parallel: 4는 실행을 4개 job으로 분산합니다.
    • ${CI_NODE_INDEX}(1, 2, 3, 4)는 해당하는 CDB 조각을 선택합니다.
    • needs는 분석기 job 이 빌드 job 이 만든 아티팩트를 받도록 보장합니다.

이렇게 설정하면 빌드 job 이 compile_commands.json 하나를 만듭니다. split_cdb 스크립트가 여러 파티션을 만들고, 분석기 job 들이 파티션을 하나씩 맡아 병렬로 실행합니다.

룰셋 설정#

GitLab Advanced SAST CPP는 사용자 지정 룰셋을 지원하며, 여기서 "규칙"은 GitLab Advanced SAST CPP 체커를 뜻합니다.

사용자 지정 룰셋은 CodeChecker 설정 파일로 구성한 패스스루로 만들 수 있습니다.

패스스루 설정은 다음과 같이 처리됩니다.

  • targetDir과 target은 무시됩니다. 패스스루를 처리한 뒤 만들어진 플래그는 CodeChecker에 그대로 전달됩니다.
  • overwrite 모드는 설정 전체를 대체하고, append 모드는 플래그를 덧붙입니다.
  • 분석기 플래그 -o, --output과 파싱 플래그 -o, --output, -e, --export를 비롯한 일부 CodeChecker 플래그는 사용자 지정할 수 없습니다.
  • server와 store 설정 항목은 무시됩니다.

다음 예시는 서로 다른 소스의 패스스루가 어떻게 결합되는지 보여 줍니다.

.gitlab/sast-ruleset.toml 파일:

[gitlab-advanced-sast-cpp]
    description = "My ruleset"

    [[gitlab-advanced-sast-cpp.passthrough]]
        # replace the GitLab default configuration with my own
        mode  = "overwrite"
        type  = "url"
        value = "https://example.com/gitlab-advanced-sast-cpp.yaml"

    [[gitlab-advanced-sast-cpp.passthrough]]
        # append flags from a file in the current repository
        mode  = "append"
        type  = "file"
        value = "gitlab-advanced-sast-cpp.yml"

https://example.com/gitlab-advanced-sast-cpp.yaml의 원격 설정:

analyzer:
  - --disable-all
  - --enable=core.DivideZero

gitlab-advanced-sast-cpp.yml의 로컬 설정:

analyzer:
  - --enable=core.CallAndMessage

결합된 최종 설정은 다음과 같습니다.

analyzer:
  - --disable-all
  - --enable=core.DivideZero
  - --enable=core.CallAndMessage

오프라인 환경#

오프라인 환경에서 GitLab Advanced SAST C/C++ 를 실행하려면 스캔을 실행하기 전에 clangsa 분석기 이미지를 로컬 레지스트리에 미러링합니다. 표준 gitlab-advanced-sast 이미지에는 다른 언어에 사용하는 clangsa 이미지가 들어 있지 않습니다. 이 이미지는 별도로 미러링해야 합니다.

clangsa 이미지를 미러링하려면 Secure-Binaries.gitlab-ci.yml 템플릿을 사용합니다. 이 템플릿에는 clangsa 이미지를 가져와 레지스트리에 푸시하는 gitlab-advanced-sast-cpp job 이 들어 있습니다.

오프라인 환경 구성에 관한 자세한 내용은 오프라인 환경을 참고합니다.

문제 해결#

cdb-rebase로 경로 재지정#

CDB 안의 경로가 CI/CD job의 컨테이너 경로와 맞지 않으면 cdb-rebase로 경로를 조정합니다.

설치는 다음과 같이 합니다.

go install gitlab.com/gitlab-org/secure/tools/cdb-rebase@latest

바이너리는 $GOPATH/bin 또는 $HOME/go/bin에 설치됩니다. 이 디렉터리가 PATH에 있는지 확인합니다.

사용 예시는 다음과 같습니다.

cdb-rebase compile_commands.json /host/path /container/path > rebased_compile_commands.json

CDB 수정#

빌드 환경과 스캔 환경이 다르면 생성된 CDB를 조정해야 할 수 있습니다. jq로 수정하거나, 미리 정의된 헬퍼 스크립트의 셸 함수 cdb_append를 사용할 수 있습니다.

cdb_append는 기존 CDB에 컴파일러 옵션을 덧붙입니다. 인자는 다음과 같습니다.

  • 첫 번째 인자: compile_commands.json 이 있는 폴더
  • 이후 인자: 덧붙일 추가 컴파일러 옵션

CI/CD 예시는 다음과 같습니다.

include:
  - project: "gitlab-org/security-products/demos/sast/gitlab-advanced-sast-cpp-templates"
    file: "templates/scripts.yml"

:
  script:
    - !reference [.gitlab-advanced-sast-cpp-scripts]
    - <your-script to generate the CDB>
    - cdb_append "${BUILD_DIR}" "-I'$PWD/include-cache'" "-Wno-error=register"

CDB 캐싱#

컴파일과 분석 과정을 빠르게 하려면 CDB를 캐시할 수 있습니다.

.cdb_cache:
  cache: &cdb_cache
    key:
      files:
        - Makefile
        - src/
    paths:
      - compile_commands.json

:
  script:
    - <your-script to generate the CDB>
  cache:
    <<: *cdb_cache
    policy: pull-push

gitlab-advanced-sast-cpp:
  cache:
    <<: *cdb_cache
    policy: pull

전체 예시는 데모 프로젝트 cached-cdb에서 확인합니다.

CDB의 절대 경로 처리#

데모 프로젝트에서는 Docker job의 Builds 디렉터리에서 bear를 실행합니다. CDB 경로는 /builds/$CI_PROJECT_PATH를 기준으로 하는 절대 경로입니다. 분석기 job gitlab-advanced-sast-cpp도 같은 위치에서 실행되므로 경로가 맞습니다.

분석 중에 사용할 수 없는 경로에서 CDB를 생성했다면 경로를 재지정해야 합니다. 분석기 이미지에 포함된 cdb-rebase 도구는 directory, file, output 경로를 다시 씁니다.

예시는 다음과 같습니다.

gitlab-advanced-sast-cpp:
  before-script:
    # Rebase the original CDB to be relative to the current directory.
    #
    # ORIGINAL_CDB_PATH     - Path to the CDB artifact from a previous job (e.g., artifacts/compile_commands.json)
    # ORIGINAL_CDB_BASEPATH - The absolute path to the project root when the ORIGINAL_CDB_PATH was generated.
    #                         (e.g., /mnt/custom_build_area/my-project or /home/user/my-project)
    - /cdb-rebase   --input "$ORIGINAL_CDB_PATH" \
                    --output compile_commands.json \
                    --src "$ORIGINAL_CDB_BASEPATH" \
                    --dst .

전체 시연은 cdb-rebase-demo에서 확인합니다.

cdb-rebase는 단순한 경로 재지정 외에 빌드 환경과 스캔 환경 사이의 include 파일도 관리할 수 있습니다.

  • 외부 헤더 캐싱: --include-cache를 사용하면 소스 트리 밖의 헤더를 이식 가능한 캐시로 복사합니다.
  • include 경로 추가: --include로 캐시할 추가 include 디렉터리를 지정합니다.
  • 파일 제외: --exclude로 가져오지 않을 헤더를 건너뜁니다.

예시는 다음과 같습니다.

/cdb-rebase --src /my-project \
            --dst /scan-env \
            --input build/compile_commands.json \
            --output rebased_cdb.json \
            --include-cache include-cache \
            --include third_party/include \
            --exclude dummy.h

cdb-rebase 도구는 Go가 설치된 환경에서도 사용할 수 있으므로, CDB를 생성할 때 바로 경로를 재지정할 수 있습니다. 예를 들면 다음과 같습니다.

go install gitlab.com/gitlab-org/security-products/analyzers/clangsa/cmd/cdb-rebase@latest
bear -o compile_commands_abs.json -- make
cdb-rebase -i compile_commands_abs.json -o compile_commands.json -s "$PWD" -d .
Note

위의 go install 명령은 cdb-rebase를 GOBIN 경로에 설치하며, 이 경로는 go env GOBIN으로 확인할 수 있습니다.

헤더 파일 누락으로 인한 부분 스캔 커버리지#

필요한 시스템 헤더나 서드파티 헤더 파일이 스캔 job에 없으면 스캔 커버리지가 일부에 그칠 수 있습니다. 빌드 job에서 설치한 헤더는 스캔 job으로 명시적으로 전달해야 하며, 컴파일 데이터베이스에 기록된 include 경로로 찾을 수 있어야 합니다.

흔히 쓰는 방법은 필요한 헤더를 캐시하고 컴파일 데이터베이스가 그 헤더를 참조하도록 갱신하는 것입니다.

# Create and populate an include cache
mkdir -p include-cache
dpkg -L <build-dependency-packages> | sed -n 's:^/usr/include/::p' > headers.txt
rsync -a --files-from=headers.txt /usr/include/ include-cache/

# Add cached headers to compile flags
cdb_append . "-I'$PWD/include-cache'"

전체 시연은 예시에서 확인합니다.

Advanced SAST C/C++ 구성

GitLab v19.5
Tier: Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기

요약

프로젝트에서 GitLab Advanced SAST C/C++ 분석을 켜려면 다음을 수행합니다. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다. Build > Pipeline editor로 이동합니다.

히스토리

GitLab Advanced SAST C/C++ 분석 켜기#

사전 요구 사항:

프로젝트에서 GitLab Advanced SAST C/C++ 분석을 켜려면 다음을 수행합니다.

  1. 상단 바에서 Search or go to를 선택하고 프로젝트를 찾습니다.

  2. Build > Pipeline editor로 이동합니다.

  3. SAST job 설정에 C/C++ 분석을 추가합니다. 여기의 안내는 컴파일 데이터베이스 이름이 compile_commands.json 이라고 가정합니다.

    • CI/CD 템플릿을 사용한다면 include: 구문 뒤에 다음 CI/CD 변수를 설정에 추가합니다.

      include:
        - template: Jobs/SAST.gitlab-ci.yml
      
      variables:
        GITLAB_ADVANCED_SAST_CPP_ENABLED: "true"
        SAST_COMPILATION_DATABASE: "compile_commands.json"
      
    • CI/CD 컴포넌트를 사용한다면 다음 입력 파라미터와 CI/CD 변수를 설정에 추가합니다.

      include:
      - component: gitlab.com/components/sast/sast@main
          inputs:
            run_advanced_sast_cpp: "true"
      
      variables:
        SAST_COMPILATION_DATABASE: "compile_commands.json"
      
  4. Validate 탭을 선택한 다음 Validate pipeline을 선택합니다.

    Simulation completed successfully 메시지가 나오면 파일이 유효한 것입니다.

  5. Edit 탭을 선택합니다.

  6. 다음 항목을 입력합니다.

    • 커밋 메시지입니다.
    • 브랜치입니다. 예를 들면 add-sast 입니다.
  7. Start a new merge request with these changes 체크박스를 선택한 다음 Commit changes를 선택합니다.

    머지 리퀘스트 페이지가 열립니다.

  8. 평소 워크플로에 맞게 항목을 입력한 다음 Create merge request를 선택합니다.

  9. 평소 워크플로에 맞게 머지 리퀘스트를 검토하고 수정한 다음 Merge를 선택합니다.

컴파일 데이터베이스#

GitLab Advanced SAST CPP 분석기는 소스 파일을 정확히 파싱하고 분석하기 위해 컴파일 데이터베이스(CDB)를 필요로 합니다.

CDB는 번역 단위마다 항목 하나를 담은 JSON 파일(compile_commands.json)입니다. 각 항목에는 보통 다음이 들어 있습니다.

  • 파일을 빌드할 때 사용한 컴파일러 명령
  • 컴파일러 플래그와 include 경로
  • 컴파일을 수행한 작업 디렉터리

CDB가 있으면 분석기가 빌드 환경을 그대로 재현할 수 있어 파싱과 의미 분석이 정확해집니다.

GitLab Advanced SAST CPP를 사용하려면 CDB를 만들어 분석기에 제공해야 합니다.

CDB 생성#

CDB를 생성하는 방법은 빌드 시스템에 따라 다릅니다. 아래는 흔히 쓰는 예시입니다.

예시: CMake#

CMake는 cmake 호출에 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 파라미터를 추가하면 CDB를 바로 생성할 수 있습니다.

cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

이 옵션은 프로젝트를 구성하고 build 폴더에 compile_commands.json 파일을 생성하며, 이 파일에는 소스 파일별 컴파일러 명령이 기록됩니다.

GitLab Advanced SAST CPP 분석기는 이 파일로 빌드 환경을 정확히 재현합니다.

다음 빌드 job 예시처럼 생성된 compile_commands.json 파일을 job 아티팩트로 내보냅니다.

:
  image: ubuntu:24.04
  before_script:
    - apt update -qq && apt install -y -qq cmake build-essential
  script:
    - mkdir -p build
    - cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
    - make -j$(nproc)
  artifacts:
    paths:
      - build/compile_commands.json # Pass the CDB file to the gitlab-advanced-sast-cpp job

여러 빌드 시스템 예시#

여러 빌드 시스템에서 CDB를 생성하고 GitLab Advanced SAST CPP를 실행하는 전체 예시도 확인할 수 있습니다.

분석기에 CDB 제공#

SAST_COMPILATION_DATABASE 변수로 GitLab Advanced SAST CPP 분석기에 CDB 위치를 알려 줍니다.

variables:
  SAST_COMPILATION_DATABASE: YOUR_COMPILATION_DATABASE.json

SAST_COMPILATION_DATABASE를 지정하지 않으면 GitLab Advanced SAST CPP 분석기는 프로젝트 루트 디렉터리의 compile_commands.json 파일을 기본값으로 사용합니다.

compile_commands.json 파일을 생성하는 빌드 job은 gitlab-advanced-sast-cpp job 이 사용할 수 있도록 그 파일을 job 아티팩트로 내보내야 합니다.

variables:
  SAST_COMPILATION_DATABASE: build/compile_commands.json

:
  image: ubuntu:24.04
  before_script:
    - apt update -qq && apt install -y -qq cmake build-essential
  script:
    - mkdir -p build
    - cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
    - make -j$(nproc)
  artifacts:
    paths:
      - build/compile_commands.json # Pass the CDB file to the gitlab-advanced-sast-cpp job

또는 CDB 캐싱을 참고합니다.

분석 실행 시간 최적화#

C/C++ 코드의 분석 실행 시간을 줄이려면 CDB를 여러 조각으로 나눠 분석을 병렬로 실행할 수 있습니다.

GitLab Advanced SAST CPP 리포지터리는 CDB를 나누고 병렬 분석을 실행하는 헬퍼 스크립트를 제공합니다.

C/C++ 코드 분석을 병렬로 실행하려면 다음을 수행합니다.

  1. 스크립트를 포함합니다.

    include:
      - project: "gitlab-org/security-products/demos/sast/gitlab-advanced-sast-cpp-templates"
        file: "templates/scripts.yml"
    
  2. 빌드 job에서 헬퍼 스크립트를 참조하고 CDB를 나눕니다.

    :
      script:
        - <your-script to generate the CDB>
        - !reference [.gitlab-advanced-sast-cpp-scripts]
        - split_cdb "${BUILD_DIR}" 1 4 # Split into 4 fragments
      artifacts:
        paths:
          - ${BUILD_DIR} # Pass the split CDB files to the parallelized gitlab-advanced-sast-cpp jobs
    

    [!note] split_cdb는 ${BUILD_DIR}/compile_commands.json을 읽도록 고정되어 있습니다. split_cdb를 호출하기 전에 빌드가 바로 이 위치에 CDB를 생성해야 합니다.

  3. 병렬 분석기 job을 실행합니다.

    gitlab-advanced-sast-cpp:
      parallel: 4
      variables:
        SAST_COMPILATION_DATABASE: "${BUILD_DIR}/compile_commands${CI_NODE_INDEX}.json"
      needs:
        - job: 
          artifacts: true
    
    • parallel: 4는 실행을 4개 job으로 분산합니다.
    • ${CI_NODE_INDEX}(1, 2, 3, 4)는 해당하는 CDB 조각을 선택합니다.
    • needs는 분석기 job 이 빌드 job 이 만든 아티팩트를 받도록 보장합니다.

이렇게 설정하면 빌드 job 이 compile_commands.json 하나를 만듭니다. split_cdb 스크립트가 여러 파티션을 만들고, 분석기 job 들이 파티션을 하나씩 맡아 병렬로 실행합니다.

룰셋 설정#

GitLab Advanced SAST CPP는 사용자 지정 룰셋을 지원하며, 여기서 "규칙"은 GitLab Advanced SAST CPP 체커를 뜻합니다.

사용자 지정 룰셋은 CodeChecker 설정 파일로 구성한 패스스루로 만들 수 있습니다.

패스스루 설정은 다음과 같이 처리됩니다.

  • targetDir과 target은 무시됩니다. 패스스루를 처리한 뒤 만들어진 플래그는 CodeChecker에 그대로 전달됩니다.
  • overwrite 모드는 설정 전체를 대체하고, append 모드는 플래그를 덧붙입니다.
  • 분석기 플래그 -o, --output과 파싱 플래그 -o, --output, -e, --export를 비롯한 일부 CodeChecker 플래그는 사용자 지정할 수 없습니다.
  • server와 store 설정 항목은 무시됩니다.

다음 예시는 서로 다른 소스의 패스스루가 어떻게 결합되는지 보여 줍니다.

.gitlab/sast-ruleset.toml 파일:

[gitlab-advanced-sast-cpp]
    description = "My ruleset"

    [[gitlab-advanced-sast-cpp.passthrough]]
        # replace the GitLab default configuration with my own
        mode  = "overwrite"
        type  = "url"
        value = "https://example.com/gitlab-advanced-sast-cpp.yaml"

    [[gitlab-advanced-sast-cpp.passthrough]]
        # append flags from a file in the current repository
        mode  = "append"
        type  = "file"
        value = "gitlab-advanced-sast-cpp.yml"

https://example.com/gitlab-advanced-sast-cpp.yaml의 원격 설정:

analyzer:
  - --disable-all
  - --enable=core.DivideZero

gitlab-advanced-sast-cpp.yml의 로컬 설정:

analyzer:
  - --enable=core.CallAndMessage

결합된 최종 설정은 다음과 같습니다.

analyzer:
  - --disable-all
  - --enable=core.DivideZero
  - --enable=core.CallAndMessage

오프라인 환경#

오프라인 환경에서 GitLab Advanced SAST C/C++ 를 실행하려면 스캔을 실행하기 전에 clangsa 분석기 이미지를 로컬 레지스트리에 미러링합니다. 표준 gitlab-advanced-sast 이미지에는 다른 언어에 사용하는 clangsa 이미지가 들어 있지 않습니다. 이 이미지는 별도로 미러링해야 합니다.

clangsa 이미지를 미러링하려면 Secure-Binaries.gitlab-ci.yml 템플릿을 사용합니다. 이 템플릿에는 clangsa 이미지를 가져와 레지스트리에 푸시하는 gitlab-advanced-sast-cpp job 이 들어 있습니다.

오프라인 환경 구성에 관한 자세한 내용은 오프라인 환경을 참고합니다.

문제 해결#

cdb-rebase로 경로 재지정#

CDB 안의 경로가 CI/CD job의 컨테이너 경로와 맞지 않으면 cdb-rebase로 경로를 조정합니다.

설치는 다음과 같이 합니다.

go install gitlab.com/gitlab-org/secure/tools/cdb-rebase@latest

바이너리는 $GOPATH/bin 또는 $HOME/go/bin에 설치됩니다. 이 디렉터리가 PATH에 있는지 확인합니다.

사용 예시는 다음과 같습니다.

cdb-rebase compile_commands.json /host/path /container/path > rebased_compile_commands.json

CDB 수정#

빌드 환경과 스캔 환경이 다르면 생성된 CDB를 조정해야 할 수 있습니다. jq로 수정하거나, 미리 정의된 헬퍼 스크립트의 셸 함수 cdb_append를 사용할 수 있습니다.

cdb_append는 기존 CDB에 컴파일러 옵션을 덧붙입니다. 인자는 다음과 같습니다.

  • 첫 번째 인자: compile_commands.json 이 있는 폴더
  • 이후 인자: 덧붙일 추가 컴파일러 옵션

CI/CD 예시는 다음과 같습니다.

include:
  - project: "gitlab-org/security-products/demos/sast/gitlab-advanced-sast-cpp-templates"
    file: "templates/scripts.yml"

:
  script:
    - !reference [.gitlab-advanced-sast-cpp-scripts]
    - <your-script to generate the CDB>
    - cdb_append "${BUILD_DIR}" "-I'$PWD/include-cache'" "-Wno-error=register"

CDB 캐싱#

컴파일과 분석 과정을 빠르게 하려면 CDB를 캐시할 수 있습니다.

.cdb_cache:
  cache: &cdb_cache
    key:
      files:
        - Makefile
        - src/
    paths:
      - compile_commands.json

:
  script:
    - <your-script to generate the CDB>
  cache:
    <<: *cdb_cache
    policy: pull-push

gitlab-advanced-sast-cpp:
  cache:
    <<: *cdb_cache
    policy: pull

전체 예시는 데모 프로젝트 cached-cdb에서 확인합니다.

CDB의 절대 경로 처리#

데모 프로젝트에서는 Docker job의 Builds 디렉터리에서 bear를 실행합니다. CDB 경로는 /builds/$CI_PROJECT_PATH를 기준으로 하는 절대 경로입니다. 분석기 job gitlab-advanced-sast-cpp도 같은 위치에서 실행되므로 경로가 맞습니다.

분석 중에 사용할 수 없는 경로에서 CDB를 생성했다면 경로를 재지정해야 합니다. 분석기 이미지에 포함된 cdb-rebase 도구는 directory, file, output 경로를 다시 씁니다.

예시는 다음과 같습니다.

gitlab-advanced-sast-cpp:
  before-script:
    # Rebase the original CDB to be relative to the current directory.
    #
    # ORIGINAL_CDB_PATH     - Path to the CDB artifact from a previous job (e.g., artifacts/compile_commands.json)
    # ORIGINAL_CDB_BASEPATH - The absolute path to the project root when the ORIGINAL_CDB_PATH was generated.
    #                         (e.g., /mnt/custom_build_area/my-project or /home/user/my-project)
    - /cdb-rebase   --input "$ORIGINAL_CDB_PATH" \
                    --output compile_commands.json \
                    --src "$ORIGINAL_CDB_BASEPATH" \
                    --dst .

전체 시연은 cdb-rebase-demo에서 확인합니다.

cdb-rebase는 단순한 경로 재지정 외에 빌드 환경과 스캔 환경 사이의 include 파일도 관리할 수 있습니다.

  • 외부 헤더 캐싱: --include-cache를 사용하면 소스 트리 밖의 헤더를 이식 가능한 캐시로 복사합니다.
  • include 경로 추가: --include로 캐시할 추가 include 디렉터리를 지정합니다.
  • 파일 제외: --exclude로 가져오지 않을 헤더를 건너뜁니다.

예시는 다음과 같습니다.

/cdb-rebase --src /my-project \
            --dst /scan-env \
            --input build/compile_commands.json \
            --output rebased_cdb.json \
            --include-cache include-cache \
            --include third_party/include \
            --exclude dummy.h

cdb-rebase 도구는 Go가 설치된 환경에서도 사용할 수 있으므로, CDB를 생성할 때 바로 경로를 재지정할 수 있습니다. 예를 들면 다음과 같습니다.

go install gitlab.com/gitlab-org/security-products/analyzers/clangsa/cmd/cdb-rebase@latest
bear -o compile_commands_abs.json -- make
cdb-rebase -i compile_commands_abs.json -o compile_commands.json -s "$PWD" -d .
Note

위의 go install 명령은 cdb-rebase를 GOBIN 경로에 설치하며, 이 경로는 go env GOBIN으로 확인할 수 있습니다.

헤더 파일 누락으로 인한 부분 스캔 커버리지#

필요한 시스템 헤더나 서드파티 헤더 파일이 스캔 job에 없으면 스캔 커버리지가 일부에 그칠 수 있습니다. 빌드 job에서 설치한 헤더는 스캔 job으로 명시적으로 전달해야 하며, 컴파일 데이터베이스에 기록된 include 경로로 찾을 수 있어야 합니다.

흔히 쓰는 방법은 필요한 헤더를 캐시하고 컴파일 데이터베이스가 그 헤더를 참조하도록 갱신하는 것입니다.

# Create and populate an include cache
mkdir -p include-cache
dpkg -L <build-dependency-packages> | sed -n 's:^/usr/include/::p' > headers.txt
rsync -a --files-from=headers.txt /usr/include/ include-cache/

# Add cached headers to compile flags
cdb_append . "-I'$PWD/include-cache'"

전체 시연은 예시에서 확인합니다.