유출된 시크릿에 대한 자동 응답

Tier: Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

GitLab Secret Detection은 특정 유출된 시크릿을 발견하면 자동으로 응답합니다. 자동 응답은 다음과 같을 수 있습니다:

  • 시크릿을 자동으로 폐기합니다.
  • 시크릿을 발급한 파트너에게 알립니다. 파트너는 시크릿을 폐기하거나, 소유자에게 통지하거나, 오용에 대비할 수 있습니다.

지원되는 시크릿 유형 및 작업

GitLab은 다음 유형의 시크릿에 대한 자동 응답을 지원합니다:

시크릿 유형 취해지는 조치 GitLab.com에서 지원됨 Self-managed에서 지원됨
GitLab 개인 액세스 토큰 즉시 토큰 폐기, 소유자에게 이메일 전송 15.9 이후
Amazon Web Services(AWS) IAM 액세스 키 AWS에 통지
Google Cloud 서비스 계정 키, API 키OAuth 클라이언트 시크릿 Google Cloud에 통지
Postman API 키 Postman에 통지; Postman 키 소유자에게 통지

컴포넌트 식별기

  • ✅ - 기본적으로 사용 가능
  • ⚙ - 토큰 폐기 API를 사용하여 수동 통합이 필요함

기능 사용 가능성

시크릿 감지가 발견한 경우에만 자격 증명이 후처리됩니다:

  • 공개 프로젝트에서, 공개적으로 노출된 자격 증명은 증가된 위협이기 때문에. 비공개 프로젝트로의 확대는 이슈 391379에서 고려됩니다.
  • 기술적인 이유로, GitLab Ultimate로 구성된 프로젝트에서만. 모든 티어로의 확대는 이슈 391763에서 추적됩니다.

고수준 구조

다음 다이어그램은 GitLab 응용 프로그램에서 후처리 후크가 시크릿을 폐기하는 방법을 설명합니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: 구조 다이어그램 accDescr: 후처리 후크가 GitLab 응용 프로그램에서 시크릿을 폐기하는 방법. 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: 폐기 가능한 키 타입 가져오기 GitLab Token Revocation API-->>-GitLab Sidekiq: OK GitLab Sidekiq->>+GitLab Token Revocation API: 폐기 가능한 키들 폐기 GitLab Token Revocation API-->>-GitLab Sidekiq: ACCEPTED GitLab Token Revocation API-->>+파트너 API: 폐기 가능한 키 폐기 파트너 API-->>+GitLab Token Revocation API: ACCEPTED
  1. 시크릿 감지 작업이 포함된 파이프라인이 완료되어 스캔 보고서를 생성합니다 (1).
  2. 보고서는 서비스 클래스에 의해 처리되어 (2) 토큰 폐기가 가능한 경우 비동기 워커를 예약합니다.
  3. 비동기 워커(3)는 외부에 배포된 HTTP 서비스와 통신하여 (45) 자동으로 폐기 가능한 시크릿 유형을 확인합니다.
  4. 워커는 폐기할 수 있는 검출된 시크릿 목록을 보내어(67) GitLab Token Revocation API가 이를 폐기합니다.
  5. GitLab Token Revocation API는 각각의 폐기 가능한 토큰을 해당 벤더의 파트너 API에 보냅니다. 자세한 내용은 GitLab Token Revocation API 문서를 참조하세요.

유출된 자격 증명 통지를 위한 파트너 프로그램

GitLab은 GitLab.com의 공개 저장소에서 유출된 자격 증명을 발행하는 파트너에게 알립니다. 클라우드 또는 SaaS 제품을 운영하고 해당 통지를 받고 싶으시면, 에픽 4944에서 자세히 알아보세요. 파트너는 파트너 API를 구현해야 하며, 이는 GitLab Token Revocation API에서 호출됩니다.

파트너 API 구현

파트너 API는 유출된 토큰 폐기 요청을 수신하고 응답하기 위해 GitLab Token Revocation API와 통합됩니다. 이 서비스는 멱득적이고 속도 제한이 있는 공개 HTTP API여야 합니다.

귀사의 서비스로의 요청은 하나 이상의 유출된 토큰과 요청 바디의 서명을 포함하는 헤더를 포함할 수 있습니다. 우리는 귀사가 이 서명을 사용하여 수신 요청을 검증하는 것을 강력히 권장합니다. 아래 다이어그램은 유입된 요청을 수신, 검증 및 시크릿 폐기를 위한 필요한 단계를 자세히 설명합니다:

%%{init: { "fontFamily": "GitLab Sans" }}%% sequenceDiagram accTitle: 파트너 API 데이터 흐름 accDescr: 파트너 API가 유출된 토큰 폐기 요청을 수신하고 응답해야 하는 방법. autonumber GitLab Token Revocation API-->>+파트너 API: 새 유출된 자격 증명 전송 파트너 API-->>+GitLab 공개 키 엔드포인트: 활성 공개 키 가져오기 GitLab 공개 키 엔드포인트-->>+파트너 API: 하나 이상의 공개 키 파트너 API-->>+파트너 API: GitLab에서 서명된 요청 확인 파트너 API-->>+파트너 API: 유출에 대한 응답 파트너 API-->>+GitLab Token Revocation API: HTTP 상태
  1. GitLab Token Revocation API는 폐기 요청(1)을 파트너 API로 보냅니다. 요청은 헤더를 포함하여 요청 바디의 공개 키 식별자와 서명을 포함합니다.
  2. 파트너 API는 GitLab으로부터 공개 키(2) 목록을 요청합니다. 응답(3)은 키 회전을 위한 경우에 여러 공개 키를 포함할 수 있으며, 요청 헤더의 식별자로 필터링되어야 합니다.
  3. 파트너 API는 실제 요청 바디에 대한 서명을 검증하기 위해(4) 요청 바디와 공개 키를 사용하여 서명을 확인합니다.
  4. 파트너 API는 자동적으로 폐기되는 유출된 토큰을 처리합니다(5).
  5. 파트너 API는 적절한 HTTP 상태 코드로(6) GitLab Token Revocation API에 응답합니다:
    • 성공적인 응답 코드(HTTP 200 ~ 299)는 파트너가 요청을 받고 처리했음을 인정합니다.
    • 오류 코드(HTTP 400 이상)는 GitLab Token Revocation API가 요청을 다시 시도하게 합니다.

취소 요청

이 JSON 스키마 문서는 취소 요청의 본문을 설명합니다.

{
    "type": "array",
    "items": {
        "description": "유출된 토큰",
        "type": "object",
        "properties": {
            "type": {
                "description": "토큰의 유형입니다. 이는 공급 업체별이며 취소 서비스에 맞게 사용자 정의할 수 있습니다",
                "type": "string",
                "examples": [
                    "my_api_token"
                ]
            },
            "token": {
                "description": "Secret Detection 분석기에 의해 일치하는 부분의 토큰입니다. 대부분의 경우 전체 토큰 자체입니다",
                "type": "string",
                "examples": [
                    "XXXXXXXXXXXXXXXX"
                ]
            },
            "url": {
                "description": "유출된 토큰이 검출된 GitLab의 원본 소스 파일에 대한 URL입니다",
                "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"}]

이 예에서 Secret Detection은 my_api_token의 인스턴스가 유출되었음을 확인했습니다. 토큰의 값은 제공되며, 유출된 토큰을 포함하는 파일의 원본 내용에 대한 공개적으로 접근 가능한 URL도 제공됩니다.

이 요청에는 두 가지 특별한 헤더가 포함되어 있습니다:

헤더 유형 설명
Gitlab-Public-Key-Identifier string 이 요청에 서명하는 데 사용된 키 쌍의 고유 식별자입니다. 주로 키 교체를 돕는 데 사용됩니다.
Gitlab-Public-Key-Signature string 요청 본문의 base64로 인코딩된 서명입니다.

이러한 헤더를 사용하여 GitLab 공개 키 엔드포인트와 함께 이 취소 요청이 진정한지 확인할 수 있습니다.

공개 키 엔드포인트

GitLab은 취소 요청을 확인하기 위해 사용되는 공개 키를 검색할 수 있는 공개 엔드포인트를 유지합니다. 엔드포인트는 요청 시 제공될 수 있습니다.

이 JSON 스키마 문서는 공개 키 엔드포인트의 응답 본문을 설명합니다:

{
    "type": "object",
    "properties": {
        "public_keys": {
            "description": "토큰 취소 요청에 서명하는 데 사용되는 GitLab이 관리하는 공개 키 배열입니다.",
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "key_identifier": {
                        "description": "키파의 고유 식별자입니다. 이 값을 Gitlab-Public-Key-Identifier 헤더의 값과 일치시킵니다",
                        "type": "string"
                    },
                    "key": {
                        "description": "공개 키의 값입니다",
                        "type": "string"
                    },
                    "is_current": {
                        "description": "키가 현재 활성화되어 새로운 요청에 서명하는지 여부입니다",
                        "type": "boolean"
                    }
                }
            }
        }
    }
}

예시:

{
    "public_keys": [
        {
            "key_identifier": "6917d7584f0fa65c8c33df5ab20f54dfb9a6e6ae",
            "key": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEN05/VjsBwWTUGYMpijqC5pDtoLEf\nuWz2CVZAZd5zfa/NAlSFgWRDdNRpazTARndB2+dHDtcHIVfzyVPNr2aznw==\n-----END PUBLIC KEY-----\n",
            "is_current": true
        }
    ]
}

요청 확인

Gitlab-Public-Key-Signature 헤더를 이용하여 요청 본문을 검증함으로써 취소 요청이 진정한지 확인할 수 있습니다. 이를 위해 API 응답에서 가져온 해당 공개 키를 사용하여 헤더 값을 본문과 대조합니다. 우리는 ECDSA와 SHA256 해싱을 사용하여 서명을 생성하고, 이를 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("")      # 공개 키 엔드포인트에서 얻음
signature_header = ""            # `Gitlab-Public-Key-Signature` 헤더에서 얻음
request_body = str.encode(r'')   # 취소 요청 본문에서 얻음

pk = load_pem_public_key(public_key)
decoded_signature = base64.b64decode(signature_header)

pk.verify(decoded_signature, request_body, ec.ECDSA(hashes.SHA256()))  # 실패하면 예외를 발생시킴

print("서명이 확인되었습니다!")

주요 단계는 다음과 같습니다:

  1. 암호 라이브러리에 적합한 형식으로 공개 키를 로드합니다.
  2. Gitlab-Public-Key-Signature 헤더 값을 base64로 디코딩합니다.
  3. 선택한 ECDSA와 SHA256 해싱을 지정하여 서명을 본문과 대조합니다.