Skip to content

静的解析ツールを使ってHelm Chartを解析する

はじめに

アプリケーションコードと比べて、Helm Chart など IaC のテストコードを書く機会は少ないと思います。そのためレビュー時に、yaml ファイルの設定を見落とす、といった懸念があります。

こういった懸念を解消する手段として静的解析ツールがあります。
業務で Helm Chart を静的解析してみたので、学んだことを書いていきます。

使用する解析ツール

今回使ってみた静的解析ツールは以下の3つです。

  • Trivy
  • Kics
  • Checkov

選定理由は以下の通りです。

  1. 静的解析に API key を前提としないこと CI やローカルで実行することを前提としており、API key の発行や管理で導入のハードルが上がる可能性があるためです。 たとえば、snyk(スニーク) は、CLI を使用するために API key を設定する必要があります。

    Terminal window
    $ helm create example
    $ helm template example --output-dir ./output
    $ snyk iac test output
    `snyk` requires an authenticated account. Please run `snyk auth` and try again.
  2. 解析項目が多いこと 解析項目の数が少ないと、自分たちで解析項目を作成、メンテナンスをする必要があるためです。

    Trivy

    Terminal window
    $ git clone https://github.com/aquasecurity/defsec.git
    $ cd defsec
    $ git checkout v0.90.3
    $ find rules/kubernetes/policies -regex ".*.rego" -not -regex ".*_test.rego" | wc -l
    153
    # cisbenchmarks ディレクトリは apiserver や cni などの解析をする設定のようなので、解析項目数から外してみる
    # https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/cisbenchmarks
    $ find rules/kubernetes/policies -regex ".*.rego" -not -regex ".*_test.rego" -not -regex ".*cisbenchmarks.*" | wc -l
    64

    Kics

    Terminal window
    $ docker run --rm --entrypoint="" checkmarx/kics:latest sh -c "find assets/queries/k8s/ -name *.json" | wc -l
    146

    Checkov

    Terminal window
    $ checkov -l | grep CKV_K8S | cut -d \| -f 3 | uniq | wc -l
    112
  3. カスタムした解析項目を追加できること 組織やチームによっては解析項目を追加したい場合があると思います。その場合、解析項目を自分たちでカスタマイズする必要が出てくる可能性があるためです。

  4. 定期的にメンテナンスがされていること 解析項目の追加や修正が行われていない場合、自分たちで脆弱性などの情報をキャッチアップし、かつ解析項目の追加をしないといけなくなるからです。

  5. eslint のように、コメントを書くと指摘事項を無視することができる機能があること 解析するコードによっては、修正する必要のない項目があり、何もしないと指摘され続けます。
    そのため細かく解析項目を制御したいケースがあると嬉しいと思ったからです。 Using configuration comments - eslint.org

Trivy の概要と特徴

バージョン
Trivy0.43.1
defsecv0.90.3

ドキュメント

Trivy とポリシー

Trivy では、解析項目を「ポリシー」と呼び、Rego 言語でポリシーを定義しています。
具体的なポリシー定義は、aquasecurity/defsecリポジトリに記述されています。
Trivy のバージョンに対応した defsec のバージョンは、Trivyのリポジトリにあるgo.mod に記載されています。

Trivy がサポートしているプラットフォーム

Trivy では以下の IaC をサポートしています。

  • Helm
  • Kustomization
  • Docker
  • Terraform
  • CloudFormation
  • その他

ポリシーの重要度(severity)

各ポリシーには、以下の重要度(severity)が割り当てられています。ポリシーをフィルタリングをコマンドのオプションで設定できます。(例: severity: CRITICAL のみ解析に使用する)

  • CRITICAL
  • HIGH
  • MEDIUM
  • LOW
  • UNKNOWN

Terraform や Helm の解析オプション

とくに Terraform や Helm の解析では、変数を上書きできるオプションが存在します。これにより、特定の値を上書きして解析することが可能です。ただし、Kics にこのようなオプションはありません。

Terraform における変数の上書きに関する詳細は、こちらのドキュメントを参照してください。

Terminal window
$ trivy conf -h
...
Misconfiguration Flags
--helm-set strings specify Helm values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
--helm-set-file strings specify Helm values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)
--helm-set-string strings specify Helm string values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
--helm-values strings specify paths to override the Helm values.yaml files
--include-non-failures include successes and exceptions, available with '--scanners config'
--reset-policy-bundle remove policy bundle
--tf-vars strings specify paths to override the Terraform tfvars files
...

Trivy ができないこと

trivy confコマンドでできないことを紹介します。

  1. 特定のクエリのみ解析に使用することはできない .trivyignore ファイルを作成することで、解析に使用するポリシーを除外できます。しかし、あらかじめ用意されたポリシーを CLI のオプションに指定して解析に使用することはできません By Finding IDs

  2. CLI のオプションで、特定のポリシーを解析から外すことはできない --exclude-policiesのようなオプションはありません。.trivyignore ファイルでしか実現できません。

  3. コメントを使用したポリシーのフィルタリング By Inline Comments のページでは、コードにインラインコメント(#trivy:ignore:)を書くことでポリシーのフィルターが可能である旨が書いてありますが、手元の Helm Chart で試したところ機能しませんでした。

    2023年8月現在、以下の Issue が Open のままでしたが、将来的にはできそうです。 Support Inline Filtering #2961

  4. Helm Chart を解析対象に指定した場合、拡張子 ymlは解析できない 拡張子がyamlなら解析できます

  5. ポリシーの一覧を表示するCLI のコマンドはない

Trivyのポリシーの一覧をテーブル形式で取得する

CLI のオプションが存在しないので、defsec のリポジトリから shell で取り出します。

以下のコマンドは severity: CRITICAL である Kubernetes のポリシーの一覧をマークダウン形式のテーブルで作成できます。

Terminal window
$ git clone https://github.com/aquasecurity/defsec.git
$ cd defsec
$ git checkout v0.90.3
$ git grep --name-only "severity: CRITICAL" -- ':!**/cisbenchmarks/**' rules/kubernetes/policies/ | xargs grep -E "(\s)id: |(\s)avd_id: |title|description" | sed 's/"//g' | awk -F : '{ if($2 == "# avd_id") { printf "[%s](https://github.com/aquasecurity/defsec/tree/v0.90.3/%s)\n",$3 ,$1} else {printf "%s # ", $3} }' | awk -F # '{printf "| %s | %s | %s | %s | \n", $3, $4, $1, $2 }'
出力結果
Terminal window
| KSV044 | [ AVD-KSV-0044](https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/general/any_any.rego) | No wildcard verb and resource roles | [ Check whether role permits wildcard verb on wildcard resource |
| KSV046 | [ AVD-KSV-0046](https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/general/any_resource.rego) | No wildcard resource roles | [ Check whether role permits specific verb on wildcard resources |
| KSV045 | [ AVD-KSV-0045](https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/general/any_verb.rego) | No wildcard verb roles | [ Check whether role permits wildcard verb on specific resources |
| KSV043 | [ AVD-KSV-0043](https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/general/impersonate_privileged_groups.rego) | Do not allow impersonation of privileged groups | [ Check whether role permits impersonating privileged groups |
| KSV050 | [ AVD-KSV-0050](https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/general/manage_kubernetes_rbac_resources.rego) | Do not allow management of RBAC resources | [ An effective level of access equivalent to cluster-admin should not be provided. |
| KSV041 | [ AVD-KSV-0041](https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/general/manage_secrets.rego) | Do not allow management of secrets | [ Check whether role permits managing secrets |
| KSV102 | [ AVD-KSV-0102](https://github.com/aquasecurity/defsec/tree/v0.90.3/rules/kubernetes/policies/general/tiller_is_deployed.rego) | Tiller Is Deployed | [ Check if Helm Tiller component is deployed. |

テーブルのヘッダーは自分で作成する必要がありますが、ヘッダーのすぐ下に、先ほどの git grep コマンドの結果をコピペすると、以下のような見た目になります。

ヘッダー

Terminal window
| id | avd_id | title | description |
|--|--|--|--|

完成した severity: CRITICAL である Kubernetes のポリシー一覧

idavd_idtitledescription
KSV044 AVD-KSV-0044No wildcard verb and resource rolesCheck whether role permits wildcard verb on wildcard resource
KSV046 AVD-KSV-0046No wildcard resource rolesCheck whether role permits specific verb on wildcard resources
KSV045 AVD-KSV-0045No wildcard verb rolesCheck whether role permits wildcard verb on specific resources
KSV043 AVD-KSV-0043Do not allow impersonation of privileged groupsCheck whether role permits impersonating privileged groups
KSV050 AVD-KSV-0050Do not allow management of RBAC resourcesAn effective level of access equivalent to cluster-admin should not be provided.
KSV041 AVD-KSV-0041Do not allow management of secretsCheck whether role permits managing secrets
KSV102 AVD-KSV-0102Tiller Is DeployedCheck if Helm Tiller component is deployed.

Trivy 使い方

Kubernetes のマニフェストは helm を使います。

基本的な使い方

trivy conf <DIR> で実行します。

Terminal window
$ helm create example
$ trivy conf example
“trivy conf example” の出力結果
Terminal window
$ trivy conf example
templates/deployment.yaml (helm)
Tests: 141 (SUCCESSES: 129, FAILURES: 12, EXCEPTIONS: 0)
Failures: 12 (UNKNOWN: 0, LOW: 10, MEDIUM: 2, HIGH: 0, CRITICAL: 0)
MEDIUM: Container 'example' of Deployment 'example' should set 'securityContext.allowPrivilegeEscalation' to false
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
A program inside the container can elevate its own privileges and run as root, which might give the program control over the container and node.
See https://avd.aquasec.com/misconfig/ksv001
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should add 'ALL' to 'securityContext.capabilities.drop'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
The container should drop all default capabilities and add only those that are needed for its execution.
See https://avd.aquasec.com/misconfig/ksv003
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should set 'resources.limits.cpu'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Enforcing CPU limits prevents DoS via resource exhaustion.
See https://avd.aquasec.com/misconfig/ksv011
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
MEDIUM: Container 'example' of Deployment 'example' should set 'securityContext.runAsNonRoot' to true
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
'runAsNonRoot' forces the running image to run as a non-root user to ensure least privileges.
See https://avd.aquasec.com/misconfig/ksv012
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should set 'securityContext.readOnlyRootFilesystem' to true
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
An immutable root file system prevents applications from writing to their local disk. This can limit intrusions, as attackers will not be able to tamper with the file system or write foreign executables to disk.
See https://avd.aquasec.com/misconfig/ksv014
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should set 'resources.requests.cpu'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
When containers have resource requests specified, the scheduler can make better decisions about which nodes to place pods on, and how to deal with resource contention.
See https://avd.aquasec.com/misconfig/ksv015
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should set 'resources.requests.memory'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
When containers have memory requests specified, the scheduler can make better decisions about which nodes to place pods on, and how to deal with resource contention.
See https://avd.aquasec.com/misconfig/ksv016
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should set 'resources.limits.memory'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Enforcing memory limits prevents DoS via resource exhaustion.
See https://avd.aquasec.com/misconfig/ksv018
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should set 'securityContext.runAsUser' > 10000
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Force the container to run with user ID > 10000 to avoid conflicts with the host’s user table.
See https://avd.aquasec.com/misconfig/ksv020
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Container 'example' of Deployment 'example' should set 'securityContext.runAsGroup' > 10000
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Force the container to run with group ID > 10000 to avoid conflicts with the host’s user table.
See https://avd.aquasec.com/misconfig/ksv021
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: Either Pod or Container should set 'securityContext.seccompProfile.type' to 'RuntimeDefault'
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
The RuntimeDefault/Localhost seccomp profile must be required, or allow specific additional profiles.
See https://avd.aquasec.com/misconfig/ksv030
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
LOW: container should drop all
══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Containers must drop ALL capabilities, and are only permitted to add back the NET_BIND_SERVICE capability.
See https://avd.aquasec.com/misconfig/ksv106
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
templates/deployment.yaml:28-46
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
28 - name: example
29 securityContext:
30 {}
31 image: "nginx:1.16.0"
32 imagePullPolicy: IfNotPresent
33 ports:
34 - name: http
35 containerPort: 80
36 protocol: TCP
..
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Tips: docker でも実行できます

Terminal window
$ tree -L 2
.
└── example
├── Chart.yaml
├── charts
├── templates
└── values.yaml
$ docker run --rm -v $(pwd)/example:/charts aquasec/trivy conf --skip-policy-update charts

seveiry: CRITICAL,HIGH のポリシーを使用する

-s, --severity オプションを使用します。

Terminal window
$ trivy conf --severity CRITICAL,HIGH example
2023-07-25T23:36:31.486+0900 INFO Misconfiguration scanning is enabled
2023-07-25T23:36:32.234+0900 INFO Detected config files: 3

Trivy の出力形式を json にする

-f, --format オプションを使用します。

Terminal window
$ trivy conf --severity MEDIUM example -f json --quiet

設定できるフォーマットは以下の通りです。

  • table
  • json
  • template
  • sarif
  • cyclonedx
  • spdx
  • spdx-json
  • github
  • cosign-vuln

Kics の概要と特徴

バージョン
Kicsv1.7.4

Kics - docs.kics.io

Kicsがサポートしているプラットフォーム

Kics では以下の IaC をサポートしています。

  • Terraform
  • Kubernetes
  • Helm
  • Docker
  • Ansible
  • その他

Supported Platforms - docs.kics.io

Kics とクエリ

Kics では解析項目のことをクエリと呼び、Rego 言語で書かれています。
クエリ一覧は Query List から確認できます。

クエリの分類

Kics は Tricy や Checkov と異なり、クエリに severitycategory という2つの分類がある点が特徴です。

--exclude-categories--exclude-severities 2つのオプションがあるので要件に合わせて柔軟にクエリのフィルターを実現できます。

severity

  • High
  • Medium
  • Low
  • Info

category

  • Access Control
  • Availability
  • Backup
  • Best Practices
  • Build Process
  • Encryption
  • Insecure Configurations
  • Insecure Defaults
  • Networking and Firewall
  • Observability
  • Resource Management
  • Secret Management
  • Structure and Semantics
  • Supply-Chain

Query Categories - docs.kics.io

exit コード

Kics は解析した結果 exit コードが変わります。そのため CI で実行に失敗したとき、exit コードに 0 以外が出ます。

コード説明
0結果がない = 異常がない
50severity: High の結果がある
40severity: Medium の結果がある
30severity: Low の結果がある
20severity: Info の結果がある

Exit Status Code - docs.kics.io

クエリをスキップする

以下のように ignore のコメントを書くと、解析時に特定のブロック、ファイルを解析対象から外します。

# kics-scan ignore
resource "google_storage_bucket" "example" {
name = "image-store.com"
location = "EU"
force_destroy = true
}

実際に試してみます。

Helm で example チャートを作成した後、severity: HIGH のクエリを実行します。
すると、Kics からクエリID:5572cc5e-1e4c-4113-92a6-7a8a3bd25e6d を指摘されました。

Terminal window
$ helm cereate example
$ docker run --rm -v $(pwd):/charts checkmarx/kics:latest scan -p /charts/example --exclude-severities info,low,medium --no-progress
...
Files scanned: 4
Parsed files: 3
Queries loaded: 32
Queries failed to execute: 0
------------------------------------
Privilege Escalation Allowed, Severity: HIGH, Results: 1
Description: Containers should not run with allowPrivilegeEscalation in order to prevent them from gaining more privileges than their parent process
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/5572cc5e-1e4c-4113-92a6-7a8a3bd25e6d
[1]: ../../charts/example/templates/deployment.yaml:30
029: {{- toYaml .Values.podSecurityContext | nindent 8 }}
030: containers:
031: - name: {{ .Chart.Name }}
Results Summary:
HIGH: 1
MEDIUM: 0
LOW: 0
INFO: 0
TOTAL: 1

このクエリを無視してもらうため、チャートのテンプレートにコメントを書いてみます。

example/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
spec:
...
template:
...
spec:
...
# kics-scan ignore-block disable=5572cc5e-1e4c-4113-92a6-7a8a3bd25e6d
containers:
...

ignore のコメントを追加したので、もう一度同じコマンドを実行してみます。

Terminal window
$ docker run --rm -v $(pwd):/charts checkmarx/kics:latest scan -p /charts/example --exclude-severities info,low,medium --no-progress
...
Files scanned: 4
Parsed files: 3
Queries loaded: 32
Queries failed to execute: 0
------------------------------------
Results Summary:
HIGH: 0
MEDIUM: 0
LOW: 0
INFO: 0
TOTAL: 0

意図した通り、Kics に指摘されなくなりました。

Using commands on scanned files as comments - docs.kics.io

Kics ができないこと

  1. Mac を開発で使用している場合、Homebrew でインストールできない 厳密には可能ですが、最新バージョンはありません。docker イメージの使用を推奨。 Installation - docs.kics.io

  2. Trivy と違い、Terraform や Helm を解析する場合、オプションで値を上書きすることができない

  3. Trivy と同様 CLI でクエリの一覧を取得する方法はない クエリ一覧は Query List から確認できます。

Kics のクエリ一覧をテーブル形式で取得する

Kics にはドキュメントにクエリ一覧があります。

チームによっては、README やドキュメントツールで、使用するクエリを管理したい場合もあると思ったので、サンプルの shell スクリプトを作成しました。

以下のコマンドは、カテゴリーが Secret Management である Kubernetes のクエリをテーブル形式で出力するコマンドです。

Terminal window
$ for severity in {CRITICAL,HIGH,MEDIUM,LOW}; do docker run --rm --entrypoint="" checkmarx/kics:latest sh -c "find assets/queries/k8s/ -name *.json | xargs cat" | jq --arg severity $severity -r 'select(.category == "Secret Management" and .severity == $severity) | [.id, .id, .severity, .queryName, .descriptionText] | @sh' | xargs printf '[%s](https://docs.kics.io/latest/queries/kubernetes-queries/%s) | %s | %s | %s|\n'; done
出力結果
Terminal window
[ae8827e2-4af9-4baa-9998-87539ae0d6f0](https://docs.kics.io/latest/queries/kubernetes-queries/ae8827e2-4af9-4baa-9998-87539ae0d6f0) | HIGH | Peer Auto TLS Set To True | When using etcd commands, the '--peer-auto-tls' should be set to false|
[98ce8b81-7707-4734-aa39-627c6db3d84b](https://docs.kics.io/latest/queries/kubernetes-queries/98ce8b81-7707-4734-aa39-627c6db3d84b) | HIGH | Auto TLS Set To True | When using etcd commands, the '--auto-tls' should be set to false|
[9391103a-d8d7-4671-ac5d-606ba7ccb0ac](https://docs.kics.io/latest/queries/kubernetes-queries/9391103a-d8d7-4671-ac5d-606ba7ccb0ac) | MEDIUM | Etcd Client Certificate Authentication Set To False | When using etcd commands, the '--client-cert-auth' flag should be defined|
[36a27826-1bf5-49da-aeb0-a60a30c0e834](https://docs.kics.io/latest/queries/kubernetes-queries/36a27826-1bf5-49da-aeb0-a60a30c0e834) | MEDIUM | Kubelet Client Certificate Or Key Not Set | When using kube-apiserver command, the 'kubelet-client-key' and 'kubelet-client-certificate' flags should be set|
[ec18a0d3-0069-4a58-a7fb-fbfe0b4bbbe0](https://docs.kics.io/latest/queries/kubernetes-queries/ec18a0d3-0069-4a58-a7fb-fbfe0b4bbbe0) | MEDIUM | Kubelet Certificate Authority Not Set | When using kube-apiserver command, the 'kubelet-certificate-authority' flag should be set|
[dab4ec72-ce2e-4732-b7c3-1757dcce01a1](https://docs.kics.io/latest/queries/kubernetes-queries/dab4ec72-ce2e-4732-b7c3-1757dcce01a1) | MEDIUM | Service Account Key File Not Properly Set | When using kube-apiserver command, the '--service-account-key-file' flag should be defined|
[b7d0181d-0a9b-4611-9d1c-1ad4f0b620ff](https://docs.kics.io/latest/queries/kubernetes-queries/b7d0181d-0a9b-4611-9d1c-1ad4f0b620ff) | MEDIUM | Etcd Peer Client Certificate Authentication Set To False | When using etcd commands, the '--peer-client-cert-auth' flag should be set to true|
[056ac60e-fe07-4acc-9b34-8e1d51716ab9](https://docs.kics.io/latest/queries/kubernetes-queries/056ac60e-fe07-4acc-9b34-8e1d51716ab9) | MEDIUM | ServiceAccount Allows Access Secrets | Roles and ClusterRoles when binded, should not use get, list or watch as verbs|
[1c621b8e-2c6a-44f5-bd6a-fb0fb7ba33e2](https://docs.kics.io/latest/queries/kubernetes-queries/1c621b8e-2c6a-44f5-bd6a-fb0fb7ba33e2) | MEDIUM | Rotate Kubelet Server Certificate Not Active | The RotateKubeletServerCertificate argument should be true|
[52d70f2e-3257-474c-b3dc-8ad9ba6a061a](https://docs.kics.io/latest/queries/kubernetes-queries/52d70f2e-3257-474c-b3dc-8ad9ba6a061a) | MEDIUM | Kubelet Client Periodic Certificate Switch Disabled | Kubelet argument --rotate-certificates should be true|
[3f5ff8a7-5ad6-4d02-86f5-666307da1b20](https://docs.kics.io/latest/queries/kubernetes-queries/3f5ff8a7-5ad6-4d02-86f5-666307da1b20) | MEDIUM | Etcd Client Certificate File Not Defined | When using kube-apiserver commands, the '--etcd-cafile' flag should be defined|
[c1032cf7-3628-44e2-bd53-38c17cf31b6b](https://docs.kics.io/latest/queries/kubernetes-queries/c1032cf7-3628-44e2-bd53-38c17cf31b6b) | MEDIUM | Shared Service Account | A Service Account token is shared between workloads|
[cb7e695d-6a85-495c-b15f-23aed2519303](https://docs.kics.io/latest/queries/kubernetes-queries/cb7e695d-6a85-495c-b15f-23aed2519303) | MEDIUM | Not Unique Certificate Authority | Certificate Authority should be unique for etcd|
[3d658f8b-d988-41a0-a841-40043121de1e](https://docs.kics.io/latest/queries/kubernetes-queries/3d658f8b-d988-41a0-a841-40043121de1e) | LOW | Secrets As Environment Variables | Container should not use secrets as environment variables|

テーブルのヘッダーは自分で作成する必要がありますが、ヘッダーのすぐ下に、先ほどのコマンドの結果をコピペすると、以下のような見た目になります。

ヘッダー

Terminal window
| id | severity | query name | description |
|--|--|--|--|

完成したカテゴリーが Secret Management である Kubernetes のクエリ一覧

idseverityquery namedescription
ae8827e2-4af9-4baa-9998-87539ae0d6f0HIGHPeer Auto TLS Set To TrueWhen using etcd commands, the ‘—peer-auto-tls’ should be set to false
98ce8b81-7707-4734-aa39-627c6db3d84bHIGHAuto TLS Set To TrueWhen using etcd commands, the ‘—auto-tls’ should be set to false
9391103a-d8d7-4671-ac5d-606ba7ccb0acMEDIUMEtcd Client Certificate Authentication Set To FalseWhen using etcd commands, the ‘—client-cert-auth’ flag should be defined
36a27826-1bf5-49da-aeb0-a60a30c0e834MEDIUMKubelet Client Certificate Or Key Not SetWhen using kube-apiserver command, the ‘kubelet-client-key’ and ‘kubelet-client-certificate’ flags should be set
ec18a0d3-0069-4a58-a7fb-fbfe0b4bbbe0MEDIUMKubelet Certificate Authority Not SetWhen using kube-apiserver command, the ‘kubelet-certificate-authority’ flag should be set
dab4ec72-ce2e-4732-b7c3-1757dcce01a1MEDIUMService Account Key File Not Properly SetWhen using kube-apiserver command, the ‘—service-account-key-file’ flag should be defined
b7d0181d-0a9b-4611-9d1c-1ad4f0b620ffMEDIUMEtcd Peer Client Certificate Authentication Set To FalseWhen using etcd commands, the ‘—peer-client-cert-auth’ flag should be set to true
056ac60e-fe07-4acc-9b34-8e1d51716ab9MEDIUMServiceAccount Allows Access SecretsRoles and ClusterRoles when binded, should not use get, list or watch as verbs
1c621b8e-2c6a-44f5-bd6a-fb0fb7ba33e2MEDIUMRotate Kubelet Server Certificate Not ActiveThe RotateKubeletServerCertificate argument should be true
52d70f2e-3257-474c-b3dc-8ad9ba6a061aMEDIUMKubelet Client Periodic Certificate Switch DisabledKubelet argument —rotate-certificates should be true
3f5ff8a7-5ad6-4d02-86f5-666307da1b20MEDIUMEtcd Client Certificate File Not DefinedWhen using kube-apiserver commands, the ‘—etcd-cafile’ flag should be defined
c1032cf7-3628-44e2-bd53-38c17cf31b6bMEDIUMShared Service AccountA Service Account token is shared between workloads
cb7e695d-6a85-495c-b15f-23aed2519303MEDIUMNot Unique Certificate AuthorityCertificate Authority should be unique for etcd
3d658f8b-d988-41a0-a841-40043121de1eLOWSecrets As Environment VariablesContainer should not use secrets as environment variables

Kics 使い方

Kics の基本的な使い方

kics scan -p <DIRS> で実行します。カンマ区切りで複数ディレクトリを指定できます。

Terminal window
$ helm create example
$ docker run --rm -v $(pwd):/charts checkmarx/kics:latest scan -p /charts/example --no-progress
“kics scan” の出力結果
Terminal window
$ docker run --rm -v $(pwd):/charts checkmarx/kics:latest scan -p /charts --no-progress
.0MO.
OMMMx
;NMX;
... ... ....
WMMMd cWMMM0. KMMMO ;xKWMMMMNOc. ,xXMMMMMWXkc.
WMMMd .0MMMN: KMMMO :XMMMMMMMMMMMWl xMMMMMWMMMMMMl
WMMMd lWMMMO. KMMMO xMMMMKc...'lXMk ,MMMMx .;dXx
WMMMd.0MMMX; KMMMO cMMMMd ' 'MMMMNl'
WMMMNWMMMMl KMMMO 0MMMN oMMMMMMMXkl.
WMMMMMMMMMMo KMMMO 0MMMX .ckKWMMMMMM0.
WMMMMWokMMMMk KMMMO oMMMMc . .:OMMMM0
WMMMK. dMMMM0. KMMMO KMMMMx' ,kNc :WOc. .NMMMX
WMMMd cWMMMX. KMMMO kMMMMMWXNMMMMMd .WMMMMWKO0NMMMMl
WMMMd ,NMMMN, KMMMO 'xNMMMMMMMNx, .l0WMMMMMMMWk,
xkkk: ,kkkkx okkkl ;xKXKx; ;dOKKkc
Scanning with Keeping Infrastructure as Code Secure v1.7.4
Files scanned: 4
Parsed files: 3
Queries loaded: 146
Queries failed to execute: 0
------------------------------------
Root Container Not Mounted Read-only, Severity: LOW, Results: 1
Description: Check if the root container filesystem is not being mounted read-only.
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/a9c2f49d-0671-4fc9-9ece-f4e261e128d0
[1]: ../../charts/example/templates/deployment.yaml:1
Pod or Container Without ResourceQuota, Severity: LOW, Results: 1
Description: Each namespace should have a ResourceQuota policy associated to limit the total amount of resources Pods, Containers and PersistentVolumeClaims can consume
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/48a5beba-e4c0-4584-a2aa-e6894e4cf424
[1]: ../../charts/example/templates/deployment.yaml:1
Pod or Container Without LimitRange, Severity: LOW, Results: 1
Description: Each namespace should have a LimitRange policy associated to ensure that resource allocations of Pods, Containers and PersistentVolumeClaims do not exceed the defined boundaries
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/4a20ebac-1060-4c81-95d1-1f7f620e983b
[1]: ../../charts/example/templates/deployment.yaml:1
No Drop Capabilities for Containers, Severity: LOW, Results: 1
Description: Sees if Kubernetes Drop Capabilities exists to ensure containers security context
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/268ca686-7fb7-4ae9-b129-955a2a89064e
[1]: ../../charts/example/templates/deployment.yaml:1
Missing AppArmor Profile, Severity: LOW, Results: 1
Description: Containers should be configured with an AppArmor profile to enforce fine-grained access control over low-level system resources
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/8b36775e-183d-4d46-b0f7-96a6f34a723f
[1]: ../../charts/example/templates/deployment.yaml:1
Image Without Digest, Severity: LOW, Results: 1
Description: Images should be specified together with their digests to ensure integrity
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/7c81d34c-8e5a-402b-9798-9f442630e678
[1]: ../../charts/example/templates/deployment.yaml:1
Image Pull Policy Of The Container Is Not Set To Always, Severity: LOW, Results: 1
Description: Image Pull Policy of the container must be defined and set to Always
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/caa3479d-885d-4882-9aac-95e5e78ef5c2
[1]: ../../charts/example/templates/deployment.yaml:1
Using Unrecommended Namespace, Severity: MEDIUM, Results: 2
Description: Namespaces like 'default', 'kube-system' or 'kube-public' should not be used
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/611ab018-c4aa-4ba2-b0f6-a448337509a6
[1]: ../../charts/example/templates/serviceaccount.yaml:5
004: metadata:
005: name: {{ include "example.serviceAccountName" . }}
006: labels:
[2]: ../../charts/example/templates/deployment.yaml:1
Service Account Token Automount Not Disabled, Severity: MEDIUM, Results: 1
Description: Service Account Tokens are automatically mounted even if not necessary
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/48471392-d4d0-47c0-b135-cdec95eb3eef
[1]: ../../charts/example/templates/deployment.yaml:1
Seccomp Profile Is Not Configured, Severity: MEDIUM, Results: 1
Description: Containers should be configured with a secure Seccomp profile to restrict potentially dangerous syscalls
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/f377b83e-bd07-4f48-a591-60c82b14a78b
[1]: ../../charts/example/templates/deployment.yaml:1
NET_RAW Capabilities Not Being Dropped, Severity: MEDIUM, Results: 1
Description: Containers should drop 'ALL' or at least 'NET_RAW' capabilities
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/dbbc6705-d541-43b0-b166-dd4be8208b54
[1]: ../../charts/example/templates/deployment.yaml:1
Memory Requests Not Defined, Severity: MEDIUM, Results: 1
Description: Memory requests should be defined for each container. This allows the kubelet to reserve the requested amount of system resources and prevents over-provisioning on individual nodes
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/229588ef-8fde-40c8-8756-f4f2b5825ded
[1]: ../../charts/example/templates/deployment.yaml:1
Memory Limits Not Defined, Severity: MEDIUM, Results: 1
Description: Memory limits should be defined for each container. This prevents potential resource exhaustion by ensuring that containers consume not more than the designated amount of memory
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/b14d1bc4-a208-45db-92f0-e21f8e2588e9
[1]: ../../charts/example/templates/deployment.yaml:1
Container Running With Low UID, Severity: MEDIUM, Results: 1
Description: Check if containers are running with low UID, which might cause conflicts with the host's user table.
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/02323c00-cdc3-4fdc-a310-4f2b3e7a1660
[1]: ../../charts/example/templates/deployment.yaml:32
031: - name: {{ .Chart.Name }}
032: securityContext:
033: {{- toYaml .Values.securityContext | nindent 12 }}
Container Running As Root, Severity: MEDIUM, Results: 1
Description: Containers should only run as non-root user. This limits the exploitability of security misconfigurations and restricts an attacker's possibilities in case of compromise
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/cf34805e-3872-4c08-bf92-6ff7bb0cfadb
[1]: ../../charts/example/templates/deployment.yaml:1
CPU Requests Not Set, Severity: MEDIUM, Results: 1
Description: CPU requests should be set to ensure the sum of the resource requests of the scheduled Containers is less than the capacity of the node
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/ca469dd4-c736-448f-8ac1-30a642705e0a
[1]: ../../charts/example/templates/deployment.yaml:1
CPU Limits Not Set, Severity: MEDIUM, Results: 1
Description: CPU limits should be set because if the system has CPU time free, a container is guaranteed to be allocated as much CPU as it requests
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/4ac0e2b7-d2d2-4af7-8799-e8de6721ccda
[1]: ../../charts/example/templates/deployment.yaml:1
Privilege Escalation Allowed, Severity: HIGH, Results: 1
Description: Containers should not run with allowPrivilegeEscalation in order to prevent them from gaining more privileges than their parent process
Platform: Kubernetes
Learn more about this vulnerability: https://docs.kics.io/latest/queries/kubernetes-queries/5572cc5e-1e4c-4113-92a6-7a8a3bd25e6d
[1]: ../../charts/example/templates/deployment.yaml:1
Results Summary:
HIGH: 1
MEDIUM: 11
LOW: 7
INFO: 0
TOTAL: 19
Scan duration: 3.600578124s

特定のクエリのみ使用する

特定のクエリのみを使用したい場合は、-i, --include-queries stringsオプションを指定します。
カンマ区切りでクエリ ID を指定します。

Terminal window
$ docker run --rm -v $(pwd):/charts checkmarx/kics:latest scan -p /charts/example -i 5572cc5e-1e4c-4113-92a6-7a8a3bd25e6d,4ac0e2b7-d2d2-4af7-8799-e8de6721ccda --no-progress

seveiry: HIGH のクエリを使用する

--exclude-severities を使用します。 オプションは exclude と書いているので、この場合は HIGH 以外の info,low,medium を指定します。

Terminal window
$ docker run --rm -v $(pwd):/charts checkmarx/kics:latest scan -p /charts/example --exclude-severities info,low,medium --no-progress

Kicsの出力形式を json にする

--report-formats strings-o, --output-path string を使用します。
Kics は -o オプションで指定したディレクトリ配下に results.json を自動的に作成します。

コマンドの最後にある /charts はコンテナ内のパスであることに注意

Terminal window
$ docker run --rm -v $(pwd):/charts checkmarx/kics:latest scan -p /charts/example --no-progress --report-formats json -o /charts

Checkov の概要と特徴

バージョン
Checkov2.3.330

Checkov とポリシー

Checkov では、解析項目のことを”ポリシー”と呼びます。
bridgecrew.cloud を利用すると、API key を取得でき、CLI のオプションに設定できます。
Checkov は API key を利用しなくても解析はできます。

インストール方法

pip または homebrew を使ってインストールできます。

Terminal window
$ pip3 install checkov
$ brew install checkov

Installing Checkov - checkov.io

Checkov ができないこと

  1. API key を発行しないとポリシーのフィルターができない Trivy では --severiry HIGH、 Kics では --excluder-severities info,low オプションを使用することで解析項目をフィルタリングできます。
    同じくCheckov にも -c, --check オプションがありますが、このオプションを使用して severity を指定した項目のフィルタリングは API key を設定しないと使用できません。
    Terminal window
    $ checkov --framework helm -d example --skip-path test -c LOW
    [WARNI] Filtering checks by severity is only possible with an API key

Checkov の使い方

Checkov の基本的な使い方

ディレクトリを指定するときは -d <DIR>, --director <DIR> を使用します。

Terminal window
$ helm create example
$ checkov --framework helm -d example

特定のパス配下を解析しない —skip-path

--skip-path <ファイル名、ディレクトリ名>

たとえば、helm createコマンドで作成したチャートにはデフォルトで tests ディレクトリができます。
Checkov はこのディレクトリ配下の yaml も解析対象に入れてしまうため、コマンドを実行するときは対象外にしたいです。

Terminal window
$ tree example -L 2 -d
example
├── charts
└── templates
└── tests

このとき --skip-path を使用して、解析対象から外すことができます。

Terminal window
$ checkov --framework helm -d example --skip-path tests

--skip-path は複数回指定できます。
以下は template/deployment.yaml を解析対象から外した例です。

Terminal window
$ checkov --framework helm -d example --skip-path tests --skip-path deployment

失敗した項目のみ出力する —quiet

Checkov で解析を実行すると、コンソールに大量の結果を出力します。

Terminal window
$ checkov --framework helm -d example --skip-path tests | wc -l
1015

--quiet オプションを設定すると、失敗した結果のみを出力できます。

Terminal window
$ checkov --framework helm -d example --skip-path tests --quiet | wc -l
710

ちなみに --compact オプションを設定するとコードブロックを出力しなくなります。

—compact オプション
Terminal window
$ checkov --framework helm -d example --skip-path tests --quiet --compact
helm scan results:
Passed checks: 73, Failed checks: 15, Skipped checks: 0
Check: CKV_K8S_37: "Minimize the admission of containers with capabilities assigned"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-34.html
Check: CKV_K8S_31: "Ensure that the seccomp profile is set to docker/default or runtime/default"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-29.html
Check: CKV_K8S_20: "Containers should not run with allowPrivilegeEscalation"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-19.html
Check: CKV_K8S_15: "Image Pull Policy should be Always"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-14.html
Check: CKV_K8S_13: "Memory limits should be set"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-12.html
Check: CKV_K8S_40: "Containers should run as a high UID to avoid host conflict"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-37.html
Check: CKV_K8S_22: "Use read-only filesystem for containers where possible"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-21.html
Check: CKV_K8S_28: "Minimize the admission of containers with the NET_RAW capability"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-27.html
Check: CKV_K8S_38: "Ensure that Service Account Tokens are only mounted where necessary"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-35.html
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html
Check: CKV_K8S_23: "Minimize the admission of root containers"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-22.html
Check: CKV_K8S_43: "Image should use digest"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-39.html
Check: CKV_K8S_11: "CPU limits should be set"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-10.html
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: Service.default.release-name-example
File: /example/templates/service.yaml:3-22
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: ServiceAccount.default.release-name-example
File: /example/templates/serviceaccount.yaml:3-12
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html

Checkov のポリシーをフィルタリングする

Terraform や Dockerfile などは、Kics と同じようにコメントを書くことで解析の対象にしない方法があります。
Kubernetes のマニフェストでは annotations に設定を追加することで、解析対象から外すことができます。

解析項目の CKV_K8S_21 は “デフォルトの namespace を使うな” という指摘です。
今回は Deployment のみ、解析に引っかからないようにします。

Terminal window
$ checkov --framework helm -d example --skip-path tests --quiet --compact | grep -A 3 CKV_K8S_21
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: Deployment.default.release-name-example
File: /example/templates/deployment.yaml:3-47
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html
--
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: Service.default.release-name-example
File: /example/templates/service.yaml:3-22
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: ServiceAccount.default.release-name-example
File: /example/templates/serviceaccount.yaml:3-12
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html
example/templates/deployments.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
...
annotations:
checkov.io/skip1: CKV_K8S_21=I don't care about default namespace
spec:
...

意図した通り、Deployment リソースのみ指摘されなくなりました。

Terminal window
$ checkov --framework helm -d example --skip-path tests --quiet --compact | grep -A 3 CKV_K8S_21
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: Service.default.release-name-example
File: /example/templates/service.yaml:3-22
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html
Check: CKV_K8S_21: "The default namespace should not be used"
FAILED for resource: ServiceAccount.default.release-name-example
File: /example/templates/serviceaccount.yaml:3-12
Guide: https://docs.paloaltonetworks.com/content/techdocs/en_US/prisma/prisma-cloud/prisma-cloud-code-security-policy-reference/kubernetes-policies/kubernetes-policy-index/bc-k8s-20.html

Suppressing/skipping - checkov.io

Checkov の出力形式を json にする

Terminal window
$ checkov --framework helm -d example -o json

Checkov のポリシー一覧を取得する

Trivy や Kics と違い Checkov は CLI でポリシーの一覧を取得できます。

一覧を取得するには、-l, --list を指定します。

Terminal window
checkov -l

まとめ

静的解析ツールを触ってみた知ったを書いてみました。実際にツールを触ってみないと良し悪しはわからない、と感じました。
今回紹介した3つはローカル環境でも実施できるツールなので、まずは興味を持ったツールから使い始めることをお勧めします。