유출된 비밀 정보에 대한 자동 응답

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를 사용하여 매뉴얼 통합 필요

기능 이용 가능 여부

  • GitLab 15.11에서 기본 브랜치가 아닌 브랜치에 대해 활성화되었습니다.

비밀 정보 감지가 발견한 경우에만 자격 증명이 후처리됩니다:

  • 공개 프로젝트에서, 공개적으로 노출된 자격 증명은 증가된 위협을 야기하므로 후속 조치가 필요합니다. 비공개 프로젝트로 확장은 이슈 391379에서 고려됩니다.
  • GitLab Ultimate를 사용하는 프로젝트에서는 기술적인 이유로 확장됩니다. 모든 티어로의 확장은 이슈 391763에서 추적됩니다.

고수준 아키텍처

이 다이어그램은 GitLab 애플리케이션에서 후처리 후크가 비밀 정보를 취소하는 방법을 설명합니다:

sequenceDiagram 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
  1. Secret Detection 작업이 완료된 파이프라인은 스캔 보고서(1)를 생성합니다.
  2. 보고서는 서비스 클래스에 의해 처리(2)되며, 토큰 취소가 가능한 경우 비동기 워커를 예약합니다.
  3. 비동기 워커(3)는 외부에 배포된 HTTP 서비스와 통신하여 자동으로 취소 가능한 비밀 정보 유형을 결정합니다(45).
  4. 워커는 GitLab 토큰 폐기 API가 폐기할 수 있는 감지된 비밀 정보 디렉터리을 보냅니다(67).
  5. GitLab 토큰 폐기 API는 각각의 폐기 가능한 토큰을 해당 공급업체의 파트너 API에 보냅니다(89). 자세한 내용은 GitLab Token Revocation API 문서를 참조하세요.

유출된 자격 증명 알림을 위한 파트너 프로그램

GitLab은 GitLab.com의 공개 리포지터리에 유출된 자격 증명이 발급되면 해당 파트너에게 알립니다. 클라우드 또는 SaaS 제품을 운영하고 해당 알림을 받고 싶은 경우, epic 4944에서 자세히 알아보세요. 파트너는 파트너 API를 구현해야 하며, 이 API는 GitLab Token Revocation API에서 호출됩니다.

파트너 API 구현

파트너 API는 GitLab Token Revocation API와 통신하여 유출된 토큰 폐기 요청에 응답합니다. 해당 서비스는 멱득한 높은 공개 HTTP API여야 하고 멱득되고 요청이 서명된 헤더를 가질 수 있습니다.

서비스에 대한 요청에는 하나 이상의 유출된 토큰과 요청 본문의 서명 헤더가 포함될 수 있습니다. 우리는 요청이 GitLab에서의 진정한 요청임을 증명하기 위해 이 서명을 검증하는 것을 강력히 권장합니다. 아래 다이어그램은 유출된 토큰 수신, 검증 및 폐기를 위한 필요한 단계를 상세히 설명하고 있습니다:

sequenceDiagram 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는 폐기 요청을 파트너 API에 보냅니다. 요청에는 본문의 공개 키 식별자와 서명 헤더가 포함됩니다.
  2. 파트너 API는 GitLab에서 공개 키 디렉터리을 요청합니다. 응답은 요청 헤더의 식별자로 필터링되는 공개 키를 포함할 수 있습니다.
  3. 파트너 API는 실제 요청 본문을 통해 서명을 확인하며, 이를 위해 공개 키를 사용합니다.
  4. 파트너 API는 유출된 토큰을 처리하며, 자동 폐기가 수반될 수 있습니다(5).
  5. 파트너 API는 올바른 HTTP 상태 코드로 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": "비밀 감지 분석기에서 일치한 하위 문자열입니다. 대부분의 경우, 이것은 토큰 자체입니다",
                "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"}]

이 예시에서, 비밀 감지는 my_api_token이 유출되었음을 확인했습니다. 토큰의 값뿐만 아니라 유출된 토큰을 포함한 파일의 공개 URL이 제공됩니다.

이 요청은 두 가지 특별한 헤더를 포함합니다:

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

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

공개 키 엔드포인트

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 헤더를 이용하여 해당 요청 본문과 일치하는 공개 키를 사용하여 취소 요청이 진정한지 확인할 수 있습니다. 우리는 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 해싱을 지정하여 본문을 디코딩된 서명과 일치시킵니다.