diff --git a/events/README.md b/events/README.md index 9f6d0151..7bdd9ece 100644 --- a/events/README.md +++ b/events/README.md @@ -42,6 +42,21 @@ var _ = events.Register( ) ``` +### Handling Unsupported Contexts/Prerequisites + +When developing actions for the event-generator, it's essential to consider whether the action is applicable to the current execution context. For example, certain actions might be intended to run exclusively within containers or specific environments. Actions that require a specific context or prerequisite to execute successfully should skip the action by return events.ErrSkipped when the necessary conditions are not met For example: + +```golang +func UserMgmtBinaries(h events.Helper) error { + if h.InContainer() { + return &events.ErrSkipped{ + Reason: "'User mgmt binaries' is excluded in containers", + } + } + return h.SpawnAsWithSymlink("vipw", "helper.ExecLs") +} +``` + ### Behavior Running an *action* should be an idempotent operation in the sense that it should not have additional effects if it is called more than once. For this reason, *actions* should revert any operation that changed the state of the system (eg. if a file is created, then it has to be removed). For example: diff --git a/events/syscall/change_namespace_privileges_via_unshare.go b/events/syscall/change_namespace_privileges_via_unshare.go index b58f3385..7ff26608 100644 --- a/events/syscall/change_namespace_privileges_via_unshare.go +++ b/events/syscall/change_namespace_privileges_via_unshare.go @@ -18,25 +18,27 @@ limitations under the License. package syscall import ( - "os/exec" + "os/exec" - "github.com/falcosecurity/event-generator/events" + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register( ChangeNamespacePrivilegesViaUnshare, - events.WithDisabled(), // this rules is not included in falco_rules.yaml (stable rules), so disable the action + events.WithDisabled(), // this rules is not included in falco_rules.yaml (stable rules), so disable the action ) func ChangeNamespacePrivilegesViaUnshare(h events.Helper) error { - if h.InContainer() { - cmd := exec.Command("unshare") - - h.Log().Infof("Change namespace privileges via unshare") - - if err := cmd.Run(); err != nil { - return err - } + if h.InContainer() { + cmd := exec.Command("unshare") + + h.Log().Infof("Change namespace privileges via unshare") + + if err := cmd.Run(); err != nil { + return err + } + } + return &events.ErrSkipped{ + Reason: "'Change Namespace Privileges Via Unshare' is applicable only to containers.", } - return nil } diff --git a/events/syscall/contact_cloud_metadata_service_from_container.go b/events/syscall/contact_cloud_metadata_service_from_container.go index 1187dd3a..511b2b87 100644 --- a/events/syscall/contact_cloud_metadata_service_from_container.go +++ b/events/syscall/contact_cloud_metadata_service_from_container.go @@ -18,29 +18,32 @@ limitations under the License. package syscall import ( - "os/exec" - "github.com/falcosecurity/event-generator/events" + "os/exec" + + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register( - ContactCloudMetadataServiceFromContainer, - events.WithDisabled(), // this rule is not included in falco_rules.yaml (stable rules), so disable the action + ContactCloudMetadataServiceFromContainer, + events.WithDisabled(), // this rule is not included in falco_rules.yaml (stable rules), so disable the action ) func ContactCloudMetadataServiceFromContainer(h events.Helper) error { - if h.InContainer() { - // The IP address 169.254.169.254 is reserved for the Cloud Instance Metadata Service, - // a common endpoint used by cloud instances (GCP, AWS and Azure) to access - // metadata about the instance itself. Detecting attempts to communicate with this - // IP address from a container can indicate potential unauthorized access to - // sensitive cloud infrastructure metadata. - cmd := exec.Command("timeout", "1s", "nc", "169.254.169.254", "80") - - if err := cmd.Run(); err != nil { - return err - } - - h.Log().Infof("Outbound connection to cloud instance metadata service") - } - return nil + if h.InContainer() { + // The IP address 169.254.169.254 is reserved for the Cloud Instance Metadata Service, + // a common endpoint used by cloud instances (GCP, AWS and Azure) to access + // metadata about the instance itself. Detecting attempts to communicate with this + // IP address from a container can indicate potential unauthorized access to + // sensitive cloud infrastructure metadata. + cmd := exec.Command("timeout", "1s", "nc", "169.254.169.254", "80") + + if err := cmd.Run(); err != nil { + return err + } + + h.Log().Infof("Outbound connection to cloud instance metadata service") + } + return &events.ErrSkipped{ + Reason: "'Contact Cloud Metadata Service From Container' is applicable only to containers.", + } } diff --git a/events/syscall/container_drift_detected_chmod.go b/events/syscall/container_drift_detected_chmod.go index 22e2c95d..92bc54cd 100644 --- a/events/syscall/container_drift_detected_chmod.go +++ b/events/syscall/container_drift_detected_chmod.go @@ -40,5 +40,7 @@ func ContainerDriftDetcted(h events.Helper) error { return err } } - return nil + return &events.ErrSkipped{ + Reason: "'Container Drift Detected (chmod)' is applicable only to containers.", + } } diff --git a/events/syscall/container_drift_detected_open_create.go b/events/syscall/container_drift_detected_open_create.go index a55c7da7..17b7d343 100644 --- a/events/syscall/container_drift_detected_open_create.go +++ b/events/syscall/container_drift_detected_open_create.go @@ -37,5 +37,7 @@ func ContainerDriftDetectedOpenCreate(h events.Helper) error { h.Log().Infof("writing to %s", file.Name()) return os.WriteFile(file.Name(), nil, os.FileMode(0755)) // Also set execute permission } - return nil + return &events.ErrSkipped{ + Reason: "'Container Drift Detected (open+create)' is applicable only to containers.", + } } diff --git a/events/syscall/debugfs_launched_in_privilleged_container.go b/events/syscall/debugfs_launched_in_privilleged_container.go index 074dfbe1..087b84ef 100644 --- a/events/syscall/debugfs_launched_in_privilleged_container.go +++ b/events/syscall/debugfs_launched_in_privilleged_container.go @@ -15,28 +15,29 @@ limitations under the License. package syscall import ( - "os/exec" - "syscall" + "os/exec" + "syscall" - "github.com/falcosecurity/event-generator/events" + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register(DebugfsLaunchedInPrivilegedContainer) func DebugfsLaunchedInPrivilegedContainer(h events.Helper) error { - if h.InContainer() { - cmd := exec.Command("debugfs") - cmd.SysProcAttr = &syscall.SysProcAttr{ - Cloneflags: syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER, - } + if h.InContainer() { + cmd := exec.Command("debugfs") + cmd.SysProcAttr = &syscall.SysProcAttr{ + Cloneflags: syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER, + } - h.Log().Info("Debugfs launched started in a privileged container") - err := cmd.Run() - if err != nil { - h.Log().WithError(err).Error("Failed to launch debugfs") - return err - } - } - - return nil + h.Log().Info("Debugfs launched started in a privileged container") + err := cmd.Run() + if err != nil { + h.Log().WithError(err).Error("Failed to launch debugfs") + return err + } + } + return &events.ErrSkipped{ + Reason: "'Debugfs Launched in Privileged Container' is applicable only to containers.", + } } diff --git a/events/syscall/decoding_payload_in_container.go b/events/syscall/decoding_payload_in_container.go index 326a13cf..23218439 100644 --- a/events/syscall/decoding_payload_in_container.go +++ b/events/syscall/decoding_payload_in_container.go @@ -15,25 +15,27 @@ limitations under the License. package syscall import ( - "os/exec" - "github.com/falcosecurity/event-generator/events" + "os/exec" + + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register( - DecodingPayloadInContainer, - events.WithDisabled(), // this rule is not included in falco_rules.yaml (stable rules), so disable the action + DecodingPayloadInContainer, + events.WithDisabled(), // this rule is not included in falco_rules.yaml (stable rules), so disable the action ) func DecodingPayloadInContainer(h events.Helper) error { - if h.InContainer() { - encodedPayload := "ZGVjb2RlZF9ieV9ldmVudC1nZW5lcmF0b3I=" - cmd := exec.Command("echo", encodedPayload, "|", "base64", "-d") - - err := cmd.Run() - if err != nil { - return err - } - } + if h.InContainer() { + encodedPayload := "ZGVjb2RlZF9ieV9ldmVudC1nZW5lcmF0b3I=" + cmd := exec.Command("echo", encodedPayload, "|", "base64", "-d") - return nil + err := cmd.Run() + if err != nil { + return err + } + } + return &events.ErrSkipped{ + Reason: "'Decoding Payload In Container' is applicable only to containers.", + } } diff --git a/events/syscall/drop_and_execute_new_binary_in_container.go b/events/syscall/drop_and_execute_new_binary_in_container.go index acb09c9e..93980d20 100644 --- a/events/syscall/drop_and_execute_new_binary_in_container.go +++ b/events/syscall/drop_and_execute_new_binary_in_container.go @@ -28,8 +28,9 @@ func DropAndExecuteNewBinaryInContainer(h events.Helper) error { // Find the path of the ls binary lsPath, err := exec.LookPath("ls") if err != nil { - h.Log().WithError(err).Error("ls binary not found") - return err + return &events.ErrSkipped{ + Reason: "ls utility not found in path", + } } // Read the ls binary content @@ -52,5 +53,7 @@ func DropAndExecuteNewBinaryInContainer(h events.Helper) error { h.Log().Info("Executed a binary not part of base image") executeCmd.Run() // Rule triggers even the command is not successful } - return nil + return &events.ErrSkipped{ + Reason: "'Drop And Execute New Binary In Container' is applicable only to containers.", + } } diff --git a/events/syscall/kubernetes_client_tool_launched_in_container.go b/events/syscall/kubernetes_client_tool_launched_in_container.go index dc31c993..c8f32103 100644 --- a/events/syscall/kubernetes_client_tool_launched_in_container.go +++ b/events/syscall/kubernetes_client_tool_launched_in_container.go @@ -32,13 +32,16 @@ func kubernetesClientToolLaunchedInContainer(h events.Helper) error { if h.InContainer() { kubectl, err := exec.LookPath("kubectl") if err != nil { - h.Log().Warnf("kubectl is needed to launch this action") - return err + return &events.ErrSkipped{ + Reason: "kubectl is needed to launch this action", + } } cmd := exec.Command(kubectl) h.Log().Infof("Kubernetes Client Tool Launched In Container") return cmd.Run() } - return nil + return &events.ErrSkipped{ + Reason: "'Kubernetes Client Tool Launched In Container' is applicable only to containers.", + } } diff --git a/events/syscall/launch_package_management_process_in_container.go b/events/syscall/launch_package_management_process_in_container.go index 373ce01f..7fb8ff64 100644 --- a/events/syscall/launch_package_management_process_in_container.go +++ b/events/syscall/launch_package_management_process_in_container.go @@ -46,5 +46,7 @@ func LaunchPackageManagementProcessInContainer(h events.Helper) error { cmd := exec.Command("apt-get") return cmd.Run() } - return nil + return &events.ErrSkipped{ + Reason: "'Launch Package Management Process In Container' is applicable only to containers.", + } } diff --git a/events/syscall/launch_remote_file_copy_tools_in_container.go b/events/syscall/launch_remote_file_copy_tools_in_container.go index 8232bc82..19c31ce9 100644 --- a/events/syscall/launch_remote_file_copy_tools_in_container.go +++ b/events/syscall/launch_remote_file_copy_tools_in_container.go @@ -15,28 +15,29 @@ limitations under the License. package syscall import ( - "os/exec" + "os/exec" - "github.com/falcosecurity/event-generator/events" + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register( - LaunchRemoteFileCopyToolsInContainer, - events.WithDisabled(), // this rules is not included in falco_rules.yaml (stable rules), so disable the action + LaunchRemoteFileCopyToolsInContainer, + events.WithDisabled(), // this rules is not included in falco_rules.yaml (stable rules), so disable the action ) func LaunchRemoteFileCopyToolsInContainer(h events.Helper) error { - if h.InContainer() { - // Launch a remote file copy tool (e.g., scp) within the container - cmd := exec.Command("scp") + if h.InContainer() { + // Launch a remote file copy tool (e.g., scp) within the container + cmd := exec.Command("scp") - h.Log().Info("Remote file copy tool launched in container") - err := cmd.Run() - if err != nil { - h.Log().WithError(err).Error("Failed to launch remote file copy tool") - return err - } - } - - return nil + h.Log().Info("Remote file copy tool launched in container") + err := cmd.Run() + if err != nil { + h.Log().WithError(err).Error("Failed to launch remote file copy tool") + return err + } + } + return &events.ErrSkipped{ + Reason: "'Launch Remote File Copy Tools In Container' is applicable only to containers.", + } } diff --git a/events/syscall/launch_remote_file_copy_tools_inside_container.go b/events/syscall/launch_remote_file_copy_tools_inside_container.go index 193e6918..678a4a50 100644 --- a/events/syscall/launch_remote_file_copy_tools_inside_container.go +++ b/events/syscall/launch_remote_file_copy_tools_inside_container.go @@ -33,5 +33,7 @@ func LaunchIngressRemoteFileCopyToolsInsideContainer(h events.Helper) error { cmd := exec.Command("wget") return cmd.Run() } - return nil + return &events.ErrSkipped{ + Reason: "'Launch Ingress Remote File Copy Tools Inside Container' is applicable only to containers.", + } } diff --git a/events/syscall/launch_suspicious_network_tool_in_container.go b/events/syscall/launch_suspicious_network_tool_in_container.go index d085dc7b..b0fc6911 100644 --- a/events/syscall/launch_suspicious_network_tool_in_container.go +++ b/events/syscall/launch_suspicious_network_tool_in_container.go @@ -15,26 +15,27 @@ limitations under the License. package syscall import ( - "os/exec" + "os/exec" - "github.com/falcosecurity/event-generator/events" + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register( - LaunchSuspiciousNetworkToolInContainer, - events.WithDisabled(), // this rule is not included in falco_rules.yaml (stable rules), so disable the action + LaunchSuspiciousNetworkToolInContainer, + events.WithDisabled(), // this rule is not included in falco_rules.yaml (stable rules), so disable the action ) func LaunchSuspiciousNetworkToolInContainer(h events.Helper) error { - if h.InContainer() { - cmd := exec.Command("nmap", "-sn", "192.168.1.0/24") - - h.Log().Infof("Network tool launched in container") - - if err := cmd.Run(); err != nil { - return err - } - } - - return nil + if h.InContainer() { + cmd := exec.Command("nmap", "-sn", "192.168.1.0/24") + + h.Log().Infof("Network tool launched in container") + + if err := cmd.Run(); err != nil { + return err + } + } + return &events.ErrSkipped{ + Reason: "'Launch Suspicious Network Tool In Container' is applicable only to containers.", + } } diff --git a/events/syscall/launch_suspicious_network_tool_on_host.go b/events/syscall/launch_suspicious_network_tool_on_host.go index 79f6c891..586827e9 100644 --- a/events/syscall/launch_suspicious_network_tool_on_host.go +++ b/events/syscall/launch_suspicious_network_tool_on_host.go @@ -15,26 +15,27 @@ limitations under the License. package syscall import ( - "os/exec" + "os/exec" - "github.com/falcosecurity/event-generator/events" + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register(LaunchSuspiciousNetworkToolOnHost) func LaunchSuspiciousNetworkToolOnHost(h events.Helper) error { - nmap, err := exec.LookPath("nmap") - if err != nil { - h.Log().Warnf("nmap is needed to launch this action") - return err - } - - cmd := exec.Command(nmap, "-sn", "192.168.1.0/24") - h.Log().Infof("Network tool launched in host") - - if err := cmd.Run(); err != nil { - return err - } - - return nil + nmap, err := exec.LookPath("nmap") + if err != nil { + return &events.ErrSkipped{ + Reason: "nmap utility is needed to launch this action ", + } + } + + cmd := exec.Command(nmap, "-sn", "192.168.1.0/24") + h.Log().Infof("Network tool launched in host") + + if err := cmd.Run(); err != nil { + return err + } + + return nil } diff --git a/events/syscall/netcat_remote_code_execution_in_container.go b/events/syscall/netcat_remote_code_execution_in_container.go index bb22ab1e..34db05b4 100644 --- a/events/syscall/netcat_remote_code_execution_in_container.go +++ b/events/syscall/netcat_remote_code_execution_in_container.go @@ -15,24 +15,25 @@ limitations under the License. package syscall import ( - "os/exec" + "os/exec" - "github.com/falcosecurity/event-generator/events" + "github.com/falcosecurity/event-generator/events" ) var _ = events.Register(NetcatRemoteCodeExecutionInContainer) func NetcatRemoteCodeExecutionInContainer(h events.Helper) error { - if h.InContainer() { - // Launch netcat (nc) with the -e flag for remote code execution - cmd := exec.Command("nc", "-e") + if h.InContainer() { + // Launch netcat (nc) with the -e flag for remote code execution + cmd := exec.Command("nc", "-e") - h.Log().Info("Netcat runs inside container that allows remote code execution") - err := cmd.Run() - if err != nil { - return err - } - } - - return nil + h.Log().Info("Netcat runs inside container that allows remote code execution") + err := cmd.Run() + if err != nil { + return err + } + } + return &events.ErrSkipped{ + Reason: "'Netcat Remote Code Execution In Container' is applicable only to containers.", + } } diff --git a/events/syscall/program_run_with_disallowed_http_proxy_env.go b/events/syscall/program_run_with_disallowed_http_proxy_env.go index 73b73160..f6f7475d 100644 --- a/events/syscall/program_run_with_disallowed_http_proxy_env.go +++ b/events/syscall/program_run_with_disallowed_http_proxy_env.go @@ -29,8 +29,9 @@ var _ = events.Register( func ProgramRunWithDisallowedHttpProxyEnv(h events.Helper) error { curl, err := exec.LookPath("curl") if err != nil { - h.Log().Warnf("Curl is needed to launch this action") - return err + return &events.ErrSkipped{ + Reason: "curl utility is needed to launch this action", + } } cmd := exec.Command(curl, "http://example.com") cmd.Env = os.Environ()