쿠버네티스를 구축하면서 GCP 관계자분들에게 배울 수 있는 Deep-Dive 라는 일주일 교육(?)을 들을 수 있었다.
교육이라지만 단순히 이론이 아닌 실제 App들을 준비해서 이를 k8s에 올려보고 시행착오를 풀어나가는 과정을 같이 수행하는 것이다.
이 교육 중 한가지를 이제 적용해보고자 한다.
Kubernetes docker의 보안
현재 Container Image Registry로 GCP의 Artifact Registry를 사용중이고, App:30 과 같은 Image 태그에 빌드 번호를 붙여서 해당 Image를 당겨오고 있었다.
이때 GCP APAC 관계자분이 “누군가 Artifact Registry에 31이라는 태그를 가진 Image를 악의적으로 넣으면 어떻게 할 것인가?” 라는 질문에,
처음으로 든 생각은 “그럴 확률은 적지 않을까?” 였지만 이는 당연히 아니다.
실제로 그런 일들이 있었고, 그에 따른 피해가 큰 고객사도 있었다고 한다.
그렇기에 Container Image 태그에 유니크 하거나 불변할 수 있는 값들을 넣어 사용한다고 한다.
Git Commit 값이나 UUID 마냥 특별한 값들을 넣어서 사용하는데, 우리는 이를 Image의 digest값으로 사용해보고자 했다.
Digest?
Digest값은 Image 태그에 대한 특정한 값을 sha256으로 암호화한 하나의 해시값으로 볼 수 있다.
여기서 주의할 점은 바로 Image 태그에 대한 해시값이라는 것이다.
그렇기 때문에 Digest는 불변이 아니라, Image를 pull하고 push 하는 과정 중에서 이미지 태그가 변경된다면 Digest값도 바뀌게 된다.
그러면 왜 Digest값을 선택했을까?
docker pull을 할 때 app:30이 아니라 app:digest 값으로 pull을 할 수 있기 때문이다.
그렇게 태그값은 그냥 식별 용도로만 사용하고 실질적인 프로세스는 전부 digest값을 통해서 수행되기 때문에 보안을 지킬 수 있는 것이다.
예를들자면 개발 이미지를 app:digestA이면, 개발 이미지를 그대로 검수 Registry에 넣으면 app:digestB가 된다.
Helm Chart로 배포하기 때문에 Values.yaml에는 digestB가 적혀있고,
누군가가 악의적으로 검수 Registry에 app:32나, app:digestC를 넣는다 하더라도 Values.yaml이 변경되지 않는 한 적용이 안된다.
반대로 빌드 넘버 같은 태그를 기준으로 할 경우에는 위험할 수 있는 것이다.
그렇게 Image 태그에는 빌드 넘버를 넣어서 식별하거나 추적하는 용도로 쓰고, 실질적인 프로세스는 digest값을 통해서 pull 및 push를 하고 있다.
docker inspect {image}
docker inspect 명령어를 입력하면 해당 docker의 자세한 정보를 확인할 수 있다.
Image가 처음으로 빌드 된 시점등 여러 데이터를 알 수 있다.
여기서 유니크한 ID값을 사용할까도 생각했지만, 아무래도 digest값으로 docker pull할 수 있다는 것이 제일 안정적이라고 생각했다.
물론 태그에 Container Image의 ID값을 적어도 크게 상관은 없다고 생각한다.
다만 해당 Container Image가 몇 번째 빌드 파이프라인에서 만들어진건지를 추적하는게 조금 힘들 것 같다고 생각한다.