mirror of
https://github.com/falcosecurity/falco.git
synced 2025-07-16 07:47:00 +00:00
add init container module loader
Signed-off-by: Michael Ducy <michael@ducy.org>
This commit is contained in:
parent
ac8204dc30
commit
01abe71256
11
docker/kernel/httploader/Dockerfile
Normal file
11
docker/kernel/httploader/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
||||
FROM golang:alpine AS build
|
||||
|
||||
RUN apk --no-cache add build-base git bzr mercurial gcc ca-certificates
|
||||
|
||||
ADD ./httploader /src
|
||||
RUN cd /src && go get golang.org/x/sys/unix && CGO_ENABLED=0 GOOS=linux go build -a -o httploader -ldflags '-extldflags "-static"' .
|
||||
|
||||
FROM scratch
|
||||
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=build /src/httploader /
|
||||
ENTRYPOINT /httploader
|
148
docker/kernel/httploader/httploader/falcoloader/loader.go
Normal file
148
docker/kernel/httploader/httploader/falcoloader/loader.go
Normal file
@ -0,0 +1,148 @@
|
||||
package falcoloader
|
||||
|
||||
import "io/ioutil"
|
||||
import "io"
|
||||
import "os"
|
||||
import "crypto/md5"
|
||||
import "encoding/hex"
|
||||
import "strings"
|
||||
import "net/http"
|
||||
import "golang.org/x/sys/unix"
|
||||
import "log"
|
||||
import "unsafe"
|
||||
import "compress/gzip"
|
||||
import "bytes"
|
||||
|
||||
func GetKernelVersion() string {
|
||||
path := "/proc/version"
|
||||
|
||||
file, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return "invaildVersion"
|
||||
}
|
||||
version_string := string(file)
|
||||
|
||||
version_fields := strings.Split(version_string, " ")
|
||||
|
||||
return version_fields[2]
|
||||
}
|
||||
|
||||
func GetKernelConfigHash() string {
|
||||
var hash string
|
||||
kernelConfigPath := getKernelConfigPath()
|
||||
hash, _ = genKernelConfigHash(kernelConfigPath)
|
||||
|
||||
return hash
|
||||
}
|
||||
|
||||
func getKernelConfigPath() string {
|
||||
kernelConfigPath := ""
|
||||
|
||||
version := GetKernelVersion()
|
||||
paths := []string{
|
||||
"/proc/config.gz",
|
||||
"/boot/config-" + version,
|
||||
"/host/boot/config-" + version,
|
||||
"/usr/lib/ostree-boot/config-" + version,
|
||||
"/usr/lib/ostree-boot/config-" + version,
|
||||
"/lib/modules/" + version + "/config" }
|
||||
|
||||
for i := range paths {
|
||||
_, err := os.Stat(paths[i])
|
||||
if err != nil {
|
||||
continue;
|
||||
}
|
||||
log.Print("Found kernel config: " + paths[i])
|
||||
return paths[i]
|
||||
}
|
||||
log.Fatal("No kernel config found")
|
||||
return kernelConfigPath
|
||||
}
|
||||
|
||||
func genKernelConfigHash(path string) (string, error) {
|
||||
var md5hash string
|
||||
var err error
|
||||
var buf bytes.Buffer
|
||||
|
||||
if strings.HasSuffix(path, "gz") {
|
||||
log.Print("Kernel config " + path + " is gz compressed")
|
||||
tmpfile, err := os.Open(path)
|
||||
if err != nil {
|
||||
return md5hash, err
|
||||
}
|
||||
defer tmpfile.Close()
|
||||
|
||||
file, err := gzip.NewReader(tmpfile)
|
||||
if err != nil {
|
||||
return md5hash, err
|
||||
}
|
||||
defer file.Close()
|
||||
io.Copy(&buf, file)
|
||||
} else {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return md5hash, err
|
||||
}
|
||||
defer file.Close()
|
||||
io.Copy(&buf,file)
|
||||
}
|
||||
|
||||
hash := md5.New()
|
||||
if _, err := io.Copy(hash, &buf); err != nil {
|
||||
return md5hash, err
|
||||
}
|
||||
md5hash = hex.EncodeToString(hash.Sum(nil))
|
||||
log.Print("Hash calculated: " + md5hash)
|
||||
|
||||
return md5hash, err
|
||||
|
||||
}
|
||||
|
||||
func FetchModule(url string, path string) error {
|
||||
log.Printf("Downloading kernel module from %s", url)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
log.Printf("Recevied HTTP Status Code: %d", resp.StatusCode)
|
||||
if resp.StatusCode == 200 {
|
||||
out, err := os.Create(path)
|
||||
if err != nil {
|
||||
log.Fatalf("Error creating file: %s", path)
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to write file: %s", path)
|
||||
return err
|
||||
}
|
||||
log.Printf("Wrote kernel module: %s", path)
|
||||
} else {
|
||||
log.Fatal("Non-200 Status code received.")
|
||||
}
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func LoadModule(path string) error {
|
||||
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
log.Fatalf("Error opening kernel module: %s", path)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Print("Opened probe: " + path)
|
||||
|
||||
_p0, err := unix.BytePtrFromString("")
|
||||
|
||||
if _, _, err := unix.Syscall(313, file.Fd(), uintptr(unsafe.Pointer(_p0)), 0); err != 0 {
|
||||
log.Fatalf("Error loading kernel module: %s. The module may already be loaded.", path)
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
50
docker/kernel/httploader/httploader/main.go
Normal file
50
docker/kernel/httploader/httploader/main.go
Normal file
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import "os"
|
||||
import "log"
|
||||
import "fmt"
|
||||
import "./falcoloader"
|
||||
|
||||
// Default behavior: calculate kernel module and download from Falco hosted probe library
|
||||
// ENV FALCO_PROBE_URL = URL to download probe.ko file
|
||||
// ENV FALCO_PROBE_REPO = URL to download probe.ko, probe name derived from `uname -r`
|
||||
|
||||
func main() {
|
||||
falco_version := getEnv("FALCO_VERSION","0.17.0")
|
||||
falco_probe_path := getEnv("FALCO_PROBE_PATH","/")
|
||||
falco_probe_file := getEnv("FALCO_PROBE_FILE","falco-probe.ko")
|
||||
falco_probe_fullpath := falco_probe_path + falco_probe_file
|
||||
falco_probe_url := getEnv("FALCO_PROBE_URL","")
|
||||
falco_probe_repo := getEnv("FALCO_PROBE_REPO","https://s3.amazonaws.com/download.draios.com/stable/sysdig-probe-binaries/")
|
||||
falco_config_hash := falcoloader.GetKernelConfigHash()
|
||||
falco_kernel_version := falcoloader.GetKernelVersion()
|
||||
|
||||
log.Printf("FALCO_VERSION: %s", falco_version)
|
||||
log.Printf("FALCO_PROBE_URL: %s", falco_probe_url)
|
||||
log.Printf("FALCO_PROBE_REPO: %s", falco_probe_repo)
|
||||
log.Printf("KERNEL_VERSION: %s", falco_kernel_version)
|
||||
log.Printf("KERNEL_CONFIG_HASH: %s", falco_config_hash)
|
||||
|
||||
// if FALCO_PROBE_URL not set, build it
|
||||
if falco_probe_url == "" {
|
||||
falco_probe_url = fmt.Sprintf("%sfalco-probe-%s-x86_64-%s-%s.ko", falco_probe_repo, falco_version, falco_kernel_version, falco_config_hash)
|
||||
}
|
||||
|
||||
// fetch module
|
||||
if err := falcoloader.FetchModule(falco_probe_url, falco_probe_fullpath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// load module
|
||||
if err := falcoloader.LoadModule(falco_probe_fullpath); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func getEnv(key, def string) string {
|
||||
value, isSet := os.LookupEnv(key)
|
||||
if (isSet) {
|
||||
return value
|
||||
}
|
||||
return def
|
||||
}
|
@ -1,15 +1,14 @@
|
||||
FROM linuxkit/kernel:4.9.184 AS ksrc
|
||||
FROM alpine:3.4 AS probe-build
|
||||
ARG FALCOVER=0.17.0
|
||||
ARG SYSDIGVER=0.26.2
|
||||
FROM falcosecurity/falco-minimal as falco
|
||||
FROM alpine:3.10 AS probe-build
|
||||
ARG FALCO_VERSION=0.17.0
|
||||
|
||||
COPY --from=ksrc /kernel-dev.tar /
|
||||
COPY --from=falco /usr/src/falco-${FALCO_VERSION} /usr/src/falco-${FALCO_VERSION}
|
||||
|
||||
RUN apk add --no-cache --update wget ca-certificates \
|
||||
RUN apk add --no-cache --update \
|
||||
build-base gcc abuild binutils \
|
||||
bc \
|
||||
cmake \
|
||||
git \
|
||||
autoconf && \
|
||||
export KERNELVER=`uname -r | cut -d '-' -f 1` && \
|
||||
export KERNELDIR=/usr/src/linux-headers-4.9.184-linuxkit/ && \
|
||||
@ -17,25 +16,14 @@ RUN apk add --no-cache --update wget ca-certificates \
|
||||
cd $KERNELDIR && \
|
||||
zcat /proc/1/root/proc/config.gz > .config && \
|
||||
make olddefconfig && \
|
||||
mkdir -p /falco/build && \
|
||||
mkdir /src && \
|
||||
cd /src && \
|
||||
wget https://github.com/falcosecurity/falco/archive/$FALCOVER.tar.gz && \
|
||||
tar zxf $FALCOVER.tar.gz && \
|
||||
wget https://github.com/draios/sysdig/archive/$SYSDIGVER.tar.gz && \
|
||||
tar zxf $SYSDIGVER.tar.gz && \
|
||||
mv sysdig-$SYSDIGVER sysdig && \
|
||||
cd /falco/build && \
|
||||
cmake /src/falco-$FALCOVER && \
|
||||
make driver && \
|
||||
rm -rf /src && \
|
||||
apk del wget ca-certificates \
|
||||
cd /usr/src/falco-${FALCO_VERSION} && \
|
||||
make && \
|
||||
apk del \
|
||||
build-base gcc abuild binutils \
|
||||
bc \
|
||||
cmake \
|
||||
git \
|
||||
autoconf
|
||||
|
||||
FROM alpine:3.4
|
||||
COPY --from=probe-build /falco/build/driver/falco-probe.ko /
|
||||
FROM alpine:3.10
|
||||
ARG FALCO_VERSION=0.17.0
|
||||
COPY --from=probe-build /usr/src/falco-${FALCO_VERSION}/falco-probe.ko /
|
||||
CMD ["insmod","/falco-probe.ko"]
|
||||
|
@ -0,0 +1,93 @@
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: falco-daemonset
|
||||
labels:
|
||||
app: falco-example
|
||||
role: security
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: falco-example
|
||||
role: security
|
||||
spec:
|
||||
serviceAccount: falco-account
|
||||
initContainers:
|
||||
- name: httploader
|
||||
image: falcosecurity/httploader:latest
|
||||
command: ['/httploader']
|
||||
securityContext:
|
||||
privileged: true
|
||||
#env:
|
||||
# - name: FALCO_VERSION
|
||||
# value: 0.17.0
|
||||
# - name: FALCO_PROBE_URL
|
||||
# value:
|
||||
# - name: FALCO_PROBE_REPO
|
||||
# value: "https://s3.amazonaws.com/download.draios.com/stable/sysdig-probe-binaries/"
|
||||
containers:
|
||||
- name: falco
|
||||
image: falcosecurity/falco-minimal:latest
|
||||
securityContext:
|
||||
privileged: true
|
||||
# Uncomment the 3 lines below to enable eBPF support for Falco.
|
||||
# This allows Falco to run on Google COS.
|
||||
# Leave blank for the default probe location, or set to the path
|
||||
# of a precompiled probe.
|
||||
# env:
|
||||
# - name: SYSDIG_BPF_PROBE
|
||||
# value: ""
|
||||
args: [ "/usr/bin/falco", "--cri", "/host/run/containerd/containerd.sock", "-K", "/var/run/secrets/kubernetes.io/serviceaccount/token", "-k", "https://$(KUBERNETES_SERVICE_HOST)", "-pk"]
|
||||
volumeMounts:
|
||||
- mountPath: /host/var/run/docker.sock
|
||||
name: docker-socket
|
||||
- mountPath: /host/run/containerd/containerd.sock
|
||||
name: containerd-socket
|
||||
- mountPath: /host/dev
|
||||
name: dev-fs
|
||||
- mountPath: /host/proc
|
||||
name: proc-fs
|
||||
readOnly: true
|
||||
- mountPath: /host/boot
|
||||
name: boot-fs
|
||||
readOnly: true
|
||||
- mountPath: /host/lib/modules
|
||||
name: lib-modules
|
||||
readOnly: true
|
||||
- mountPath: /host/usr
|
||||
name: usr-fs
|
||||
readOnly: true
|
||||
- mountPath: /host/etc/
|
||||
name: etc-fs
|
||||
readOnly: true
|
||||
- mountPath: /etc/falco
|
||||
name: falco-config
|
||||
volumes:
|
||||
- name: docker-socket
|
||||
hostPath:
|
||||
path: /var/run/docker.sock
|
||||
- name: containerd-socket
|
||||
hostPath:
|
||||
path: /run/containerd/containerd.sock
|
||||
- name: dev-fs
|
||||
hostPath:
|
||||
path: /dev
|
||||
- name: proc-fs
|
||||
hostPath:
|
||||
path: /proc
|
||||
- name: boot-fs
|
||||
hostPath:
|
||||
path: /boot
|
||||
- name: lib-modules
|
||||
hostPath:
|
||||
path: /lib/modules
|
||||
- name: usr-fs
|
||||
hostPath:
|
||||
path: /usr
|
||||
- name: etc-fs
|
||||
hostPath:
|
||||
path: /etc
|
||||
- name: falco-config
|
||||
configMap:
|
||||
name: falco-config
|
Loading…
Reference in New Issue
Block a user