🌊

GKE で Falco を動かしてみる

2024/06/12に公開

こんにちは、SRE 部所属の松島です。

本記事ではクラウドネイティブのランタイム監視ツールである Falco を GKE 上で動かしたのち、実運用するにあたって気になる点を考えてみたいと思います。

Falco とは

Falco とは、Sysdig によって開発された、CNCF のプロジェクトの一つであるクラウドネイティブのランタイム監視ツールです。
VM やコンテナ、Kubernetes ノードで発生した異常を Falco ルールによって検知することができます。
攻撃検知だけでなく、ファイル監視なども可能なことから、各種セキュリティコンプライアンスへの対応にも有効なツールとなっています。

公式サイトはこちらです。

なお、CNCF での成熟度は graduated となっています。
CKS の試験でも Falco を利用した異常検出に関する問いが出題されており、十分な実績のあるツールだと捉えることができます。

GKE で動かしてみる

注意点

GKE Autopilot では Falco を利用できないことにご注意ください。
本手順では、GKE Standard に Falco をインストールします。(なお、2024/05/04 時点では Cloud Run でも利用不可です)

0. 下準備

下記を準備しておきます。詳しい手順は趣旨から外れるため、割愛します。

  • GKE Standard クラスタを作成
  • 静的グローバル IP アドレス falco-sidekick を作成

1. GKE へのインストール

Falco 公式のこちらの記事を参考に、Helm を使ってインストールします。
また、Falco での 検出結果を閲覧、および外部連携することができるツールである Falco Sidekick も、こちらを参考に併せてインストールし、Web UI を有効化します。

helm repo add falcosecurity \
https://falcosecurity.github.io/charts && \
helm repo update

kubectl create namespace falco

helm install falco \
-n falco \
--set tty=true \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.webui.enabled=true \
falcosecurity/falco 

次のように表示されれば成功です。

NAME: falco
LAST DEPLOYED: Fri May  3 23:23:24 2024
NAMESPACE: falco
STATUS: deployed
REVISION: 1
NOTES:
Falco agents are spinning up on each node in your cluster. After a few
seconds, they are going to start monitoring your containers looking for
security issues.
No further action should be required.

Falco 本体の DaemonSet と、Falco Sidekick 用の Deployment が立ち上がっていることを確認できました。

$ kubectl get all -n falco
NAME                                       READY   STATUS    RESTARTS   AGE
pod/falco-falcosidekick-7467cbf888-h4zt2   1/1     Running   0          2m42s
pod/falco-falcosidekick-7467cbf888-m56dh   1/1     Running   0          2m42s
pod/falco-hpc96                            2/2     Running   0          2m42s

NAME                          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
service/falco-falcosidekick   ClusterIP   10.155.169.233   <none>        2801/TCP,2810/TCP   2m43s

NAME                   DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/falco   1         1         1       1            1           <none>          2m42s

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/falco-falcosidekick   2/2     2            2           2m42s

NAME                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/falco-falcosidekick-7467cbf888   2         2         2       2m42s

Falco Sidekick の Web UI にアクセスするため、Ingress も併せて用意します。

ingress.yaml
apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: falco-sidekick
  namespace: falco
spec:
  redirectToHttps:
    enabled: true

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: falco-sidekick
  namespace: falco
  annotations:
    kubernetes.io/ingress.global-static-ip-name: falco-sidekick
    networking.gke.io/managed-certificates: falco-sidekick
spec:
  rules:
    - host: "<Falco Sidekick 用ホスト名>"
      http:
        paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: falco-falcosidekick-ui
              port:
                number: 2802

---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
  name: falco-sidekick
  namespace: falco
spec:
  domains:
    - <Falco Sidekick 用ホスト名>

これを apply し、URL にアクセス、ユーザー、パスワード共に admin でログインできれば OK です。

login.png
dashboard.png

2. 検出確認

Falco には充実したデフォルトルールセットが用意されているため、インストール直後から異常検知を行うことができます。
デフォルトのルールセットの内容はこちらをご参照ください。

早速この中の「Terminal shell in container」と「Drop and execute new binary in container」を試してみます。
適当な Pod を立て、シェルを立ち上げたのち、Nginx をインストールしてみます。

$ kubectl run test --image=ubuntu -it /bin/sh

# apt update && apt install nginx

検出結果は Falco のログとして出力されるため、Cloud Logging を確認すると、検出された旨のログが見つかりました。

detect-result1.png

Falco Sidekick の方でも検知されていることを確認できました。

detect-result2.png

3. カスタムルールの追加

Falco ではカスタムルールを追加することで、任意の動作の検知を行うことができます。
デフォルトのルールでは足りない場合や、デフォルトルールの動作を改造したい場合などに有用です。

ここでは、ノードのファイル変更と root への昇格の監視を行なってみたいと思います。
次のようにファイルを作成し、helm upgradeでカスタムルールを反映させます。

additional-rules.yaml
customRules:
  additional-rules.yaml: |-
    - rule: Change sensitive files
      desc: >
        Capture sensitive file changes
      condition: > 
        open_write
        and sensitive_files
      output: Sensitive file was changed (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty %container.info)
      priority: WARNING
    - rule: Execute command of privileges or as a different user
      desc: >
        Capture commands of privileges or as a different user
      condition: > 
        evt.type = execve
        and proc.name in (userexec_binaries)
      output: Someone became root (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty %container.info)
      priority: WARNING
カスタムルール追加コマンド
helm upgrade falco \
-n falco \
--set tty=true \
--set driver.kind=ebpf \
--set falcosidekick.enabled=true \
--set falcosidekick.webui.enabled=true \
-f additional-rules.yaml \
falcosecurity/falco 

この状態で GKE ノードに SSH し、sudo で root に昇格したのち、/etc/sudoers を改変してみると、次のようにそれぞれの操作が検知されることを確認できました。(実際にはノードに SSH しただけで複数異常検知が行われることも併せて確認できました。)

detect-result3.png

なお、Falco ルールの詳細な記法はこちらをご参照ください

運用を考える

ここまで試してきた中で、実運用するにあたって気になったポイントをいくつか検討してみます。

ルールの更新

例えば不要なアラートを検知しないよう除外するなど、特に運用し始めた直後は検知ルールを変更することが多いと思いますが、検知ルールは変更フローを厳格に運用したいところです。
GitHub 上のリポジトリで管理の上、ArgoCD で Helm チャートを管理するなど、GitOps 的に画一的なフローでカスタムルールを適用できることが望ましいと考えます。

例えば、下記のような ArgoCD Application を作成することで、カスタムルールを GitOps で運用することができます

ArgoCD Application 設定例
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: falco
  namespace: argocd
spec:
  project: otameshi
  sources:
  - chart: falco
    repoURL: https://falcosecurity.github.io/charts
    targetRevision: "4.3.0"
    helm:
      releaseName: falco
      parameters:
      - name: "tty"
        value: "true"
      - name: "driver.kind"
        value: "ebpf"
      - name: "falcosidekick.enabled"
        value: "true"
      - name: "falcosidekick.webui.enabled"
        value: "true"
      valueFiles: 
      - $values/<カスタムルール配置パス>/<カスタムルールファイル名>.yaml
  - repoURL: <カスタムルール配置 GitHubリ ポジトリ>
    targetRevision: HEAD
    ref: values
  destination:
    server: "https://kubernetes.default.svc"
    namespace: falco

アラートへの対応

今回は Web UI のみを設定しましたが、Falco Sidekick を使うことで Slack への通知などを行うことができますので、緊急度の高いものは通知を設定するのが良いと考えられます。
Google Cloud の機能を利用すれば、Falco のログをトリガーに、Cloud Logging からログアラートで通知する方法も取ることができます。

また、発生したアラートに対して調査や対応記録をつける必要がある場合は、Falco Sidekick から Pub/Sub や Cloud Functions に連携することでチケット作成を自動化するなどの対応が考えられます。

SIEM など、他に外部のログ監視ツールを運用している場合はとりあえずそちらに飛ばしておき、外部ツール側で通知を仕分けるような実装も可能だと思います。

WebUI の管理

セキュリティに関する情報であるため、Ingress や Gateway でパブリック IP アドレスで Web UI を公開する場合、Cloud Armor で IP アドレス制限をかける、IAP で保護するなど何らかの保護を行うのが望ましいと考えられます。

また、ユーザーおよびパスワードの管理ですが、私の調べた範囲だと Helm の value として ID:password を指定する方法しか見つかりませんでした。
ユーザーが多人数になる場合、ID とパスワードの管理が難しくなるため、共用アカウントを利用しつつも IAP を併せて利用することでアクセス制限および監査を行う方法も考えられます。

追加情報

Google Cloud の監査ログを Falco で扱う機能がこちらの記事で紹介されています。
こちらもまた機会があれば試してみたいと思います。

おわりに

本記事では Falco とその利用方法、運用上の検討事項を紹介しました。
プリセットのルールが充実しているため少ない手間で GKE クラスタの異常検知を始めることができますので、是非お試しください。

Discussion