KubesecでKubernetes マニフェストのStatic Analysis

Tetsuya Isogai
13 min readDec 4, 2020

数あるKubernetesのマニフェストファイルに対する静的セキュリティ解析ツールの中からKubesecを紹介。

Kubesecとは

  • Static Analysisツールの一種。Kubernetes リソースに対するSecurity Risk Analysisができる。公式サイトGithubcontrolplaneという会社が中心。
  • Opensource
  • Security Best Practiceにのっとったルールのチェック(Fixed set of rules)
  • バイナリ、Docker Container、Kubectl plugin、Admission Controllerとして動作が可能

Static Analysisとは

ソースコードやテキストファイルをチェックし、ルールに対して適合しているかをチェックし、場合によってはルールを強制する。CI/CDツールの中ではCode Commit前、コンテナイメージビルド前等に使われる。KubesecはKubernetesのマニフェスト(Yaml)をチェックするツール。

Static Analysis ルールの例

  • 常に resource.limit を強制する
  • デフォルトのサービスアカウントを使ってはいけない

これらは一般的には非推奨な事項ではあるものの、ユーザの状況やワークロードの種類によって判別されるものであり、ユーザ自身のポリシーに依存するためプロダクトとして制御されない。そういったギャップをチェックするために有効に使うことができる。

簡易的な使い方(公式サイト上でのYamlチェック)

公式サイトのトップページにあるLive Demoで使い方のイメージがつかめる。まずはhttps://kubesec.io/ にアクセスし、Live Demoの下にある”Submit this Yaml to Kubesec”をクリックする。

すると表示されていたPodのマニフェストに対する性的解析の結果が以下のJsonファイル(Yamlファイルのスキャンの結果)として表示される。


[
{
"object": "Pod/kubesec-demo.default",
"valid": true,
"message": "Passed with a score of 1 points",
"score": 1,
"scoring": {
"passed": [
{
"selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
"reason": "An immutable root filesystem can prevent malicious binaries being added to PATH and increase attack cost",
"points": 1
}
],
"advise": [
{
"selector": ".metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"",
"reason": "Well defined AppArmor policies may provide greater protection from unknown threats. WARNING: NOT PRODUCTION READY",
"points": 3
},
{
"selector": ".spec .serviceAccountName",
"reason": "Service accounts restrict Kubernetes API access and should be configured with least privilege",
"points": 3
},
{
"selector": ".metadata .annotations .\"container.seccomp.security.alpha.kubernetes.io/pod\"",
"reason": "Seccomp profiles set minimum privilege and secure against unknown threats",
"points": 1
},
{
"selector": "containers[] .resources .limits .cpu",
"reason": "Enforcing CPU limits prevents DOS via resource exhaustion",
"points": 1
},
{
"selector": "containers[] .resources .limits .memory",
"reason": "Enforcing memory limits prevents DOS via resource exhaustion",
"points": 1
},
{
"selector": "containers[] .resources .requests .cpu",
"reason": "Enforcing CPU requests aids a fair balancing of resources across the cluster",
"points": 1
},
{
"selector": "containers[] .resources .requests .memory",
"reason": "Enforcing memory requests aids a fair balancing of resources across the cluster",
"points": 1
},
{
"selector": "containers[] .securityContext .capabilities .drop",
"reason": "Reducing kernel capabilities available to a container limits its attack surface",
"points": 1
},
{
"selector": "containers[] .securityContext .capabilities .drop | index(\"ALL\")",
"reason": "Drop all capabilities and add only those required to reduce syscall attack surface",
"points": 1
},
{
"selector": "containers[] .securityContext .runAsNonRoot == true",
"reason": "Force the running image to run as a non-root user to ensure least privilege",
"points": 1
},
{
"selector": "containers[] .securityContext .runAsUser -gt 10000",
"reason": "Run as a high-UID user to avoid conflicts with the host's user table",
"points": 1
}
]
}
}
]

jsonファイルの見方

score: 高いほど良い。kubesecに事前定義されたチェック項目を満たした分だけscoreに加算される。

"object": "Pod/kubesec-demo.default",
"valid": true,
"message": "Passed with a score of 1 points",
"score": 1,

passedフィールドにはチェックにパスした項目(Scoreに加算されることとなった推奨される And 設定済みセキュリティ設定)が表示される。

"passed": [
{
"selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
"reason": "An immutable root filesystem can prevent malicious binaries being added to PATH and increase attack cost",
"points": 1

advice フィールドには追加で設定すべきセキュリティ設定、それを設定することで得られるポイントが表示される。

"advise": [
{
"selector": ".metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"",
"reason": "Well defined AppArmor policies may provide greater protection from unknown threats. WARNING: NOT PRODUCTION READY",
"points": 3
},
{
"selector": ".spec .serviceAccountName",
"reason": "Service accounts restrict Kubernetes API access and should be configured with least privilege",
"points": 3
},
...

実際の環境での使い方(Docker イメージの場合)

手元のKinDで実行。結果は一部省略しているところもあり。Docker イメージ以外の使い方はこちらのGithubを参照。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.3",...
Server Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.1",...
$ k get node
NAME STATUS ROLES AGE VERSION
kind-control-plane Ready master 17h v1.19.1
kind-worker Ready <none> 17h v1.19.1
kind-worker2 Ready <none> 17h v1.19.1
kind-worker3 Ready <none> 17h v1.19.1
  1. 以下コマンドでPodを作るためのYamlを作る。
$ kubectl run pod --image=nginx --dry-run=client -oyaml |tee pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod
name: pod
spec:
containers:
- image: nginx
name: pod
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
$ ls pod.yaml
pod.yaml

2. pod.yamlをkubesec コンテナイメージに食わせて実行する。(実行するためのkubesecコンテナイメージはこちらから最新の情報をチェック)

$ docker run -i kubesec/kubesec:512c5e0 scan /dev/stdin <pod.yaml
[
{
"object": "Pod/pod.default",
"valid": true,
"message": "Passed with a score of 0 points",
"score": 0,
"scoring": {
"advise": [
{
"selector": "containers[] .resources .requests .cpu",
"reason": "Enforcing CPU requests aids a fair balancing of resources across the cluster"
},
{
"selector": ".metadata .annotations .\"container.apparmor.security.beta.kubernetes.io/nginx\"",
"reason": "Well defined AppArmor policies may provide greater protection from unknown threats. WARNING: NOT PRODUCTION READY"
...

何もセキュリティ対策を施さない状態ではScoreが0のまま。表示されたアドバイスに従い、試しに一つセキュリティ設定を足してみる。(securityContext.readOnlyRootFilesystem)

$ cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod
name: pod
spec:
containers:
- image: nginx
name: pod
resources: {}
securityContext:
readOnlyRootFilesystem: true
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}

再度実行するとスコアが1加算された状態になる。

$ docker run -i kubesec/kubesec:512c5e0 scan /dev/stdin <pod.yaml
[
{
"object": "Pod/pod.default",
"valid": true,
"message": "Passed with a score of 1 points",
"score": 1,

まとめ

Kubernetesにデプロイする前のYamlファイルをチェックするため、現在動いているクラスタに影響を与えずにセキュリティのチェックができる。結果として表示されるスコアやadviceの結果を用いること、またそれを実行する手段も複数用意されていることから、遵守させたいポリシーがYamlに記載されているかどうかのチェックも比較的簡単にCI/CDツールに組み込みすることができる。

セキュリティ対策は「これをやったら問題なし」という事はなく、多少防御によって守ることが基本。簡単に始められてある程度網羅的にチェックをしてくれるkubesec、興味があったら使ってみてはどうでしょうか。

--

--

Tetsuya Isogai

Working at Microsoft/Cloud Solution Architect/Azure Core Infra