KCA — Kyverno 인증 어소시에이트 · 이미지 검증과 공급망 · 실습
서명 검증 정책과 자격 증명 세우기
목표
cosign 서명과 attestation 을 검증하는 Kyverno 정책을 작성하고, Kyverno 와 파드가 각각 프라이빗 레지스트리에 접근하는 데 필요한 자격 증명 리소스를 실제 클러스터에 올립니다.
왜 중요한가
서명 검증 정책은 문법보다 운영 조건이 어렵습니다. 서명이 있는지, 그 서명을 조회할 수 있는지, 조회한 서명이 내가 신뢰하는 주체의 것인지가 각각 다른 실패 모드이고 증상은 모두 파드가 안 뜬다로 같습니다. 특히 attestors.count 를 빼먹으면 entries 전부가 통과해야 하므로 키를 추가한 순간 전부 막히고, mutateDigest 를 켜면 태그를 밀어 파드를 재생성하던 파이프라인이 조용히 무력화됩니다. 이 실습은 그 함정들을 매니페스트 위에서 미리 밟아 봅니다.
단계
1. /root/kca-verify/ 디렉터리를 만들고 verify-keys.yaml 에 kind ClusterPolicy, metadata.name kca-verify-images, spec.rules[0].name verify-signature 를 쓰세요. verifyImages[0].imageReferences 에 10.0.0.202/platform/* 를 넣고, attestors[0].entries[0].keys.publicKeys 에 BEGIN PUBLIC KEY 로 시작하는 PEM 공개키를 넣으세요.
2. 같은 attestors[0] 에 count 를 1 로 두고 entries 를 두 개로 만드세요. 두 번째 항목은 keyless 이며 url 은 https://fulcio.sigstore.dev, rekor.url 은 https://rekor.sigstore.dev, issuer 는 https://token.actions.githubusercontent.com, subject 에는 .github/workflows/ 가 들어간 워크플로 경로를 쓰세요.
3. 같은 verifyImages[0] 에 required, verifyDigest, mutateDigest 를 모두 true 로 두고 skipImageReferences 에 10.0.0.202/platform/legacy-* 를 넣으세요. 그리고 spec.webhookConfiguration.timeoutSeconds 를 20에서 30 사이 값으로 두되 deprecated 인 spec.webhookTimeoutSeconds 는 쓰지 마세요.
4. /root/kca-verify/verify-attestations.yaml 에 kind ClusterPolicy 를 쓰고 verifyImages[0].attestations 에 두 항목을 넣으세요. 하나는 type https://slsa.dev/provenance/v1 이고 conditions[0].all[0].key 로 빌더 신원을 검사하며, 다른 하나는 type https://cyclonedx.org/bom/v1.4 이고 conditions[0].all[0].key 로 log4j-core 컴포넌트 버전을 검사합니다.
5. /root/kca-verify/allowed-registries.yaml 에 kind ClusterPolicy, metadata.name kca-allowed-registries 를 쓰세요. spec.rules[0].validate.foreach[0].list 는 request.object.spec.[initContainers, containers][] 이고 중괄호로 감싸지 마세요. deny.conditions.all[0].operator 는 AnyNotIn, value 목록에 10.0.0.202/platform/* 를 넣고 validate.failureAction 은 Enforce 로 하세요.
6. 클러스터에 네임스페이스 kca-verify 를 만들고 그 안에 Secret harbor-cred 를 실제로 만드세요. 타입은 kubernetes.io/dockerconfigjson 이고 서버는 10.0.0.202 입니다.
7. 같은 네임스페이스에 ServiceAccount kca-deployer 를 만들어 imagePullSecrets 에 harbor-cred 를 달고, Deployment kca-payments 를 실제로 만들어 serviceAccountName 을 kca-deployer 로 하고 컨테이너 이미지를 10.0.0.202/platform/payments@sha256: 뒤에 64자 16진수를 붙인 형태로 쓰세요.
참고
kubectl create secret docker-registry harbor-cred --docker-server=10.0.0.202 --docker-username=robot --docker-password=... -n kca-verify를 쓰면 타입과 키가 알아서 맞습니다.- 64자 다이제스트는
printf 'kca' | sha256sum같은 방법으로 아무 값이나 만들어 써도 됩니다. - 흔한 실수 1: attestors 에 entries 만 늘리고 count 를 빼먹는 것. 전부 통과해야 하는 상태가 됩니다.
- 흔한 실수 2: foreach 의 list 를 중괄호로 감싸는 것. list 는 JMESPath 표현식 자체를 받습니다.
단계 7개
- 정적 키 기반 verifyImages
- keyless 추가와 count 의 의미
- 다이제스트 고정과 예외, 그리고 타임아웃
- provenance 와 SBOM 조건
- 허용 레지스트리 검사
- 레지스트리 자격 증명 시크릿
- 서비스어카운트와 다이제스트 고정 배포