일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Pulumi
- mlops
- xdp
- blue/green
- eBPF
- Continuous Deployment
- gitops
- keda
- Kopf
- Kubernetes
- Litmus
- kubernetes operator
- Argo
- operator
- seldon core
- opensearch
- 카오스 엔지니어링
- CANARY
- serving
- 오퍼레이터
- MLflow
- Kubeflow
- CI/CD
- opentelemetry
- knative
- tekton
- Kubernetes 인증
- nginx ingress
- Model Serving
- argocd
- Today
- Total
Kubernetes 이야기
Kubernetes에서 Connaisseur 를 사용하여 이미지 서명 검증하기 본문
Connaisseur
Connaisseur는 컨테이너 이미지 서명 확인을 위한 Kubernetes admission controller 이다.
Cosign (https://github.com/sigstore/cosign) 을 사용하여 이미지 서명을 하였는데 서명된 이미지를 Kubernetes Pod로 실행 시 검증을 하기 위해서 Connaisseur을 사용한다.
Connaisseur는 Kubernetes 클러스터에서 컨테이너 이미지의 무결성과 출처를 보장한다. 이미지 검증 결과에 따라 해당 요청을 수락하거나 거부할 수 있다.
Connaisseur는 아래의 이미지 서명 솔루션과 연동을 목표로 하고 있다.
Notary V1 / Docker Content Trust
Sigstore / Cosign
Notary V2 (예정)
주요기능
- 감지 모드 : 경고하지만 잘못된 이미지를 차단하지 않는다.
- 네임스페이스 유효성 검사 : 전용 네임스페이스로 유효성 검사를 제한한다.
- 알림 : 확인 결과에 따라 알림을 보낸다.
- 자동 하위 승인 : Kubernetes 하위 리소스의 승인 구성
설치
helm 설치를 위해 helm chart가 저장된 git 소스를 내려받는다.
git clone https://github.com/sse-secure-systems/connaisseur.git
helm 설치 전 value를 설정한다.
...
validators:
# static validator that allows each image
- name: allow
type: static
approve: true
# static validator that denies each image
- name: deny
type: static
approve: false
# the `default` validator is used if no validator is specified in image policy
- name: custom-validator
type: cosign # or other supported validator (e.g. "cosign")
trust_roots:
- name: ghcr
key: k8s://image-sign/cosignkey
...
Policy 정책을 추가한다.
...
policy:
- pattern: "ghcr.io/kmaster8/*:*"
validator: custom-validator
with:
trust_root: ghcr
...
모든 NS가 아닌 특정한 NS만 이미지 검증을 하고 싶은 경우가 있을 것이다. 이때는 아래의 옵션을 적용한다.
...
namespacedValidation:
enabled: true
mode: validate # 'ignore' or 'validate'
...
위와 같이 하면 검사하고자 하는 NS에 securesystemsengineering.connaisseur/webhook=validate 라벨이 있는 Namepsace만 검사한다.
이제, Helm으로 설치를 진행한다.
helm install connaisseur helm --atomic --create-namespace --namespace connaisseur
이제 pod상태를 확인해 보자.
# kubectl get po -n connaisseur
NAME READY STATUS RESTARTS AGE
connaisseur-deployment-5b586b5f6b-bwckl 1/1 Running 0 21s
connaisseur-deployment-5b586b5f6b-gbxv7 1/1 Running 0 21s
connaisseur-deployment-5b586b5f6b-jlhzb 1/1 Running 0 21s
Kubernetes 설정
이미지 서명 검사를 하고자 하는 Namespace에 라벨을 추가해 보자.
# kubectl create ns image-test
# kubectl label namespaces image-test securesystemsengineering.connaisseur/webhook=validate --overwrite=true
이제 이미지 서명이 없는 container를 kubernetes에서 실행해 보자
# kubectl run demo --image=docker.io/securesystemsengineering/testimage:unsigned -n image-test
Error from server: admission webhook "connaisseur-svc.connaisseur.svc" denied the request: unknown error. please check the logs.
반대로 label이 없는 default NS에서 실행해 보자.
# kubectl run demo --image=docker.io/securesystemsengineering/testimage:unsigned
pod/demo created
위와 같이 Namespace에 "securesystemsengineering.connaisseur/webhook=validate" 라벨이 없는 Namespace에서는 이미지 서명 검사를 하지 않는 것을 볼 수 있다.
그 다음으로 이미지 서명이 완료된 이미지를 kubernetes에서 실행해 보자
# kubectl run demo --image=docker.io/securesystemsengineering/testimage:signed -n image-test
pod/demo created
ghcr.io 연동 테스트
이제 ghcr.io에 저장된 container도 이미지 서명 검사를 잘 하는지 확인해 보자.
현재 ghcr.io에는 아래의 두가지 이미지가 존재한다.
- ghcr.io/kmaster8/image-sign
- ghcr.io/kmaster8/image-nosign
이제 각각 배포해 보자.
# kubectl run demo --image=ghcr.io/kmaster8 -n image-test
Error from server: admission webhook "connaisseur-svc.connaisseur.svc" denied the request: Unexpected Cosign exception for image "ghcr.io/kmaster8/image-sign:latest": Error: loading public key: checking if secret exists: secrets "cosignkey" is forbidden: User "system:serviceaccount:connaisseur:connaisseur-serviceaccount" cannot get resource "secrets" in API group "" in the namespace "image-sign"
main.go:46: error during command execution: loading public key: checking if secret exists: secrets "cosignkey" is forbidden: User "system:serviceaccount:connaisseur:connaisseur-serviceaccount" cannot get resource "secrets" in API group "" in the namespace "image-sign"
위의 에러는 system:serviceaccount:connaisseur:connaisseur-serviceaccount 서비스 계정이 image-sign namespace의 secret 조회 권한이 없어서 발생하는 오류이다.
connaisseur cluster role에 secrets 권한을 추가한다. ( 권한을 주기 싫으면 values.yaml에서 secret 대신 public key를 직접 입력해도 된다.
이제 다시 실행해 보자
# kubectl run demo --image=ghcr.io/kmaster8/image-sign -n image-test
pod/demo created
정상적으로 실행되는 것을 확인하였고, 이제 다시 이미지 서명이 없는 이미지를 실행해 보자
# kubectl run demo --image=ghcr.io/kmaster8/image-nosign -n image-test
Error from server: admission webhook "connaisseur-svc.connaisseur.svc" denied the request: No trust data for image "ghcr.io/kmaster8/image-nosign:latest".
'Kubernetes > 보안' 카테고리의 다른 글
Kubernetes 에서 Vault 활용 (0) | 2022.03.14 |
---|---|
Kubernetes에서 Secret 암호화 (0) | 2022.03.13 |
trivy를 활용한 Container Image 취약성 검사 (3) | 2022.03.06 |
Cosign 으로 Container 이미지 서명하기 (0) | 2022.02.22 |
Kyverno ( Kubernetes Policy) (0) | 2022.02.20 |