以前に試したことはあるけど、CKSコースにしたがって試してみたメモ。
参考リンク
- https://github.com/open-policy-agent/conftest
- https://github.com/killer-sh/cks-course-environment/tree/master/course-content/supply-chain-security/static-analysis/conftest
- Conftestを用いたCIでのポリシーチェックの紹介 | メルカリエンジニアリング
Kubernetesマニフェストのテスト
検査対象のマニフェストを用意する。
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: test name: test spec: replicas: 1 selector: matchLabels: app: test strategy: {} template: metadata: creationTimestamp: null labels: app: test spec: containers: - image: httpd name: httpd resources: {} status: {}
ルールは以下。policyフォルダに下に配置する。
# from https://www.conftest.dev package main deny[msg] { input.kind = "Deployment" not input.spec.template.spec.securityContext.runAsNonRoot = true msg = "Containers must not run as root" } deny[msg] { input.kind = "Deployment" not input.spec.selector.matchLabels.app msg = "Containers must provide app label for pod selectors" }
Dockerコンテナでスキャンを実行する。
root@cks-master:~/cks-course-environment/course-content/supply-chain-security/static-analysis/conftest/kubernetes# docker run --rm -v $(pwd):/project instrumenta/conftest test deploy.yaml Unable to find image 'instrumenta/conftest:latest' locally latest: Pulling from instrumenta/conftest df20fa9351a1: Pull complete bc9daf005a99: Pull complete e1e7755abe89: Pull complete 09afddcf2064: Pull complete Digest: sha256:7da62b227612d5cf50d6de80db740b77bcfb7fd52b2e1aa679dd9edd692fec21 Status: Downloaded newer image for instrumenta/conftest:latest FAIL - deploy.yaml - Containers must not run as root 2 tests, 1 passed, 0 warnings, 1 failure, 0 exceptions
マニフェストを修正して、PodのsecurityContextにrunAsNonRoot: true
を追加する。
apiVersion: apps/v1 kind: Deployment metadata: creationTimestamp: null labels: app: test name: test spec: replicas: 1 selector: matchLabels: app: test strategy: {} template: metadata: creationTimestamp: null labels: app: test spec: securityContext: runAsNonRoot: true containers: - image: httpd name: httpd resources: {} status: {}
スキャンを再実行する。
root@cks-master:~/cks-course-environment/course-content/supply-chain-security/static-analysis/conftest/kubernetes# docker run --rm -v $(pwd):/project instrumenta/conftest test deploy.yaml 2 tests, 2 passed, 0 warnings, 0 failures, 0 exceptions
Dockerfileのテスト
検査対象のDockerfileを用意する。
FROM ubuntu ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y golang-go COPY app.go . RUN go build app.go CMD ["./app"]
ルールは以下。policyフォルダに下に配置する。
# from https://www.conftest.dev package main denylist = [ "ubuntu" ] deny[msg] { input[i].Cmd == "from" val := input[i].Value contains(val[i], denylist[_]) msg = sprintf("unallowed image found %s", [val]) }
# from https://www.conftest.dev package commands denylist = [ "apk", "apt", "pip", "curl", "wget", ] deny[msg] { input[i].Cmd == "run" val := input[i].Value contains(val[_], denylist[_]) msg = sprintf("unallowed commands found %s", [val]) }
Dockerコンテナでスキャンを実行する。
root@cks-master:~/cks-course-environment/course-content/supply-chain-security/static-analysis/conftest/docker# docker run --rm -v $(pwd):/project instrumenta/conftest test Dockerfile --all-namespaces FAIL - Dockerfile - unallowed image found ["ubuntu"] FAIL - Dockerfile - unallowed commands found ["apt-get update && apt-get install -y golang-go"] 2 tests, 0 passed, 0 warnings, 2 failures, 0 exceptions
Dockerfileを修正して、FROMをalpine
に変更する。これではビルドは通らないが、テスト目的。
FROM alpine ARG DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y golang-go COPY app.go . RUN go build app.go CMD ["./app"]
スキャンを再実行する。
root@cks-master:~/cks-course-environment/course-content/supply-chain-security/static-analysis/conftest/docker# docker run --rm -v $(pwd):/project instrumenta/conftest test Dockerfile --all-namespaces FAIL - Dockerfile - unallowed commands found ["apt-get update && apt-get install -y golang-go"] 2 tests, 1 passed, 0 warnings, 1 failure, 0 exceptions
ルールを変更してaptをdenylistから削除する。
# from https://www.conftest.dev package commands denylist = [ "apk", "pip", "curl", "wget", ] deny[msg] { input[i].Cmd == "run" val := input[i].Value contains(val[_], denylist[_]) msg = sprintf("unallowed commands found %s", [val]) }
スキャンを再実行する。
root@cks-master:~/cks-course-environment/course-content/supply-chain-security/static-analysis/conftest/docker# docker run --rm -v $(pwd):/project instrumenta/conftest test Dockerfile --all-namespaces 2 tests, 2 passed, 0 warnings, 0 failures, 0 exceptions