Skip to content

Instantly share code, notes, and snippets.

@Issif
Last active October 16, 2023 14:38
Show Gist options
  • Save Issif/e17c9294b4e1a76a274db387fe58343c to your computer and use it in GitHub Desktop.
Save Issif/e17c9294b4e1a76a274db387fe58343c to your computer and use it in GitHub Desktop.
Monitor audit-logs with Falco in a Kind cluster
  • Create the audit-policy.yaml.
cat << EOF > audit-policy.yaml
apiVersion: audit.k8s.io/v1 # This is required.
kind: Policy
# Don't generate audit events for all requests in RequestReceived stage.
omitStages:
  - "RequestReceived"
rules:
  # Log pod changes at RequestResponse level
  - level: RequestResponse
    resources:
    - group: ""
      # Resource "pods" doesn't match requests to any subresource of pods,
      # which is consistent with the RBAC policy.
      resources: ["pods", "deployments"]

  - level: RequestResponse
    resources:
    - group: "rbac.authorization.k8s.io"
      # Resource "pods" doesn't match requests to any subresource of pods,
      # which is consistent with the RBAC policy.
      resources: ["clusterroles", "clusterrolebindings"]

  # Log "pods/log", "pods/status" at Metadata level
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  # Don't log requests to a configmap called "controller-leader"
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]

  # Don't log watch requests by the "system:kube-proxy" on endpoints or services
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # core API group
      resources: ["endpoints", "services"]

  # Don't log authenticated requests to certain non-resource URL paths.
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # Wildcard matching.
    - "/version"

  # Log the request body of configmap changes in kube-system.
  - level: Request
    resources:
    - group: "" # core API group
      resources: ["configmaps"]
    # This rule only applies to resources in the "kube-system" namespace.
    # The empty string "" can be used to select non-namespaced resources.
    namespaces: ["kube-system"]

  # Log configmap changes in all other namespaces at the RequestResponse level.
  - level: RequestResponse
    resources:
    - group: "" # core API group
      resources: ["configmaps"]

  # Log secret changes in all other namespaces at the Metadata level.
  - level: Metadata
    resources:
    - group: "" # core API group
      resources: ["secrets"]

  # Log all other resources in core and extensions at the Request level.
  - level: Request
    resources:
    - group: "" # core API group
    - group: "extensions" # Version of group should NOT be included.

  # A catch-all rule to log all other requests at the Metadata level.
  - level: Metadata
    # Long-running requests like watches that fall under this rule will not
    # generate an audit event in RequestReceived.
    omitStages:
      - "RequestReceived"
EOF
  • Create the webhook-config.yaml:
cat << EOF > webhook-config.yaml
apiVersion: v1
kind: Config
clusters:
- name: falco
  cluster:
    server: http://localhost:30007/k8s-audit
contexts:
- context:
    cluster: falco
    user: ""
  name: default-context
current-context: default-context
preferences: {}
users: []
EOF
  • Create the kind-config.yaml:
cat << EOF > kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: ClusterConfiguration
    apiServer:
        # enable auditing flags on the API server
        extraArgs:
          audit-webhook-config-file: /etc/kubernetes/policies/webhook-config.yaml
          audit-policy-file: /etc/kubernetes/policies/audit-policy.yaml
        # mount new files / directories on the control plane
        extraVolumes:
          - name: audit-policies
            hostPath: /etc/kubernetes/policies
            mountPath: /etc/kubernetes/policies
            readOnly: true
            pathType: "DirectoryOrCreate"
  extraMounts:
    # Allow Falco to use devices provided by the kernel module
  - hostPath: /dev
    containerPath: /dev
    # allow Falco to use the Docker unix socket
  - hostPath: /var/run/docker.sock
    containerPath: /var/run/docker.sock
    # mount config files for kind
  - hostPath: ./webhook-config.yaml
    containerPath: /etc/kubernetes/policies/webhook-config.yaml
    readOnly: true
  - hostPath: ./audit-policy.yaml
    containerPath: /etc/kubernetes/policies/audit-policy.yaml
    readOnly: true
EOF
  • Deploy the kind cluster:
kind create cluster -n falco --config kind-config.yaml
  • Create the values.yaml for falco:
cat << EOF > values.yaml
driver:
  enabled: false
  kind: module

collectors:
  enabled: false

controller:
  kind: deployment
  deployment:
    replicas: 1

falcoctl:
  artifact:
    install:
      enabled: true
    follow:
      enabled: true
  config:
    artifact:
      install:
        resolveDeps: false
        refs: [k8saudit-rules:0]
      follow:
        refs: [k8saudit-rules:0]

services:
  - name: k8saudit-webhook
    type: NodePort
    ports:
      - port: 9765 # See plugin open_params
        nodePort: 30007
        protocol: TCP

falco:
  rules_file:
    - /etc/falco/falco_rules.yaml
    - /etc/falco/k8s_audit_rules.yaml
    - /etc/falco/rules.d
  plugins:
    - name: k8saudit
      library_path: libk8saudit.so
      init_config:
        ""
      open_params: "http://:9765/k8s-audit"
    - name: json
      library_path: libjson.so
      init_config: ""
  load_plugins: [k8saudit, json]

tty: true
EOF
  • Deploy falco with Helm:
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco -n falco falcosecurity/falco --create-namespace -f values.yaml
  • Create a fake secret:
kubectl create secret generic db-user-pass --from-literal=username=admin --from-literal=password='S!B\*d$zDsb='
  • Get falco logs:
kubectl logs -f -l app.kubernetes.io/instance=falco -n falco
  • Result:
falco-5f47786987-9hssb falco 14:07:48.050346000: Informational K8s Secret Created (user=kubernetes-admin secret=db-user-pass ns=default resource=secrets resp=201 decision=allow reason=)  
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment