Skip to content

Commit

Permalink
feat: Add k8saudiovh plugin in falcosecurity repo
Browse files Browse the repository at this point in the history
Signed-off-by: scraly <[email protected]>
  • Loading branch information
scraly committed Dec 19, 2024
1 parent a236e4b commit 7901a07
Show file tree
Hide file tree
Showing 11 changed files with 765 additions and 5 deletions.
3 changes: 3 additions & 0 deletions plugins/k8saudit-ovh/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
libk8saudit-ovh.so
.vscode
falco.yaml
5 changes: 5 additions & 0 deletions plugins/k8saudit-ovh/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Changelog

## v0.1.0

* First version of the `k8saudit-ovh` plugin 🎉
22 changes: 22 additions & 0 deletions plugins/k8saudit-ovh/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
SHELL=/bin/bash -o pipefail
GO ?= go

NAME := k8saudit-ovh
OUTPUT := lib$(NAME).so

ifeq ($(DEBUG), 1)
GODEBUGFLAGS= GODEBUG=cgocheck=1
else
GODEBUGFLAGS= GODEBUG=cgocheck=0
endif

all: build

clean:
@rm -f lib$(NAME).so

build: clean
@$(GODEBUGFLAGS) $(GO) build -buildmode=c-shared -buildvcs=false -o $(OUTPUT) ./plugin

install:
sudo cp $(OUTPUT) /usr/share/falco/plugins/
3 changes: 3 additions & 0 deletions plugins/k8saudit-ovh/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
approvers:
- scraly
- Issif
218 changes: 218 additions & 0 deletions plugins/k8saudit-ovh/README.md

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions plugins/k8saudit-ovh/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module github.com/falcosecurity/plugins/plugins/k8saudit-ovh

go 1.23.3

require (
github.com/falcosecurity/plugin-sdk-go v0.7.4
github.com/falcosecurity/plugins/plugins/k8saudit v0.11.0
github.com/gorilla/websocket v1.5.3
golang.org/x/net v0.32.0
)

require (
github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b // indirect
github.com/iancoleman/orderedmap v0.3.0 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
)
37 changes: 37 additions & 0 deletions plugins/k8saudit-ovh/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b h1:doCpXjVwui6HUN+xgNsNS3SZ0/jUZ68Eb+mJRNOZfog=
github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/falcosecurity/plugin-sdk-go v0.7.4 h1:iNV0pgWgJwOHqSCjTw4Hsvtu5WuwoqckAWzpIEy9giQ=
github.com/falcosecurity/plugin-sdk-go v0.7.4/go.mod h1:NP+y22DYOS+G3GDXIXNmzf0CBL3nfPPMoQuHvAzfitQ=
github.com/falcosecurity/plugins/plugins/k8saudit v0.11.0 h1:ywwQ8kQmMS0HL3PuwBSKUmERqePrCSnajxnSCNC0HQY=
github.com/falcosecurity/plugins/plugins/k8saudit v0.11.0/go.mod h1:RmSc1za6asI52w3uVhZGb/p6RoQr2OWmp/Zc8+kiMWw=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc=
github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
190 changes: 190 additions & 0 deletions plugins/k8saudit-ovh/pkg/k8sauditovh/k8sauditovh.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package k8sauditovh

import (
"bytes"
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"net/url"
"os"
"text/template"
"time"

"github.com/falcosecurity/plugin-sdk-go/pkg/sdk"
"github.com/falcosecurity/plugin-sdk-go/pkg/sdk/plugins"
"github.com/falcosecurity/plugin-sdk-go/pkg/sdk/plugins/source"
"github.com/falcosecurity/plugins/plugins/k8saudit/pkg/k8saudit"

"github.com/gorilla/websocket"
)

var (
ID uint32
Name string
Description string
Contact string
Version string
EventSource string
)

const (
pluginName = "k8saudit-ovh"

// Time allowed to read the next pong message from the client.
pongWait = 60 * time.Second
)

type PluginConfig struct {
MaxEventSize uint64 `json:"maxEventSize" jsonschema:"title=Maximum event size,description=Maximum size of single audit event (Default: 262144),default=262144"`
}

// Plugin represents our plugin
type Plugin struct {
k8saudit.Plugin
Logger *log.Logger
Config PluginConfig
}

// Resets sets the configuration to its default values
func (k *PluginConfig) Reset() {
k.MaxEventSize = uint64(sdk.DefaultEvtSize)
}

// SetInfo is used to set the Info of the plugin
func (p *Plugin) SetInfo(id uint32, name, description, contact, version, eventSource string) {
ID = id
Name = name
Contact = contact
Version = version
EventSource = eventSource
}

// Info displays information of the plugin to Falco plugin framework
func (p *Plugin) Info() *plugins.Info {
return &plugins.Info{
ID: ID,
Name: Name,
Description: Description,
Contact: Contact,
Version: Version,
EventSource: EventSource,
}
}

// Init is called by the Falco plugin framework as first entry,
// we use it for setting default configuration values and mapping
// values from `init_config` (json format for this plugin)
func (p *Plugin) Init(config string) error {
p.Plugin.Config.Reset()
p.Config.Reset()
p.Logger = log.New(os.Stderr, "["+pluginName+"] ", log.LstdFlags|log.LUTC|log.Lmsgprefix)
return nil
}

func (p *Plugin) OpenParams() ([]sdk.OpenParam, error) {
return []sdk.OpenParam{
{Value: "", Desc: "The LDP Websocket URL to use to get the OVHcloud MKS Audit Logs sent to a LDP data stream"},
}, nil
}

// Open is called by Falco plugin framework for opening a stream of events, we call that an instance
func (p *Plugin) Open(ovhLDPURL string) (source.Instance, error) {
t, err := template.New("template").Funcs(template.FuncMap{
"color": color,
"bColor": bColor,
"noColor": func() string { return color("reset") },
"date": date,
"join": join,
"concat": concat,
"duration": duration,
"int": toInt,
"float": toFloat,
"string": toString,
"get": get,
"column": column,
"begin": begin,
"contain": contain,
"level": level,
}).Parse("{{._appID}}> {{.short_message}}")
if err != nil {
p.Logger.Fatalf("Failed to parse pattern: %s", err.Error())
}

if ovhLDPURL == "" {
return nil, fmt.Errorf("OVHcloud LDP URL can't be empty")
}

eventC := make(chan source.PushEvent)

go func() {
defer close(eventC)

u := url.URL{Scheme: "wss", Host: ovhLDPURL, Path: ""}
v, _ := url.QueryUnescape(u.String())

headers := make(http.Header)
// headers.Set("Origin", "http://mySelf")
wsChan, _, err := websocket.DefaultDialer.Dial(v, headers)
if err != nil {
eventC <- source.PushEvent{Err: err}
return
}
defer wsChan.Close()

for {
//wsChan.SetReadDeadline(time.Now().Add(5 * time.Second))
wsChan.SetReadDeadline(time.Now().Add(pongWait))
_, msg, err := wsChan.ReadMessage()

// Keep the WebSocket connection alive
if t, ok := err.(net.Error); ok && t.Timeout() {
// Timeout, send a Ping && continue
if err := wsChan.WriteMessage(websocket.PingMessage, nil); err != nil {
p.Logger.Println("The end host probably closed the connection", err.Error())
}
continue
}

if err != nil {
p.Logger.Printf("Error while reading from %q: %q. Will try to reconnect after 1s...\n", u.Host, err.Error())
time.Sleep(1 * time.Second)
break
}

// Extract Message
var logMessage struct {
Message string `json:"message"`
}
json.Unmarshal(msg, &logMessage)

// Extract infos
var message map[string]interface{}
json.Unmarshal([]byte(logMessage.Message), &message)

var m bytes.Buffer
err = t.Execute(&m, message)
if err != nil {
p.Logger.Println(err)
continue
}

// Parse audit events payload thanks to k8saudit extract parse and extract methods
values, err := p.Plugin.ParseAuditEventsPayload([]byte(m.String())[12:])
if err != nil {
p.Logger.Println(err)
continue
}
for _, j := range values {
if j.Err != nil {
p.Logger.Println(j.Err)
continue
}

eventC <- *j
}
}
}()
return source.NewPushInstance(eventC)
}
Loading

0 comments on commit 7901a07

Please sign in to comment.