add init container module loader

Signed-off-by: Michael Ducy <michael@ducy.org>
This commit is contained in:
Michael Ducy
2019-08-26 15:43:40 -04:00
committed by Leo Di Donato
parent ac8204dc30
commit 01abe71256
5 changed files with 313 additions and 23 deletions

View 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

View 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
}

View 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
}

View File

@@ -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"]