CKSで学ぶKubernetesで使えるセキュリティ関連ツール

# はじめに
CKSを通して学んだKubernetesで使えるセキュリティ関連ツールの概要について振り返ります。
これからCKSに取り組みたい方、Kubernetesのセキュリティツールについてざっくり知りたい方向けです。
CKSの学習方法はたくさん記事があるので取り扱いません。

# 記事を読む前の前提知識
下記のことが頭に入っていることを前提にお話しをします。

## Kubernetesの各コンポーネント
Kubernetesの各種コンポーネントについては下記を参考。
![k8s-arch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3149565/faaa8598-dcaa-2050-515b-79dbd5746ab4.png)

引用元：　https://kubernetes.io/docs/concepts/overview/components/

これらのコンポーネントがセキュアに起動するための推奨オプションとなっているかを確認するツールが存在します。

## Workerノードの内部構成
Kubernetesのワーカノードの内部構成は下記のようになっています。

![workernode.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3149565/e4116239-698a-7cca-9d04-33ae32c8ad04.png)

Workerノード上ではcontainerランタイムが動いていて（この図の場合はcontainerd）、Kernelの機能をsyscallを通して利用します。
Kernelはコンテナでシェアして利用されます。

# セキュリティツール一覧
前項の構成を踏まえ、kubernetesを取り巻くセキュリティツールは下記の通りです。
CKSで取り扱う範囲の中からピックアップしたものであり、もちろん他にもたくさんのプロダクトがあります。

| セキュリティ概要 | セキュリティツール |
|:-:|:-:|
| WorkerノードのOSレベルの設定チェック | CIS Benchmark |
| Kubernetes各コンポーネントの設定チェック | CIS Benchmark(kube-bench) |
| コンテナイメージの脆弱性チェック| trivy |
| コンテナからsyscallの利用制限 | seccomp |
| コンテナからホストOSのfilesystem等の利用制限| AppArmor |
| manifestの定義強制 |　OPA　|
| manifestの静的解析| kubesec |
| Workerノード上での振る舞い検知| falco |

# CIS Benchmark
CIS Benchmarkとは、サーバ設定のベストプラクティスをまとめた資料の集合です。
https://www.cisecurity.org/cis-benchmarks

例えばAWSだと、WorkerノードのOS設定がベストプラクティスとして提示されている内容になっているかをInspectorというサービスでEC2を評価することができます。
https://docs.aws.amazon.com/ja_jp/inspector/latest/user/scanning-cis.html

CIS Benchmarkには、Kubernetesの項目もあり、各コンポーネントの設定のベストプラクティスも公開されています。
これをチェックするには、kube-benchというツールを使います。
https://github.com/aquasecurity/kube-bench

CronJobとしてKubernetes上で実行すると、下記のようにCIS Benchmarkに従っているか否かを判定レポートを出力してくれます。
![kube-bench.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3149565/0386d532-7e70-978a-1483-d1c45674ab3c.png)


# trivy
trivyは、コンテナイメージの脆弱性スキャンしてくれるCLIツールです。
他にも、kubernetes自体やDockerfile等もスキャンできるようです。
参考： https://github.com/aquasecurity/trivy

trivyを実行すると、下記の様にテーブルで該当するCVEとともに重要度を表示してくれます。
```
$ trivy image --sbom-sources rekor otms61/alpine:3.7.3                                                                            [~/src/github.com/aquasecurity/trivy]
2022-09-16T17:37:13.258+0900    INFO    Vulnerability scanning is enabled
2022-09-16T17:37:13.258+0900    INFO    Secret scanning is enabled
2022-09-16T17:37:13.258+0900    INFO    If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2022-09-16T17:37:13.258+0900    INFO    Please see also https://aquasecurity.github.io/trivy/dev/docs/secret/scanning/#recommendation for faster secret detection
2022-09-16T17:37:14.827+0900    INFO    Detected SBOM format: cyclonedx-json
2022-09-16T17:37:14.901+0900    INFO    Found SBOM (cyclonedx) attestation in Rekor
2022-09-16T17:37:14.903+0900    INFO    Detected OS: alpine
2022-09-16T17:37:14.903+0900    INFO    Detecting Alpine vulnerabilities...
2022-09-16T17:37:14.907+0900    INFO    Number of language-specific files: 0
2022-09-16T17:37:14.908+0900    WARN    This OS version is no longer supported by the distribution: alpine 3.7.3
2022-09-16T17:37:14.908+0900    WARN    The vulnerability detection may be insufficient because security updates are not provided

otms61/alpine:3.7.3 (alpine 3.7.3)
==================================
Total: 2 (UNKNOWN: 0, LOW: 0, MEDIUM: 0, HIGH: 0, CRITICAL: 2)

┌────────────┬────────────────┬──────────┬───────────────────┬───────────────┬──────────────────────────────────────────────────────────┐
│  Library   │ Vulnerability  │ Severity │ Installed Version │ Fixed Version │                          Title                           │
├────────────┼────────────────┼──────────┼───────────────────┼───────────────┼──────────────────────────────────────────────────────────┤
│ musl       │ CVE-2019-14697 │ CRITICAL │ 1.1.18-r3         │ 1.1.18-r4     │ musl libc through 1.1.23 has an x87 floating-point stack │
│            │                │          │                   │               │ adjustment im ......                                     │
│            │                │          │                   │               │ https://avd.aquasec.com/nvd/cve-2019-14697               │
├────────────┤                │          │                   │               │                                                          │
│ musl-utils │                │          │                   │               │                                                          │
│            │                │          │                   │               │                                                          │
│            │                │          │                   │               │                                                          │
└────────────┴────────────────┴──────────┴───────────────────┴───────────────┴──────────────────────────────────────────────────────────┘
```
引用元：　https://aquasecurity.github.io/trivy/v0.52/docs/supply-chain/attestation/rekor/

コンテナイメージをスキャンしたい場合は、trivy実行環境にコンテナランタイムが必要です。
プロダクション環境というよりかは、開発環境やローカル環境での実行が望ましいです。

# seccomp
seccompは、コンテナから実行させたくないsyscallを制限することができます。
Podを定義する際に、securityContextでseccompの定義プロファイルを設定することで利用することができます。
参考：　https://kubernetes.io/docs/tutorials/security/seccomp/
```
  securityContext:
    seccompProfile:
      type: Localhost
      localhostProfile: profiles/fine-grained.json
```
一言で言えば簡単ですが、syscallの関数は沢山あり、1つのlinuxコマンドで複数のsyscallを呼び出されます。例えば参考URLの`fine-grained.json`に定義されているように、どれが呼び出されると致命的なのか等把握しながら、素人が1からseccompのプロファイルを書くというのはキツイものがあります。

そこで、KubernetesではSeccompDefaultという機能があり、kubeletでこの機能をONにすると、すべてのPodに対してRuntimeDefaultというseccompプロファイルを充てることができ、危険なsyscallをブロックしてくれます。

# AppArmor
AppArmorは、コンテナからホストOSのfilesystemを操作したり参照することを制御することができます。
参考：　https://kubernetes.io/ja/docs/tutorials/clusters/apparmor/

利用条件
* AppArmorが利用できるコンテナランタイムを使っていること
* すべてのWorkerノードにインストールすること

コンテナに制限したいルールをプロファイルとして定義し、各WorkerノードにインストールしたAppArmorに読み込ませます。
下記は、すべてのファイル書き込みを拒否するプロファイルです。
```
#include <tunables/global>

profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
  #include <abstractions/base>

  file,

  # Deny all file writes.
  deny /** w,
}
```
利用したいプロファイルを、Podのannotationで`container.apparmor.security.beta.kubernetes.io/<コンテナ名>: localhost/<プロファイル名>`のように定義して利用します。

```
apiVersion: v1
kind: Pod
metadata:
  name: hello-apparmor
  annotations:
    container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
  containers:
  - name: hello
    image: busybox
    command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
```


# OPA
Open Policy Agent、略してオーパと読みます。
参考：　https://www.openpolicyagent.org/docs/latest/

ポリシーエンジンであり、リクエストに対してRegoという言語で定義したルールに沿っているかを判定します。
Kubernetesでは、デプロイするmanifestに「特定のレジストリからしかpullできない」、「特定のラベルをつけていないといけない」といった制限をつけることができます。

OPAの中でもkubernetes向けには複数のプロダクトがあります。
* Gatekeeper
* Conftest

GatekeeperはAPI Serverがリクエストを受け取った時にフックし、manifestがルールに沿っているかを判定して、NGであればデプロイを拒否します。
Conftestは、CI/CDに組み込んで、事前にmanifestを評価できるCLIツールです。

# kubesec
kubesecは、kubernetes manifestの静的解析するCLIです。
参考：　https://kubesec.io/

マニフェストを指定してCLIを実行すると、json形式で静的解析結果が表示されます。
jsonにはスコアとPassedかどうかが出力され、スコアが高い程安全、マイナスだとクリティカルな脆弱性があることを示します。

```
[
  {
    "object": "Pod/security-context-demo.default",
    "valid": true,
    "message": "Failed with a score of -30 points",
    "score": -30,
    "scoring": {
      "critical": [
        {
          "selector": "containers[] .securityContext .capabilities .add == SYS_ADMIN",
          "reason": "CAP_SYS_ADMIN is the most privileged capability and should always be avoided"
        },
        {
          "selector": "containers[] .securityContext .runAsNonRoot == true",
          "reason": "Force the running image to run as a non-root user to ensure least privilege"
        },
  // ...
```

スコアが0である場合、Passedと判定されますが、jsonにはadviseとしてより安全にできる設定推奨値が表示されるので、これに従うとスコアが上がります。

```
[
  {
    "object": "Pod/nginx.default",
    "valid": true,
    "message": "Passed with a score of 0 points",
    "score": 0,
    "scoring": {
      "advise": [
        {
          "selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
          "reason": "An immutable root filesystem can prevent malicious binaries being added to PATH and increase attack cost"
        },
  // ...
```

CIツールに導入すると便利そうですね。

# falco
コンテナの侵入・改ざんを検知するツールです。各Workerノードにインストールします。
https://falco.org/docs/

例えばコンテナに`kubectl exec`を使ってshellまたはbashでアクセスされた時に、/var/log/syslogにログが残すといったことができます。

デフォルトのルールセットがあるため、検知ルールをすべて定義する必要はありません。（カスタマイズももちろん可能）
ダッシュボードやメール通知といった機能もKubernetes上にデプロイすれば利用できます。
参考：　https://github.com/falcosecurity/falcosidekick-ui
　　　　https://github.com/falcosecurity/falcosidekick

こちらの解説がとてもイメージしやすいです。
https://www.klab.com/jp/blog/tech/2023/falcokuberenetes.html

# おわりに
CKSに取り組むにあたり、どのツールが何をしてくれるツールなのか学習をすすめるほど違いがわからなくなったりしました。
学び始める手引きとして、参考になれば幸いです。