Skip to content
Published on

Kyverno 이미지 검증: Sigstore와 공급망 보안

Authors

1. verifyImages 규칙 개요

Kyverno의 verifyImages 규칙은 컨테이너 이미지의 서명과 증명(attestation)을 검증하여 공급망 보안을 강화합니다.

1.1 기본 구조

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-images
spec:
  validationFailureAction: Enforce
  webhookTimeoutSeconds: 30
  rules:
    - name: verify-signature
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
        - imageReferences:
            - 'ghcr.io/myorg/*'
            - 'myregistry.io/apps/*'
          attestors:
            - entries:
                - keys:
                    publicKeys: |-
                      -----BEGIN PUBLIC KEY-----
                      MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
                      -----END PUBLIC KEY-----

2. Cosign 서명 검증

2.1 정적 키 기반

verifyImages:
  - imageReferences:
      - 'ghcr.io/myorg/*'
    attestors:
      - entries:
          - keys:
              publicKeys: |-
                -----BEGIN PUBLIC KEY-----
                MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
                -----END PUBLIC KEY-----

2.2 Keyless 서명 (Fulcio)

OIDC 기반 키리스 서명 검증:

verifyImages:
  - imageReferences:
      - 'ghcr.io/myorg/*'
    attestors:
      - entries:
          - keyless:
              url: https://fulcio.sigstore.dev
              rekor:
                url: https://rekor.sigstore.dev
              subject: 'https://github.com/myorg/*'
              issuer: 'https://token.actions.githubusercontent.com'

이 정책은:

  • Fulcio CA에서 발급한 인증서로 서명 확인
  • Rekor 투명성 로그에서 서명 기록 확인
  • GitHub Actions에서 빌드된 이미지만 허용 (subject/issuer 매칭)

2.3 KMS 키

verifyImages:
  - imageReferences:
      - 'myregistry.io/apps/*'
    attestors:
      - entries:
          - keys:
              kms: awskms:///arn:aws:kms:us-east-1:123456789:key/abc-123
          # 또는
          - keys:
              kms: gcpkms://projects/my-project/locations/global/keyRings/my-ring/cryptoKeys/my-key
          # 또는
          - keys:
              kms: azurekms://my-vault.vault.azure.net/keys/my-key

3. Attestation 검증

3.1 in-toto Attestation

verifyImages:
  - imageReferences:
      - 'ghcr.io/myorg/*'
    attestations:
      - type: https://slsa.dev/provenance/v1
        attestors:
          - entries:
              - keyless:
                  url: https://fulcio.sigstore.dev
                  rekor:
                    url: https://rekor.sigstore.dev
        conditions:
          - all:
              - key: '{{ builder.id }}'
                operator: Equals
                value: 'https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v1.9.0'

3.2 SLSA Provenance 검증

verifyImages:
  - imageReferences:
      - 'ghcr.io/myorg/*'
    attestations:
      - type: https://slsa.dev/provenance/v1
        attestors:
          - entries:
              - keyless:
                  url: https://fulcio.sigstore.dev
                  subject: 'https://github.com/myorg/*'
                  issuer: 'https://token.actions.githubusercontent.com'
        conditions:
          - all:
              - key: '{{ buildDefinition.buildType }}'
                operator: Equals
                value: 'https://slsa-framework.github.io/github-actions-buildtypes/workflow/v1'
              - key: '{{ runDetails.builder.id }}'
                operator: Equals
                value: 'https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@refs/tags/v1.9.0'

4. 이미지 레지스트리 인증

4.1 프라이빗 레지스트리 접근

# Kyverno가 프라이빗 레지스트리의 서명을 조회하려면
# imagePullSecrets 또는 ServiceAccount에 레지스트리 인증 정보가 필요

# values.yaml (Helm 설치 시)
# admissionController:
#   container:
#     image:
#       pullSecrets:
#         - name: my-registry-secret

5. SBOM 검증

5.1 CycloneDX SBOM attestation 검증

verifyImages:
  - imageReferences:
      - 'ghcr.io/myorg/*'
    attestations:
      - type: https://cyclonedx.org/bom/v1.4
        attestors:
          - entries:
              - keyless:
                  url: https://fulcio.sigstore.dev
        conditions:
          - all:
              - key: "{{ components[?name=='log4j-core'].version | [0] }}"
                operator: NotEquals
                value: '2.14.1'

6. 이미지 변형(Mutation)

6.1 태그를 다이제스트로 변환

verifyImages:
  - imageReferences:
      - 'ghcr.io/myorg/*'
    mutateDigest: true # 태그를 다이제스트로 자동 변환
    required: true # 서명이 반드시 존재해야 함
    verifyDigest: true # 다이제스트 검증
    attestors:
      - entries:
          - keys:
              publicKeys: |-
                -----BEGIN PUBLIC KEY-----
                ...
                -----END PUBLIC KEY-----

mutateDigest: true는 이미지 태그를 다이제스트(SHA256)로 자동 변환하여 이미지 불변성을 보장합니다.


7. 실전 예시: 종합 이미지 보안 정책

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: comprehensive-image-security
spec:
  validationFailureAction: Enforce
  webhookTimeoutSeconds: 30
  rules:
    # 1. 허용된 레지스트리만 사용
    - name: allowed-registries
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: 'Images must be from approved registries'
        foreach:
          - list: 'request.object.spec.[initContainers, containers][]'
            deny:
              conditions:
                all:
                  - key: '{{ element.image }}'
                    operator: AnyNotIn
                    value:
                      - 'ghcr.io/myorg/*'
                      - 'myregistry.io/*'

    # 2. latest 태그 금지
    - name: deny-latest
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Using 'latest' tag is not allowed"
        foreach:
          - list: 'request.object.spec.[initContainers, containers][]'
            deny:
              conditions:
                any:
                  - key: '{{ element.image }}'
                    operator: Equals
                    value: '*:latest'

    # 3. 서명 검증
    - name: verify-signature
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
        - imageReferences:
            - 'ghcr.io/myorg/*'
          mutateDigest: true
          required: true
          attestors:
            - entries:
                - keyless:
                    url: https://fulcio.sigstore.dev
                    subject: 'https://github.com/myorg/*'
                    issuer: 'https://token.actions.githubusercontent.com'

8. 정리

Kyverno 이미지 검증의 핵심:

  1. cosign 서명 검증: 정적 키, Keyless(Fulcio), KMS 지원
  2. Attestation 검증: in-toto, SLSA provenance 조건 기반 검증
  3. SBOM 검증: CycloneDX/SPDX attestation 내 취약 컴포넌트 확인
  4. 다이제스트 변환: mutateDigest로 이미지 불변성 보장
  5. 종합 정책: 레지스트리 제한 + 태그 정책 + 서명 검증 결합

다음 글에서는 Kyverno와 OPA/Gatekeeper의 비교 분석을 다룹니다.