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

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

기능 가용성

비밀 정보는 Secret Detection에서 그들을 찾았을 때에만 사후 처리됩니다:

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

고수준 아키텍처

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

%%{init: { "fontFamily": "GitLab Sans" }}%% 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 Token Revocation API로 보냅니다 (67).
  5. GitLab Token Revocation API는 각각의 취소 가능한 토큰을 해당 벤더의 파트너 API로 보냅니다. 자세한 내용은 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-->>+Partner API: 새로운 노출된 자격 증명 전송 Partner API-->>+GitLab Public Keys endpoint: 활성 공개 키 가져오기 GitLab Public Keys endpoint-->>+Partner API: 하나 이상의 공개 키 Partner API-->>+Partner API: 요청이 GitLab에 의해 서명되었는지 검증 Partner API-->>+Partner API: 노출에 대한 응답 Partner API-->>+GitLab Token Revocation API: HTTP 상태
  1. GitLab Token Revocation API는 노출 요청을 파트너 API로 전송합니다. 이 요청에는 헤더가 포함되며, 해당 헤더에는 공개 키 식별자와 요청 본문의 서명이 포함됩니다.
  2. 파트너 API는 GitLab로부터 공개 키 디렉터리을 요청합니다. 응답은 여러 개의 공개 키를 포함할 수 있으며, 헤더의 식별자로 필터링되어야 합니다.
  3. 파트너 API는 실제 요청 본문으로부터의 서명을 검증합니다. 이 과정에서 공개 키가 사용됩니다 (4).
  4. 파트너 API는 노출된 토큰을 처리하며, 자동으로 취소를 포함할 수 있습니다 (5).
  5. 파트너 API는 적절한 HTTP 상태 코드로 GitLab Token Revocation API에 응답합니다 (6):
    • 성공적인 응답 코드 (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 문자열 이 요청을 서명하는 데 사용된 키 쌍의 고유 식별자입니다. 주로 키 교체를 돕기 위해 사용됩니다.
Gitlab-Public-Key-Signature 문자열 요청 본문의 base64로 인코딩된 서명입니다.

이러한 헤더를 통해 GitLab Public Keys 엔드포인트와 함께 사용하여 무효화 요청이 진정한 것임을 검증할 수 있습니다.

Public Keys 엔드포인트

GitLab은 철회 요청을 확인하는 데 사용되는 공개 키를 검색하기 위한 공개 접근 가능한 엔드포인트를 유지합니다. 이 엔드포인트는 요청 시 제공될 수 있습니다.

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

{
    "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로 인코딩됩니다.

아래 파이썬 스크립트는 서명을 확인하는 방법을 보여줍니다. 암호 작업을 위해 인기 있는 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("")      # public keys 엔드포인트에서 얻음
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 해싱을 지정하여 본문을 디코딩된 서명과 대조합니다.