[CKS] Demo Encrypting Secret Data at Rest
Kubernetes etcd에 저장된 Secret 데이터를 AES-CBC 암호화로 보호하는 방법입니다. 암호화 설정을 활성화하여 기밀 정보 노출을 방지할 수 있습니다.
개요
CKS 자격증을 위해 아래 내용을 정리했습니다.
Kubernetes Secret 저장하기
k8s etcd에 저장된 비밀 데이터를 암호화하여 안전하게 보호하는 방법을 설명합니다.
Secret 객체 생성, base64 인코딩 저장, 암호화 설정 활성화까지 etcd에 안전하게 보호하는 방법을 확인합니다.
- 시크릿 객체 생성 (예시입니다)
--allow-missing-template-keys=true--append-hash=false--dry-run='none'
# Create a new secret named my-secret by loading files from a directory
kubectl create secret generic my-secret --from-file=path/to/bar
# Create a secret with specified keys taken from disk files
kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa --from-file=ssh-publickey=path/to/id_rsa.pub
# Create a secret with literal values for keys
kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
# Create a secret using a combination of a file and a literal value
kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa --from-literal=passphrase=topsecret
# Create a secret from environment files
kubectl create secret generic my-secret --from-env-file=path/to/foo.env --from-env-file=path/to/bar.env
기본적인 secert 생성 방법과 확인 방법은 아래 가이드를 참고하세요
Secret이 base64를 통해 인코딩되어 저장된다는 것을 명심하세요.
저장 시 암호화가 되어있지않다면 누구나 접근하여 기밀 데이터를 노출하거나 열람할 수 있습니다.
Inspecting Secrets in etcd
etcd에 Secret을 저장하는 방식을 정리했습니다.
/registry/secrets/default/secret1Secret은 다음과 같은 정보에 저장됩니다.
따라서 etcdctl 명령어를 통해 원시 데이터를 볼 수 있습니다.
apt-get install etcd-client
ETCDCTL_API=3 etcdctl \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets/default/secret1 | hexdump -C
2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret|
31 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |1..............|
31 2e 6b 38 73 73 73 73 73 73 73 73 73 73 73 73 |1.k8sssssssssss...|
06 2f 76 31 |./v1|
암호화되지 않은 상태로출력됩니다. 따라서 etcd 접근 권한과 적절한 인증서만 있다면 누구나 검색하고 해독 가능합니다.
- 암호화 되었다면
k8s:enc:aescbc:v1:key1로 구성됩니다.
저장 데이터 암호화 활성화 여부 확인
--encryption-provider-config파라미터 혹은 API Server Manifest 파일을 확인합니다.
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep encryption-provider-config
apiVersion: v1
kind: Pod
metadata:
name: kube-apiserver
namespace: kube-system
spec:
containers:
- command:
- kube-apiserver
- --encryption-provider-config=/etc/kubernetes/enc/encryption-config.yaml # 이 라인이 있어야 함
- --advertise-address=192.168.1.10
- --allow-privileged=true
# ... 기타 파라미터들
volumeMounts:
- mountPath: /etc/kubernetes/enc
name: enc
readOnly: true
volumes:
- hostPath:
path: /etc/kubernetes/enc
type: DirectoryOrCreate
name: enc
암호화 구성 파일을 확인할 수 있습니다.
enc.yaml(encryption-config.yaml****)
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64로 인코딩된 32바이트 키> # head -c 32 /dev/urandom | base64
- identity: {} # fallback으로 암호화되지 않은 데이터 읽기용
AES-CBC알고리즘 사용identity: {}는 fallback용. → 상단에 위치하면 암호화가 적용되지 않습니다.
Kube API Server manifest 업데이트
- 암호화 파일을 저장할 로컬 디렉터리를 생성합니다(예:
/etc/kubernetes/enc)
mkdir /etc/kubernetes/enc
mv enc.yaml /etc/kubernetes/enc/
- Kube API Server 매니페스트(
/etc/kubernetes/manifests/kube-apiserver.yaml)를 수정--encryption-provider-config플래그를 추가- 새로운 볼륨 마운트(암호화 파일 디렉토리 →
/etc/kubernetes/enc)
spec:
containers:
- command:
- kube-apiserver
...
- --encryption-provider-config=/etc/kubernetes/enc/enc.yaml
volumeMounts:
...
- name: enc
mountPath: /etc/kubernetes/enc
readOnly: true
volumes:
...
- name: enc
hostPath:
path: /etc/kubernetes/enc
type: DirectoryOrCreate
변경사항을 저장하면 API Server가 다시 시작된 뒤 새로운 구성이 로드됩니다
ps aux | grep kube-api
암호화 검증
kubectl create secret generic my-secret-2 --from-literal=key2=topsecret
kubectl get secret
NAME TYPE DATA AGE
my-secret Opaque 1 16m
my-secret-2 Opaque 1 3s
ETCDCTL_API=3 etcdctl \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
get /registry/secrets/default/my-secret-2 | hexdump -C
# 평문 값이 더 이상 보이지 않는지 확인합니다.
기존 secret을 업데이트하렴녀 아래 명령어를 실행합니다.
kubectl get secrets --all-namespaces -o json | kubectl replace -f -