Falco Rulesの利用

## はじめに

前回の記事では、Falcoの概要とその仕組みについて紹介しました。

https://qiita.com/kumo-rn5s/items/6e96d2386ab2366641ef

今回は、Falco Ruleについて詳しく解説します。

## Falco Ruleとは

Falco Ruleは、システムコールやKubernetesのイベントなど、システム上のさまざまなアクティビティを監視し、特定の条件に一致した場合にアラートを生成するためのポリシーです。

### Falco Ruleの利用方法
Falco Ruleは、Falco Controller（Daemon）によって読み込まれ、Rule Engineによって評価されます。
Kubernetes環境でFalcoを利用する場合、事前にFalco Rulesを作成し、設定ファイルに追加する必要があります。

Custom Ruleの追加やDefault Ruleの上書きは、すべてFalcoの設定ファイルを通じて行います。
Falco Ruleの上書きの適用はFileの読み込み順番で決まります。
一般的な順番は以下です。

```yaml
rules_files:
  - /etc/falco/falco_rules.yaml
  - /etc/falco/falco_rules.local.yaml
  - /etc/falco/faclo_plugin_***.yaml
  - /etc/falco/rules.d
```

そのうち、/etc/falco以下のyamlが先に読み込まれます。

Helmなどを利用している場合、Custom Fileは/etc/falco/rules.d/以下に自動的に追加されるので、Plugin/Default Ruleに対する修正として最後に適用されます。
また、小規模な利用は、/etc/falco/rules.dではなく、falco_rules.local.yamlの修正が推奨されています。

![Falco構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618703/f97cf09c-0001-4d6f-ae83-e7090aea822f.png)

詳細な設定方法（Helmなど）については、次回の記事で解説します。

### Falco Ruleの構成

Falco Ruleの本体は、以下の基礎フィールドで構成されています。

- rule: Falco Ruleの名前、識別子
- condition: アラートを生成する条件
- output: アラート発生時の出力メッセージ
- priority: アラートの重要度

また、オプションフィールドとして、以下のものも設定可能です

- tags: Ruleのカテゴリや特性を示すタグ
- desc: Ruleの説明
- enabled: Rule自体の有効化か無効化
- exceptions: 特定の条件下でアラートを生成しないための例外設定

### Falco Rule File(Set)の構成

Falco Rule Fileは、以下の3つの要素で構成されます。

1. Rule: Falco Rule本体

2. Macro: Rule内で再利用可能な条件の断片
   共通の条件として複数のRuleで利用することが可能です
   例えば、以下の`K8s Deployment Created`というRuleでは、`kactivity`などのMacroを複数利用しています。別のRuleでも`kactivity`が多用されています

    ```yaml
    - macro: kcreate
      condition: ka.verb=create
    - macro: kactivity
      condition: (kevt and consider_activity_events)
    - macro: response_successful
      condition: (ka.response.code startswith 2)
    - macro: deployment
      condition: ka.target.resource=deployments
    - rule: K8s Deployment Created
      desc: Detect any attempt to create a deployment
      condition: (kactivity and kcreate and deployment and response_successful)
      # ...
    ```
3. List: 特定の値の集合（RuleやMacro内で参照可能）
   RuleやMacro内で参照できます。
   例えば、`Disallowed K8s User`というRuleでは、事前に許可したユーザ(`eks_allowed_k8s_users`)を定義し、RuleのConditionから除外しました
   ```yaml
   - list: eks_allowed_k8s_users
     items:
     [
          "eks:node-manager",
          "eks:certificate-controller",
          "eks:fargate-scheduler",
          "eks:k8s-metrics",
          "eks:authenticator",
          "eks:cluster-event-watcher",
          "eks:nodewatcher",
          "eks:pod-identity-mutating-webhook",
          "eks:cloud-controller-manager",
          "eks:vpc-resource-controller",
          "eks:addon-manager",
     ]
   - rule: Disallowed K8s User
     desc: Detect any k8s operation by users outside of an allowed set of users.
     condition: kevt and non_system_user and not ka.user.name in (allowed_k8s_users) and not ka.user.name in (eks_allowed_k8s_users)
     # ...
   ```

### Falco RulesのOverride

既存のRuleやMacro、Listは環境や要件に応じてカスタマイズが可能です。
#### Overrideの方法
Custom Rule File内でoverrideセクションを使用することで、既存のList、Macro、Ruleを上書きまたは追加できます。具体的には、以下の2つの操作が可能です：

1. append: 既存のListやMacro、Ruleに新しい値や条件を追加
2. replace: 既存のListやMacro、Ruleを完全に置き換え

前述のk8s_auditの例を利用して、Overrideのやり方を紹介します。

#### conditionのOverride

例えば、K8s Deployment CreatedというRuleに「default Namespace以外」という条件を追加し、既存のRuleをOverrideします。

k8s_auditのRule本文: 
```yaml
- macro: kcreate
  condition: ka.verb=create
- macro: kactivity
  condition: (kevt and consider_activity_events)
- macro: response_successful
  condition: (ka.response.code startswith 2)
- macro: deployment
  condition: ka.target.resource=deployments
- rule: K8s Deployment Created
  desc: Detect any attempt to create a deployment
  condition: (kactivity and kcreate and deployment and response_successful)
  # ...
```

Override時の構文:

```yaml
- rule: K8s Deployment Created
  condition: and ka.target.namespace != default # Appendの場合は追加部分のみを記載
  desc: Detect any attempt to create a deployment except default namespace # Replaceの場合は新しい内容を用意する
  override:
    condition: append
    desc: replace
```

#### listのOverride

例えば、`Disallowed K8s User`というRuleに特定ユーザを許可するようにOverrideします

k8s_auditのRule本文: 
```yaml
- list: eks_allowed_k8s_users
  items:
  [
      "eks:node-manager",
      "eks:certificate-controller",
      "eks:fargate-scheduler",
      "eks:k8s-metrics",
      "eks:authenticator",
      "eks:cluster-event-watcher",
      "eks:nodewatcher",
      "eks:pod-identity-mutating-webhook",
      "eks:cloud-controller-manager",
      "eks:vpc-resource-controller",
      "eks:addon-manager",
  ]
- rule: Disallowed K8s User
  desc: Detect any k8s operation by users outside of an allowed set of users.
  condition: kevt and non_system_user and not ka.user.name in (allowed_k8s_users) and not ka.user.name in (eks_allowed_k8s_users)
 # ...
```

Override時の構文:

```yaml
- list: eks_allowed_k8s_users # List名も識別子です
  items:
  [
    "eks:network-policy-controller",
    "eks:coredns-autoscaler",
    "eks:az-poller"
  ]
  override:
    items: append
```

#### enableのOverride

上記の二つのRuleをdisableにする例です。

```yaml
- rule: K8s Deployment Created
  enable: false
  override:
    enable: replace
- rule: Disallowed K8s User
  enable: false
  override:
    enable: replace
```

## Falco Rulesの難しさ

### 難点1: セキュリティエンジニアの不在

すべての組織にセキュリティ専門のエンジニアがいるわけではありません。
特に小規模なチームでは、DevOpsやSREの特定メンバーがFalcoの導入と運用を兼任するケースが多く、Ruleの最適化に時間を割くのが難しいです。

### 難点2: Ruleの精査とチューニングの負担
Falcoはデフォルトで多数のRuleを提供していますが、すべての環境で適用できるわけではありません。むしろ、多くのRuleが過剰なアラートを生み出し、ノイズが増えてしまうことがあります。

そのため、
- Ruleの内容を理解し、自組織に適したものを選別する
- 不要なRuleを無効化または調整する

といった作業が必要になります。この精査とチューニングには、セキュリティに関する一定の知識が求められるため、導入のハードルが上がります。


## 小規模環境での最適な運用方法

小規模な環境でFalcoを効率的に運用するには、以下の方針を意識すると良いと思います。

**Ruleはできるだけ新規作成せず、既存のものを活用**

特定のセキュリティ問題がない限り、ゼロからRuleを作成するのではなく、既存のRuleを活用しましょう。新しいRuleを増やすと、その分メンテナンスコストも上がります。

既存のRuleの活用方法は以下となります。

1. **必要なRuleのみを抽出して新しいRule Fileを作成**

    組織の要件に合うRuleだけを選別し、新しいRule Fileを作成すると管理しやすくなります。
    例えば、AWS関連のRuleSetを作成したい場合、以下のFalco RulesからAWS関連のRuleを抽出して、新しいRuleSetとして利用することができます。
    1. [AWS CloudTrail Rules](https://github.com/falcosecurity/plugins/blob/main/plugins/cloudtrail/rules/aws_cloudtrail_rules.yaml)
        - (必要に応じて)全て
    1. [Falco Stable Rules](https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml#L1135,L1147)
         - Find AWS Credentials
    1. [Falco Incubating Rules](https://github.com/falcosecurity/rules/blob/main/rules/falco-incubating_rules.yaml#L880,L891)
        - Contact EC2 Instance Metadata Service From Container

2. **既存のRule Fileを導入し、一部のRulesを無効化または調整**
    
    Default Ruleをそのまま使うのではなく、
    - 不要なRuleを無効化
    - 一部のRuleを組織のポリシーに合わせて修正

    することで、誤検知を減らしつつ必要なセキュリティ監視を維持できます。

    例えば、ExternalSecretOperatorを利用している場合、k8s_audit RuleSetの [K8s Secret Get Successfully](https://github.com/falcosecurity/plugins/blob/main/plugins/k8saudit/rules/k8s_audit_rules.yaml#L725,L735) Error Ruleに引っかかってしまいます。
    そのため、以下の修正を加えることでExternalSecretOperatorからのイベントを条件から外すことができます。
    ```yaml
    - rule: K8s Secret Get Successfully
      condition: and not ka.user.name startswith "system:serviceaccount:external-secret-operator:external-secrets-"
      override:
        condition: append
    ```
    また、一部のRuleが要らないであれば、以下の方法でdisableすることもできます。
    ```yaml
    - rule: Create Sensitive Mount Pod
      enabled: false
      override:
         enabled: replace
    - rule: Create HostNetwork Pod
      enabled: false
      override:
        enabled: replace
    - rule: Pod Created in Kube Namespace
      enabled: false
      override:
        enabled: replace
    ```

## EKSでのプラクティス

私のEKS上でのFalco運用経験に基づき、以下のアプローチがある程度効果的だと考えています。

### 1. KubernetesのAuditログを監視する
ほとんどの組織では、KubernetesのAuditログを監視するだけで、基本的なセキュリティニーズを満たせます。

- **k8saudit-eks plugin**を利用
- **Falco Controller(Daemon) DaemonSetは使用しない**
- **k8s_audit Ruleを適用**
- **一部のRuleはListを追加して調整するか、無効化する**

    ```yaml
      # Helm
      customRules:
        k8s_audit_rules_common_override.yaml: |- # customRules以下のFileは自動的に`/etc/falco/rules.d`で作成される
          - rule: Create HostNetwork Pod
            enabled: false
            override:
              enabled: replace
          - rule: Pod Created in Kube Namespace
            enabled: false
            override:
              enabled: replace
      serviceAccount:
        create: true
        annotations:
          - eks.amazonaws.com/role-arn: <IAM Role ARN> # CloudWatch Logsの権限が必要
      driver: # 各ノードの監視が不要であるため
        enabled: false
      collectors: # 各ノードの監視が不要であるため
        enabled: false
      controller:
        kind: deployment # デフォルトはDaemonSet
        deployment:
          replicas: 1
      falco:
        rules_files:
        - /etc/falco/k8s_audit_rules.yaml # k8s_audit_rulesのみ追加
        - /etc/falco/rules.d
        load_plugins: [ k8saudit-eks, json ]
        plugins:
        - name: k8saudit-eks
          library_path: libk8saudit-eks.so
          init_config:
            shift: 10
            polling_interval: 10
            use_async: false
            buffer_size: 500
          open_params: <EKS Cluter名>
        - name: json
          library_path: libjson.so
          init_config: ""
    ```

### 2. コンテナ内部のファイル操作や通信アクティビティの監視
必要に応じて、コンテナ内部の動作も監視対象に含めることができます。

- **FalcoのDefault stable ruleを導入**
- **監視対象が多くなりすぎないよう、重要なRuleを選別**
- **不要なRuleは無効化または調整**


    ```yaml
      # Helm
      customRules:
        falco-sandbox_rules_selected.yaml |- # 選別したSandbox Rules追加
        falco-incubating_rules_selected.yaml |- # 選別したIncubating Rules追加
        falco_rules_override.yaml |- # Stable Rulesの置き換え
      serviceAccount:
        create: true
        annotations:
          - eks.amazonaws.com/role-arn: <IAM Role ARN> # CloudWatch Logsの権限が必要
      falco:
        rules_files:
        - /etc/falco/falco_rules.yaml # Stable Rules追加
        - /etc/falco/k8s_audit_rules.yaml # k8s_audit_rulesのみ追加
        - /etc/falco/rules.d
        load_plugins: [ k8saudit-eks, json ]
        plugins:
        - name: k8saudit-eks
          library_path: libk8saudit-eks.so
          init_config:
            shift: 10
            polling_interval: 10
            use_async: false
            buffer_size: 500
          open_params: <EKS Cluter名>
        - name: json
          library_path: libjson.so
          init_config: ""
    ```

### おすすめのRules

- Stable Rules:
    - [WARNING以上全部](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=stable&priority=WARNING)
- Incubating Rules:
    - [Network Connection outside Local Subnet](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=incubating&priority=WARNING&hash=206cb97c10e38d639e03767466f289e0)
      `namespace_scope_network_only_subnet`対象のContainerになるので、事前の定義が必要
    - [Launch Package Management Process in Container](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=incubating&priority=ERROR&hash=2acaeee8988b0854328b0fbe8c9cf63f)
      特に本番環境では利用した方がいい
    - [Contact EC2 Instance Metadata Service From Container](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=incubating&priority=NOTICE&hash=ba11587ae5bd52a9b3873b053ab19802)
    - [Unexpected UDP Traffic](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=incubating&priority=NOTICE&hash=c56289ee4fb60625edda0baff211e42b)
- Sandbox Rules:
    - [Netcat/Socat Remote Code Execution on Host](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=sandbox&priority=WARNING&hash=370ac9805cc88f9d95595457b14bd706)
- K8s Audit Rules:
    - [Create Privileged Pod](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=WARNING&source=k8s_audit&hash=70ca8c72d4fffc0c2f21c8aa705141fd)
      Gatekeeperとの併用がおすすめです
    - [Attach/Exec Pod](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=NOTICE&source=k8s_audit&hash=9f96af4ff812f6921ca7ef17e047bc7d)
      デフォルトは`NOTICE`レベルですが、本番環境では`ERROR`レベルに上げるのおすすめです
    - [Attach to cluster-admin Role](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=WARNING&source=k8s_audit&hash=ebe83079283dd56ef5073890d897fbb3)
    - [Full K8s Administrative Access](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=WARNING&source=k8s_audit&hash=fdc73e7ea6f6062e87e06bc3a197bbba)
    - [Ingress Object without TLS Certificate Created](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=WARNING&source=k8s_audit&hash=f31d97edc305ecc002c782965508c07c)
    - [Untrusted Node Successfully Joined the Cluster](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=ERROR&source=k8s_audit&hash=35e82364277453c3ce626b5f5c3585fc)
    - [Untrusted Node Unsuccessfully Tried to Join the Cluster](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=WARNING&source=k8s_audit&hash=3d7bdfd28a7d480013104a5ef2723a57 )
    - [Disallowed K8s User](https://thomas.labarussias.fr/falco-rules-explorer/?maturity=all&priority=WARNING&source=k8s_audit&hash=3c7c39a2467726e0ac1db091b3fa729a)
      k8s_audit_rulesの中に、事前に定義済みのリストがあります。例えば、Disallowed K8s UserというRulesは、以下のConditionの中で二つのList `allowed_k8s_users`と`eks_allowed_k8s_users` を利用しています。
      `condition: kevt and non_system_user and not ka.user.name in (allowed_k8s_users) and not ka.user.name in (eks_allowed_k8s_users)`
      既存のListへ信頼できるユーザを追加してもいいし、正規表現で一括除外しても良いです
      
      ```yaml
          - list: allowed_k8s_users
            items:
              [
                "system:serviceaccount:kube-system:argocd-manager"
              ]
            override:
              items: append
          - list: eks_allowed_k8s_users
            items:
              [
                "eks:network-policy-controller",
                "eks:coredns-autoscaler",
                "eks:az-poller"
              ]
            override:
              items: append
          - rule: Disallowed K8s User
            condition: and not ka.user.name regex "^arn:aws:iam::[0-9]+:role/(role-a|role-b)/.+"
            override:
              condition: append
      ```
    
    
## 重要なリンク

### Falco Default Rules

Stable, Incubating, Sandboxの3種類が用意されています。

https://github.com/falcosecurity/rules/tree/main/rules

### Falco PluginのRules

https://github.com/falcosecurity/plugins/tree/main/plugins

### Rulesのブラウザ

DefaultとPlugin Rulesが含まれています。公式ではないため、あくまで参考用です。
自前のRule Setを作成した場合、下記のRepoから自前で運用した方がいいと思います。

https://thomas.labarussias.fr/falco-rules-explorer/

https://github.com/Issif/falco-rules-explorer

### Falco Rules公式ドキュメント

文法のチェックやRulesの一覧を確認するには有用です。

https://falco.org/docs/concepts/rules/

https://falcosecurity.github.io/rules/

### コミュニティRules

https://github.com/CloudDefenseAI/falco_extended_rules/tree/master/rules

### conditionを書く際に役にたつリンク

Conditionは大抵のロジックを表現できます。また、パターンマッチやstartswithなどのComparison operatorsも利用できます。
 
https://falco.org/docs/concepts/rules/conditions/

Conditionで設定するイベントとフィールドは幅広く利用できます。詳細は以下のドキュメントで参照できます。

https://falco.org/docs/reference/rules/supported-events/

https://falco.org/docs/reference/rules/supported-fields/

Pluginで利用するフィールドは、各PluginのREADMEで記載されています。

例えばk8s_audit

https://github.com/falcosecurity/plugins/blob/main/plugins/k8saudit/README.md#supported-fields


## まとめ
本記事では、Falco Ruleの基本構成や運用方法について解説しました。Falcoを適切にカスタマイズすることで、誤検知を減らしつつセキュリティ監視を強化できます。
次回は、FalcoをHelmで導入する方法について詳しく紹介します。