CKAD, CKA 에 이어 CKS 도 pass 했습니다. CKS는 kubernetes 환경에서 OS 부터 시작해서 POD 레벨 container 레벨 docker image 레벨까지 각각의 요소의 취약점을 파악하는 방법을 알아보고 어떤 문제가 있으며 어떻게 해결하면 좋은지 그리고 자동화된 분석도구를 사용해 보도록 가이드 합니다.
무엇을 알게되는가?
CKS 를 취득하면서 배우면 k8s 를 도입하면 각 영역마다 어떤 부분을 체크해야 하는지 어떤 부분이 보안상 취약할 수 있는지를 전체적으로 바라보고 가이드 할 수 있는 역량을 취득할 수 있습니다.
kube-bench, trivy 등으로 각node 와 container image 취약점을 자동 스케닝 하고 Dockerfile 과 kubernetes yaml 파일을 직접 (manually) 점검하는 방법도 익혀야 합니다. 또한 RBAC 을 통한 세부적인 권한 관리와 audit log 를 설정하여 이상 징후를 감지하고 찾아내는 방법도 익힐 수 있습니다.
해킹과 방어, 창과 방패의 싸움에서 해킹은 점점 강해지고 방어하는 기술도 점점 진화해야 합니다. 한순간에 익힌 보안 기술이 전부가 아니겠습니다. CKAD와 CKA 는 3년의 자격 유지가 인정되는 반면 CKS 는 2년의 자격 유지가 인정됩니다. 2년 후에는 새로운 보안 기술을 익혀야 하며, 2년이 지난 보안 기술은 자격자로 인정하기 어렵다는 뜻이겠습니다.
공부 방법과 걸린 시간 간단한 소회
CKAD, CKA 를 공부하게 되면 기본적으로 kubernetes document 를 검색하고 사용하는 방법 yaml 작성 능력과 vim 사용능력을 키우게 되므로 회사 생활과 병행하며 CKS자격을 취득하는 대는 약 한 달의 시간이 소요되었던 것 같습니다. 주말에는 아내가 공부하는 시간을 많이 배려해 주었습니다.
udemy 강의를 구독하여 1차례 수강 후 강사가 제공하는 killer.sh 에서 각 챕터별 실습을 하였고 시험 결제를 하면 총 2회의 모의고사 (같은 문제) 를 풀 수 있습니다. 처음에는 40점이 나왔으나 그냥 꾸준히 틀린 문제를 반복하여 100점에 나올 때 까지 session reset (문제를 풀고 있는 VM 을 초기화) 을 통해 각 문제에서 모른 부분은 더이상 없도록 할 때까지 반복해서 풀었습니다. 이 때 애매한 개념들이 많이 해소 되었습니다.
시험에는 gviser 설정, trivy 돌려보기, docker 및 pod 취약점 있을 만한 것 찾기, pod security policy 구성, RBAC role / clusterrole binding, OPA, CKA 에 자주 등장한 network policy, ETCD를 이용한 secret 찾기 base64 decode 하기 등
공부했던 거의 모든 부분이 출제 되었습니다. 특히 kube-apiserver 취약 설정 찾아내서 고치는 부분의 경우 manifest 의 pod이 재시작 되고 항상 잘 기동되길 바라는 마음을 가져야 했습니다.
docker 가 아닌 crictl 로 구동 되기에 watch -n 0.5 crictl ps 명령을 자주 사용 하여 kube-apiserver 가 재기동 되는 순간을 알아낼 수 있었습니다. 지금에서야 느끼는데 kube-apiserver 가 죽는데는 거의 10~15 초가 걸리고, 되살아나는대는 2~3초 밖에 안 걸린다는 점입니다. udemy 강사는 4~5 초만에 재기동 되는 것 같은데.. 시험보는 VM 서버는 사양이 좋지 않은 모양입니다. 그래서 manifest 를 수정 후, watch -n 0.5 crictl ps 를 치면서 그야말로 그냥 기다리는 시간은 좀 아깝다고 느껴졌습니다. (그래서 다음 문제를 먼저 살펴보기도 했습니다.)
시험 보는 중에 trivy 나 gviser 문제에서 해당 document 는 탭으로 하나 더 열어도 된다 라는 내용을 보고 k8s document 외에 2개의 탭을 더 열게 되었는데 감독관이 10분 후쯤에 화면을 잠구더니 그러지 말라 해서 그냥 알겠다고 하고 닫았더니 문제는 없었습니다. 그러니까…. 10분 정도는 감독관이 못 본 것 같고 실시간 감시도 아닌 것 같습니다.
만약 시험이 떨어지게 되면, 거의 비슷한 출제 내용으로 1번 공짜로 볼 수 있습니다. 그래서 자격증만을 위해서 시험을 치루는 경우라면 어서빨리 시험을 보고, 패턴을 익혀서 한주 후 쯤에 또 치루는 것도 방법일 수는 있겠습니다.
마치며
digital badges 를 모으는게 새로운 취미가 된 것 같은데 다음 자격증으로는 elastic search 사의 자격증을 따보려고 합니다. 업무상 kibana 를 많이 사용하는데 로그를 검색 하는 것이 아닌 분석하는 사람이 되고 싶습니다.
cp /mnt/c/Users/[USERID]/.kube/config ~/.kube/config #복사
sed -i 's/C:/\/mnt\/c/g' ~/.kube/config # c 드라이브 경로를 mnt로 치환
sed -i 's/\\/\//g' ~/.kube/config # \를 / 로 변환
회사에서 운영하는 대외 서비스의 서비스를 모니터링 하기 위해 그 유명하다는 prometheus 를 사용해 보았다. 공식 홈페이지의 기본 예제로 진행해 보았다. 내 식대로 이해해보면 prometheus 는 단순히 metric 이라는 것을 긁어서 저장하는 크롤링 서버다. (pull metrics)
무엇을 크롤링 하는가? 프로메테우스가 이해하기 좋은 형태의 시시각각 새로고침 되는 상태 정보다. 프로메테우스 설정에 등록된 모든 서버들에 프로메테우스가 주기적으로 접속해서 내용을 계속 긁어온다.
exporter
프로메테우스가 데이터를 잘 긁어갈 수 있도록 준비된 서버들이 필요하다. 이것을 보통 exporter 라고 부르며 이것이 준비 되어야 프로메테우스가 긁는 역할을 담당할 수 있다. exporter 는 독립실행형 프로그램이므로 프로메테우스를 설치 하기 전에 실행 할 수 있다. 따라서 잠시 프로메테우스에 대해서 잊도록 하자.
프로메테우스에게 긁힐만한 정보를 가진 서버들은 xx_exporter 라 불리우는 “추출기” 서비스가 기동되어 있어야 한다. 그 서비스의 포트로 프로메테우스가 주기적으로 접속해서 내용들을 주기적으로 가져간다. 물론 xx_exporter 는 계속 내용을 갱신하기 때문에 프로메테우스는 시시각각 변하는 서버의 정보를 끊임없이 모을 수 있게 된다.
공식 아키텍쳐. Retrieval 프로세서가 계속 긁어간다.
아래와 같이 프로메테우스에 등록된 어떤 URL 이 있다고 할 때 그 metric 지표는 아래와 같이 plain_text_key value 쌍으로 구성된 단순 text 여러줄의 모음이다. 중간에 주석이 많은데 그냥 고마운 설명이라 생각하고 넘어가자.
http://somehost.com:9115/metric
# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds
# TYPE probe_dns_lookup_time_seconds gauge
# plain_text_key valueprobe_dns_lookup_time_seconds0.199540841
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds2.299759862 # 웹서버의 응답시간
이런 정보가 프로메테우스에 수집되면 그 plain_text_key 키값 그대로 검색을 할 수 있고 시시각각 변하는 값이 그래프로 나타나게 된다.
blackbox_exporter
프로메테우스에게 데이터를 모두 주기위해서 많은 서버들이 스스로 exporter 가 작동하는 등의 노력을 할 수도 있겠지만 내가 관리 할 수 없는 특정 API 의 상태를 체크 하고 싶다면 그 API 를 찔러보는 서버를 대상 서버 밖의 다른 곳에 두는 수 밖에 없다. 따라서 blackbox_exporter 를 이용하면 부족하나마 서비스를 모니터링 할 수 있다.
blackbox.yml
modules:
http_2xx:
prober: http
timeout: 5s
http:
preferred_ip_protocol: "ip4" # 이 설정이 매우 중요
method: GET
valid_status_codes: [200, 302]
headers:
User-Agent: "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Mobile Safari/537.36 Edg/96.0.1054.34"
http_post_2xx:
prober: http
http:
method: POST
여기에는 어떤 서버를 모니터링 할지는 안 나와 있고 blackbox_exporter 자체의 속성만 편집한다. 여기서
preferred_ip_protocol: "ip4"
가 매우 중요한데, ipv6 를 지원하지 않는 서버의 상태를 조회 할 때 저것을 명시 하지 않으면 조회하지 못한다는 에러가 난다. (보통 다 그럴 것이다)
proxy
blackbox_exporter 는 일종의 proxy 이다. 프로메테우스는 blackbox_exporter 를 경유해서 서버의 상태를 조회하며, blackbox_exporter 는 서버의 상태를 프로메테우스가 이해하기 쉬운 형태로 그 결과를 변환 해 준다.
target 서버를 뭘로 인자를 주느냐에 따라서 그 서버의 http 상태 정보를 추출할 수 있다. prometheus 의 영어 사전을 리턴하는 네이버의 응답 속도를 모니터링 하고 싶다면
blackbox_exporter 의 probe API 에 target 인자로 그 URL 을 주면 된다. 이렇게 target 인자를 프로메테우스가 필요에 따라 설정할 수 있도록 하면 된다.
Prometheus 에서 조회 대상 target 설정
prometheus 에서 조회 대상 설정
blackbox_exporter 서버가 대신 조회
응답을 prometheus 용으로 생성
prometheus 가 시시각각 변하는 metric 지표를 저장
prometheus
드디어 prometheus 를 시작해보다. 기본 설정에서 blackbox_exporter 관련 설정만 추가 한다.
localhost:9115 에 떠 있는 blackbox_exporter 에게 targets 에 명시된 서버들을 조회하라는 설정이다. relabel 을 prometheus 의 유연성 중 하나로 언급되기도 한다.
이 설정은 blackbox_exporter 와 연계하여 호환 설정하는 내용이 아님을 명심하자. 사실 prometheus 는 blackbox_exporter 가 주는 값만 중요할 뿐이지 blackbox_exporter 인지는 중요하지 않다.
이 설정은 단지 job_name (배치 job?) 에 대한 시시각각 변경되는 값을 가져오기 위해서 URL 을 어떻게 조합해 갈 것인가에 대한 트릭이 담겨있는 설정이다. 위와 같이 설정하고 나면 prometheus 는 아래와 같이 target 에 명시된 URL 을 크롤링 하기 위한 blackbox_exporter 용 URL 을 생성하여 그것을 pulling 한다.
#1 여기서 __address__ 는 target 내의 서비스들을 말하는데 [] 로 감싸져있어 배열이다. (그래서 labels 도 복수형) 이것이 __param_ 이 된다. 즉 blackbox_exporter 의 target 파라미터로 대체되어 들어간다.
#2 또한 그 target 들은 prometheus 의 instance label 이 된다. 표시되는 그래프에서 구별해 볼 수 있는 구분자 라벨이다. 즉 #1의 target_label 은 __param_ 이 prefix 이므로 파라미터로 전환되는 것이고 #2는 prefix 가 없으므로 그대로 label이 된다.
#3 마지막으로 마지막으로 __address__ 즉 조회할 서버 (target_label) 의 주소는 localhost:9115 로 대체된다.
너무 target 이 길면 나중에 prometheus 에서 조회한 URL 이 너무 길고 나중나중에 grafana 로 연계 할 때도 안 좋기 때문에 (#.*) # 뒤에 오는 것을 $1번 변수에 담아서 instance 라는 라벨에 할당할 수 있다. 나중에 화면 볼때 쓸데 없이 긴 라벨이 없어 깔끔하다.
서비스별 응답시간
여기까지 prometheus 에 웹서버의 상태를 표시하기 위한 여정을 마친다. metric 을 쭑 훑어보면 웹서버의 응답 시간을 나타내는 probe_duration_seconds 를 찾을 수 있고 최종적으로는 등록된 API 들에 대한 측정치를 확인 할 수 있다.
다음은 응답시간을 받아올 수 없을 때, 즉, blackbox_exporter 의 조회 API 인 probe API 의 조회 실패 케이스 probe_success 0 일 때 slack 으로 알림을 받는 방법을 알아본다.
C:\src\learninggo\src\anydir>go run anyfile.go
anyfile.go:3:8: package greet is not in GOROOT (C:\Program Files\Go\src\greet)
C:\src\learninggo\src\anydir>set GO111MODULE=off
or
go env -w GO111MODULE=auto
C:\src\learninggo\src\anydir>go run anyfile.go
Hello greeting pack
책의 go version 과 요즘음의 go version 의 차이로 module 의 기본 사용이 강제 되는 듯.
회사 코드도 컴파일이 안되는게 이것 때문인듯. 오히려 예전 버전의 go를 설치 하고 있는 것도 문제.
일단 결론적으로 나의 경우 안되었던 이유는 docker container 를 띄운 windows 컴퓨터가 붙은 공유기를 “공용 네트워크” 로 선택했기 때문이었다.
컴퓨터를 세팅한 첫날부터 잘못된 선택이었다. 처음에는 outbound 로 인터넷만 하는 컴퓨터라 신경을 안 썼는데 “서버” 로 돌릴 host 컴퓨터라면 당연 “개인 네트워크”로 선택하는 것이 좋겠다. 왜냐하면 host 컴퓨터의 입장에서는 내 공유기가 “공용 네트워크” 로 “선언” 했다는 것은 마치 커피숖 wi-fi 붙은거랑 같게 보안을 강화해 달라는 설정을 한 것이나 다름 없기 때문이다.
그러니 옆에 컴퓨터에서 host 컴퓨터에 붙으려고 해도 대부분 기본 차단된다. 이는 커피숖의 다른 누군가가 내 컴퓨터에 접속 시도하는 것을 죄다 막는 “공용 네트워크” 설정 때문이다.
host 컴퓨터가 붙은 wi-fi 가 “개인 네트워크” 설정을 했다면 기본적으로 외부 컴퓨터에서 host 컴퓨터가 열어 놓은 port 에 접속이 잘 되기 마련인데 이는 docker for desktop 등을 설치 했을 때, 처음 서버를 기동 했을 때 windows 가 분명히 물어봤을 것이다.
시작>실행> wf.msc 에서 나오는 인바운드 규칙을 보면 나의 경우는 docker 프로그램이 여는 모든 포트가 허용되되 개인 프로필 즉, 개인 네트워크에 붙어 있을 때에만 허용하고 “공용 프로필” 은 명시적으로 거절하도록 되어 있다.
이것이 무슨 포트인지는 중요하지 않다. docker 로 실행된 모든 포트는 허용을 하게 된다.
windows 에서 리스닝 중인 포트에 대해서 어떠한 프로그램이 그 포트를 열고 있는가를 거꾸로 찾아 들어가는 방법이 있다.
netstat -aon 과 linux 의 grep 격인 findstr 를 조합하면 된다. 9998 을 열고 있는 프로그램의 ID 를 찾는다.
netstat -aon 과 findstr
프로그램 ID 를 찾았다면 이제 프로그램이 무엇인지 단번에 알아낼 수 있다.
linux 의 ps -ef 격인 tasklist 이다. 여기서도 findstr 를 조합한다.
com.docker.backend.exe 가 결국 9998 포트를 열고 있는 프로그램인 것을 알 수 있다.
com.docker.backend.exe 프로그램의 fullpath 를 아는 방법은 아래의 명령으로 가능하나 외우기가 어렵다. 따라서 작업관리자 > 세부정보 탭에서 파일 위치 열기를 하는 것이 낫겠다.
C:\Users\nzin4>wmic process where “name=’com.docker.backend.exe'” get executablepath ExecutablePath C:\Program Files\Docker\Docker\resources\com.docker.backend.exe
이제 옆 컴퓨터에서의 테스트가 끝났다면 공유기 외부에서의 접속을 시도해볼 차례다. 공유기는 각 공유기 제조사마다 “포트 포워딩” 가이드를 제공하고 있다. port forwarding 설정을 잘만 한다면 host 즉, windows 컴퓨터의 외부에서의 접속 테스트는 완료된 상태이므로 무리없이 진행될 것이다.
회사에서 몇가지 s/w 를 구매해야 하는데 그냥 법카로 사서 청구하라고 해서 개인용으로 구매하라는 뜻인지.. 결론적으로 s/w 회사에서 license 를 개인용 / 업무용을 명확하게 나누지 않고서야 개인용으로 구매해도 문제가 없다는 생각이 든다. 즉, 개인용으로 귀속시키면 내 전용 s/w 가 되고 어딜 가서 사용해도 괜찮다는 의미가 되겠다.
SecureCrt 에 문의 메일을 보내서 가능하다는 답변을 받았다.
구매 라이센스는 computer 에 귀속된다.
제목: Re: Can I use personal license S/W at my company? [T02035873:002]
Hello,
Thank you for your e-mail.
Providing you stay in compliance with our End-user License Agreement and are authorized by your company to install a personal License on your work computer there should not be an issue.
That being said SecureCRT is licensed per “computer” as defined in section 3 of the SecureCRT EULA which can be found at the following location:
https://www.vandyke.com/pricing/licensing.html
As defined in the SecureCRT EULA, a “computer” can be one of the following:
A client machine running a client operating system like Windows 10, macOS or Linux.
A “seat” which is defined as a software or hardware client that has access to use SecureCRT on a terminal or RDS server.
You will need 1 SecureCRT License for each “computer” that has access to use SecureCRT locally or remotely.
A single SecureCRT License can be used by a single individual to register SecureCRT on one additional “computer” as defined in the SecureCRT EULA as long as the individual has SecureCRT running on a single “computer” at a time.
Please let me know if there is anything else I can do for you.
Misty Buck VanDyke Software, Inc. 505-332-5710 505-332-5701 (fax) sales@vandyke.com www.vandyke.com