Sigstore 완벽 가이드 — cosign·Rekor·Fulcio로 소프트웨어 공급망 보안 서명

Sigstore 완벽 가이드 — cosign·Rekor·Fulcio로 소프트웨어 공급망 보안 서명

이 글의 핵심

Sigstore는 GPG 같은 장기 키 관리 없이 "일회용 인증서"로 소프트웨어를 서명·검증하는 오픈소스 표준입니다. Linux Foundation 프로젝트로 Google·RedHat·Chainguard·Docker 등이 참여하며 OCI 컨테이너 이미지·SBOM·바이너리 서명의 사실상 표준이 되었습니다. 이 글은 cosign·Rekor·Fulcio의 개념부터 GitHub Actions·Kyverno/Sigstore policy-controller 통합까지 실전 위주로 정리합니다.

왜 공급망 보안인가

사건영향
SolarWinds (2020)18,000 조직에 악성 업데이트
Codecov (2021)CI 토큰 대량 탈취
Log4Shell (2021)수천 조직의 Java 앱 RCE
xz-utils 백도어 (2024)오픈소스 유지보수자 사회공학 공격
npm/PyPI typo-squatting연간 수백 건

공통점: “빌드·배포 파이프라인 어디에선가 신뢰할 수 없는 코드가 들어왔다”. 방어 핵심은:

  1. 출처 증명 — 누가 만들었는가 (서명)
  2. 내용 증명 — 무엇이 들어있는가 (SBOM)
  3. 빌드 증명 — 어떻게 빌드되었는가 (SLSA Provenance)
  4. 정책 집행 — 허용된 것만 배포 (admission controller)

Sigstore는 1·3의 기반 서명 인프라이자 2의 서명에도 쓰이는 공통 도구입니다.

Sigstore 구성 요소

┌──────────────────────────────────────────────────────┐
│  개발자 / CI 러너                                    │
│    │                                                   │
│    ▼  1) OIDC 토큰 요청 (GitHub/Google/...)          │
│  OIDC IdP                                              │
│    │                                                   │
│    ▼  2) OIDC 토큰으로 단명 인증서 발급 요청         │
│  Fulcio  ── 3) 단명(10분) x509 인증서 발급            │
│    │                                                   │
│    ▼  4) 인증서 개인키로 아티팩트 서명                │
│  cosign CLI                                            │
│    │                                                   │
│    ▼  5) 서명·인증서를 Rekor(투명성 로그)에 기록      │
│  Rekor                                                 │
│    │                                                   │
│    ▼  6) 서명과 인증서를 OCI 레지스트리에 저장        │
│  OCI Registry                                          │
└──────────────────────────────────────────────────────┘

검증 측:
  OCI Registry → cosign verify → Fulcio/Rekor 확인 → OK/FAIL
  • cosign: CLI/라이브러리, 서명·검증·SBOM 첨부
  • Fulcio: OIDC → 단명 x509 발급 CA
  • Rekor: 투명성 로그 (immutable append-only)
  • TUF: 신뢰 앵커(공개 키) 배포 체계

설치

# macOS
brew install cosign

# Linux
wget -qO cosign https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod +x cosign && sudo mv cosign /usr/local/bin/

# Windows
winget install cosign

Kubernetes 측 policy-controller(구 Cosigned) 또는 Kyverno도 준비합니다.

1. Keyless 서명: 개인 개발자

# 서명
cosign sign ghcr.io/myorg/myapp:1.2.3

# 실행되는 일:
# - 브라우저가 열려 OIDC 인증 (GitHub/Google/Microsoft 선택)
# - Fulcio가 "[email protected]" 주소로 10분짜리 인증서 발급
# - 서명이 레지스트리에 `:sha256-...sig` 태그로 저장
# - Rekor에 영구 기록

검증

cosign verify ghcr.io/myorg/myapp:1.2.3 \
  [email protected] \
  --certificate-oidc-issuer=https://github.com/login/oauth

--certificate-identity / --certificate-oidc-issuer“누가 어떤 IdP로 서명했는가” 를 강제합니다. 이게 빠지면 아무나 서명해도 통과됩니다.

2. GitHub Actions에서 자동 서명

# .github/workflows/release.yml
name: release

on:
  push:
    tags: ["v*"]

permissions:
  contents: read
  packages: write
  id-token: write       # ← Sigstore OIDC 토큰 필수

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        id: build
        uses: docker/build-push-action@v6
        with:
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

      - uses: sigstore/cosign-installer@v3
        with: {cosign-release: "v2.4.1"}

      - name: Sign image (keyless)
        env:
          COSIGN_EXPERIMENTAL: "1"
          DIGEST: ${{ steps.build.outputs.digest }}
        run: |
          cosign sign --yes \
            ghcr.io/${{ github.repository }}@${DIGEST}

id-token: write 퍼미션이 OIDC 토큰을 발급받아 사람의 개입 없이 CI가 서명하게 해줍니다.

검증 규칙

cosign verify ghcr.io/myorg/myapp:v1.2.3 \
  --certificate-identity-regexp="^https://github.com/myorg/myapp/.github/workflows/.+@refs/tags/v.*" \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com

“이 저장소의 이 워크플로에서 tag push로 서명된 이미지만” 통과합니다. 매우 강력한 출처 정책입니다.

3. SBOM 첨부

# Syft로 SBOM 생성
syft ghcr.io/myorg/myapp:1.2.3 -o cyclonedx-json > sbom.json

# Sigstore 서명 + OCI에 첨부
cosign attest --yes --predicate sbom.json \
  --type cyclonedx \
  ghcr.io/myorg/myapp:1.2.3

검증 측은 SBOM이 서명된 상태임을 확인하고 내용을 취약점 스캐너에 넘길 수 있습니다.

cosign verify-attestation \
  --certificate-identity-regexp="..." \
  --certificate-oidc-issuer="..." \
  --type cyclonedx \
  ghcr.io/myorg/myapp:1.2.3 | jq .

4. SLSA Provenance

빌드 시스템이 “이 바이너리는 커밋 abc123의 소스 코드를 이 빌더가 이 단계로 만들었다”를 증명하는 문서입니다. GitHub Actions는 slsa-github-generator 액션으로 자동 생성·서명해줍니다.

- uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
  with:
    image: ghcr.io/${{ github.repository }}
    digest: ${{ steps.build.outputs.digest }}
    registry-username: ${{ github.actor }}
  secrets:
    registry-password: ${{ secrets.GITHUB_TOKEN }}

SLSA Level 3 증명을 자동 첨부하고, cosign verify-attestation --type slsaprovenance로 검증합니다.

5. Kubernetes 배포 시 검증

Option A: Sigstore policy-controller

helm repo add sigstore https://sigstore.github.io/helm-charts
helm install policy-controller sigstore/policy-controller \
  --namespace cosign-system --create-namespace
apiVersion: policy.sigstore.dev/v1beta1
kind: ClusterImagePolicy
metadata:
  name: require-myorg-signature
spec:
  images:
    - glob: "ghcr.io/myorg/**"
  authorities:
    - keyless:
        identities:
          - issuer: https://token.actions.githubusercontent.com
            subjectRegExp: "^https://github.com/myorg/.*/\\.github/workflows/release\\.yml@refs/tags/v.*"
        url: https://fulcio.sigstore.dev
      ctlog:
        url: https://rekor.sigstore.dev

ghcr.io/myorg/ 경로의 이미지는 이 정책에 맞게 서명되어 있어야만 Pod가 생성됩니다. 아니면 admission webhook에서 차단.

Option B: Kyverno verifyImages

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-signed-images
spec:
  validationFailureAction: Enforce
  webhookTimeoutSeconds: 30
  rules:
    - name: verify-signature
      match:
        any:
          - resources:
              kinds: [Pod]
      verifyImages:
        - imageReferences:
            - "ghcr.io/myorg/*"
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/myorg/*/.github/workflows/release.yml@refs/tags/v*"
                    issuer: "https://token.actions.githubusercontent.com"
                    rekor:
                      url: https://rekor.sigstore.dev

Kyverno가 여러 정책(리소스 요구량·태그·서명)을 한 번에 관리할 수 있는 장점이 있습니다.

6. private Sigstore (에어갭/규제 환경)

금융·공공 등에서 인터넷 연결 없이 쓰려면 자체 Fulcio + Rekor + TUF를 구축합니다.

  • sigstore/sigstore-scaffolding으로 Kubernetes 위에 스택 배포
  • 사내 OIDC(Keycloak/Okta) 연동
  • 자체 TUF 루트를 모든 클라이언트에 배포

운영 부담이 있으므로 클라우드 규제 요건이 강한 경우에만 고려하세요. 대부분은 공개 Sigstore 인프라로 충분합니다.

7. 키 기반 서명 (Hybrid)

Keyless가 낯선 조직은 기존 방식으로 시작할 수 있습니다:

cosign generate-key-pair
# cosign.key, cosign.pub 생성

cosign sign --key cosign.key ghcr.io/myorg/myapp:1.0.0

cosign verify --key cosign.pub ghcr.io/myorg/myapp:1.0.0

KMS(AWS KMS / GCP KMS / Azure Key Vault / HashiCorp Vault) 통합도 1급 지원:

cosign sign --key "awskms:///alias/cosign" ghcr.io/...

모니터링: Rekor 감시

Rekor는 누가 언제 무엇을 서명했는지의 공개 로그입니다. 자신의 조직 명의로 예상하지 못한 서명이 일어나면 즉시 감지할 수 있습니다.

# 특정 이메일로 서명된 최근 엔트리
rekor-cli search --email [email protected]

# 특정 리포지토리에서 발행된 서명
rekor-cli search --artifact sha256:...

SIEM 파이프라인에 붙여 조직 외부에서 내 명의로 서명이 등록되면 알림을 받는 체계 구축이 권장됩니다.

트러블슈팅

no matching signatures

  • --certificate-identity--certificate-oidc-issuer가 실제 서명자와 일치하는지
  • 이미지가 @digest가 아닌 태그라면 중간에 재태깅되어 서명된 다이제스트와 다를 수 있음 → 다이제스트로 검증

could not find identity

  • GitHub Actions OIDC 설정: permissions.id-token: write 누락

Rekor 일시 장애

  • COSIGN_EXPERIMENTAL=1 없이 --insecure-skip-tlog 사용은 금지
  • 비상시 별도 로그 저장소(자체 Rekor)로 이중화

레지스트리에 서명 태그 밀림

  • cosign clean 은 서명 제거 가능 — 사용 금지 or RBAC으로 차단
  • GCR/ECR의 lifecycle 정책이 :sha256-*.sig를 삭제하지 않도록 필터

체크리스트

  • 모든 컨테이너 이미지에 Sigstore 서명
  • 중요한 바이너리(go/rust release)도 서명
  • SBOM(CycloneDX/SPDX)을 cosign attest로 첨부
  • SLSA Provenance 자동 생성
  • Kubernetes admission에서 서명 검증 강제
  • Rekor 감사 로그 SIEM 연동
  • 키 기반/Keyless 정책을 조직 표준 문서로 관리
  • 재해 복구: 서명 복제·오프라인 검증 도구 준비

마무리

Sigstore는 GPG 시대의 무거운 키 관리를 CI OIDC 기반 단명 인증서로 뒤집어, “서명이 당연한 것”이 되도록 만들었습니다. 2026년 현재 Kubernetes 생태계·주요 OSS 릴리스(kubectl, helm, istioctl, Node.js, Python)가 Sigstore 서명을 제공하며 EU Cyber Resilience Act와 미국 Executive Order 14028 같은 규제가 공급망 서명·SBOM을 의무화하는 방향입니다. 오늘 당장 CI에 10줄 추가로 서명을 시작해, 다음 사건의 피해자가 되지 마세요.

관련 글

  • Docker 완벽 가이드
  • Kubernetes 완벽 가이드
  • DevSecOps 완벽 가이드
  • Kyverno 정책 엔진 가이드