v0.9.264
셀프서비스 게이트가 통과시킨 값 넷
internal/servicecatalog 는 158줄이지만 단위 테스트가 0개인 패키지였습니다. 그런데 셀프서비스 요청 본문의 values — 전부 사용자 입력 — 가 운영자가 승인하고 kubectl apply 하는 manifest 로 바뀌는 사이에 서는 게이트는 이 패키지의 ValidateInput 하나뿐입니다. 실제로 들어올 수 있는 값의 형태와 대조해 보니 결함 네 가지가 나왔습니다.
① port 는 아예 검증되지 않았습니다
사용자가 준 숫자가 containerPort: 에 그대로 렌더됩니다. 그래서 0 · -1 · 70000 이 문법상 멀쩡한 manifest 를 만들고, 그 manifest 는 검증 · 정책 미리보기 · 승인까지 전부 통과한 뒤 apply 시점에 API server 에게 거절당했습니다 — 실패가 가장 늦게, 사람이 이미 승인 버튼을 누른 다음에 드러나는 자리입니다. 이제 1~65535 를 요구합니다.
② 태그 없는 이미지가 latest 가드를 우회했습니다
가드는 Contains(image, ":latest") 였는데, harbor.local/library/postgres 처럼 태그가 없는 참조는 Kubernetes 가 latest 로 해석합니다 — 즉 막으려던 바로 그 값이 통과했습니다.
같은 구멍이 한 칸 뒤 호출부의 운영 환경 게이트에도 있었습니다: Contains(image, ":") && !Contains(image, "@sha256:") 이라 콜론이 없으면 digest 요구 자체를 건너뜁니다. 무태그 이미지는 운영 환경의 digest 고정 검사까지 함께 우회했습니다.
③ 같은 substring 검사가 정상 태그를 거절했습니다
tomcat:latest-jdk21 은 고정 태그인데 :latest 를 포함한다는 이유로 막혔고, 반대로 digest 로 고정된 repo:latest@sha256:... 은 불변인데도 막혔습니다.
②③ 모두 substring 검사를 버리고 해결했습니다. 참조를 [registry[:port]/]repo[:tag][@digest] 로 분해해, digest 가 없으면 태그를 요구하고 태그가 정확히 latest 일 때만 거절합니다. 운영 환경 게이트는 콜론 유무와 무관하게 digest 를 요구합니다.
④ 0 이 유효한 수량이었습니다
^[0-9]+(Ki|Mi|Gi|Ti)?$ 는 0 · 0Gi 를 통과시킵니다 — storage 0 은 PVC 검증기가 거절하고, memory limit 0 은 컨테이너가 첫 할당에서 OOM 으로 죽습니다. 세 수량 모두 0 초과를 요구합니다.
초록불을 믿지 않았습니다
신규 테스트 7개를 고치기 전 코드에 되돌려 붙여 확인했습니다 — 넷이 위 결함을 각각 정확히 지목하며 실패했습니다(정상 입력 · 형식 오류 · 빌트인 6종 렌더 결과의 YAML 디코드는 원래 통과했습니다). 이 패키지의 첫 단위 테스트이기도 합니다.
검증: go build ./... · go vet ./... · go test ./... 전부 통과(21 패키지).
- 이미지:
clustara:v0.9.264 - 배포 압축본:
clustara-v0.9.264.tar.gz