Falcoをyumで入れる場合のPodとの連携

Falcoをyumで入れた場合に、Helmで入れたekscloudwatchfalcosidekickとの連携を確認したメモ。

クラスターの作成

コンポーネント バージョン
EKS 1.19
プラットフォームバージョン eks.5
Falco 0.29.1
falcosidekick 2.23.1
falcosidekickチャート 0.3.10
ekscloudwatch ekscloudwatch-0.3

クラスターの準備

1.19でクラスターを作成する。ノードなしで作成する。

cat << EOF > cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: falco
  region: ap-northeast-1
  version: "1.19"
vpc:
  cidr: "10.2.0.0/16"

availabilityZones:
  - ap-northeast-1a
  - ap-northeast-1c

cloudWatch:
  clusterLogging:
    enableTypes: ["*"]

iam:
  withOIDC: true
EOF
eksctl create cluster -f cluster.yaml

ノードグループを作成する。

cat << "EOF" > managed-ng-2.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: falco
  region: ap-northeast-1

managedNodeGroups:
  - name: managed-ng-2
    minSize: 2
    maxSize: 2
    desiredCapacity: 2
    privateNetworking: true
    preBootstrapCommands:
      - |
        #!/bin/bash

        set -o errexit
        set -o pipefail
        set -o nounset

        rpm --import https://falco.org/repo/falcosecurity-3672BA8F.asc
        curl -s -o /etc/yum.repos.d/falcosecurity.repo https://falco.org/repo/falcosecurity-rpm.repo
        yum -y install kernel-devel-$(uname -r)
        yum -y install falco
        sed -i -e '/syslog_output/ { N; s/enabled: true/enabled: false/ }' /etc/falco/falco.yaml
        systemctl enable falco
        systemctl start falco
EOF
eksctl create nodegroup -f managed-ng-2.yaml

falcosidekickの導入

ノードポートを指定してfalcosidekickを導入する。

$ helm search repo falco
NAME                            CHART VERSION   APP VERSION DESCRIPTION
falcosecurity/falco             1.15.3          0.29.1      Falco
falcosecurity/falco-exporter    0.5.1           0.5.0       Prometheus Metrics Exporter for Falco output ev...
falcosecurity/falcosidekick     0.3.10          2.23.1      A simple daemon to help you with falco's outputs
stable/falco                    1.1.8           0.0.1       DEPRECATED - incubator/falco
helm upgrade --install falcosidekick falcosecurity/falcosidekick -n falco --create-namespace \
  --set webui.enabled=true \
  --set service.type=NodePort

NodePortの番号を確認する。

$ k -n falco get svc
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
falcosidekick      NodePort    172.20.139.21    <none>        2801:31490/TCP   5d1h
falcosidekick-ui   ClusterIP   172.20.168.108   <none>        2802/TCP         5d1h

ノードにSSMでログインし、/etc/falco/falco.yamlを修正する。

# Whether to output events in json or text
json_output: true

http_output:
  enabled: true
  url: "http://localhost:31490/"

なお、このようにNodePort経由ではなく、ClusterIPを直接指定してもいいかも知れない。

この修正は新しいノードに反映されないので、恒久化するための対応が必要。

  • ユーザーデータでsedで頑張る
  • S3に置いて、ユーザーデータでs3からダウンロードするようにする

ekscloudwatchの導入

ConfigMapを作成する。

cat << "EOF" > ekscloudwatch-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ekscloudwatch-config
  namespace: falco
data:
  # Required: Endpoint to forward audit events to, such as Sysdig Secure agent
  # The agent must expose a k8s audit server (k8s_audit_server_port must be configured in the agent as well)
  endpoint: "http://falco:8765/k8s-audit"

  # Required: Cloudwatch polling interval
  cw_polling: "1m"

  # Required: CloudWatch query filter
  cw_filter: '{ $.sourceIPs[0] != "::1" && $.sourceIPs[0] != "127.0.0.1" }'

  # Optional: both the EKS cluster name and region must be set
  # This can be omitted if the EC2 instance can perform the ec2metadata and ec2:DescribeInstances action
  cluster_name: "falco"
  aws_region: "ap-northeast-1"
EOF

ここのendpoint: "http://falco:8765/k8s-audit"はDeploymentでENDPOINT環境変数を定義するので使わない。

ConfiMapを作成する。

k apply -f ekscloudwatch-config.yaml

ServiceAccountを作成する。

k -n falco create sa eks-cloudwatch

IRSAで必要な権限を与える。

eksctl create iamserviceaccount \
    --name eks-cloudwatch \
    --namespace falco \
    --cluster ekscloudwatch \
    --attach-policy-arn arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess \
    --override-existing-serviceaccounts \
    --approve

deployment.yamlもNamespaceを修正し、ServiceAccoutNameを指定する。ノードのIPを取得して環境変数でエンドポイントで設定するようにする。

cat << EOF > ekscloudwatch-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: eks-cloudwatch
  namespace: falco
spec:
  minReadySeconds: 5
  replicas: 1
  selector:
    matchLabels:
      app: eks-cloudwatch
  template:
    metadata:
      labels:
        app: eks-cloudwatch
    spec:
      serviceAccountName: eks-cloudwatch
      containers:
        - image: sysdiglabs/k8sauditlogforwarder:ekscloudwatch-0.3
          imagePullPolicy: Always
          name: eks-cloudwatch-container
          env:
            - name: NODEIP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: ENDPOINT
              value: "http://$(NODEIP):8765/k8s-audit"
            - name: CLUSTER_NAME
              valueFrom:
                configMapKeyRef:
                  name: ekscloudwatch-config
                  key: cluster_name
            - name: AWS_REGION
              valueFrom:
                configMapKeyRef:
                  name: ekscloudwatch-config
                  key: aws_region
            - name: CW_POLLING
              valueFrom:
                configMapKeyRef:
                  name: ekscloudwatch-config
                  key: cw_polling
            - name: CW_FILTER
              valueFrom:
                configMapKeyRef:
                  name: ekscloudwatch-config
                  key: cw_filter
EOF

デプロイする。

k apply -f ekscloudwatch-deployment.yaml

Podが動いていることを確認する。

$ k -n falco get po
NAME                                READY   STATUS    RESTARTS   AGE
eks-cloudwatch-74c984f494-ztkrq     1/1     Running   0          40s
falcosidekick-586c44fc5c-8n89g      1/1     Running   0          40s
falcosidekick-586c44fc5c-p254p      1/1     Running   0          40s
falcosidekick-ui-5d6b4bd557-s4k7t   1/1     Running   0          40s

確認

ポートフォワードでfalcosidekick-uiにアクセスする。

k -n falco port-forward svc/falcosidekick-ui 2802

aws-auth ConfigMapを適当に修正してみる。こちらを参照。

k -n kube-system edit cm aws-auth

通知されない!これはFalcoルール作る必要がありそう。

ConfigMapを作成してみる。

cat << "EOF" > my-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
  namespace: default
data:
  ui.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
  access.properties: |
    aws_access_key_id = MY-ID
    aws_secret_access_key = MY-KEY
EOF
k apply -f my-config.yaml

これは通知された。

f:id:sotoiwa:20210719094159p:plain

Falco設定の永続化

ノードが再起動してもいいように、Falcoの設定をS3に置く。

バケットを作成する。

ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
BUCKET_NAME="eks-falco-config-${ACCOUNT_ID}"
AWS_REGION=$(aws configure get region)
aws s3api create-bucket \
    --bucket ${BUCKET_NAME} \
    --region ${AWS_REGION} \
    --create-bucket-configuration LocationConstraint=${AWS_REGION}

バージョニングとSSE-S3でのバケットのデフォルト暗号化を有効にする。要件に応じて設定する。

aws s3api put-bucket-versioning \
  --bucket ${BUCKET_NAME} \
  --versioning-configuration Status=Enabled
aws s3api put-bucket-encryption \
    --bucket ${BUCKET_NAME} \
    --server-side-encryption-configuration '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"AES256"}}]}'

このバケットへのアクセスを許可するポリシーを作成する。

cat <<EOF > eks-falco-config-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::${BUCKET_NAME}",
                "arn:aws:s3:::${BUCKET_NAME}/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        }
    ]
}
EOF
aws iam create-policy \
    --policy-name eks-falco-config-policy \
    --policy-document file://eks-falco-config-policy.json

このポリシーをインスタンスロールにアタッチする。

また、一時的にAmazonS3FullAccessもアタッチする。

インスタンスからS3にファイルをアップロードする。

ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
BUCKET_NAME="eks-falco-config-${ACCOUNT_ID}"
aws s3 cp falco.yaml s3://${BUCKET_NAME}/

アップロードできたらAmazonS3FullAccessをデタッチする。

ダウンロードできることを確認する。

aws s3 cp s3://${BUCKET_NAME}/falco.yaml /tmp/

ノードグループを作成する。

ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
cat << EOF > managed-ng-1.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: falco
  region: ap-northeast-1

managedNodeGroups:
  - name: managed-ng-1
    minSize: 2
    maxSize: 2
    desiredCapacity: 2
    privateNetworking: true
    iam:
      attachPolicyARNs:
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::${ACCOUNT_ID}:policy/eks-falco-config-policy
EOF
cat << "EOF" >> managed-ng-1.yaml
    preBootstrapCommands:
      - |
        #!/bin/bash

        set -o errexit
        set -o pipefail
        set -o nounset

        rpm --import https://falco.org/repo/falcosecurity-3672BA8F.asc
        curl -s -o /etc/yum.repos.d/falcosecurity.repo https://falco.org/repo/falcosecurity-rpm.repo
        yum -y install kernel-devel-$(uname -r)
        yum -y install falco
        ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
        BUCKET_NAME="eks-falco-config-${ACCOUNT_ID}"
        aws s3 cp s3://${BUCKET_NAME}/falco.yaml /etc/falco/falco.yaml
        systemctl enable falco
        systemctl start falco
EOF
eksctl create nodegroup -f managed-ng-1.yaml

ノードが作成できたら古いノードグループを削除する。

eksctl delete nodegroup --cluster falco managed-ng-2

新しい−ノードを確認する。

$ k get node
NAME                                             STATUS   ROLES    AGE     VERSION
ip-10-2-112-95.ap-northeast-1.compute.internal   Ready    <none>   5m58s   v1.19.6-eks-49a6c0
ip-10-2-75-246.ap-northeast-1.compute.internal   Ready    <none>   5m59s   v1.19.6-eks-49a6c0

ポートフォワードでfalcosidekick-uiにアクセスする。

k -n falco port-forward svc/falcosidekick-ui 2802

ConfigMapを作ってみる。

kubectl create configmap my-config-2 --from-literal=key1=config1 --from-literal=key2=config2

しばし待ち、だいたい1分位で通知されることを確認する。

f:id:sotoiwa:20210720184141p:plain