사용자 정의 규칙 집합
- GitLab 16.2에서 모호한 passthrough refs를 지정하는 지원을 활성화했습니다.
저희의 SAST 분석기의 동작을 구체적으로 정의하는 규칙 집합 구성 파일을 정의함으로써 커스터마이징할 수 있습니다. 두 가지 유형의 커스터마이징이 있습니다:
-
미리 정의된 규칙의 동작 수정. 이에는 다음이 포함됩니다:
- 미리 정의된 규칙 비활성화. 모든 분석기에서 사용 가능합니다.
- 미리 정의된 규칙 재정의. 모든 분석기에서 사용 가능합니다.
- Passthroughs를 사용하여 미리 정의된 규칙 대체. Semgrep 기반 분석기에서만 사용 가능합니다.
고급 SAST는 미리 정의된 규칙의 동작 수정만 지원하며, 미리 정의된 규칙을 대체하는 기능은 제공하지 않습니다.
미리 정의된 규칙 비활성화
어떤 SAST 분석기의 미리 정의된 규칙을 비활성화할 수 있습니다.
규칙을 비활성화하면:
- 대부분의 분석기는 여전히 취약점을 스캔합니다. 스캔이 완료된 후 처리 단계에서 결과가 제거되며,
gl-sast-report.json
artifact에 표시되지 않습니다. - 비활성화된 규칙의 발견 사항은 더 이상 파이프라인 보안 탭에 나타나지 않습니다.
- 기본 브랜치에서 비활성화된 규칙의 기존 발견 사항은 더 이상 감지되지 않음으로 표시됩니다. 취약점 보고서에서.
Semgrep 기반 분석기는 비활성화된 규칙을 다르게 처리합니다:
- 성능을 향상시키기 위해, Semgrep 기반 분석기는 비활성화된 규칙을 전혀 스캔하지 않습니다.
- Semgrep 기반 분석기에서 규칙을 비활성화하면 해당 규칙에 대한 기존 취약점 발견 사항은
sast-ruleset.toml
파일을 기본 브랜치에 병합한 후 자동으로 해결됩니다.
이 동작을 구성하는 방법에 대한 정보는 스키마 및 예시 섹션을 참조하십시오.
미리 정의된 규칙 재정의
어떤 SAST 분석기에 대한 미리 정의된 규칙의 특정 속성을 재정의할 수 있습니다. 이것은 SAST를 기존의 워크플로나 도구에 적응시킬 때 유용합니다. 예를 들어, 기관 정책에 따라 취약점의 심각도를 재정의하거나, 취약점 보고서에 표시할 다른 메시지를 선택할 수 있습니다.
이 동작을 구성하는 방법에 대한 정보는 스키마 및 예시 섹션을 참조하십시오.
사용자 정의 구성 빌드
Semgrep 기반 분석기를 위한 GitLab이 제공하는 규칙집합을 사용자 정의로 대체할 수 있습니다.
Passthroughs를 통해 사용자 지정을 제공하며, 이는 실행시 passthrough 체인으로 구성되어 완전한 구성을 생성하기 위해 평가됩니다. 결과적으로 기존 스캐너는 이 새로운 구성 대상으로 실행됩니다.
파일에 커밋하거나 규칙 집합 구성 파일 내부에 인라인으로 구성을 제공하는 등 다양한 passthrough 유형이 있습니다. 또한 체인 내의 이후 passthrough가 이전 구성을 덮어쓰거나 추가하는 방식을 선택할 수 있습니다.
이 동작을 구성하는 방법에 대한 정보에는 스키마 및 예시 섹션을 참조하십시오.
구성 파일 생성
규칙 집합 구성 파일을 생성하려면:
- 프로젝트 루트에
.gitlab
디렉토리를 만듭니다(이미 존재하지 않는 경우). -
.gitlab
디렉토리에sast-ruleset.toml
라는 파일을 만듭니다.
원격 구성 파일 지정
- 16.1에서 도입됨.
현재 저장소 외부에 저장된 규칙 집합 구성 파일을 사용하려면 CI/CD 변수를 설정할 수 있습니다. 이를 통해 여러 프로젝트에 걸쳐 동일한 규칙을 적용할 수 있습니다.
SAST_RULESET_GIT_REFERENCE
변수는 프로젝트 URI, 선택적 인증, 선택적 Git SHA와 유사한 형식을 사용합니다. 다음 형식을 사용합니다:
[<AUTH_USER>[:<AUTH_PASSWORD>]@]<PROJECT_PATH>[@<GIT_SHA>]
참고:
만약 프로젝트에 .gitlab/sast-ruleset.toml
파일이 커밋되어 있다면 현재 저장소의 local configuration이 우선시되며 SAST_RULESET_GIT_REFERENCE
에서 가져온 파일은 사용되지 않습니다.
다음 예시는 SAST 구성을 설정하고 공유된 규칙 집합 커스터마이징 파일을 사용합니다. 이 예시에서 해당 파일은 example-ruleset-project
의 기본 브랜치에 커밋되어 있는 경로인 .gitlab/sast-ruleset.toml
입니다.
include:
- template: Jobs/SAST.gitlab-ci.yml
variables:
SAST_RULESET_GIT_REFERENCE: "gitlab.com/example-group/example-ruleset-project"
고급 사용법에 대해서는 특정 사례에 대한 사설 원격 구성 지정을 참조하십시오.
원격 구성 파일 문제 해결
원격 구성 파일이 사용자 지정을 올바르게 적용하지 못하는 경우 원인은 다음과 같을 수 있습니다:
- 현재 저장소에 로컬
.gitlab/sast-ruleset.toml
파일이 있습니다.- 기본적으로, 로컬 파일이 있으면 원격 구성이 변수로 설정되었더라도 로컬 구성 파일이 사용됩니다.
- 로컬 구성파일을 무시하려면 SECURE_ENABLE_LOCAL_CONFIGURATION CI/CD 변수를
false
로 설정할 수 있습니다.
- 인증에 문제가 있습니다.
- 이것이 문제의 원인인지 확인하려면 인증이 필요 없는 저장소 위치에서 구성 파일을 참조해 보십시오.
스키마
최상위 섹션
최상위 섹션에는 TOML 테이블로 정의된 하나 이상의 _구성 섹션_이 포함됩니다.
설정 | 설명 |
---|---|
[$분석기]
| 이름은 SAST 분석기 목록에 정의된 snake-case 이름에 따라 분석기에 대한 구성 섹션을 선언합니다. |
구성 예시:
[semgrep]
...
기존 규칙을 수정하고 사용자 정의 규칙 집합을 빌드파일에 커밋하지 마십시오. 후자는 미리 정의된 규칙을 완전히 대체합니다.
[$analyzer]
구성 섹션
[$analyzer]
섹션을 사용하면 분석기의 동작을 사용자 정의할 수 있습니다. 유효한 속성은 구성하는 종류에 따라 다릅니다.
설정 | 적용 대상 | 설명 |
---|---|---|
[[$analyzer.ruleset]]
| 미리 정의된 규칙 | 기존 규칙을 수정하는 것을 정의합니다. |
interpolate
| 전체 |
true 로 설정하면 구성에서 환경 변수를 평가하기 위해 $VAR 를 사용할 수 있습니다. 이 기능을 사용할 때에는 주의하세요. 비밀이나 토큰이 노출되지 않도록 주의하세요. (기본값: false )
|
description
| 패스스루 | 사용자 지정 규칙의 설명 |
targetdir
| 패스스루 | 최종 구성이 유지되어야 하는 디렉토리. 비어 있으면 무작위 이름의 디렉토리가 생성됩니다. 디렉토리에는 최대 100MB의 파일이 포함될 수 있습니다. |
validate
| 패스스루 |
true 로 설정하면 각 패스스루의 내용이 유효성 검사됩니다. 유효성 검사는 yaml , xml , json , toml 콘텐츠에 대해 작동합니다. 올바른 유효성 검사기는 [[$analyzer.passthrough]] 섹션의 target 매개변수에서 사용된 확장자를 기반으로 식별됩니다. (기본값: false )
|
timeout
| 패스스루 | 타임 아웃되기 전에 패스스루 체인을 평가하는 데 소요되는 최대 시간. 타임아웃은 300초를 초과할 수 없습니다. (기본값: 60) |
interpolate
경고: 비밀이 노출되는 위험을 줄이려면 이 기능을 주의하여 사용하세요.
아래 예제는 $GITURL
환경 변수를 사용하여 개인 저장소에 액세스하는 구성을 보여줍니다. 해당 변수에는 사용자 이름 및 토큰(예: https://user:token@url
)이 포함되어 있으므로 구성 파일에 명시적으로 저장되지 않습니다.
[semgrep]
description = "내 개인 Semgrep 규칙집"
interpolate = true
[[semgrep.passthrough]]
type = "git"
value = "$GITURL"
ref = "main"
[[$analyzer.ruleset]]
섹션
[[$analyzer.ruleset]]
섹션은 단일 미리 정의된 규칙을 대상으로 수정합니다. 분석기 당 하나 이상의 이러한 섹션을 정의할 수 있습니다.
설정 | 설명 |
---|---|
disable
| 규칙을 비활성화해야 하는지 여부. (기본값: false )
|
[$analyzer.ruleset.identifier]
| 수정할 미리 정의된 규칙을 선택합니다. |
[$analyzer.ruleset.override]
| 규칙을 위해 오버라이드를 정의합니다. |
구성 예시:
[semgrep]
[[semgrep.ruleset]]
disable = true
...
[$analyzer.ruleset.identifier]
섹션
[$analyzer.ruleset.identifier]
섹션은 수정하려는 미리 정의된 규칙의 식별자를 정의합니다.
설정 | 설명 |
---|---|
type
| 미리 정의된 규칙이 사용하는 식별자의 유형 |
value
| 미리 정의된 규칙이 사용하는 식별자의 값 |
분석기가 생성한 gl-sast-report.json
파일을 보고 식별자의 올바른 값을 확인할 수 있습니다.
분석기의 CI 작업에서 작업 artifact로 이 파일을 다운로드할 수 있습니다.
예를 들어, 아래 스니펫은 세 가지 식별자를 가진 semgrep
규칙에서의 결과를 보여줍니다. JSON 객체의 type
및 value
키는 이 섹션에서 제공해야 하는 값과 일치합니다.
...
"vulnerabilities": [
{
"id": "7331a4b7093875f6eb9f6eb1755b30cc792e9fb3a08c9ce673fb0d2207d7c9c9",
"category": "sast",
"message": "Entity Authentication이 없는 키 교환",
"description": "ssh.InsecureIgnoreHostKey의 사용을 감사",
...
"identifiers": [
{
"type": "semgrep_id",
"name": "gosec.G106-1",
"value": "gosec.G106-1"
},
{
"type": "cwe",
"name": "CWE-322",
"value": "322",
"url": "https://cwe.mitre.org/data/definitions/322.html"
},
{
"type": "gosec_rule_id",
"name": "Gosec Rule ID G106",
"value": "G106"
}
]
}
...
]
...
구성 예시:
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.identifier]
type = "semgrep_id"
value = "gosec.G106-1
...
[$analyzer.ruleset.override]
섹션
[$analyzer.ruleset.override]
섹션을 사용하면 미리 정의된 규칙의 속성을 재정의할 수 있습니다.
설정 | 설명 |
---|---|
description
| 문제에 대한 자세한 설명 |
message
| (폐기됨) 문제에 대한 설명 |
name
| 규칙의 이름 |
severity
| 규칙의 심각성. Critical , High , Medium , Low , Unknown , Info 와 같은 유효한 옵션이 있습니다.
|
참고:
message
는 분석기가 채웁니다. 그러나 이제 name
및 description
을 선호하므로 폐기되었습니다.
구성 예시:
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.override]
severity = "Critical"
name = "명령 삽입"
...
[[$analyzer.passthrough]]
섹션
참고: 패스스루 구성은 Semgrep 기반 분석기에만 해당됩니다.
[[$analyzer.passthrough]]
섹션은 분석기의 사용자 지정 구성을 만들 수 있게 해줍니다. 분석기 당 최대 20개의 이러한 섹션을 정의할 수 있습니다. 패스스루는 완전한 구성으로 변환되는 _패스스루 체인_을 구성합니다. 이를 통해 분석기의 미리 정의된 규칙을 대체할 수 있습니다.
패스스루는 순서대로 평가됩니다. 체인에 나중에 나오는 패스스루가 우선적으로 처리되어 이전 패스스루에 의해 생성된 데이터를 덮어쓰거나 추가할 수 있습니다(mode
에 따라 다름). 이는 기존 구성을 사용하거나 수정해야 하는 경우 유용합니다.
단일 패스스루에 의해 생성된 구성의 크기는 10MB로 제한됩니다.
설정 | 적용 대상 | 설명 |
---|---|---|
type
| 전체 |
file , raw , git , url 중 하나
|
target
| 전체 | 패스스루 평가에 의해 작성되는 데이터를 포함하는 대상 파일. 비어 있으면 무작위 파일 이름이 사용됩니다. |
mode
| 전체 |
overwrite 인 경우 target 파일이 덮어쓰입니다. append 인 경우 새 콘텐츠가 target 파일에 추가됩니다. git 유형은 overwrite 만 지원합니다. (기본값: overwrite )
|
ref
| type = "git"
| 가져올 브랜치, 태그 또는 SHA의 이름을 포함 |
subdir
| type = "git"
| Git 저장소의 하위디렉토리를 구성 소스로 선택하는 데 사용됨 |
value
| 전체 |
file , url , git 유형의 경우 파일 또는 Git 저장소의 위치를 정의합니다. raw 유형의 경우 인라인 구성을 포함합니다.
|
validator
| 전체 | 패스스루의 평가 후 대상 파일에 대해 명시적으로 유효성 검사기(xml , yaml , json , toml )를 호출하는 데 사용됩니다.
|
Passthrough 유형
유형 | 설명 |
---|---|
file
| Git 저장소에 있는 파일을 사용합니다. |
raw
| 인라인으로 구성을 제공합니다. |
git
| 원격 Git 저장소에서 구성을 가져옵니다. |
url
| HTTP를 사용하여 구성을 가져옵니다. |
경고:
raw
passthrough를 사용할 때 YAML 스니펫을 사용하는 경우 모든 들여쓰기를 sast-ruleset.toml
파일에서 공백으로 형식을 지정하는 것이 좋습니다. YAML 사양은 탭보다 공백을 요구하며, 들여쓰기가 이에 맞게 표시되지 않으면 분석기가 사용자 정의 규칙세트를 구문 분석하지 못합니다.
예시
SAST 분석기의 사전 정의된 규칙 비활성화
다음 사용자 정의 규칙세트 구성으로 보고서에서 다음 규칙을 제외합니다:
-
semgrep
규칙 중semgrep_id
가gosec.G106-1
이거나cwe
가322
인 것. -
sobelow
규칙 중sobelow_rule_id
가sql_injection
인 것. -
flawfinder
규칙 중flawfinder_func_name
이memcpy
인 것.
[semgrep]
[[semgrep.ruleset]]
disable = true
[semgrep.ruleset.identifier]
type = "semgrep_id"
value = "gosec.G106-1"
[[semgrep.ruleset]]
disable = true
[semgrep.ruleset.identifier]
type = "cwe"
value = "322"
[sobelow]
[[sobelow.ruleset]]
disable = true
[sobelow.ruleset.identifier]
type = "sobelow_rule_id"
value = "sql_injection"
[flawfinder]
[[flawfinder.ruleset]]
disable = true
[flawfinder.ruleset.identifier]
type = "flawfinder_func_name"
value = "memcpy"
SAST 분석기의 사전 정의된 규칙 재정의
다음 사용자 정의 규칙세트 구성으로, semgrep
에서 발견된 취약점의 유형이 CWE
이고 값이 322
인 경우 심각성이 Critical
로 재정의됩니다.
[semgrep]
[[semgrep.ruleset]]
[semgrep.ruleset.identifier]
type = "cwe"
value = "322"
[semgrep.ruleset.override]
severity = "Critical"
semgrep
에 대한 파일 passthrough를 사용하여 사용자 지정 구성 빌드
다음 사용자 정의 규칙세트 구성으로, semgrep
분석기의 사전 정의된 규칙세트를 대상 저장소의 my-semgrep-rules.yaml
이라는 파일에 포함된 사용자 정의 규칙세트로 대체합니다.
# my-semgrep-rules.yml
---
rules:
- id: my-custom-rule
pattern: print("Hello World")
message: |
Unauthorized use of Hello World.
severity: ERROR
languages:
- python
[semgrep]
description = "Semgrep를 위한 내 사용자 정의 규칙세트"
[[semgrep.passthrough]]
type = "file"
value = "my-semgrep-rules.yml"
semgrep
에 대한 passthrough 체인을 사용하여 사용자 정의 구성 빌드
다음 사용자 정의 규칙세트 구성으로, semgrep
분석기의 사전 정의된 규칙세트를 네 개의 passthrough를 평가하여 생성된 사용자 정의 규칙세트로 대체합니다. 각 passthrough는 컨테이너 내의 /sgrules
디렉터리에 쓰여지는 파일을 생성합니다. Git 원격 저장소에 반응하지 않는 경우를 대비하여 timeout
을 60초로 설정합니다.
이 예시에서 다양한 passthrough 유형을 시연합니다:
- 두 개의
git
passthrough. 첫 번째는myrules
Git 저장소에서develop
브랜치, 두 번째는sast-rules
저장소에서go
하위 디렉토리에 있는97f7686
버전을 가져오고 있습니다.-
sast-rules
항목은 구성에서 나중에 나타나기 때문에 더 높은 우선순위를 가집니다. - 두 체크아웃 사이에 파일명 충돌이 있는 경우,
sast-rules
저장소의 파일이myrules
저장소의 파일을 덮어씁니다.
-
-
raw
passthrough,value
를/sgrules/insecure.yml
에 씁니다. -
url
passthrough, URL에 호스팅된 구성을 가져와/sgrules/gosec.yml
에 씁니다.
이후 Semgrep은 /sgrules
아래에 있는 최종 구성을 사용하여 호출됩니다.
[semgrep]
description = "Semgrep를 위한 내 사용자 정의 규칙세트"
targetdir = "/sgrules"
timeout = 60
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/user/myrules.git"
ref = "develop"
[[semgrep.passthrough]]
type = "git"
value = "https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/playground/sast-rules.git"
ref = "97f7686db058e2141c0806a477c1e04835c4f395"
subdir = "go"
[[semgrep.passthrough]]
type = "raw"
target = "insecure.yml"
value = """
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function insecure detected
metadata:
cwe: "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor"
severity: "ERROR"
languages:
- "go"
"""
[[semgrep.passthrough]]
type = "url"
value = "https://semgrep.dev/c/p/gosec"
target = "gosec.yml"
체인 내의 passthrough의 모드 구성
체인 내에서 발생하는 passthrough 간의 파일명 충돌을 어떻게 처리할지 선택할 수 있습니다. 기본 동작은 동일한 이름을 가진 기존 파일을 덮어쓰지만, 대신 mode = append
를 선택하여 이후 파일의 내용을 이전 파일로 추가할 수 있습니다.
append
모드는 file
, url
, raw
passthrough 유형에만 사용할 수 있습니다.
다음 사용자 정의 규칙세트 구성으로, 두 개의 raw
passthrough를 사용하여 반복적으로 /sgrules/my-rules.yml
파일을 조합하고, 이 파일은 Semgrep에 규칙세트로 제공됩니다. 각 passthrough는 규칙세트에 한 개의 규칙을 추가합니다. 첫 번째 passthrough는 최상위 수준의 rules
개체를 초기화합니다.
[semgrep]
description = "Semgrep를 위한 내 사용자 정의 규칙세트"
targetdir = "/sgrules"
validate = true
[[semgrep.passthrough]]
type = "raw"
target = "my-rules.yml"
value = """
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function 'insecure' detected
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""
[[semgrep.passthrough]]
type = "raw"
mode = "append"
target = "my-rules.yml"
value = """
- id: "secret"
patterns:
- pattern-either:
- pattern: '$MASK = "..."'
- metavariable-regex:
metavariable: "$MASK"
regex: "(password|pass|passwd|pwd|secret|token)"
message: |
Use of hard-coded password
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
"""
# /sgrules/my-rules.yml
rules:
- id: "insecure"
patterns:
- pattern: "func insecure() {...}"
message: |
Insecure function 'insecure' detected
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
- id: "secret"
patterns:
- pattern-either:
- pattern: '$MASK = "..."'
- metavariable-regex:
metavariable: "$MASK"
regex: "(password|pass|passwd|pwd|secret|token)"
message: |
Use of hard-coded password
metadata:
cwe: "..."
severity: "ERROR"
languages:
- "go"
개인 원격 구성 지정
다음 예시는 SAST 활성화하고 공유된 규칙 집합 사용자 정의 파일을 사용합니다. 해당 파일은 다음과 같습니다:
- 그룹 액세스 토큰을 사용하여 인증이 필요한 개인 프로젝트에서 다운로드하며, 이 토큰은 CI 변수 내에 안전하게 저장됩니다.
- 기본 브랜치 대신 특정한 Git 커밋 SHA에서 체크아웃됩니다.
그룹 토큰과 연결된 사용자명을 찾는 방법은 그룹 액세스 토큰을 참조하세요.
include:
- template: Jobs/SAST.gitlab-ci.yml
variables:
SAST_RULESET_GIT_REFERENCE: "group_2504721_bot_7c9311ffb83f2850e794d478ccee36f5:$PERSONAL_ACCESS_TOKEN@gitlab.com/example-group/example-ruleset-project@c8ea7e3ff126987fb4819cc35f2310755511c2ab"
데모 프로젝트
이러한 구성 옵션 중 일부를 설명하는 데모 프로젝트가 있습니다.
이러한 프로젝트 중 많은 프로젝트는 원격 규칙 집합을 사용하여 규칙을 재정의하거나 비활성화하는 내용을 보여주며, 해당 프로젝트들은 해당 분석기에 따라 그룹화되어 있습니다.
또한 원격 규칙 집합 설정 방법을 안내하는 동영상 데모도 있습니다: