Falco can ingest events from sources beyond syscalls, like Kubernetes audit logs or cloud provider logs, by using its plugin system.

# Example Falco configuration snippet
# ... other falco.yaml settings ...
plugins:
  - name: k8s_audit
    library_path: /usr/local/lib/falco/k8s_audit.so
    # For k8s_audit plugin, no specific init_args are usually needed
    # as it typically connects to the Kubernetes API server directly.
    # init_args: {}
  - name: aws_cloudtrail
    library_path: /usr/local/lib/falco/aws_cloudtrail.so
    init_args:
      bucket-name: my-falco-cloudtrail-bucket
      region: us-east-1
      # For IAM role-based authentication, no explicit credentials are needed.
      # If using access keys, they would be passed here or via environment variables.
      # aws_access_key_id: AKIAIOSFODNN7EXAMPLE
      # aws_secret_access_key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# ... other falco.yaml settings ...

This allows Falco to monitor a much wider attack surface than just what happens on the host’s kernel. Imagine detecting a pod being created with a privileged security context, or an unauthorized API call being made to your AWS environment. Falco’s rules engine can then correlate these events with host-level activity or other external events.

Here’s how it works under the hood:

  1. Plugin Interface: Falco defines a C/C++ API that plugins must adhere to. This API specifies functions for initialization, event processing, and deinitialization.
  2. Dynamic Loading: When Falco starts, it reads the plugins section of its configuration file. For each plugin listed, it attempts to load the shared object (.so) file specified by library_path using dlopen.
  3. Initialization: Once loaded, Falco calls an initialization function within the plugin (e.g., falco_plugin_init). This function receives any init_args defined in the configuration. The plugin uses this to set up its connection to the event source (e.g., connect to Kubernetes API, configure AWS SDK).
  4. Event Ingestion: The plugin then starts actively collecting events from its configured source. When an event is received, the plugin formats it into a structure that Falco understands and passes it back to Falco’s core engine via a callback function provided during initialization.
  5. Rule Matching: Falco’s engine receives these events just like it receives syscall events. It parses them and runs them against its loaded rules. If a rule matches, Falco generates an alert.

Let’s say you want to monitor Kubernetes API server audit logs. You’d deploy the k8s_audit plugin.

Configuration (falco.yaml):

plugins:
  - name: k8s_audit
    library_path: /usr/local/lib/falco/k8s_audit.so

Rule Example (rules.yaml):

- rule: Kubernetes Pod Created with Privileged Security Context
  desc: A pod was created with privileged security context enabled. This is a highly sensitive configuration.
  condition: >
    k8s.audit.stage = "ResponseComplete" and
    k8s.audit.verb = "create" and
    k8s.audit.resource = "pods" and
    k8s.audit.response.spec.containers[*].securityContext.privileged = true
  output: "Kubernetes pod created with privileged security context (user: %k8s.audit.user.username, pod: %k8s.audit.response.metadata.name, namespace: %k8s.audit.response.metadata.namespace)"
  priority: critical

When a user makes a POST request to /api/v1/namespaces/default/pods with a pod spec including securityContext.privileged: true, the k8s_audit plugin captures this as an audit event. Falco processes it, and if the rule above is loaded, it triggers an alert.

The init_args are crucial for configuring the plugin’s behavior. For a plugin like aws_cloudtrail, you might specify the S3 bucket where CloudTrail logs are stored and the AWS region. The plugin then uses the AWS SDK to download and parse these logs. Authentication is typically handled via environment variables or IAM roles attached to the EC2 instance or Kubernetes pod running Falco, rather than passing explicit credentials in falco.yaml for security reasons.

A common point of confusion is how events from different sources are distinguished within Falco’s rules. Falco prepends the source name to the field names when events are ingested from plugins. So, a syscall event might have a field like proc.name, while a Kubernetes audit event from the k8s_audit plugin will have fields prefixed with k8s.audit., such as k8s.audit.user.username or k8s.audit.requestURI. This namespace separation prevents conflicts and allows you to write rules that specifically target events from a particular source.

The next challenge is often orchestrating the deployment of these plugins and their associated configurations alongside Falco itself, especially in dynamic Kubernetes environments.

Want structured learning?

Take the full Falco course →