유출된 시크릿에 대한 자동 대응
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
GitLab 시크릿 감지는 특정 유형의 유출된 시크릿을 발견하면 자동으로 대응합니다. GitLab은 다음 유형의 시크릿에 대해 자동 대응을 지원합니다: 자격 증명은 시크릿 감지가 다음의 경우에만 후처리됩니다: 이 다이어그램은 후처리 훅이 GitLab 애플리케이션에서 시크릿을 취소하는 방법을 설명합니다:
GitLab 시크릿 감지는 특정 유형의 유출된 시크릿을 발견하면 자동으로 대응합니다. 자동 대응은 다음을 수행할 수 있습니다:
- 시크릿을 자동으로 취소합니다.
- 시크릿을 발행한 파트너에게 알립니다. 파트너는 시크릿을 취소하거나 소유자에게 알리거나 남용에 대비할 수 있습니다.
지원되는 시크릿 유형 및 액션#
GitLab은 다음 유형의 시크릿에 대해 자동 대응을 지원합니다:
| 시크릿 유형 | 취해지는 액션 | GitLab.com에서 지원 | GitLab Self-Managed에서 지원 |
|---|---|---|---|
| GitLab 개인 접근 토큰 | 즉시 토큰 취소, 소유자에게 이메일 전송. 1 | ✅ | ✅ |
| Amazon Web Services(AWS) IAM 접근 키 | AWS에 알림. | ✅ | ⚙ |
| Google Cloud 서비스 계정 키, API 키, OAuth 클라이언트 시크릿 | Google Cloud에 알림. | ✅ | ⚙ |
| Postman API 키 | Postman에 알림. Postman이 키 소유자에게 알림. | ✅ | ⚙ |
각주:
gitlab_personal_access_token에 대해서만 지원됩니다.
컴포넌트 범례:
- ✅ - 기본으로 사용 가능
- ⚙ - Token Revocation API를 사용한 수동 통합 필요
기능 가용성#
히스토리
- GitLab 15.11에서 기본이 아닌 브랜치에 대해 활성화됨.
자격 증명은 시크릿 감지가 다음의 경우에만 후처리됩니다:
- 공개 프로젝트에서. 공개적으로 노출된 자격 증명은 위협이 증가하기 때문입니다. 비공개 프로젝트로의 확장은 이슈 391379에서 검토 중입니다.
- 기술적인 이유로 GitLab Ultimate가 있는 프로젝트에서. 모든 티어로의 확장은 이슈 391763에서 추적됩니다.
고수준 아키텍처#
이 다이어그램은 후처리 훅이 GitLab 애플리케이션에서 시크릿을 취소하는 방법을 설명합니다:
소스 코드 보기
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: Architecture diagram
accDescr: How a post-processing hook revokes a secret in the GitLab application.
autonumber
GitLab Rails-->+GitLab Rails: gl-secret-detection-report.json
GitLab Rails->>+GitLab Sidekiq: StoreScansService
GitLab Sidekiq-->+GitLab Sidekiq: ScanSecurityReportSecretsWorker
GitLab Sidekiq-->+GitLab token revocation API: GET revocable keys types
GitLab token revocation API-->>-GitLab Sidekiq: OK
GitLab Sidekiq->>+GitLab token revocation API: POST revoke revocable keys
GitLab token revocation API-->>-GitLab Sidekiq: ACCEPTED
GitLab token revocation API-->>+Partner API: revoke revocable keys
Partner API-->>+GitLab token revocation API: ACCEPTED</code></pre></details></div>
- 시크릿 감지 잡이 포함된 파이프라인이 완료되어 스캔 보고서(1)를 생성합니다.
- 보고서가 서비스 클래스에 의해 처리(2)되며, 토큰 취소가 가능한 경우 비동기 워커가 예약됩니다.
- 비동기 워커(3)는 외부에 배포된 HTTP 서비스(4와 5)와 통신하여 어떤 종류의 시크릿이 자동으로 취소될 수 있는지 결정합니다.
- 워커는 GitLab 토큰 취소 API가 취소할 수 있는 감지된 시크릿 목록을 전송(6과 7)합니다.
- GitLab 토큰 취소 API는 각 취소 가능한 토큰을 해당 벤더의 파트너 API에 전송(8과 9)합니다.
유출된 자격 증명 알림을 위한 파트너 프로그램#
GitLab은 GitLab.com의 공개 리포지터리에서 발행한 자격 증명이 유출되면 파트너에게 알립니다.
클라우드 또는 SaaS 제품을 운영하고 이러한 알림을 받는 데 관심이 있다면 에픽 4944에서 자세히 알아보세요.
파트너는 파트너 API를 구현해야 하며, GitLab 토큰 취소 API에 의해 호출됩니다.
파트너 API 구현#
파트너 API는 유출된 토큰 취소 요청을 수신하고 대응하기 위해 GitLab 토큰 취소 API와 통합됩니다. 서비스는 멱등성이 있고 속도 제한이 있는 공개적으로 접근 가능한 HTTP API여야 합니다.
서비스에 대한 요청에는 하나 이상의 유출된 토큰과 요청 본문의 서명이 포함된 헤더가 포함될 수 있습니다. 진짜 GitLab 요청임을 증명하기 위해 이 서명을 사용하여 수신 요청을 확인하는 것을 강력히 권장합니다. 아래 다이어그램은 유출된 토큰을 수신, 검증, 취소하는 데 필요한 단계를 자세히 설명합니다:
Mermaid 다이어그램 (12줄)소스 코드 보기
%%{init: { "fontFamily": "GitLab Sans" }}%%
sequenceDiagram
accTitle: Partner API data flow
accDescr: How a partner API should receive and respond to leaked token revocation requests.
autonumber
GitLab token revocation API-->>+Partner API: Send new leaked credentials
Partner API-->>+GitLab public keys endpoint: Get active public keys
GitLab public keys endpoint-->>+Partner API: One or more public keys
Partner API-->>+Partner API: Verify request is signed by GitLab
Partner API-->>+Partner API: Respond to leaks
Partner API-->>+GitLab token revocation API: HTTP status</code></pre></details></div>
- GitLab 토큰 취소 API는 파트너 API에 취소 요청을 전송(1)합니다. 요청에는 공개 키 식별자와 요청 본문의 서명이 포함된 헤더가 포함됩니다.
- 파트너 API는 GitLab에서 공개 키 목록을 요청(2)합니다. 응답(3)에는 키 순환의 경우 여러 공개 키가 포함될 수 있으며 요청 헤더의 식별자로 필터링해야 합니다.
- 파트너 API는 공개 키(4)를 사용하여 실제 요청 본문에 대해 서명을 검증합니다.
- 파트너 API는 유출된 토큰을 처리하며, 자동 취소(5)가 포함될 수 있습니다.
- 파트너 API는 적절한 HTTP 상태 코드로 GitLab 토큰 취소 API(6)에 응답합니다:
- 성공 응답 코드(HTTP 200~299)는 파트너가 요청을 수신하고 처리했음을 확인합니다.
- 오류 코드(HTTP 400 이상)는 GitLab 토큰 취소 API가 요청을 재시도하게 합니다.
취소 요청#
이 JSON 스키마 문서는 취소 요청의 본문을 설명합니다:
{
"type": "array",
"items": {
"description": "A leaked token",
"type": "object",
"properties": {
"type": {
"description": "The type of token. This is vendor-specific and can be customized to suit your revocation service",
"type": "string",
"examples": [
"my_api_token"
]
},
"token": {
"description": "The substring that was matched by the secret detection analyzer. In most cases, this is the entire token itself",
"type": "string",
"examples": [
"XXXXXXXXXXXXXXXX"
]
},
"url": {
"description": "The URL to the raw source file hosted on GitLab where the leaked token was detected",
"type": "string",
"examples": [
"https://gitlab.example.com/some-repo/-/raw/abcdefghijklmnop/compromisedfile1.java"
]
}
}
}
}
예시:
[{"type": "my_api_token", "token": "XXXXXXXXXXXXXXXX", "url": "https://example.com/some-repo/-/raw/abcdefghijklmnop/compromisedfile1.java"}]
이 예시에서 시크릿 감지는 my_api_token의 인스턴스가 유출되었다고 판단했습니다. 토큰의 값은 유출된 토큰이 포함된 파일의 원시 내용에 대한 공개적으로 접근 가능한 URL과 함께 제공됩니다.
요청에는 두 개의 특별한 헤더가 포함됩니다:
헤더
유형
설명
Gitlab-Public-Key-Identifier
string
이 요청에 서명하는 데 사용된 키 쌍의 고유 식별자. 주로 키 순환을 돕는 데 사용됩니다.
Gitlab-Public-Key-Signature
string
요청 본문의 base64 인코딩된 서명.
이러한 헤더를 GitLab 공개 키 엔드포인트와 함께 사용하여 취소 요청이 진짜임을 확인할 수 있습니다.
공개 키 엔드포인트#
GitLab은 취소 요청을 검증하는 데 사용되는 공개 키를 검색하기 위한 공개적으로 접근 가능한 엔드포인트를 유지합니다. 엔드포인트는 요청 시 제공될 수 있습니다.
이 JSON 스키마 문서는 공개 키 엔드포인트의 응답 본문을 설명합니다:
{
"type": "object",
"properties": {
"public_keys": {
"description": "An array of public keys managed by GitLab used to sign token revocation requests.",
"type": "array",
"items": {
"type": "object",
"properties": {
"key_identifier": {
"description": "A unique identifier for the keypair. Match this against the value of the Gitlab-Public-Key-Identifier header",
"type": "string"
},
"key": {
"description": "The value of the public key",
"type": "string"
},
"is_current": {
"description": "Whether the key is currently active and signing new requests",
"type": "boolean"
}
}
}
}
}
}
예시:
{
"public_keys": [
{
"key_identifier": "6917d7584f0fa65c8c33df5ab20f54dfb9a6e6ae",
"key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEN05/VjsBwWTUGYMpijqC5pDtoLEf\nuWz2CVZAZd5zfa/NAlSFgWRDdNRpazTARndB2+dHDtcHIVfzyVPNr2aznw==\n-----END PUBLIC KEY-----\n",
"is_current": true
}
]
}
요청 검증#
위의 API 응답에서 가져온 해당 공개 키를 사용하여 요청 본문에 대해 Gitlab-Public-Key-Signature 헤더를 검증함으로써 취소 요청이 진짜인지 확인할 수 있습니다. 서명을 생성하기 위해 SHA256 해싱과 함께 ECDSA를 사용하며, 그런 다음 헤더 값으로 base64 인코딩됩니다.
아래 Python 스크립트는 서명을 검증하는 방법을 보여줍니다. 암호화 작업에 인기 있는 pyca/cryptography 모듈을 사용합니다:
import hashlib
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.serialization import load_pem_public_key
from cryptography.hazmat.primitives.asymmetric import ec
public_key = str.encode("") # obtained from the public keys endpoint
signature_header = "" # obtained from the `Gitlab-Public-Key-Signature` header
request_body = str.encode(r'') # obtained from the revocation request body
pk = load_pem_public_key(public_key)
decoded_signature = base64.b64decode(signature_header)
pk.verify(decoded_signature, request_body, ec.ECDSA(hashes.SHA256())) # throws if unsuccessful
print("Signature verified!")
주요 단계는 다음과 같습니다:
- 사용 중인 암호화 라이브러리에 적합한 형식으로 공개 키를 로드합니다.
Gitlab-Public-Key-Signature 헤더 값을 base64 디코딩합니다.
- SHA256 해싱과 함께 ECDSA를 지정하여 디코딩된 서명에 대해 본문을 검증합니다.
