Compare commits

..

No commits in common. "master" and "v0.9.6" have entirely different histories.

153 changed files with 3979 additions and 8328 deletions

235
.circleci/config.yml Normal file
View File

@ -0,0 +1,235 @@
version: 2.1
jobs:
"build-test":
docker:
- image: alpine:3.16
steps:
- checkout
- setup_remote_docker: # used by integration tests that runs driverkit binary that needs docker
version: 20.10.12
- run:
name: Install deps
command: apk add gcc musl-dev make bash git go
- run:
name: Build
command: make build
- run:
name: Test
command: make test
- run:
name: Integration tests # test cross build too!
command: make -e TARGET_TEST_ARCH=* integration_test
- run:
name: Prepare Artifacts
command: |
mkdir -p /tmp/build-amd64
cp _output/bin/driverkit /tmp/build-amd64/
- store_artifacts:
path: /tmp/build-amd64/driverkit
destination: driverkit_amd64
- persist_to_workspace:
root: /tmp
paths:
- build-amd64/
"build-test-arm64":
machine:
enabled: true
image: ubuntu-2004:2022.04.1
resource_class: arm.medium
steps:
- checkout:
path: /tmp/source
- run:
name: Prepare project
command: |
docker run --rm -it -v /tmp/source:/source -v /var/run/docker.sock:/var/run/docker.sock -w /source --name alpine_sh -d alpine:3.16 sh
docker exec alpine_sh apk add gcc musl-dev make bash git go docker
docker exec alpine_sh git config --global --add safe.directory /source
- run:
name: Build
command: docker exec alpine_sh make build
- run:
name: Test
command: docker exec alpine_sh make test
- run:
name: Integration tests
command: docker exec alpine_sh make integration_test
- run:
name: Prepare Artifacts
command: |
mkdir -p /tmp/build-arm64
cp /tmp/source/_output/bin/driverkit /tmp/build-arm64/
- store_artifacts:
path: /tmp/build-arm64/driverkit
destination: driverkit_arm64
- persist_to_workspace:
root: /tmp
paths:
- build-arm64/
"build-images":
docker:
- image: alpine:3.16
steps:
- attach_workspace:
at: /
- checkout
- setup_remote_docker:
version: 20.10.12
docker_layer_caching: true
- run:
name: Install deps
command: |
apk update
apk add make bash git docker docker-cli-buildx
- run:
name: Login to registry
command: echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
- run:
name: Prepare artifact for driverkit image
command: | # driverkit dockerfile expects the binary there
mkdir -p build-amd64
cp /build-amd64/driverkit build-amd64/
- run:
name: Build and Push docker images
command: GIT_BRANCH="$CIRCLE_BRANCH" GIT_TAG="$CIRCLE_TAG" make push/all
- run:
name: Push latest images
command: |
if [ -n "$CIRCLE_TAG" ]
then
GIT_BRANCH="$CIRCLE_BRANCH" GIT_TAG="$CIRCLE_TAG" make push/latest
else
echo "Skipping (no git tag)"
fi
"build-images-arm64":
machine:
enabled: true
image: ubuntu-2004:2022.04.1
docker_layer_caching: true
resource_class: arm.medium
steps:
- attach_workspace:
at: /tmp
- checkout:
path: /tmp/source
- run:
name: Install deps
command: |
sudo apt update
sudo apt install make bash git
- run:
name: Login to registry
command: echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
- run:
name: Prepare artifact for driverkit image
command: | # driverkit dockerfile expects the binary there
mkdir -p /tmp/source/build-arm64
cp /tmp/build-arm64/driverkit /tmp/source/build-arm64/
- run:
name: Build and Push docker images
command: |
cd /tmp/source
GIT_BRANCH="$CIRCLE_BRANCH" GIT_TAG="$CIRCLE_TAG" make push/all
- run:
name: Push latest images if needed
command: |
cd /tmp/source
if [ -n "$CIRCLE_TAG" ]
then
GIT_BRANCH="$CIRCLE_BRANCH" GIT_TAG="$CIRCLE_TAG" make push/latest
else
echo "Skipping (no git tag)"
fi
"images":
docker:
- image: cimg/base:stable
user: root
steps:
- checkout
- setup_remote_docker:
version: 20.10.12
- run:
name: Prepare env
command: |
echo ${DOCKERHUB_SECRET} | docker login -u ${DOCKERHUB_USER} --password-stdin
sudo apt update
sudo apt install make bash git
- run:
name: Build and Push manifest to registry
command: |
GIT_BRANCH="$CIRCLE_BRANCH" GIT_TAG="$CIRCLE_TAG" make manifest/all
- run:
name: Push latest manifest if needed
command: |
if [ -n "$CIRCLE_TAG" ]
then
GIT_BRANCH="$CIRCLE_BRANCH" GIT_TAG="$CIRCLE_TAG" make manifest/latest
else
echo "Skipping (no git tag)"
fi
"release":
docker:
- image: circleci/golang:1.17
steps:
- checkout
- run:
name: Install goreleaser
command: |
echo 'deb [trusted=yes] https://repo.goreleaser.com/apt/ /' | sudo tee /etc/apt/sources.list.d/goreleaser.list
sudo apt update
sudo apt install goreleaser
- run:
name: Release
command: GIT_TAG="$CIRCLE_TAG" make release
workflows:
version: 2.1
build:
jobs:
- "build-test":
filters:
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
- "build-test-arm64":
filters:
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
- "build-images":
context: falco
filters:
branches:
only:
- master
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
requires:
- "build-test"
- "build-images-arm64":
context: falco
filters:
branches:
only:
- master
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
requires:
- "build-test-arm64"
- "images":
context: falco
filters:
branches:
only:
- master
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
requires:
- "build-images"
- "build-images-arm64"
- "release":
context: falco
filters:
branches:
ignore: /.*/
tags:
only: /v[0-9]+(\.[0-9]+)*(-.*)*/
requires:
- "images"

View File

@ -66,5 +66,5 @@ For example, `action required: change the API interface of the rule engine`.
-->
```release-note
NONE
```

View File

@ -1,12 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
groups:
actions:
update-types:
- "minor"
- "patch"

View File

@ -1,77 +0,0 @@
name: CI Build
on:
pull_request:
branches: [master]
workflow_dispatch:
# Checks if any concurrent jobs under the same pull request or branch are being executed
# NOTE: this will cancel every workflow that is being ran against a PR as group is just the github ref (without the workflow name)
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
build-test-dev:
strategy:
matrix:
arch: [amd64, arm64]
uses: ./.github/workflows/reusable_build_test_driverkit.yml
with:
arch: ${{ matrix.arch }}
paths-filter:
runs-on: ubuntu-latest
outputs:
docker_needs_build: ${{ steps.filter.outputs.docker }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
id: filter
with:
filters: |
docker:
- 'docker/**'
build-images-dev:
needs: [build-test-dev,paths-filter]
if: needs.paths-filter.outputs.docker_needs_build == 'true'
strategy:
matrix:
arch: [ amd64, arm64 ]
uses: ./.github/workflows/reusable_build_push_images.yml
with:
arch: ${{ matrix.arch }}
push: false
secrets: inherit
gomodtidy:
name: Enforce go.mod tidiness
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: "${{ github.event.pull_request.head.sha }}"
repository: ${{github.event.pull_request.head.repo.full_name}}
persist-credentials: false
- name: Setup Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
with:
go-version-file: 'go.mod'
- name: Execute go mod tidy and check the outcome
working-directory: ./
run: |
go mod tidy
exit_code=$(git diff --exit-code)
exit ${exit_code}
- name: Print a comment in case of failure
run: |
echo "The go.mod and/or go.sum files appear not to be correctly tidied.
Please, rerun go mod tidy to fix the issues."
exit 1
if: |
failure() && github.event.pull_request.head.repo.full_name == github.repository

View File

@ -1,36 +0,0 @@
name: Master CI
on:
push:
branches: [master]
# Checks if any concurrent jobs is running for master CI and eventually cancel it
concurrency:
group: ci-master
cancel-in-progress: true
jobs:
build-test-master:
strategy:
matrix:
arch: [amd64, arm64]
uses: ./.github/workflows/reusable_build_test_driverkit.yml
with:
arch: ${{ matrix.arch }}
push-images-master:
needs: build-test-master
strategy:
matrix:
arch: [amd64, arm64]
uses: ./.github/workflows/reusable_build_push_images.yml
with:
arch: ${{ matrix.arch }}
push: true
secrets: inherit
images-master:
needs: push-images-master
uses: ./.github/workflows/reusable_manifest_images.yml
secrets: inherit

View File

@ -1,68 +0,0 @@
name: Release
on:
push:
tags:
- v*
permissions:
contents: write # needed to write releases
id-token: write # needed for keyless signing
jobs:
build-test-release:
strategy:
matrix:
arch: [amd64, arm64]
uses: ./.github/workflows/reusable_build_test_driverkit.yml
with:
arch: ${{ matrix.arch }}
push-images-release:
needs: build-test-release
strategy:
matrix:
arch: [amd64, arm64]
uses: ./.github/workflows/reusable_build_push_images.yml
with:
arch: ${{ matrix.arch }}
tag: ${{ github.ref_name }}
is_latest: true
push: true
secrets: inherit
images-release:
needs: push-images-release
uses: ./.github/workflows/reusable_manifest_images.yml
with:
tag: ${{ github.ref_name }}
is_latest: true
secrets: inherit
release:
needs: images-release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Fetch
run: git fetch --prune --force --tags
- name: Setup Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
with:
go-version-file: 'go.mod'
- name: Install GoReleaser
uses: goreleaser/goreleaser-action@9c156ee8a17a598857849441385a2041ef570552 # v6.3.0
with:
install-only: true
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_TAG: ${{ github.ref_name }}
run: make release

View File

@ -1,72 +0,0 @@
# This is a reusable workflow used by master and release CI
on:
workflow_call:
inputs:
arch:
description: amd64 or arm64
required: true
type: string
branch:
description: name of the branch
required: false
type: string
default: 'master'
tag:
description: The tag to use (e.g. "master" or "0.35.0")
required: false
type: string
default: ''
is_latest:
description: Update the latest tag with the new image
required: false
type: boolean
default: false
push:
description: Whether to also push images
required: false
type: boolean
default: false
jobs:
build-images:
runs-on: ${{ (inputs.arch == 'arm64' && 'ubuntu-22.04-arm') || 'ubuntu-22.04' }}
env:
GIT_BRANCH: ${{ inputs.branch }}
GIT_TAG: ${{ inputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Create download folder
run: mkdir -p build-${{ inputs.arch }}
- name: Download Driverkit
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: driverkit-${{ inputs.arch }}
path: build-${{ inputs.arch }}
- name: Enforce executable bit
run: chmod +x build-${{ inputs.arch }}/driverkit
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Login to Docker Hub
if: inputs.push
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_SECRET }}
- name: Build and Push docker images
if: inputs.push
run: make push/all
- name: Build docker images
if: inputs.push == false
run: make image/all
- name: Push latest images if needed
if: inputs.push && inputs.is_latest
run: make push/latest

View File

@ -1,47 +0,0 @@
# This is a reusable workflow used by master and release CI
on:
workflow_call:
inputs:
arch:
description: amd64 or arm64
required: true
type: string
jobs:
build-test:
# See https://github.com/actions/runner/issues/409#issuecomment-1158849936
runs-on: ${{ (inputs.arch == 'arm64' && 'ubuntu-22.04-arm') || 'ubuntu-22.04' }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5
with:
go-version-file: 'go.mod'
- name: Build
run: make build
- name: Test
run: make test
- name: Set integration tests DRIVERVERSIONS env
if: inputs.arch == 'amd64'
run: echo "DRIVERVERSIONS=master 6.0.1+driver 2.0.0+driver 17f5df52a7d9ed6bb12d3b1768460def8439936d" >> $GITHUB_ENV
- name: Set integration tests DRIVERVERSIONS env
if: inputs.arch == 'arm64'
run: echo "DRIVERVERSIONS=master 6.0.1+driver 2.0.0+driver" >> $GITHUB_ENV
- name: Integration tests
run: make integration_test
- name: Upload driverkit
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: driverkit-${{ inputs.arch }}
path: |
${{ github.workspace }}/_output/bin/driverkit

View File

@ -1,45 +0,0 @@
# This is a reusable workflow used by master and release CI
on:
workflow_call:
inputs:
branch:
description: name of the branch
required: false
type: string
default: 'master'
tag:
description: The tag to use (e.g. "master" or "0.35.0")
required: false
type: string
default: ''
is_latest:
description: Update the latest tag with the new image
required: false
type: boolean
default: false
jobs:
push-manifest:
runs-on: ubuntu-latest
env:
GIT_BRANCH: ${{ inputs.branch }}
GIT_TAG: ${{ inputs.tag }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Login to Docker Hub
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_SECRET }}
- name: Build and Push manifest to registry
run: make manifest/all
- name: Push latest manifest if needed
if: inputs.is_latest
run: make manifest/latest

4
.gitignore vendored
View File

@ -1,7 +1,7 @@
_output/
dist/
vendor/
.idea/
driverkit
coverage.out
coverage.out

View File

@ -1,10 +1,6 @@
version: 2
project_name: driverkit
builds:
- id: "driverkit"
env:
- GOEXPERIMENT=loopvar
goos:
- linux
goarch:
@ -13,6 +9,7 @@ builds:
main: .
flags:
- -v
- -buildmode=pie
ldflags:
- "{{.Env.LDFLAGS}}"
binary: driverkit

View File

@ -1,35 +1,81 @@
# Example Configs
## aliyun linux 2 (Alibaba Cloud Linux 2)
## ubuntu
Example configuration file to build both the Kernel module and eBPF probe for Ubuntu (works with any flavor!).
```yaml
kernelrelease: 4.19.91-26.al7.x86_64
target: alinux
kernelrelease: 5.0.0-1021-aws-5.0
kernelversion: 24~18.04.1
target: ubuntu
output:
module: /tmp/falco_alinux_4.19.91-26.al7.x86_64.ko
probe: /tmp/falco_alinux_4.19.91-26.al7.x86_64.o
module: /tmp/falco-ubuntu-generic.ko
probe: /tmp/falco-ubuntu-generic.o
driverversion: master
```
## aliyun linux 3 (Alibaba Cloud Linux 3)
## ubuntu-generic
Example configuration file to build both the Kernel module and eBPF probe for Ubuntu generic.
```yaml
kernelrelease: 5.10.84-10.4.al8.x86_64
target: alinux
kernelrelease: 4.15.0-72-generic
kernelversion: 81
target: ubuntu-generic
output:
module: /tmp/falco_alinux_4.19.91-26.al7.x86_64.ko
probe: /tmp/falco_alinux_4.19.91-26.al7.x86_64.o
module: /tmp/falco-ubuntu-generic.ko
probe: /tmp/falco-ubuntu-generic.o
driverversion: master
```
## alma linux
> **NOTE:** ubuntu-generic exists to retain backward compatibility only,
> and should not be used in new configs.
## ubuntu-aws
Example configuration file to build both the Kernel module and eBPF probe for Ubuntu AWS.
```yaml
kernelrelease: 5.14.0-162.12.1.el9_1.x86_64
target: almalinux
kernelrelease: 4.15.0-1057-aws
kernelversion: 59
target: ubuntu-aws
output:
module: /tmp/falco_almalinux_5.14.0-162.12.1.el9_1.x86_64.ko
probe: /tmp/falco_almalinux_5.14.0-162.12.1.el9_1.x86_64.o
module: /tmp/falco-ubuntu-aws.ko
probe: /tmp/falco-ubuntu-aws.o
driverversion: master
```
> **NOTE:** ubuntu-aws exists to retain backward compatibility only,
> and should not be used in new configs.
## centos 6
```yaml
kernelrelease: 2.6.32-754.14.2.el6.x86_64
kernelversion: 1
target: centos
output:
module: /tmp/falco-centos6.ko
driverversion: master
```
## centos 7
```yaml
kernelrelease: 3.10.0-957.12.2.el7.x86_64
kernelversion: 1
target: centos
output:
module: /tmp/falco-centos7.ko
driverversion: master
```
## centos 8
```yaml
kernelrelease: 4.18.0-147.5.1.el8_1.x86_64
kernelversion: 1
target: centos
output:
module: /tmp/falco-centos8.ko
driverversion: master
```
@ -65,58 +111,6 @@ output:
driverversion: master
```
## archlinux
Example configuration file to build both the Kernel module and eBPF probe for Archlinux.
Note: archlinux target uses the [Arch Linux Archive](https://wiki.archlinux.org/title/Arch_Linux_Archive) to fetch
all ever supported kernel releases.
For arm64, it uses an user-provided mirror, as no official mirror is available: http://tardis.tiny-vps.com/aarm/.
The mirror has been up and updated since 2015.
```yaml
kernelversion: 1
kernelrelease: 6.0.6.arch1-1
target: arch
output:
module: /tmp/falco-arch.ko
probe: /tmp/falco-arch.o
driverversion: master
builderimage: ${ARCH_BUILD_IMAGE_HERE}
```
## centos 6
```yaml
kernelrelease: 2.6.32-754.14.2.el6.x86_64
kernelversion: 1
target: centos
output:
module: /tmp/falco-centos6.ko
driverversion: master
```
## centos 7
```yaml
kernelrelease: 3.10.0-957.12.2.el7.x86_64
kernelversion: 1
target: centos
output:
module: /tmp/falco-centos7.ko
driverversion: master
```
## centos 8
```yaml
kernelrelease: 4.18.0-147.5.1.el8_1.x86_64
kernelversion: 1
target: centos
output:
module: /tmp/falco-centos8.ko
driverversion: master
```
## debian
Example configuration file to build both the Kernel module and eBPF probe for Debian.
@ -131,22 +125,10 @@ target: debian
driverversion: master
```
## fedora
```yaml
kernelrelease: 5.19.16-200.fc36.x86_64
kernelversion: 1
target: fedora
output:
module: /tmp/falco-fedora.ko
driverversion: master
```
## flatcar
Example configuration file to build both the Kernel module and eBPF probe for Flatcar.
The Flatcar release version needs to be provided in the `kernelrelease` field instead of the kernel version;
moreover, kernelconfigdata must be provided.
The Flatcar release version needs to be provided in the `kernelrelease` field instead of the kernel version.
```yaml
kernelrelease: 3185.0.0
@ -155,7 +137,6 @@ output:
module: /tmp/falco-flatcar-3185.0.0.ko
probe: /tmp/falco-flatcar-3185.0.0.o
driverversion: master
kernelconfigdata: Q09ORklHX0ZBTk9USUZZPXkKQ09ORklHX0t...
```
## minikube
@ -171,14 +152,21 @@ output:
kernelconfigdata: Q09ORklHX0ZBTk9USUZZPXkKQ09ORklHX0t...
```
## oracle linux 8
## archlinux
Example configuration file to build both the Kernel module and eBPF probe for Archlinux.
Note: archlinux target uses the [Arch Linux Archive](https://wiki.archlinux.org/title/Arch_Linux_Archive) to fetch
all ever supported kernel releases.
For arm64, it uses an user-provided mirror, as no official mirror is available: http://tardis.tiny-vps.com/aarm/.
The mirror has been up and updated since 2015.
```yaml
kernelrelease: 5.4.17-2011.3.2.1.el8uek.x86_64
kernelversion: 1
target: ol
kernelrelease: 4.20.3-arch1
target: archlinux
output:
module: /tmp/falco-ol8.ko
module: /tmp/falco-arch.ko
probe: /tmp/falco-arch.o
driverversion: master
```
@ -269,86 +257,9 @@ and Dockerfile.rhel9:
FROM docker.io/redhat/ubi9
RUN yum install gcc elfutils-libelf-devel kmod make cpio llvm-toolset -y
RUN ln -s /usr/bin/$(uname -p)-redhat-linux-gcc-11 /usr/bin/gcc-11
```
The `ln -s /usr/bin/$(uname -p)-redhat-linux-gcc-11 /usr/bin/gcc-11` command creates a symbolic link which makes sure driverkit finds the correct compiler binary.
| :exclamation: **subscription-manager does not work on RHEL9 containers**: Host must have a valid RHEL subscription. However, if you want to build the Docker image on a host that is not RHEL9, the container will not have access to the required repositories. In that case, the subscription manager can be enabled with some additional adjustments. |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Dockerfile.rhel9.containerSkip:
```bash
FROM docker.io/redhat/ubi9
ENV SMDEV_CONTAINER_OFF 1
ARG REDHAT_USERNAME
ARG REDHAT_PASSWORD
RUN subscription-manager register --username $REDHAT_USERNAME --password $REDHAT_PASSWORD --auto-attach
RUN yum install gcc elfutils-libelf-devel kmod make cpio llvm-toolset -y
RUN ln -s /usr/bin/$(uname -p)-redhat-linux-gcc-11 /usr/bin/gcc-11
```
Setting `SMDEV_CONTAINER_OFF 1` makes sure the container detection is skipped and therefore enables the subscription manager again.
## rocky linux
```yaml
kernelrelease: 5.14.0-162.18.1.el9_1.x86_64
target: rocky
output:
module: /tmp/falco_almalinux_5.14.0-162.18.1.el9_1.x86_64.ko
probe: /tmp/falco_almalinux_5.14.0-162.18.1.el9_1.x86_64.o
driverversion: master
```
## ubuntu
Example configuration file to build both the Kernel module and eBPF probe for Ubuntu (works with any flavor!).
```yaml
kernelrelease: 5.0.0-1021-aws-5.0
kernelversion: 24~18.04.1
target: ubuntu
output:
module: /tmp/falco-ubuntu-generic.ko
probe: /tmp/falco-ubuntu-generic.o
driverversion: master
```
## ubuntu-aws
Example configuration file to build both the Kernel module and eBPF probe for Ubuntu AWS.
```yaml
kernelrelease: 4.15.0-1057-aws
kernelversion: 59
target: ubuntu-aws
output:
module: /tmp/falco-ubuntu-aws.ko
probe: /tmp/falco-ubuntu-aws.o
driverversion: master
```
> **NOTE:** ubuntu-aws exists to retain backward compatibility only,
> and should not be used in new configs.
## ubuntu-generic
Example configuration file to build both the Kernel module and eBPF probe for Ubuntu generic.
```yaml
kernelrelease: 4.15.0-72-generic
kernelversion: 81
target: ubuntu-generic
output:
module: /tmp/falco-ubuntu-generic.ko
probe: /tmp/falco-ubuntu-generic.o
driverversion: master
```
> **NOTE:** ubuntu-generic exists to retain backward compatibility only,
> and should not be used in new configs.
| :exclamation: **subscription-manager does not work on RHEL9 containers**: Host must have a valid RHEL subscription |
|--------------------------------------------------------------------------------------------------------------------|
## vanilla
@ -382,4 +293,4 @@ So, we suggest to increase the `driverkit` timeout (defaults to `60` seconds):
```bash
driverkit docker -c /tmp/vanilla.yaml --timeout=300
```
```

View File

@ -16,24 +16,23 @@ ifeq ($(COMMITS_FROM_GIT_TAG),0)
endif
endif
DRIVERVERSIONS ?= master
DOCKER_ORG ?= falcosecurity
ARCH := $(shell uname -m)
IMAGE_NAME_BUILDER ?= docker.io/$(DOCKER_ORG)/driverkit-builder
BUILDERS := $(patsubst docker/builders/builder-%.Dockerfile,%,$(wildcard docker/builders/builder*$(ARCH)*.Dockerfile))
IMAGE_NAME_BUILDER_BASE ?= docker.io/$(DOCKER_ORG)/driverkit-builder
IMAGE_NAME_BUILDER_REF := $(IMAGE_NAME_BUILDER):$(GIT_REF)_$(shell uname -m)
IMAGE_NAME_BUILDER_COMMIT := $(IMAGE_NAME_BUILDER):$(GIT_COMMIT)_$(shell uname -m)
IMAGE_NAME_BUILDER_LATEST := $(IMAGE_NAME_BUILDER):latest_$(shell uname -m)
IMAGE_NAME_DRIVERKIT ?= docker.io/$(DOCKER_ORG)/driverkit
IMAGE_NAME_DRIVERKIT_REF := $(IMAGE_NAME_DRIVERKIT):$(GIT_REF)_$(ARCH)
IMAGE_NAME_DRIVERKIT_COMMIT := $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT)_$(ARCH)
IMAGE_NAME_DRIVERKIT_LATEST := $(IMAGE_NAME_DRIVERKIT):latest_$(ARCH)
IMAGE_NAME_DRIVERKIT_REF := $(IMAGE_NAME_DRIVERKIT):$(GIT_REF)_$(shell uname -m)
IMAGE_NAME_DRIVERKIT_COMMIT := $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT)_$(shell uname -m)
IMAGE_NAME_DRIVERKIT_LATEST := $(IMAGE_NAME_DRIVERKIT):latest_$(shell uname -m)
LDFLAGS := -X github.com/falcosecurity/driverkit/pkg/version.buildTime=$(shell date +%s) -X github.com/falcosecurity/driverkit/pkg/version.gitCommit=${GIT_COMMIT} -X github.com/falcosecurity/driverkit/pkg/version.gitTag=$(if ${GIT_TAG},${GIT_TAG},v0.0.0) -X github.com/falcosecurity/driverkit/pkg/version.commitsFromGitTag=${COMMITS_FROM_GIT_TAG} -X github.com/falcosecurity/driverkit/pkg/driverbuilder/builder.defaultImageTag=$(GIT_COMMIT)
TARGET_TEST_ARCH ?= $(ARCH)
LDFLAGS := -X github.com/falcosecurity/driverkit/pkg/version.buildTime=$(shell date +%s) -X github.com/falcosecurity/driverkit/pkg/version.gitCommit=${GIT_COMMIT} -X github.com/falcosecurity/driverkit/pkg/version.gitTag=$(if ${GIT_TAG},${GIT_TAG},v0.0.0) -X github.com/falcosecurity/driverkit/pkg/version.commitsFromGitTag=${COMMITS_FROM_GIT_TAG} -X github.com/falcosecurity/driverkit/pkg/driverbuilder.BuilderBaseImage=${IMAGE_NAME_BUILDER_COMMIT}
TARGET_TEST_ARCH ?= $(shell uname -m)
test_configs := $(wildcard test/$(TARGET_TEST_ARCH)/configs/*.yaml)
driverkit ?= _output/bin/driverkit
@ -43,7 +42,7 @@ driverkit_docgen ?= _output/bin/docgen
build: clean ${driverkit}
${driverkit}:
CGO_ENABLED=0 GOEXPERIMENT=loopvar go build -v -ldflags '${LDFLAGS}' -o $@ .
CGO_ENABLED=0 go build -v -buildmode=pie -ldflags '${LDFLAGS}' -o $@ .
.PHONY: release
release: clean
@ -58,58 +57,61 @@ image/all: image/builder image/driverkit
.PHONY: image/builder
image/builder:
$(foreach b,$(BUILDERS),\
$(DOCKER) buildx build -o type=image,push="false" -f docker/builders/builder-$b.Dockerfile . ; \
)
$(DOCKER) buildx build -o type=image,push="false" -f build/builder.Dockerfile .
.PHONY: image/driverkit
image/driverkit:
$(DOCKER) buildx build -o type=image,push="false" -f docker/driverkit.Dockerfile .
$(DOCKER) buildx build -o type=image,push="false" -f build/driverkit.Dockerfile .
push/all: push/builder push/driverkit
.PHONY: push/builder
push/builder:
$(foreach b,$(BUILDERS),\
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_BUILDER_BASE):$b-$(GIT_REF)" -t "$(IMAGE_NAME_BUILDER_BASE):$b-$(GIT_COMMIT)" -f docker/builders/builder-$b.Dockerfile . ; \
)
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_BUILDER_REF)" -t "$(IMAGE_NAME_BUILDER_COMMIT)" -f build/builder.Dockerfile .
.PHONY: push/driverkit
push/driverkit:
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_DRIVERKIT_REF)" -t "$(IMAGE_NAME_DRIVERKIT_COMMIT)" -f docker/driverkit.Dockerfile .
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_DRIVERKIT_REF)" -t "$(IMAGE_NAME_DRIVERKIT_COMMIT)" -f build/driverkit.Dockerfile .
.PHONY: push/latest
push/latest:
$(foreach b,$(BUILDERS),\
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_BUILDER_BASE):$b-latest" -f docker/builders/builder-$b.Dockerfile . ; \
)
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_DRIVERKIT_LATEST)" -f docker/driverkit.Dockerfile .
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_BUILDER_LATEST)" -f build/builder.Dockerfile .
$(DOCKER) buildx build --push -t "$(IMAGE_NAME_DRIVERKIT_LATEST)" -f build/driverkit.Dockerfile .
manifest/all: manifest/driverkit
manifest/all: manifest/builder manifest/driverkit
.PHONY: manifest/builder
manifest/builder:
$(DOCKER) manifest create $(IMAGE_NAME_BUILDER):$(GIT_REF) $(IMAGE_NAME_BUILDER):$(GIT_REF)_x86_64 $(IMAGE_NAME_BUILDER):$(GIT_REF)_aarch64
$(DOCKER) manifest push $(IMAGE_NAME_BUILDER):$(GIT_REF)
$(DOCKER) manifest create $(IMAGE_NAME_BUILDER):$(GIT_COMMIT) $(IMAGE_NAME_BUILDER):$(GIT_COMMIT)_x86_64 $(IMAGE_NAME_BUILDER):$(GIT_COMMIT)_aarch64
$(DOCKER) manifest push $(IMAGE_NAME_BUILDER):$(GIT_COMMIT)
.PHONY: manifest/driverkit
manifest/driverkit:
$(DOCKER) buildx imagetools create -t $(IMAGE_NAME_DRIVERKIT):$(GIT_REF) $(IMAGE_NAME_DRIVERKIT):$(GIT_REF)_x86_64 $(IMAGE_NAME_DRIVERKIT):$(GIT_REF)_aarch64
$(DOCKER) buildx imagetools create -t $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT) $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT)_x86_64 $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT)_aarch64
$(DOCKER) manifest create $(IMAGE_NAME_DRIVERKIT):$(GIT_REF) $(IMAGE_NAME_DRIVERKIT):$(GIT_REF)_x86_64 $(IMAGE_NAME_DRIVERKIT):$(GIT_REF)_aarch64
$(DOCKER) manifest push $(IMAGE_NAME_DRIVERKIT):$(GIT_REF)
$(DOCKER) manifest create $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT) $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT)_x86_64 $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT)_aarch64
$(DOCKER) manifest push $(IMAGE_NAME_DRIVERKIT):$(GIT_COMMIT)
.PHONY: manifest/latest
manifest/latest:
$(DOCKER) buildx imagetools create -t $(IMAGE_NAME_DRIVERKIT):latest $(IMAGE_NAME_DRIVERKIT):latest_x86_64 $(IMAGE_NAME_DRIVERKIT):latest_aarch64
$(DOCKER) manifest create $(IMAGE_NAME_BUILDER):latest $(IMAGE_NAME_BUILDER):latest_x86_64 $(IMAGE_NAME_BUILDER):latest_aarch64
$(DOCKER) manifest push $(IMAGE_NAME_BUILDER):latest
$(DOCKER) manifest create $(IMAGE_NAME_DRIVERKIT):latest $(IMAGE_NAME_DRIVERKIT):latest_x86_64 $(IMAGE_NAME_DRIVERKIT):latest_aarch64
$(DOCKER) manifest push $(IMAGE_NAME_DRIVERKIT):latest
.PHONY: test
test:
go clean -testcache
GOEXPERIMENT=loopvar go test -v -cover -race ./...
GOEXPERIMENT=loopvar go test -v -cover ./cmd
go test -v -cover -race ./...
go test -v -cover -buildmode=pie ./cmd
.PHONY: integration_test
integration_test: $(test_configs)
.PHONY: $(test_configs)
$(test_configs): ${driverkit}
$(foreach d,$(DRIVERVERSIONS),\
${driverkit} docker -c $@ --builderimage auto:master -l debug --timeout 600 --driverversion $d; \
)
${driverkit} docker -c $@ --builderimage falcosecurity/driverkit-builder:latest -l debug --timeout 600
.PHONY: ${driverkit_docgen}
${driverkit_docgen}: ${PWD}/docgen
@ -117,6 +119,6 @@ ${driverkit_docgen}: ${PWD}/docgen
.PHONY: docs
docs: ${driverkit_docgen}
$(RM) -R docs/driverkit*
$(RM) -R docs/*
@mkdir -p docs
${driverkit_docgen}

4
OWNERS
View File

@ -2,9 +2,5 @@ approvers:
- leodido
- dwindsor
- fededp
- EXONER4TED
- lowaiz
- LucaGuerra
emeritus_approvers:
- fntlnz

View File

@ -1,11 +1,7 @@
# driverkit
[![Falco Ecosystem Repository](https://github.com/falcosecurity/evolution/blob/main/repos/badges/falco-ecosystem-blue.svg)](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#ecosystem-scope) [![Incubating](https://img.shields.io/badge/status-incubating-orange?style=for-the-badge)](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#incubating)
[![Latest](https://img.shields.io/github/v/release/falcosecurity/driverkit?style=for-the-badge)](https://github.com/falcosecurity/driverkit/releases/latest)
![Architectures](https://img.shields.io/badge/ARCHS-x86__64%7Caarch64-blueviolet?style=for-the-badge)
[![Go Report Card](https://goreportcard.com/badge/github.com/falcosecurity/driverkit?style=for-the-badge)](https://goreportcard.com/report/github.com/falcosecurity/driverkit)
[![Docker pulls](https://img.shields.io/docker/pulls/falcosecurity/driverkit?style=for-the-badge)](https://hub.docker.com/r/falcosecurity/driverkit)
A command line tool that can be used to build the [Falco](https://github.com/falcosecurity/falco) kernel module and eBPF probe.
@ -59,7 +55,7 @@ that allows to specify a list of headers.
A solution to crawl all supported kernels by multiple distro was recently developed,
and it provides a json output with aforementioned `kernelheaders`: https://github.com/falcosecurity/kernel-crawler.
Json for supported architectures can be found at https://falcosecurity.github.io/kernel-crawler/.
Json for supported architectures can be found at https://github.com/falcosecurity/kernel-crawler/tree/main/kernels.
## How to use
@ -107,14 +103,10 @@ For a comprehensive list of examples, heads to [example configs](Example_configs
## Support a new target
To add support for a new target, a new builder must be added.
For more info, you can find specific docs in [docs/builder.md](docs/builder.md) file.
## Support a new builder image
To add support for a new builder image, follow the doc at [docs/builder_images.md](docs/builder_images.md) file.
For more info, you can find specific docs under [pkg/driverbuilder/builder](/pkg/driverbuilder/builder) README file.
## Survey
We are conducting a [survey](http://bit.ly/driverkit-survey-vote) to know what is the most interesting set of Operating Systems we must support first in driverkit.
You can find the results of the survey [here](http://bit.ly/driverkit-survey-results)
You can find the results of the survey [here](http://bit.ly/driverkit-survey-results)

View File

@ -1,6 +1,6 @@
# Release Process
Our release process is fully automated using [Github actions](.github/workflows/release.yml) and [goreleaser](https://github.com/goreleaser/goreleaser) tool for artifacts.
Our release process is based upon [CircleCI](https://app.circleci.com/pipelines/github/falcosecurity/driverkit) and [goreleaser](https://github.com/goreleaser/goreleaser) tool for artifacts.
When we release we do the following process:

View File

@ -5,29 +5,23 @@ LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG TARGETARCH
RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
# Use 20250630T203427Z debian apt snapshot as it still contains support for buster.
RUN cat <<EOF > /etc/apt/sources.list
deb http://snapshot.debian.org/archive/debian/20250630T203427Z buster main
deb http://snapshot.debian.org/archive/debian-security/20250630T203427Z buster/updates main
deb http://snapshot.debian.org/archive/debian/20250630T203427Z buster-updates main
EOF
RUN echo 'deb http://deb.debian.org/debian buster-backports main' >>/etc/apt/sources.list
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bash-completion \
bc \
clang \
llvm \
clang-7 \
ca-certificates \
curl \
dkms \
dwarves \
dwarves/buster-backports \
gnupg2 \
gcc \
jq \
libc6-dev \
libelf-dev \
llvm-7 \
netcat \
xz-utils \
rpm2cpio \
@ -45,19 +39,15 @@ RUN apt-get update \
software-properties-common \
gpg \
zstd \
gawk \
mawk \
git \
&& rm -rf /var/lib/apt/lists/*
&& rm -rf /var/lib/apt/lists/*
RUN if [ "$TARGETARCH" = "amd64" ] ; then apt-get install -y --no-install-recommends libmpx2; fi
# gcc 4.9 is required on x86 to build some 3.10+ kernels
# note: on arm gcc 4.9 could not be found.
RUN echo 'deb http://dk.archive.ubuntu.com/ubuntu/ xenial main' >> /etc/apt/sources.list && \
echo 'deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe' >> /etc/apt/sources.list
# repo is unsigned therefore the APT options
RUN if [ "$TARGETARCH" = "amd64" ] ; then apt-get -o Acquire::AllowInsecureRepositories=true -o Acquire::AllowDowngradeToInsecureRepositories=true update && apt-get -o APT::Get::AllowUnauthenticated=true install -y --no-install-recommends gcc-4.9; fi
# Install clang 12
RUN cd /tmp \
&& wget https://apt.llvm.org/llvm.sh \
&& chmod +x llvm.sh \
&& ./llvm.sh 12
# gcc 6 is no longer included in debian stable, but we need it to
# build kernel modules on the default debian-based ami used by
@ -130,17 +120,3 @@ RUN curl -L -o binutils_2.30-22_${TARGETARCH}.deb https://download.falco.org/dep
&& curl -L -o binutils-common_2.30-22_${TARGETARCH}.deb https://download.falco.org/dependencies/binutils-common_2.30-22_${TARGETARCH}.deb \
&& dpkg -i *binutils*.deb \
&& rm -f *binutils*.deb
# Install a recent version of cmake (debian buster has at most 3.13)
RUN curl -L -o /tmp/cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.22.5/cmake-3.22.5-linux-$(uname -m).tar.gz; \
gzip -d /tmp/cmake.tar.gz; \
tar -xpf /tmp/cmake.tar --directory=/tmp; \
cp -R /tmp/cmake-3.22.5-linux-$(uname -m)/* /usr; \
rm -rf /tmp/cmake-3.22.5-linux-$(uname -m)/
# Properly create soft link
RUN ln -s /usr/bin/gcc-4.8 /usr/bin/gcc-4.8.0
RUN if [ "$TARGETARCH" = "amd64" ] ; then ln -s /usr/bin/gcc-4.9 /usr/bin/gcc-4.9.0; fi;
RUN ln -s /usr/bin/gcc-5 /usr/bin/gcc-5.0.0
RUN ln -s /usr/bin/gcc-6 /usr/bin/gcc-6.0.0
RUN ln -s /usr/bin/gcc-8 /usr/bin/gcc-8.0.0

View File

@ -1,24 +1,13 @@
//go:build !race
// +build !race
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"io/ioutil"
"os"
"path/filepath"
"runtime"
@ -27,9 +16,6 @@ import (
"testing"
"text/template"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"github.com/acarl005/stripansi"
"gotest.tools/assert"
)
@ -130,8 +116,6 @@ var tests = []testCase{
"ubuntu-aws",
"--output-module",
"/tmp/falco-ubuntu-aws.ko",
"--output-probe",
"/tmp/falco-ubuntu-aws.o",
"--loglevel",
"debug",
},
@ -144,7 +128,6 @@ var tests = []testCase{
env: map[string]string{
"DRIVERKIT_KERNELVERSION": "59",
"DRIVERKIT_OUTPUT_MODULE": "/tmp/falco-ubuntu-aws.ko",
"DRIVERKIT_OUTPUT_PROBE": "/tmp/falco-ubuntu-aws.o",
},
args: []string{
"docker",
@ -219,7 +202,7 @@ var tests = []testCase{
"--kernelurls",
"http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-headers-4.15.0-1057-azure_4.15.0-1057.62_amd64.deb",
"--target",
"ubuntu-azure",
"ubuntu-aws",
"--output-module",
"/tmp/falco-ubuntu-azure.ko",
"--loglevel",
@ -316,14 +299,9 @@ var tests = []testCase{
func run(t *testing.T, test testCase) {
// Setup
configOpts, err := NewConfigOptions()
assert.NilError(t, err)
rootOpts, err := NewRootOptions()
assert.NilError(t, err)
var buf bytes.Buffer
configOpts.setOutput(&buf, true)
c := NewRootCmd(configOpts, rootOpts)
c.SetOutput(&buf)
c := NewRootCmd()
b := bytes.NewBufferString("")
c.SetOutput(b)
if len(test.args) == 0 || (test.args[0] != "__complete" && test.args[0] != "__completeNoDesc" && test.args[0] != "help" && test.args[0] != "completion") {
test.args = append(test.args, "--dryrun")
}
@ -334,18 +312,19 @@ func run(t *testing.T, test testCase) {
}
}
// Test
err = c.Execute()
err := c.Execute()
if err != nil {
if test.expect.err == "" {
t.Fatalf("error executing CLI: %v", err)
} else {
assert.Error(t, err, test.expect.err)
}
// Exactly same behavior as rootCmd.Start(), but here we use ERROR instead of FATAL to avoid leaving
configOpts.Printer.Logger.Error("error executing driverkit", configOpts.Printer.Logger.Args("err", err.Error()))
}
out := buf.String()
res := stripansi.Strip(out)
out, err := ioutil.ReadAll(b)
if err != nil {
t.Fatalf("error reading CLI output: %v", err)
}
res := stripansi.Strip(string(out))
assert.Equal(t, test.expect.out, res)
// Teardown
for k := range test.env {
@ -370,7 +349,7 @@ type testTemplateData struct {
}
func readTemplateFile(t *testing.T, s string) string {
out, err := os.ReadFile("testdata/templates/" + s)
out, err := ioutil.ReadFile("testdata/templates/" + s)
assert.NilError(t, err)
return string(out)
}
@ -399,7 +378,7 @@ type flagsTemplateData struct {
}
func initFlagsTemplateData(args []string) flagsTemplateData {
targets := builder.Targets()
targets := builder.BuilderByTarget.Targets()
sort.Strings(targets)
cmd := "driverkit"
@ -440,7 +419,7 @@ func TestCLI(t *testing.T) {
test.descr = strings.TrimSuffix(filepath.Base(test.expect.out), ".txt")
}
if test.expect.out != "" {
out, err := os.ReadFile(test.expect.out)
out, err := ioutil.ReadFile(test.expect.out)
if err != nil {
t.Fatalf("output fixture not found: %v", err)
}

View File

@ -1,23 +1,8 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"fmt"
"github.com/spf13/pflag"
"os"
"strings"
"text/template"
@ -47,12 +32,12 @@ func validateArgs() cobra.PositionalArgs {
if len(args) == 0 {
return nil
}
return cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs)(c, args)
return cobra.ExactValidArgs(1)(c, args)
}
}
// NewCompletionCmd ...
func NewCompletionCmd(_ *ConfigOptions, _ *RootOptions, _ *pflag.FlagSet) *cobra.Command {
func NewCompletionCmd() *cobra.Command {
var long bytes.Buffer
tmpl := template.Must(template.New("long").Parse(longUsageTemplate))
tmpl.Execute(&long, map[string]interface{}{
@ -66,23 +51,25 @@ func NewCompletionCmd(_ *ConfigOptions, _ *RootOptions, _ *pflag.FlagSet) *cobra
Args: validateArgs(),
ValidArgs: cmdArgs,
DisableAutoGenTag: true,
RunE: func(c *cobra.Command, args []string) error {
Run: func(c *cobra.Command, args []string) {
if len(args) == 0 {
return c.Help()
c.Help()
return
}
arg := args[0]
switch arg {
case "bash":
return c.Root().GenBashCompletion(os.Stdout)
c.Root().GenBashCompletion(os.Stdout)
break
case "zsh":
return c.Root().GenZshCompletion(os.Stdout)
c.Root().GenZshCompletion(os.Stdout)
break
case "fish":
return c.Root().GenFishCompletion(os.Stdout, true)
c.Root().GenFishCompletion(os.Stdout, true)
case "help":
return c.Help()
c.Help()
}
return nil
},
}

View File

@ -1,155 +1,49 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"errors"
"github.com/falcosecurity/falcoctl/pkg/output"
"github.com/mitchellh/go-homedir"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"io"
"os"
"strings"
"fmt"
"github.com/creasty/defaults"
"github.com/falcosecurity/driverkit/validate"
"github.com/go-playground/validator/v10"
"github.com/pterm/pterm"
logger "github.com/sirupsen/logrus"
)
var validProcessors = []string{"docker", "kubernetes", "kubernetes-in-cluster", "local"}
var aliasProcessors = []string{"docker", "k8s", "k8s-ic"}
var validProcessors = []string{"docker", "kubernetes"}
var aliasProcessors = []string{"docker", "k8s"}
var configOptions *ConfigOptions
// ConfigOptions represent the persistent configuration flags of driverkit.
type ConfigOptions struct {
configFile string
ConfigFile string
LogLevel string `validate:"logrus" name:"log level" default:"info"`
Timeout int `validate:"number,min=30" default:"120" name:"timeout"`
ProxyURL string `validate:"omitempty,proxy" name:"proxy url"`
dryRun bool
DryRun bool
// Printer used by all commands to output messages.
Printer *output.Printer
// writer is used to write the output of the printer.
writer io.Writer
logLevel *output.LogLevel
disableStyling bool
}
func (co *ConfigOptions) initPrinter() {
// DisableStyling is only enforced by tests.
if co.disableStyling {
pterm.DisableStyling()
}
co.Printer = output.NewPrinter(co.logLevel.ToPtermLogLevel(), pterm.LogFormatterColorful, co.writer)
if co.disableStyling {
// Disable time print for tests
co.Printer.Logger = co.Printer.Logger.WithTime(false)
}
}
// Called by tests to disable styling and set bytes buffer as output
func (co *ConfigOptions) setOutput(writer io.Writer, disableStyling bool) {
co.writer = writer
co.disableStyling = disableStyling
co.initPrinter()
configErrors bool
}
// NewConfigOptions creates an instance of ConfigOptions.
func NewConfigOptions() (*ConfigOptions, error) {
o := &ConfigOptions{
writer: os.Stdout,
logLevel: output.NewLogLevel(),
disableStyling: false,
}
o.initPrinter()
func NewConfigOptions() *ConfigOptions {
o := &ConfigOptions{}
if err := defaults.Set(o); err != nil {
// Return ConfigOptions anyway because we need the logger
return o, err
logger.WithError(err).WithField("options", "ConfigOptions").Fatal("error setting driverkit options defaults")
}
return o, nil
return o
}
// Validate validates the ConfigOptions fields.
func (co *ConfigOptions) validate() []error {
func (co *ConfigOptions) Validate() []error {
if err := validate.V.Struct(co); err != nil {
var errs validator.ValidationErrors
errors.As(err, &errs)
var errArr []error
for _, e := range errs {
errors := err.(validator.ValidationErrors)
errArr := []error{}
for _, e := range errors {
// Translate each error one at a time
errArr = append(errArr, errors.New(e.Translate(validate.T)))
errArr = append(errArr, fmt.Errorf(e.Translate(validate.T)))
}
co.configErrors = true
return errArr
}
return nil
}
// AddFlags registers the common flags.
func (co *ConfigOptions) AddFlags(flags *pflag.FlagSet) {
flags.StringVarP(&co.configFile, "config", "c", co.configFile, "config file path (default $HOME/.driverkit.yaml if exists)")
flags.VarP(co.logLevel, "loglevel", "l", "set level for logs "+co.logLevel.Allowed())
flags.IntVar(&co.Timeout, "timeout", co.Timeout, "timeout in seconds")
flags.StringVar(&co.ProxyURL, "proxy", co.ProxyURL, "the proxy to use to download data")
flags.BoolVar(&co.dryRun, "dryrun", co.dryRun, "do not actually perform the action")
}
// Init reads in config file and ENV variables if set.
func (co *ConfigOptions) Init() bool {
configErr := false
if errs := co.validate(); errs != nil {
for _, err := range errs {
co.Printer.Logger.Error("error validating config options",
co.Printer.Logger.Args("err", err.Error()))
}
configErr = true
}
if co.configFile != "" {
viper.SetConfigFile(co.configFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
co.Printer.Logger.Error("error getting the home directory",
co.Printer.Logger.Args("err", err.Error()))
// not setting configErr = true because we fallback to `$HOME/.driverkit.yaml` and try with it
}
viper.AddConfigPath(home)
viper.SetConfigName(".driverkit")
}
viper.AutomaticEnv()
viper.SetEnvPrefix("driverkit")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
// If a config file is found, read it in.
err := viper.ReadInConfig()
// Init printer with either read or existent one,
// so that we can further log considering log level set.
co.initPrinter()
if err == nil {
co.Printer.Logger.Info("using config file",
co.Printer.Logger.Args("file", viper.ConfigFileUsed()))
} else {
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
// Config file not found, ignore ...
co.Printer.Logger.Debug("running without a configuration file")
}
}
return configErr
}

View File

@ -1,56 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
logger "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
// NewDockerCmd creates the `driverkit docker` command.
func NewDockerCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
func NewDockerCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
dockerCmd := &cobra.Command{
Use: "docker",
Short: "Build Falco kernel modules and eBPF probes against a docker daemon.",
RunE: func(c *cobra.Command, args []string) error {
configOpts.Printer.Logger.Info("starting build",
configOpts.Printer.Logger.Args("processor", c.Name()))
if !configOpts.dryRun {
if !rootOpts.Output.HasOutputs() {
configOpts.Printer.Logger.Info("no output specified")
return nil
Run: func(c *cobra.Command, args []string) {
logger.WithField("processor", c.Name()).Info("driver building, it will take a few seconds")
if !configOptions.DryRun {
if err := driverbuilder.NewDockerBuildProcessor(viper.GetInt("timeout"), viper.GetString("proxy")).Start(rootOpts.toBuild()); err != nil {
logger.WithError(err).Fatal("exiting")
}
// Since we use a spinner, cache log data to a bytesbuffer;
// we will later print it once we stop the spinner.
var b *builder.Build
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
var buf bytes.Buffer
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
}
return driverbuilder.NewDockerBuildProcessor(configOpts.Timeout, configOpts.ProxyURL).Start(b)
}
return nil
},
}
// Add root flags

View File

@ -1,74 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"os"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
// NewImagesCmd creates the `driverkit images` command.
func NewImagesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
imagesCmd := &cobra.Command{
Use: "images",
Short: "List builder images",
RunE: func(c *cobra.Command, args []string) error {
configOpts.Printer.Logger.Info("starting loading images",
configOpts.Printer.Logger.Args("processor", c.Name()))
// Since we use a spinner, cache log data to a bytesbuffer;
// we will later print it once we stop the spinner.
var (
buf bytes.Buffer
b *builder.Build
)
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("listing images, it will take a few seconds")
}
b.LoadImages()
if !configOpts.disableStyling {
_ = configOpts.Printer.Spinner.Stop()
configOpts.Printer.DefaultText.Print(buf.String())
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Image", "Target", "Arch", "GCC"})
table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false})
table.SetCenterSeparator("|")
for _, img := range b.Images {
data := make([]string, 4)
data[0] = img.Name
data[1] = img.Target.String()
data[2] = b.Architecture
data[3] = img.GCCVersion.String()
table.Append(data)
}
table.Render() // Send output
return nil
},
}
// Add root flags
imagesCmd.PersistentFlags().AddFlagSet(rootFlags)
return imagesCmd
}

View File

@ -1,34 +1,20 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"regexp"
"strings"
"github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/kubernetes/factory"
logger "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
// NewKubernetesCmd creates the `driverkit kubernetes` command.
func NewKubernetesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
func NewKubernetesCmd(rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
kubernetesCmd := &cobra.Command{
Use: "kubernetes",
Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster.",
@ -48,48 +34,35 @@ func NewKubernetesCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlag
f.Usage = upperAfterPointRegexp.ReplaceAllString(f.Usage, ", ${1}")
f.Usage = upperAfterCommaRegexp.ReplaceAllStringFunc(f.Usage, strings.ToLower)
})
// Add Kubernetes pods options flags
flags := kubernetesCmd.Flags()
addKubernetesFlags(flags)
kubernetesCmd.PersistentFlags().AddFlagSet(flags)
// Add root flags
kubernetesCmd.PersistentFlags().AddFlagSet(rootFlags)
kubefactory := factory.NewFactory(configFlags)
kubernetesCmd.RunE = func(c *cobra.Command, args []string) error {
configOpts.Printer.Logger.Info("starting build",
configOpts.Printer.Logger.Args("processor", c.Name()))
if !configOpts.dryRun {
if !rootOpts.Output.HasOutputs() {
configOpts.Printer.Logger.Info("no output specified")
return nil
kubernetesCmd.Run = func(cmd *cobra.Command, args []string) {
logger.WithField("processor", cmd.Name()).Info("driver building, it will take a few seconds")
if !configOptions.DryRun {
if err := kubernetesRun(cmd, args, kubefactory, rootOpts); err != nil {
logger.WithError(err).Fatal("exiting")
}
// Since we use a spinner, cache log data to a bytesbuffer;
// we will later print it once we stop the spinner.
var b *builder.Build
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
var buf bytes.Buffer
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
}
return kubernetesRun(kubefactory, b, configOpts)
}
return nil
}
return kubernetesCmd
}
func kubernetesRun(kubefactory factory.Factory,
b *builder.Build,
configOpts *ConfigOptions,
) error {
func kubernetesRun(cmd *cobra.Command, args []string, kubefactory factory.Factory, rootOpts *RootOptions) error {
f := cmd.Flags()
b := rootOpts.toBuild()
namespaceStr, err := f.GetString("namespace")
if err != nil {
return err
}
if len(namespaceStr) == 0 {
namespaceStr = "default"
}
kc, err := kubefactory.KubernetesClientSet()
if err != nil {
return err
@ -102,12 +75,7 @@ func kubernetesRun(kubefactory factory.Factory,
return err
}
buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(),
clientConfig,
kubernetesOptions.RunAsUser,
kubernetesOptions.Namespace,
kubernetesOptions.ImagePullSecret,
configOpts.Timeout,
configOpts.ProxyURL)
buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(), clientConfig, namespaceStr, viper.GetInt("timeout"), viper.GetString("proxy"))
return buildProcessor.Start(b)
}

View File

@ -1,94 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"bytes"
"github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kubernetes/factory"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
// NewKubernetesInClusterCmd creates the `driverkit kubernetes` command.
func NewKubernetesInClusterCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
kubernetesInClusterCmd := &cobra.Command{
Use: "kubernetes-in-cluster",
Short: "Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.",
Aliases: []string{"k8s-ic"},
}
// Add Kubernetes pods options flags
flags := kubernetesInClusterCmd.Flags()
addKubernetesFlags(flags)
kubernetesInClusterCmd.PersistentFlags().AddFlagSet(flags)
// Add root flags
kubernetesInClusterCmd.PersistentFlags().AddFlagSet(rootFlags)
kubernetesInClusterCmd.RunE = func(c *cobra.Command, args []string) error {
configOpts.Printer.Logger.Info("starting build",
configOpts.Printer.Logger.Args("processor", c.Name()))
if !configOpts.dryRun {
if !rootOpts.Output.HasOutputs() {
configOpts.Printer.Logger.Info("no output specified")
return nil
}
// Since we use a spinner, cache log data to a bytesbuffer;
// we will later print it once we stop the spinner.
var b *builder.Build
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
var buf bytes.Buffer
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
}
return kubernetesInClusterRun(b, configOpts)
}
return nil
}
return kubernetesInClusterCmd
}
func kubernetesInClusterRun(b *builder.Build, configOpts *ConfigOptions) error {
kubeConfig, err := rest.InClusterConfig()
if err != nil {
return err
}
if err = factory.SetKubernetesDefaults(kubeConfig); err != nil {
return err
}
kc, err := kubernetes.NewForConfig(kubeConfig)
if err != nil {
return err
}
buildProcessor := driverbuilder.NewKubernetesBuildProcessor(kc.CoreV1(),
kubeConfig,
kubernetesOptions.RunAsUser,
kubernetesOptions.Namespace,
kubernetesOptions.ImagePullSecret,
configOpts.Timeout,
configOpts.ProxyURL)
return buildProcessor.Start(b)
}

View File

@ -1,31 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import flag "github.com/spf13/pflag"
var kubernetesOptions = &KubeOptions{}
type KubeOptions struct {
RunAsUser int64 `json:"runAsUser,omitempty" protobuf:"varint,2,opt,name=runAsUser" default:"0"`
Namespace string `validate:"required" name:"namespace" default:"default"`
ImagePullSecret string `validate:"omitempty" name:"image-pull-secret" default:""`
}
func addKubernetesFlags(flags *flag.FlagSet) {
flags.StringVarP(&kubernetesOptions.Namespace, "namespace", "n", "default", "If present, the namespace scope for the pods and its config ")
flags.Int64Var(&kubernetesOptions.RunAsUser, "run-as-user", 0, "Pods runner user")
flags.StringVar(&kubernetesOptions.ImagePullSecret, "image-pull-secret", "", "ImagePullSecret")
}

View File

@ -1,81 +0,0 @@
package cmd
import (
"bytes"
"github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
type localCmdOptions struct {
useDKMS bool
downloadHeaders bool
srcDir string
envMap map[string]string
}
// NewLocalCmd creates the `driverkit local` command.
func NewLocalCmd(configOpts *ConfigOptions, rootOpts *RootOptions, rootFlags *pflag.FlagSet) *cobra.Command {
opts := localCmdOptions{}
localCmd := &cobra.Command{
Use: "local",
Short: "Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.",
RunE: func(c *cobra.Command, args []string) error {
configOpts.Printer.Logger.Info("starting build",
configOpts.Printer.Logger.Args("processor", c.Name()))
if !configOpts.dryRun {
if !rootOpts.Output.HasOutputs() {
configOpts.Printer.Logger.Info("no output specified")
return nil
}
// Since we use a spinner, cache log data to a bytesbuffer;
// we will later print it once we stop the spinner.
var b *builder.Build
if configOpts.disableStyling {
b = rootOpts.ToBuild(configOpts.Printer)
} else {
var buf bytes.Buffer
b = rootOpts.ToBuild(configOpts.Printer.WithWriter(&buf))
configOpts.Printer.Spinner, _ = configOpts.Printer.Spinner.Start("driver building, it will take a few seconds")
defer func() {
configOpts.Printer.DefaultText.Print(buf.String())
}()
}
return driverbuilder.NewLocalBuildProcessor(opts.useDKMS,
opts.downloadHeaders,
false,
opts.srcDir,
opts.envMap,
configOpts.Timeout).Start(b)
}
return nil
},
}
// Add root flags, but not the ones unneeded
unusedFlagsSet := map[string]struct{}{
"architecture": {},
"kernelurls": {},
"builderrepo": {},
"builderimage": {},
"gccversion": {},
"kernelconfigdata": {},
"proxy": {},
"registry-name": {},
"registry-password": {},
"registry-plain-http": {},
"registry-user": {},
}
flagSet := pflag.NewFlagSet("local", pflag.ExitOnError)
rootFlags.VisitAll(func(flag *pflag.Flag) {
if _, ok := unusedFlagsSet[flag.Name]; !ok {
flagSet.AddFlag(flag)
}
})
flagSet.BoolVar(&opts.useDKMS, "dkms", false, "Enforce usage of DKMS to build the kernel module.")
flagSet.BoolVar(&opts.downloadHeaders, "download-headers", false, "Try to automatically download kernel headers.")
flagSet.StringVar(&opts.srcDir, "src-dir", "", "Enforce usage of local source dir to build drivers.")
flagSet.StringToStringVar(&opts.envMap, "env", make(map[string]string), "Env variables to be enforced during the driver build.")
localCmd.PersistentFlags().AddFlagSet(flagSet)
return localCmd
}

View File

@ -1,43 +1,29 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"errors"
"fmt"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"io"
"os"
"runtime"
"sort"
"strings"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"github.com/falcosecurity/driverkit/pkg/version"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
homedir "github.com/mitchellh/go-homedir"
logger "github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, rootOpts *RootOptions) func(c *cobra.Command, args []string) error {
func persistentValidateFunc(rootCommand *RootCmd, rootOpts *RootOptions) func(c *cobra.Command, args []string) error {
return func(c *cobra.Command, args []string) error {
var validationError = errors.New("exiting for validation errors")
configErr := configOpts.Init()
// Early exit if detect some error into config flags
if configErr {
return validationError
if configOptions.configErrors {
return fmt.Errorf("exiting for validation errors")
}
// Merge environment variables or config file values into the RootOptions instance
skip := map[string]bool{ // do not merge these
@ -58,13 +44,13 @@ func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, roo
// rather than replace, it appends. Since viper will already have the cli options set
// if supplied, we only need this step if rootCommand doesn't already have them e.g.
// not set on CLI so read from config.
if cliURLs, err := rootCommand.c.Flags().GetStringSlice(name); err == nil && len(cliURLs) != 0 {
if cli_urls, err := rootCommand.c.Flags().GetStringSlice(name); err == nil && len(cli_urls) != 0 {
return
}
value := viper.GetStringSlice(name)
if len(value) != 0 {
strValue := strings.Join(value, ",")
_ = rootCommand.c.Flags().Set(name, strValue)
rootCommand.c.Flags().Set(name, strValue)
}
} else {
value := viper.GetString(name)
@ -76,7 +62,7 @@ func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, roo
}
// set the value, if any, otherwise let the default
if value != "" {
_ = rootCommand.c.Flags().Set(name, value)
rootCommand.c.Flags().Set(name, value)
}
}
}
@ -89,12 +75,11 @@ func persistentValidateFunc(rootCommand *RootCmd, configOpts *ConfigOptions, roo
if c.Root() != c && c.Name() != "help" && c.Name() != "__complete" && c.Name() != "__completeNoDesc" && c.Name() != "completion" {
if errs := rootOpts.Validate(); errs != nil {
for _, err := range errs {
configOpts.Printer.Logger.Error("error validating build options",
configOpts.Printer.Logger.Args("err", err.Error()))
logger.WithError(err).Error("error validating build options")
}
return validationError
return fmt.Errorf("exiting for validation errors")
}
rootOpts.Log(configOpts.Printer)
rootOpts.Log()
}
return nil
}
@ -106,7 +91,9 @@ type RootCmd struct {
}
// NewRootCmd instantiates the root command.
func NewRootCmd(configOpts *ConfigOptions, rootOpts *RootOptions) *RootCmd {
func NewRootCmd() *RootCmd {
configOptions = NewConfigOptions()
rootOpts := NewRootOptions()
rootCmd := &cobra.Command{
Use: "driverkit",
Short: "A command line tool to build Falco kernel modules and eBPF probes.",
@ -115,51 +102,60 @@ func NewRootCmd(configOpts *ConfigOptions, rootOpts *RootOptions) *RootCmd {
Args: cobra.OnlyValidArgs,
DisableFlagsInUseLine: true,
DisableAutoGenTag: true,
SilenceErrors: true,
SilenceUsage: true,
Version: version.String(),
RunE: func(c *cobra.Command, args []string) error {
Run: func(c *cobra.Command, args []string) {
if len(args) == 0 {
configOpts.Printer.Logger.Info("specify a valid processor", configOpts.Printer.Logger.Args("processors", validProcessors))
logger.WithField("processors", validProcessors).Info("specify a valid processor")
}
// Fallback to help
return c.Help()
c.Help()
},
}
ret := &RootCmd{
c: rootCmd,
}
rootCmd.PersistentPreRunE = persistentValidateFunc(ret, configOpts, rootOpts)
rootCmd.PersistentPreRunE = persistentValidateFunc(ret, rootOpts)
flags := rootCmd.Flags()
targets := builder.Targets()
targets := builder.BuilderByTarget.Targets()
sort.Strings(targets)
configOpts.AddFlags(flags)
rootOpts.AddFlags(flags, targets)
flags.StringVarP(&configOptions.ConfigFile, "config", "c", configOptions.ConfigFile, "config file path (default $HOME/.driverkit.yaml if exists)")
flags.StringVarP(&configOptions.LogLevel, "loglevel", "l", configOptions.LogLevel, "log level")
flags.IntVar(&configOptions.Timeout, "timeout", configOptions.Timeout, "timeout in seconds")
flags.BoolVar(&configOptions.DryRun, "dryrun", configOptions.DryRun, "do not actually perform the action")
flags.StringVar(&configOptions.ProxyURL, "proxy", configOptions.ProxyURL, "the proxy to use to download data")
if err := viper.BindPFlags(flags); err != nil {
panic(err)
}
flags.StringVar(&rootOpts.Output.Module, "output-module", rootOpts.Output.Module, "filepath where to save the resulting kernel module")
flags.StringVar(&rootOpts.Output.Probe, "output-probe", rootOpts.Output.Probe, "filepath where to save the resulting eBPF probe")
flags.StringVar(&rootOpts.Architecture, "architecture", runtime.GOARCH, "target architecture for the built driver, one of "+kernelrelease.SupportedArchs.String())
flags.StringVar(&rootOpts.DriverVersion, "driverversion", rootOpts.DriverVersion, "driver version as a git commit hash or as a git tag")
flags.StringVar(&rootOpts.KernelVersion, "kernelversion", rootOpts.KernelVersion, "kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v'")
flags.StringVar(&rootOpts.KernelRelease, "kernelrelease", rootOpts.KernelRelease, "kernel release to build the module for, it can be found by executing 'uname -v'")
flags.StringVarP(&rootOpts.Target, "target", "t", rootOpts.Target, "the system to target the build for, one of ["+strings.Join(targets, ",")+"]")
flags.StringVar(&rootOpts.KernelConfigData, "kernelconfigdata", rootOpts.KernelConfigData, "base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc")
flags.StringVar(&rootOpts.ModuleDeviceName, "moduledevicename", rootOpts.ModuleDeviceName, "kernel module device name (the default is falco, so the device will be under /dev/falco*)")
flags.StringVar(&rootOpts.ModuleDriverName, "moduledrivername", rootOpts.ModuleDriverName, "kernel module driver name, i.e. the name you see when you check installed modules via lsmod")
flags.StringVar(&rootOpts.BuilderImage, "builderimage", rootOpts.BuilderImage, "docker image to be used to build the kernel module and eBPF probe. If not provided, the default image will be used.")
flags.StringSliceVar(&rootOpts.KernelUrls, "kernelurls", nil, "list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls \"<URL3>,<URL4>\")")
viper.BindPFlags(flags)
// Flag annotations and custom completions
_ = rootCmd.MarkFlagFilename("config", viper.SupportedExts...)
_ = rootCmd.RegisterFlagCompletionFunc("target", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
rootCmd.MarkFlagFilename("config", viper.SupportedExts...)
rootCmd.RegisterFlagCompletionFunc("target", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return targets, cobra.ShellCompDirectiveDefault
})
_ = rootCmd.RegisterFlagCompletionFunc("architecture", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
rootCmd.RegisterFlagCompletionFunc("architecture", func(c *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return kernelrelease.SupportedArchs.Strings(), cobra.ShellCompDirectiveDefault
})
// Subcommands
rootCmd.AddCommand(NewKubernetesCmd(configOpts, rootOpts, flags))
rootCmd.AddCommand(NewKubernetesInClusterCmd(configOpts, rootOpts, flags))
rootCmd.AddCommand(NewDockerCmd(configOpts, rootOpts, flags))
rootCmd.AddCommand(NewLocalCmd(configOpts, rootOpts, flags))
rootCmd.AddCommand(NewImagesCmd(configOpts, rootOpts, flags))
rootCmd.AddCommand(NewCompletionCmd(configOpts, rootOpts, flags))
rootCmd.AddCommand(NewKubernetesCmd(rootOpts, flags))
rootCmd.AddCommand(NewDockerCmd(rootOpts, flags))
rootCmd.AddCommand(NewCompletionCmd())
ret.StripSensitive()
@ -188,15 +184,16 @@ func (r *RootCmd) Command() *cobra.Command {
return r.c
}
// SetArgs proxies the arguments to the underlying cobra.Command.
func (r *RootCmd) SetArgs(args []string) {
r.c.SetArgs(args)
}
// SetOutput sets the main command output writer.
func (r *RootCmd) SetOutput(w io.Writer) {
r.c.SetOut(w)
r.c.SetErr(w)
logger.SetOutput(w)
}
// SetArgs proxies the arguments to the underlying cobra.Command.
func (r *RootCmd) SetArgs(args []string) {
r.c.SetArgs(args)
}
// Execute proxies the cobra.Command execution.
@ -206,30 +203,59 @@ func (r *RootCmd) Execute() error {
// Start creates the root command and runs it.
func Start() {
configOpts, err := NewConfigOptions()
if err != nil {
// configOpts will never be nil here
if configOpts != nil {
configOpts.Printer.Logger.Fatal("error setting driverkit config options defaults",
configOpts.Printer.Logger.Args("err", err.Error()))
} else {
os.Exit(1)
}
}
rootOpts, err := NewRootOptions()
if err != nil {
configOpts.Printer.Logger.Fatal("error setting driverkit root options defaults",
configOpts.Printer.Logger.Args("err", err.Error()))
}
// Cleanup spinner upon leaving if any
defer func() {
if configOpts.Printer.Spinner != nil {
_ = configOpts.Printer.Spinner.Stop()
}
}()
root := NewRootCmd(configOpts, rootOpts)
if err = root.Execute(); err != nil {
configOpts.Printer.Logger.Fatal("error executing driverkit", configOpts.Printer.Logger.Args("err", err.Error()))
root := NewRootCmd()
if err := root.Execute(); err != nil {
logger.WithError(err).Fatal("error executing driverkit")
}
}
func init() {
logger.SetFormatter(&logger.TextFormatter{
ForceColors: true,
DisableLevelTruncation: false,
DisableTimestamp: true,
})
cobra.OnInitialize(initConfig)
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if errs := configOptions.Validate(); errs != nil {
for _, err := range errs {
logger.WithError(err).Error("error validating config options")
}
// configOptions.configErrors should be true here
}
if configOptions.ConfigFile != "" {
viper.SetConfigFile(configOptions.ConfigFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
logger.WithError(err).Debug("error getting the home directory")
// not setting configOptions.configErrors = true because we fallback to `$HOME/.driverkit.yaml` and try with it
}
viper.AddConfigPath(home)
viper.SetConfigName(".driverkit")
}
viper.AutomaticEnv()
viper.SetEnvPrefix("driverkit")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
logger.WithField("file", viper.ConfigFileUsed()).Info("using config file")
} else {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found, ignore ...
logger.Debug("running without a configuration file")
} else {
// Config file was found but another error was produced
logger.WithField("file", viper.ConfigFileUsed()).WithError(err).Debug("error running with config file")
configOptions.configErrors = true
}
}
}

View File

@ -1,32 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd
import (
"errors"
"github.com/falcosecurity/falcoctl/pkg/output"
"github.com/spf13/pflag"
"os"
"runtime"
"strings"
"fmt"
"github.com/creasty/defaults"
"github.com/falcosecurity/driverkit/pkg/driverbuilder"
"github.com/falcosecurity/driverkit/pkg/driverbuilder/builder"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"github.com/falcosecurity/driverkit/validate"
"github.com/go-playground/validator/v10"
logger "github.com/sirupsen/logrus"
)
// OutputOptions wraps the two drivers that driverkit builds.
@ -35,22 +17,6 @@ type OutputOptions struct {
Probe string `validate:"required_without=Module,filepath,omitempty,endswith=.o" name:"output probe path"`
}
func (oo *OutputOptions) HasOutputs() bool {
return oo.Module != "" || oo.Probe != ""
}
type RepoOptions struct {
Org string `default:"falcosecurity" name:"organization name"`
Name string `default:"libs" name:"repo name"`
}
type Registry struct {
Name string `validate:"required_with=Username Password" name:"registry name"`
Username string `validate:"required_with=Registry Password" name:"registry username"`
Password string `validate:"required_with=Username Registry" name:"registry password"`
PlainHTTP bool `default:"false" name:"registry plain http"`
}
// RootOptions ...
type RootOptions struct {
Architecture string `validate:"required,architecture" name:"architecture"`
@ -61,160 +27,96 @@ type RootOptions struct {
KernelRelease string `validate:"required,ascii" name:"kernel release"`
Target string `validate:"required,target" name:"target"`
KernelConfigData string `validate:"omitempty,base64" name:"kernel config data"` // fixme > tag "name" does not seem to work when used at struct level, but works when used at inner level
BuilderImage string `validate:"omitempty,imagename" name:"builder image"`
BuilderRepos []string `default:"[\"docker.io/falcosecurity/driverkit-builder\"]" validate:"omitempty" name:"docker repositories to look for builder images or absolute path pointing to a yaml file containing builder images index"`
GCCVersion string `validate:"omitempty,semvertolerant" name:"gcc version"`
BuilderImage string `validate:"imagename" name:"builder image"`
KernelUrls []string `name:"kernel header urls"`
Repo RepoOptions
Output OutputOptions
Registry Registry
}
func init() {
validate.V.RegisterStructValidation(RootOptionsLevelValidation, RootOptions{})
}
func (ro *RootOptions) SetDefaults() {
if defaults.CanUpdate(ro.BuilderImage) {
ro.BuilderImage = driverbuilder.BuilderBaseImage
}
}
// NewRootOptions ...
func NewRootOptions() (*RootOptions, error) {
func NewRootOptions() *RootOptions {
rootOpts := &RootOptions{}
if err := defaults.Set(rootOpts); err != nil {
return nil, err
logger.WithError(err).WithField("options", "RootOptions").Fatal("error setting driverkit options defaults")
}
return rootOpts, nil
return rootOpts
}
// Validate validates the RootOptions fields.
func (ro *RootOptions) Validate() []error {
if err := validate.V.Struct(ro); err != nil {
var errs validator.ValidationErrors
errors.As(err, &errs)
errors := err.(validator.ValidationErrors)
errArr := []error{}
for _, e := range errs {
for _, e := range errors {
// Translate each error one at a time
errArr = append(errArr, errors.New(e.Translate(validate.T)))
errArr = append(errArr, fmt.Errorf(e.Translate(validate.T)))
}
return errArr
}
// check that the kernel versions supports at least one of probe and module
kr := kernelrelease.FromString(ro.KernelRelease)
kr.Architecture = kernelrelease.Architecture(ro.Architecture)
if !kr.SupportsModule() && !kr.SupportsProbe() {
return []error{errors.New("both module and probe are not supported by given options")}
}
return nil
}
func (ro *RootOptions) AddFlags(flags *pflag.FlagSet, targets []string) {
flags.StringVar(&ro.Output.Module, "output-module", ro.Output.Module, "filepath where to save the resulting kernel module")
flags.StringVar(&ro.Output.Probe, "output-probe", ro.Output.Probe, "filepath where to save the resulting eBPF probe")
flags.StringVar(&ro.Architecture, "architecture", runtime.GOARCH, "target architecture for the built driver, one of "+kernelrelease.SupportedArchs.String())
flags.StringVar(&ro.DriverVersion, "driverversion", ro.DriverVersion, "driver version as a git commit hash or as a git tag")
flags.StringVar(&ro.KernelVersion, "kernelversion", ro.KernelVersion, "kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v'")
flags.StringVar(&ro.KernelRelease, "kernelrelease", ro.KernelRelease, "kernel release to build the module for, it can be found by executing 'uname -v'")
flags.StringVarP(&ro.Target, "target", "t", ro.Target, "the system to target the build for, one of ["+strings.Join(targets, ",")+"]")
flags.StringVar(&ro.KernelConfigData, "kernelconfigdata", ro.KernelConfigData, "base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc")
flags.StringVar(&ro.ModuleDeviceName, "moduledevicename", ro.ModuleDeviceName, "kernel module device name (the default is falco, so the device will be under /dev/falco*)")
flags.StringVar(&ro.ModuleDriverName, "moduledrivername", ro.ModuleDriverName, "kernel module driver name, i.e. the name you see when you check installed modules via lsmod")
flags.StringVar(&ro.BuilderImage, "builderimage", ro.BuilderImage, "docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.")
flags.StringSliceVar(&ro.BuilderRepos, "builderrepo", ro.BuilderRepos, "list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'.")
flags.StringVar(&ro.GCCVersion, "gccversion", ro.GCCVersion, "enforce a specific gcc version for the build")
flags.StringSliceVar(&ro.KernelUrls, "kernelurls", nil, "list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls \"<URL3>,<URL4>\")")
flags.StringVar(&ro.Repo.Org, "repo-org", ro.Repo.Org, "repository github organization")
flags.StringVar(&ro.Repo.Name, "repo-name", ro.Repo.Name, "repository github name")
flags.StringVar(&ro.Registry.Name, "registry-name", ro.Registry.Name, "registry name to which authenticate")
flags.StringVar(&ro.Registry.Username, "registry-user", ro.Registry.Username, "registry username")
flags.StringVar(&ro.Registry.Password, "registry-password", ro.Registry.Password, "registry password")
flags.BoolVar(&ro.Registry.PlainHTTP, "registry-plain-http", ro.Registry.PlainHTTP, "allows interacting with remote registry via plain http requests")
}
// Log emits a log line containing the receiving RootOptions for debugging purposes.
//
// Call it only after validation.
func (ro *RootOptions) Log(printer *output.Printer) {
printer.Logger.Debug("running with options",
printer.Logger.Args(
"output-module", ro.Output.Module,
"output-probe", ro.Output.Probe,
"driverversion", ro.DriverVersion,
"kernelrelease", ro.KernelRelease,
"kernelversion", ro.KernelVersion,
"target", ro.Target,
"arch", ro.Architecture,
"kernelurls", ro.KernelUrls,
"repo-org", ro.Repo.Org,
"repo-name", ro.Repo.Name,
))
func (ro *RootOptions) Log() {
fields := logger.Fields{}
if ro.Output.Module != "" {
fields["output-module"] = ro.Output.Module
}
if ro.Output.Probe != "" {
fields["output-probe"] = ro.Output.Probe
}
if ro.DriverVersion != "" {
fields["driverversion"] = ro.DriverVersion
}
if ro.KernelRelease != "" {
fields["kernelrelease"] = ro.KernelRelease
}
if ro.KernelVersion != "" {
fields["kernelversion"] = ro.KernelVersion
}
if ro.Target != "" {
fields["target"] = ro.Target
}
fields["arch"] = ro.Architecture
if len(ro.KernelUrls) > 0 {
fields["kernelurls"] = ro.KernelUrls
}
logger.WithFields(fields).Debug("running with options")
}
func (ro *RootOptions) ToBuild(printer *output.Printer) *builder.Build {
func (ro *RootOptions) toBuild() *builder.Build {
kernelConfigData := ro.KernelConfigData
if len(kernelConfigData) == 0 {
kernelConfigData = "bm8tZGF0YQ==" // no-data
}
build := &builder.Build{
TargetType: builder.Type(ro.Target),
DriverVersion: ro.DriverVersion,
KernelVersion: ro.KernelVersion,
KernelRelease: ro.KernelRelease,
Architecture: ro.Architecture,
KernelConfigData: kernelConfigData,
ModuleFilePath: ro.Output.Module,
ProbeFilePath: ro.Output.Probe,
ModuleDriverName: ro.ModuleDriverName,
ModuleDeviceName: ro.ModuleDeviceName,
GCCVersion: ro.GCCVersion,
BuilderImage: ro.BuilderImage,
BuilderRepos: ro.BuilderRepos,
KernelUrls: ro.KernelUrls,
RepoOrg: ro.Repo.Org,
RepoName: ro.Repo.Name,
Images: make(builder.ImagesMap),
RegistryName: ro.Registry.Name,
RegistryUser: ro.Registry.Username,
RegistryPassword: ro.Registry.Password,
RegistryPlainHTTP: ro.Registry.PlainHTTP,
Printer: printer,
return &builder.Build{
TargetType: builder.Type(ro.Target),
DriverVersion: ro.DriverVersion,
KernelVersion: ro.KernelVersion,
KernelRelease: ro.KernelRelease,
Architecture: ro.Architecture,
KernelConfigData: kernelConfigData,
ModuleFilePath: ro.Output.Module,
ProbeFilePath: ro.Output.Probe,
ModuleDriverName: ro.ModuleDriverName,
ModuleDeviceName: ro.ModuleDeviceName,
CustomBuilderImage: ro.BuilderImage,
KernelUrls: ro.KernelUrls,
}
// loop over BuilderRepos to build the list ImagesListers based on the value of the builderRepo:
// if it's a local path use FileImagesLister, otherwise use RepoImagesLister
var (
imageLister builder.ImagesLister
err error
)
for _, builderRepo := range build.BuilderRepos {
if _, err = os.Stat(builderRepo); err == nil {
imageLister, err = builder.NewFileImagesLister(builderRepo, build)
} else {
imageLister, err = builder.NewRepoImagesLister(builderRepo, build)
}
if err != nil {
printer.Logger.Warn("skipping repo",
printer.Logger.Args("repo", builderRepo, "err", err.Error()))
} else {
build.ImagesListers = append(build.ImagesListers, imageLister)
}
}
// attempt the build in case it comes from an invalid config
kr := build.KernelReleaseFromBuildConfig()
if len(build.ModuleFilePath) > 0 && !kr.SupportsModule() {
build.ModuleFilePath = ""
printer.Logger.Warn("skipping build attempt of module for unsupported kernel release",
printer.Logger.Args("kernelrelease", kr.String()))
}
if len(build.ProbeFilePath) > 0 && !kr.SupportsProbe() {
build.ProbeFilePath = ""
printer.Logger.Warn("skipping build attempt of probe for unsupported kernel release",
printer.Logger.Args("kernelrelease", kr.String()))
}
return build
}
// RootOptionsLevelValidation validates KernelConfigData and Target at the same time.
@ -223,20 +125,17 @@ func (ro *RootOptions) ToBuild(printer *output.Printer) *builder.Build {
func RootOptionsLevelValidation(level validator.StructLevel) {
opts := level.Current().Interface().(RootOptions)
if opts.Target == builder.TargetTypeVanilla.String() ||
opts.Target == builder.TargetTypeMinikube.String() ||
opts.Target == builder.TargetTypeFlatcar.String() {
if len(opts.KernelConfigData) == 0 {
level.ReportError(opts.KernelConfigData, "kernelConfigData", "KernelConfigData", "required_kernelconfigdata_with_target_vanilla", "")
}
if len(opts.KernelConfigData) == 0 && opts.Target == builder.TargetTypeVanilla.String() {
level.ReportError(opts.KernelConfigData, "kernelConfigData", "KernelConfigData", "required_kernelconfigdata_with_target_vanilla", "")
}
if opts.KernelVersion == "" && (opts.Target == builder.TargetTypeUbuntu.String()) {
// UbuntuAWS and UbuntuGeneric should be deprecated in future in favor of just Ubuntu
if opts.KernelVersion == "" && (opts.Target == builder.TargetTypeUbuntu.String() || opts.Target == builder.TargetTypeUbuntuAWS.String() || opts.Target == builder.TargetTypeUbuntuGeneric.String()) {
level.ReportError(opts.KernelVersion, "kernelVersion", "KernelVersion", "required_kernelversion_with_target_ubuntu", "")
}
// Target redhat requires a valid build image (has to be registered in order to download packages)
if opts.Target == builder.TargetTypeRedhat.String() && opts.BuilderImage == "" {
if opts.Target == builder.TargetTypeRedhat.String() && opts.BuilderImage == driverbuilder.BuilderBaseImage {
level.ReportError(opts.BuilderImage, "builderimage", "builderimage", "required_builderimage_with_target_redhat", "")
}
}

View File

@ -1,5 +1,4 @@
INFO specify a valid processor
└ processors: [docker kubernetes kubernetes-in-cluster local]
INFO specify a valid processor processors="[docker kubernetes]"
{{ .Desc }}
{{ .Usage }}
@ -7,6 +6,6 @@ INFO specify a valid processor
{{ .Commands }}
{{ .Flags }}
-v, --version version for driverkit
-v, --version version for driverkit
{{ .Info }}

View File

@ -3,5 +3,4 @@ kernelversion: 59
target: ubuntu-aws
output:
module: /tmp/falco-ubuntu-aws.ko
probe: /tmp/falco-ubuntu-aws.o
driverversion: master

View File

@ -7,5 +7,4 @@ kernelurls: [
target: ubuntu-aws
output:
module: /tmp/falco-ubuntu-aws.ko
probe: /tmp/falco-ubuntu-aws.o
driverversion: master

View File

@ -1,13 +1,3 @@
INFO using config file file: testdata/configs/1.yaml
DEBUG running with options
├ output-module: /tmp/falco-ubuntu-aws.ko
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 59
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: []
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker
INFO using config file file=testdata/configs/1.yaml
DEBU running with options arch={{ .CurrentArch }} driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=59 output-module=/tmp/falco-ubuntu-aws.ko target=ubuntu-aws
INFO driver building, it will take a few seconds processor=docker

View File

@ -1,13 +1,3 @@
INFO using config file file: testdata/configs/1.yaml
DEBUG running with options
├ output-module: /tmp/override.ko
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 229
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: []
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker
INFO using config file file=testdata/configs/1.yaml
DEBU running with options arch={{ .CurrentArch }} driverversion=master kernelrelease=4.15.0-1057-aws kernelversion=229 output-module=/tmp/override.ko target=ubuntu-aws
INFO driver building, it will take a few seconds processor=docker

View File

@ -1,13 +1,3 @@
INFO using config file file: testdata/configs/2.yaml
DEBUG running with options
├ output-module: /tmp/falco-ubuntu-aws.ko
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 59
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: [https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker
INFO using config file file=testdata/configs/2.yaml
DEBU running with options arch={{ .CurrentArch }} driverversion=master kernelrelease=4.15.0-1057-aws kernelurls="[https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]" kernelversion=59 output-module=/tmp/falco-ubuntu-aws.ko target=ubuntu-aws
INFO driver building, it will take a few seconds processor=docker

View File

@ -1,13 +1,3 @@
DEBUG running without a configuration file
DEBUG running with options
├ output-module: /tmp/falco-ubuntu-azure.ko
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-azure
├ kernelversion: 62
├ target: ubuntu-azure
├ arch: {{ .CurrentArch }}
├ kernelurls: [http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-azure-headers-4.15.0-1057_4.15.0-1057.62_all.deb http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-headers-4.15.0-1057-azure_4.15.0-1057.62_amd64.deb]
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker
DEBU running without a configuration file
DEBU running with options arch={{ .CurrentArch }} driverversion=master kernelrelease=4.15.0-1057-azure kernelurls="[http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-azure-headers-4.15.0-1057_4.15.0-1057.62_all.deb http://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-azure/linux-headers-4.15.0-1057-azure_4.15.0-1057.62_amd64.deb]" kernelversion=62 output-module=/tmp/falco-ubuntu-azure.ko target=ubuntu-aws
INFO driver building, it will take a few seconds processor=docker

View File

@ -1,4 +1,8 @@
DEBUG running without a configuration file
ERROR error validating build options
└ err: builder image is a required field when target is redhat
ERROR error executing driverkit err: exiting for validation errors
DEBU running without a configuration file
ERRO error validating build options error="builder image is a required field when target is redhat"
Error: exiting for validation errors
Usage:
driverkit docker [flags]
{{ .Flags }}

View File

@ -1,13 +1,3 @@
DEBUG running without a configuration file
DEBUG running with options
├ output-module: /tmp/falco-ubuntu-aws.ko
├ output-probe: /tmp/falco-ubuntu-aws.o
├ driverversion: master
├ kernelrelease: 4.15.0-1057-aws
├ kernelversion: 59
├ target: ubuntu-aws
├ arch: {{ .CurrentArch }}
├ kernelurls: [https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]
├ repo-org: falcosecurity
└ repo-name: libs
INFO starting build processor: docker
DEBU running without a configuration file
DEBU running with options arch={{ .CurrentArch }} driverversion=master kernelrelease=4.15.0-1057-aws kernelurls="[https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-aws-headers-4.15.0-1057_4.15.0-1057.59_all.deb https://mirrors.edge.kernel.org/ubuntu/pool/main/l/linux-aws/linux-headers-4.15.0-1057-aws_4.15.0-1057.59_amd64.deb]" kernelversion=59 output-module=/tmp/falco-ubuntu-aws.ko target=ubuntu-aws
INFO driver building, it will take a few seconds processor=docker

View File

@ -1 +1 @@
INFO starting build processor: docker
INFO driver building, it will take a few seconds processor=docker

View File

@ -1,7 +1,10 @@
ERROR error validating build options err: kernel release is a required field
ERROR error validating build options err: target is a required field
ERROR error validating build options
└ err: output module path is required when probe is missing
ERROR error validating build options
└ err: output probe path is required when module is missing
ERROR error executing driverkit err: exiting for validation errors
ERRO error validating build options error="kernel release is a required field"
ERRO error validating build options error="target is a required field"
ERRO error validating build options error="output module path is required when probe is missing"
ERRO error validating build options error="output probe path is required when module is missing"
Error: exiting for validation errors
Usage:
driverkit docker [flags]
{{ .Flags }}

View File

@ -5,6 +5,6 @@
{{ .Commands }}
{{ .Flags }}
-v, --version version for driverkit
-v, --version version for driverkit
{{ .Info }}

View File

@ -5,6 +5,5 @@
{{ .Commands }}
{{ .Flags }}
-v, --version version for driverkit
{{ .Info }}

View File

@ -1,3 +1,11 @@
ERROR error validating config options
└ err: proxy url must start with http:// or https:// or socks5:// prefix
ERROR error executing driverkit err: exiting for validation errors
ERRO error validating config options error="proxy url must start with http:// or https:// or socks5:// prefix"
Error: exiting for validation errors
{{ .Usage }}
{{ .Commands }}
{{ .Flags }}
-v, --version version for driverkit
{{ .Info }}

View File

@ -1 +1,10 @@
ERROR error executing driverkit err: invalid argument "abc" for "driverkit"
Error: invalid argument "abc" for "driverkit"
{{ .Usage }}
{{ .Commands }}
{{ .Flags }}
-v, --version version for driverkit
{{ .Info }}

View File

@ -1,8 +1,5 @@
Available Commands:
completion Generates completion scripts.
docker Build Falco kernel modules and eBPF probes against a docker daemon.
help Help about any command
images List builder images
kubernetes Build Falco kernel modules and eBPF probes against a Kubernetes cluster.
kubernetes-in-cluster Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.
local Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.
completion Generates completion scripts.
docker Build Falco kernel modules and eBPF probes against a docker daemon.
help Help about any command
kubernetes Build Falco kernel modules and eBPF probes against a Kubernetes cluster.

View File

@ -1,27 +1,19 @@
Flags:
--architecture string target architecture for the built driver, one of {{ .Architectures }} (default "{{ .CurrentArch }}")
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.
--builderrepo strings list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'. (default [docker.io/falcosecurity/driverkit-builder])
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--gccversion string enforce a specific gcc version for the build
-h, --help help for {{ .Cmd }}
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
--registry-name string registry name to which authenticate
--registry-password string registry password
--registry-plain-http allows interacting with remote registry via plain http requests
--registry-user string registry username
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
-t, --target string the system to target the build for, one of {{ .Targets }}
--timeout int timeout in seconds (default 120)
--architecture string target architecture for the built driver, one of {{ .Architectures }} (default "{{ .CurrentArch }}")
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, the default image will be used. (default "falcosecurity/driverkit-builder:latest")
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
-h, --help help for {{ .Cmd }}
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string log level (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
-t, --target string the system to target the build for, one of {{ .Targets }}
--timeout int timeout in seconds (default 120)

View File

@ -1,28 +1,16 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"bytes"
"flag"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"github.com/falcosecurity/driverkit/cmd"
logger "github.com/sirupsen/logrus"
"github.com/spf13/cobra/doc"
)
@ -59,22 +47,7 @@ func main() {
flag.Parse()
// Get root command
configOpts, err := cmd.NewConfigOptions()
if err != nil {
// configOpts will never be nil here
if configOpts != nil {
configOpts.Printer.Logger.Fatal("error setting driverkit config options defaults",
configOpts.Printer.Logger.Args("err", err.Error()))
} else {
os.Exit(1)
}
}
rootOpts, err := cmd.NewRootOptions()
if err != nil {
configOpts.Printer.Logger.Fatal("error setting driverkit root options defaults",
configOpts.Printer.Logger.Args("err", err.Error()))
}
driverkit := cmd.NewRootCmd(configOpts, rootOpts)
driverkit := cmd.NewRootCmd()
root := driverkit.Command()
num := len(root.Commands()) + 1
@ -97,20 +70,20 @@ func main() {
}
// Generate markdown docs
err = doc.GenMarkdownTreeCustom(root, outputDir, prepender(num), linker)
err := doc.GenMarkdownTreeCustom(root, outputDir, prepender(num), linker)
if err != nil {
configOpts.Printer.Logger.Fatal("markdown generation", configOpts.Printer.Logger.Args("err", err.Error()))
logger.WithError(err).Fatal("markdown generation")
}
if targetWebsite {
err = os.Rename(path.Join(outputDir, "driverkit.md"), path.Join(outputDir, "_index.md"))
err := os.Rename(path.Join(outputDir, "driverkit.md"), path.Join(outputDir, "_index.md"))
if err != nil {
configOpts.Printer.Logger.Fatal("renaming main docs page", configOpts.Printer.Logger.Args("err", err.Error()))
logger.WithError(err).Fatal("renaming main docs page")
}
}
if err = stripSensitive(); err != nil {
configOpts.Printer.Logger.Fatal("error replacing sensitive data", configOpts.Printer.Logger.Args("err", err.Error()))
if err := stripSensitive(); err != nil {
logger.WithError(err).Fatal("error replacing sensitive data")
}
}
@ -127,7 +100,7 @@ func stripSensitive() error {
for _, file := range files {
filePath := path.Join(outputDir, file.Name())
file, err := os.ReadFile(filePath)
file, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
@ -137,7 +110,7 @@ func stripSensitive() error {
target := []byte(os.Getenv(s))
file = bytes.ReplaceAll(file, target, append(envMark, []byte(s)...))
}
if err = os.WriteFile(filePath, file, 0666); err != nil {
if err = ioutil.WriteFile(filePath, file, 0666); err != nil {
return err
}
}

View File

@ -1,32 +0,0 @@
FROM amazonlinux:2.0.20240529.0
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
RUN yum -y install gcc10 \
clang \
llvm \
bash-completion \
bc \
ca-certificates \
curl \
gnupg2 \
libc6-dev \
elfutils-libelf-devel \
xz \
cpio \
flex \
bison \
openssl \
openssl-devel \
wget \
binutils \
which \
make \
cmake3 \
tar \
zstd \
git
# Properly create soft links
RUN ln -s /usr/bin/gcc10-cc /usr/bin/gcc-10.0.0
RUN ln -s /usr/bin/cmake3 /usr/bin/cmake

View File

@ -1 +0,0 @@
builder-any-x86_64_gcc10.0.0_gcc9.0.0.Dockerfile

View File

@ -1 +0,0 @@
builder-any-x86_64_gcc12.0.0_gcc11.0.0.Dockerfile

View File

@ -1 +0,0 @@
builder-any-x86_64_gcc13.0.0.Dockerfile

View File

@ -1 +0,0 @@
builder-any-x86_64_gcc14.0.0.Dockerfile

View File

@ -1 +0,0 @@
builder-any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0.Dockerfile

View File

@ -1,48 +0,0 @@
FROM debian:bullseye
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG TARGETARCH
RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bash-completion \
bc \
clang \
llvm \
ca-certificates \
curl \
dkms \
dwarves \
gnupg2 \
gcc \
gcc-9 \
jq \
libc6-dev \
libelf-dev \
netcat \
xz-utils \
rpm2cpio \
cpio \
flex \
bison \
openssl \
libssl-dev \
libncurses-dev \
libudev-dev \
libpci-dev \
libiberty-dev \
lsb-release \
wget \
software-properties-common \
gpg \
zstd \
cmake \
git \
&& rm -rf /var/lib/apt/lists/*
# Properly create soft link
RUN ln -s /usr/bin/gcc-9 /usr/bin/gcc-9.0.0
RUN ln -s /usr/bin/gcc-10 /usr/bin/gcc-10.0.0

View File

@ -1,48 +0,0 @@
FROM debian:bookworm
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG TARGETARCH
RUN cp /etc/skel/.bashrc /root && cp /etc/skel/.profile /root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
bash-completion \
bc \
clang \
llvm \
ca-certificates \
curl \
dkms \
dwarves \
gnupg2 \
gcc \
gcc-11 \
jq \
libc6-dev \
libelf-dev \
netcat-openbsd \
xz-utils \
rpm2cpio \
cpio \
flex \
bison \
openssl \
libssl-dev \
libncurses-dev \
libudev-dev \
libpci-dev \
libiberty-dev \
lsb-release \
wget \
software-properties-common \
gpg \
zstd \
cmake \
git \
&& rm -rf /var/lib/apt/lists/*
# Properly create soft links
RUN ln -s /usr/bin/gcc-11 /usr/bin/gcc-11.0.0
RUN ln -s /usr/bin/gcc-12 /usr/bin/gcc-12.0.0

View File

@ -1,40 +0,0 @@
FROM fedora:39
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG TARGETARCH
RUN dnf install -y \
bash-completion \
bc \
clang \
llvm \
ca-certificates \
curl \
dkms \
dwarves \
gnupg2 \
gcc \
jq \
glibc-devel \
elfutils-libelf-devel \
netcat \
xz \
cpio \
flex \
bison \
openssl \
openssl-devel \
ncurses-devel \
systemd-devel \
pciutils-devel \
binutils-devel \
lsb-release \
wget \
gpg \
zstd \
cmake \
git
# Properly create soft links
RUN ln -s /usr/bin/gcc /usr/bin/gcc-13.0.0

View File

@ -1,40 +0,0 @@
FROM fedora:41
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
ARG TARGETARCH
RUN dnf install -y \
bash-completion \
bc \
clang \
llvm \
ca-certificates \
curl \
dkms \
dwarves \
gnupg2 \
gcc \
jq \
glibc-devel \
elfutils-libelf-devel \
netcat \
xz \
cpio \
flex \
bison \
openssl \
openssl-devel \
ncurses-devel \
systemd-devel \
pciutils-devel \
binutils-devel \
lsb-release \
wget \
gpg \
zstd \
cmake \
git
# Properly create soft links
RUN ln -s /usr/bin/gcc /usr/bin/gcc-14.0.0

View File

@ -1,50 +0,0 @@
FROM centos:7
LABEL maintainer="cncf-falco-dev@lists.cncf.io"
# Fix broken mirrors - centos:7 eol
RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo; \
sed -i s/^#.*baseurl=http/baseurl=https/g /etc/yum.repos.d/*.repo; \
sed -i s/^mirrorlist=http/#mirrorlist=https/g /etc/yum.repos.d/*.repo
RUN yum -y install centos-release-scl
# fix broken mirrors (again)
RUN sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/*.repo; \
sed -i s/^#.*baseurl=http/baseurl=https/g /etc/yum.repos.d/*.repo; \
sed -i s/^mirrorlist=http/#mirrorlist=https/g /etc/yum.repos.d/*.repo
RUN yum -y install gcc \
llvm-toolset-7.0 \
bash-completion \
bc \
ca-certificates \
curl \
gnupg2 \
libc6-dev \
elfutils-libelf-devel \
xz \
cpio \
flex \
bison \
openssl \
openssl-devel \
wget \
binutils \
which \
make \
git
# Install cmake3.x (on centos7 `cmake` package installs cmake2.x)
RUN curl -L -o /tmp/cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.22.5/cmake-3.22.5-linux-$(uname -m).tar.gz; \
gzip -d /tmp/cmake.tar.gz; \
tar -xpf /tmp/cmake.tar --directory=/tmp; \
cp -R /tmp/cmake-3.22.5-linux-$(uname -m)/* /usr; \
rm -rf /tmp/cmake-3.22.5-linux-$(uname -m)/
# Properly create soft link
RUN ln -s /usr/bin/gcc /usr/bin/gcc-4.8.5
RUN source scl_source enable llvm-toolset-7.0
RUN echo "source scl_source enable llvm-toolset-7.0" >> /etc/bashrc
RUN source /etc/bashrc

View File

@ -1,196 +0,0 @@
# Builders
The [builder](../pkg/driverbuilder/builder) package contains all of the actual builders code, for each supported target.
Their bash-like build templates live under the [templates](../pkg/driverbuilder/builder/templates) subfolder.
# Support a new distro
You probably came here because you want to tell the [Falco Drivers Build Grid](https://github.com/falcosecurity/test-infra/tree/master/driverkit) to
build drivers for a specific distro you care about.
If that distribution is not yet supported by driverkit, the Falco Drivers Build Grid will not be able to just build it as it does for other distros.
Adding support for a new distro is a multiple-step work:
* first of all, a new builder on driverkit must be created
* secondly, [kernel-crawler](https://github.com/falcosecurity/kernel-crawler) must also be updated to support the new distro; see [below](#5-kernel-crawler) section
* third, [dbg-go](https://github.com/falcosecurity/dbg-go) must [bump driverkit](https://github.com/falcosecurity/dbg-go?tab=readme-ov-file#bumping-driverkit) and enable support to generate configs for the new distro: https://github.com/falcosecurity/dbg-go/blob/main/pkg/root/distro.go#L30.
* lastly, [test-infra](https://github.com/falcosecurity/test-infra) must be updated to add the new [prow config](https://github.com/falcosecurity/test-infra/tree/master/config/jobs/build-drivers) for new distro related jobs and `dbg-go` images must be bumped, see https://github.com/falcosecurity/test-infra/tree/master/images/build-drivers and https://github.com/falcosecurity/test-infra/tree/master/images/update-dbg.
Here, we will only focus about driverkit part.
## Creating a new Builder
To add a new supported distribution, you need to create a specific file implementing the `builder.Builder` interface.
Here's the [archlinux](../pkg/driverbuilder/builder/archlinux.go) one for reference.
Following this simple set of instructions should help you while you implement a new `builder.Builder`.
### 1. Builder file
Create a file, named with the name of the distro you want to add in the `pkg/driverbuilder/builder` folder.
```bash
touch pkg/driverbuilder/builder/archlinux.go
```
### 2. Target name
Your builder will need a constant for the target it implements. Usually that constant
can just be the ID of the distribution you are implementing, as taken reading `/etc/os-release` file.
A builder can implement more than one target at time. For example, the minikube builder is just a vanilla one.
Once you have the constant, you will need to add it to the [byTarget](https://github.com/falcosecurity/driverkit/blob/master/pkg/driverbuilder/builder/target.go) map.
Open your file and you will need to add something like this:
```go
// TargetTypeArchLinux identifies the Arch Linux target.
const TargetTypeArchLinux Type = "arch"
type archLinux struct {
}
func init() {
byTarget[TargetTypeArchLinux] = &archLinux{}
}
```
Now, you can implement the `builder.Builder` interface for the `archlinux` struct
you just registered.
Here's a very minimalistic example:
```go
func (c *archlinux) Name() string {
return TargetTypeArchlinux.String()
}
func (c *archlinux) TemplateKernelUrlsScript() string {
return archlinuxKernelTemplate
}
func (c *archlinux) TemplateScript() string {
return archlinuxTemplate
}
func (c archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
urls := []string{}
if kr.Architecture == kernelrelease.ArchitectureAmd64 {
urls = append(urls, fmt.Sprintf("https://archive.archlinux.org/packages/l/linux-headers/linux-headers-%s.%s-%d-%s.pkg.tar.xz",
kr.Fullversion,
kr.Extraversion,
cfg.KernelVersion,
kr.Architecture.ToNonDeb()))
} else {
urls = append(urls, fmt.Sprintf("https://alaa.ad24.cz/packages/l/linux-%s-headers/linux-%s-headers-%s-%d-%s.pkg.tar.xz",
kr.Architecture.ToNonDeb(),
kr.Architecture.ToNonDeb(),
kr.Fullversion,
cfg.KernelVersion,
kr.Architecture.ToNonDeb()))
}
return urls, nil
}
func (c *archlinux) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
return archlinuxTemplateData{
KernelDownloadURL: urls[0],
}
}
```
Essentially, the various methods that you are implementing are needed to:
* fill the kernel download/extract script template, a `bash` script responsible to fetch and extract the kernel headers for the distro
* fill the build script template (see below), that is a `bash` script that will be executed by driverkit at build time
* return a list of possible kernel headers urls that will later be downloaded by the kernel download script, and then used for the driver build
Under `pkg/driverbuilder/builder/templates` folder, you can find all the template scripts for the supported builders.
Adding a new template there and using `go:embed` to include it in your builder, allows leaner code
without mixing up templates and builder logic.
For example:
```go
//go:embed templates/archlinux_kernel.sh
var archlinuxKernelTemplate string
//go:embed templates/archlinux.sh
var archlinuxTemplate string
```
Depending on how the distro works, the "kernel" template script will fetch the kernel headers for it at the specific kernel version specified
in the `Config` struct at `c.Build.KernelVersion`, and then extracting them.
Finally, the script will also `export` the `KERNELDIR` variable to be consumed by the actual build script.
Example kernel download template for archlinux:
```bash
set -xeuo pipefail
# Fetch the kernel
mkdir /tmp/kernel-download
cd /tmp/kernel-download
curl --silent -o kernel-devel.pkg.tar.xz -SL {{ .KernelDownloadURL }}
tar -xf kernel-devel.pkg.tar.xz
rm -Rf /tmp/kernel
mkdir -p /tmp/kernel
mv usr/lib/modules/*/build/* /tmp/kernel
# exit value
export KERNELDIR=/tmp/kernel
```
Once you have those, based on what that kernel can do and based on what was configured
by the user, the build script will build the kernel module driver and/or the eBPF probe driver.
Example build template for archlinux:
```bash
set -xeuo pipefail
cd {{ .DriverBuildDir }}
mkdir -p build && cd build
{{ .CmakeCmd }}
{{ if .BuildModule }}
# Build the module
make CC=/usr/bin/gcc-{{ .GCCVersion }} driver
strip -g {{ .ModuleFullPath }}
# Print results
modinfo {{ .ModuleFullPath }}
{{ end }}
{{ if .BuildProbe }}
# Build the eBPF probe
make bpf
ls -l driver/bpf/probe.o
{{ end }}
```
How does this work?
If the user specifies:
- `c.Build.ModuleFilePath` you will need to build the kernel module and save it in /tmp/driver/falco.ko`
- `c.Build.ProbeFilePath` you will need to build the eBPF probe and save it in /tmp/driver/probe.o`
The `/tmp/driver` MUST be interpolated from the `DriverDirectory` constant from [`builders.go`](/pkg/driverbuilder/builder/builders.go).
If you look at the various builder implemented, you will see that the task of creating a new builder
can be easy or difficult depending on how the distribution ships their artifacts.
Indeed, the hardest part is fetching the kernel headers urls for each distro.
### 3. Customize GCC version
A builder can enforce a GCC selection algorithm,
by implementing the `builder.GCCVersionRequestor` interface.
A sane default algorithm is provided, that selects a GCC version based on the kernel version.
The requested gcc version is then [used to find the correct builder image to be used](builder_images.md#selection-algorithm).
> **NOTE**: when implementing the `builder.GCCVersionRequestor`, returning an empty `semver.Version` means to fallback at default algorithm.
However, there is no mechanism to dynamically choose a clang version, because there should never be any need of touching it.
The build will use the one provided by the chosen builder image.
Any failure must be treated as a bug, and reported on [libs](https://github.com/falcosecurity/libs) repository.
### 5. kernel-crawler
When creating a new builder, it is recommended to check that [kernel-crawler](https://github.com/falcosecurity/kernel-crawler)
can also support collecting the new builders kernel versions and header package URLs. This will make sure that the latest drivers
for the new builder are automatically built by [test-infra](https://github.com/falcosecurity/test-infra). If required, add a feature request
for support for the new builder on the kernel-crawler repository.
> **NOTE**: be sure that the crawler you are going to add is interesting for the community as a whole.

View File

@ -1,68 +0,0 @@
# Builder Images
Driverkit supports multiple builder images.
A builder image is the docker image used to build the drivers.
## Adding a builder image
Adding a builder image is just a matter of adding a new dockerfile under the [docker/builders](../docker/builders) folder,
with a name matching the following regex: `builder-(?P<target>[a-z0-9]+)-(?P<arch>x86_64|aarch64)(?P<gccVers>(_gcc[0-9]+.[0-9]+.[0-9]+)+).Dockerfile$`.
For example: `builder-centos-x86_64_gcc5.8.0_gcc6.0.0.Dockerfile`.
> **NOTE:** `any` is also a valid target, and means "apply as fallback for any target"
The image **MUST** symlink all of its provided GCC versions to their full semver name, like:
* `/usr/bin/gcc5` must be linked to `/usr/bin/gcc-5.0.0`
* `/usr/bin/gcc-4.8` must be linked to `/usr/bin/gcc-4.8.0`
This is needed because driverkit logic must be able to differentiate eg: between
an image that provides gcc4 and one that provides 4.8, in a reliable manner.
The makefile will be then automatically able to collect the new docker images and pushing it as part of the CI.
Note: the images will be pushed under the `falcosecurity/driverkit-builder` repository, each with a tag reflecting its name, eg:
* `falcosecurity/driverkit-builder:centos-x86_64_gcc5.8.0_gcc6.0.0-latest`
* `falcosecurity/driverkit-builder:any-x86_64_gcc12.0.0-454eff8fcc7d9abc615d312e9eccbd41abffb810`
As you can see, the last part of the image tag is the real versioned tag (ie: `-latest` or `-$commithash`).
## Selection algorithm
Once pushed, driverkit will be able to correctly load the image during startup, using [falcoctl](https://github.com/falcosecurity/falcoctl/) OCI utilities.
Then, it will map images whose target and architecture are correct for the current build, storing the provided GCCs list.
Moreover, it will also take care of only using images with correct tag (ie: `latest` or `commithash`), as requested by user or automatically set by Makefile.
The algorithm goes as follows:
* load any image for the build arch, tag and target
* load any image for the build arch, tag and "any" target
* if any of the target-specific image provides the targetGCC for the build, we are over
* if any of the "any" fallback image provides the targetGCC for the build, we are over
* else, find the image between target-specific and fallback ones, that provides nearest GCC.
In this latest step, there is no distinction between/different priority given to target specific or fallback images.
## Customize builder images repos
Moreover, users can also ship their own builder images in their own docker repositories, by using `--builderrepo` CLI option.
Instead of passing a docker repo, one can also pass the full path to a so-called builder images index yaml file.
It is mostly convenient in "static" scenarios, but it also gives the ability to freely define images name since all required infos are explicitly stated in the index file.
For an example of such a file, see [index.yaml](./index.yaml).
One can use this option multiple times; builder repos are a priority first list of docker repositories or builder images indexes (they can be mixed too!).
## Force use a builder image
Users can also force-specify the builder image to be used for the current build,
instead of relying on the internal algorithm, by using `--builderimage` CLI option.
> **NOTE**: builderimage MUST provide the selected gcc for the build
A special value for builder image is available:
* `auto:$tag`, that is used to tell driverkit to use the automatic algorithm, but forcing a certain image tag
## Force use a gcc version
Users can specify the target gcc version of the build, using `--gccversion` option.
As seen above, this needs to be a fully expanded gcc version, like `4.8.0`, or `8.0.0`.
When set, the image selection algorithm will pick the best builder image,
ie: the one that provides the nearest gcc version.
One can also play with both `--gccversion` and `--builderimage` options to enforce the
usage of a specific builder image that ships a specific gcc version.

View File

@ -2,6 +2,10 @@
A command line tool to build Falco kernel modules and eBPF probes.
### Synopsis
A command line tool to build Falco kernel modules and eBPF probes.
```
driverkit
```
@ -9,40 +13,28 @@ driverkit
### Options
```
--architecture string target architecture for the built driver, one of [amd64,arm64] (default "amd64")
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.
--builderrepo strings list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'. (default [docker.io/falcosecurity/driverkit-builder])
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--gccversion string enforce a specific gcc version for the build
-h, --help help for driverkit
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
--registry-name string registry name to which authenticate
--registry-password string registry password
--registry-plain-http allows interacting with remote registry via plain http requests
--registry-user string registry username
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120)
--architecture string target architecture for the built driver (default "$runtime.GOARCH")
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
-h, --help help for driverkit
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls []string list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion uint16 kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default 1)
-l, --loglevel string log level (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
-t, --target string the system to target the build for
--timeout int timeout in seconds (default 120)
```
### SEE ALSO
* [driverkit completion](driverkit_completion.md) - Generates completion scripts.
* [driverkit docker](driverkit_docker.md) - Build Falco kernel modules and eBPF probes against a docker daemon.
* [driverkit images](driverkit_images.md) - List builder images
* [driverkit kubernetes](driverkit_kubernetes.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster.
* [driverkit kubernetes-in-cluster](driverkit_kubernetes-in-cluster.md) - Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.
* [driverkit local](driverkit_local.md) - Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.

View File

@ -2,6 +2,10 @@
Build Falco kernel modules and eBPF probes against a docker daemon.
### Synopsis
Build Falco kernel modules and eBPF probes against a docker daemon.
```
driverkit docker [flags]
```
@ -9,32 +13,24 @@ driverkit docker [flags]
### Options
```
--architecture string target architecture for the built driver, one of [amd64,arm64] (default "amd64")
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.
--builderrepo strings list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'. (default [docker.io/falcosecurity/driverkit-builder])
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--gccversion string enforce a specific gcc version for the build
-h, --help help for docker
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
--registry-name string registry name to which authenticate
--registry-password string registry password
--registry-plain-http allows interacting with remote registry via plain http requests
--registry-user string registry username
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120)
--architecture string target architecture for the built driver (default "$runtime.GOARCH")
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, the default image will be used. (default "falcosecurity/driverkit-builder:latest")
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
-h, --help help for docker
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls []string list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion uint16 kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default 1)
-l, --loglevel string log level (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
-t, --target string the system to target the build for
--timeout int timeout in seconds (default 120)
```
### SEE ALSO

View File

@ -1,43 +0,0 @@
## driverkit images
List builder images
```
driverkit images [flags]
```
### Options
```
--architecture string target architecture for the built driver, one of [amd64,arm64] (default "amd64")
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.
--builderrepo strings list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'. (default [docker.io/falcosecurity/driverkit-builder])
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--gccversion string enforce a specific gcc version for the build
-h, --help help for images
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
--registry-name string registry name to which authenticate
--registry-password string registry password
--registry-plain-http allows interacting with remote registry via plain http requests
--registry-user string registry username
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120)
```
### SEE ALSO
* [driverkit](driverkit.md) - A command line tool to build Falco kernel modules and eBPF probes.

View File

@ -1,46 +0,0 @@
## driverkit kubernetes-in-cluster
Build Falco kernel modules and eBPF probes against a Kubernetes cluster inside a Kubernetes cluster.
```
driverkit kubernetes-in-cluster [flags]
```
### Options
```
--architecture string target architecture for the built driver, one of [amd64,arm64] (default "amd64")
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.
--builderrepo strings list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'. (default [docker.io/falcosecurity/driverkit-builder])
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--gccversion string enforce a specific gcc version for the build
-h, --help help for kubernetes-in-cluster
--image-pull-secret string ImagePullSecret
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
-n, --namespace string If present, the namespace scope for the pods and its config (default "default")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
--registry-name string registry name to which authenticate
--registry-password string registry password
--registry-plain-http allows interacting with remote registry via plain http requests
--registry-user string registry username
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
--run-as-user int Pods runner user
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120)
```
### SEE ALSO
* [driverkit](driverkit.md) - A command line tool to build Falco kernel modules and eBPF probes.

View File

@ -2,6 +2,10 @@
Build Falco kernel modules and eBPF probes against a Kubernetes cluster.
### Synopsis
Build Falco kernel modules and eBPF probes against a Kubernetes cluster.
```
driverkit kubernetes [flags]
```
@ -9,50 +13,36 @@ driverkit kubernetes [flags]
### Options
```
--architecture string target architecture for the built driver, one of [amd64,arm64] (default "amd64")
--as string username to impersonate for the operation, user could be a regular user or a service account in a namespace
--architecture string target architecture for the built driver (default "$runtime.GOARCH")
--as string username to impersonate for the operation
--as-group stringArray group to impersonate for the operation, this flag can be repeated to specify multiple groups
--as-uid string uID to impersonate for the operation
--builderimage string docker image to be used to build the kernel module and eBPF probe. If not provided, an automatically selected image will be used.
--builderrepo strings list of docker repositories or yaml file (absolute path) containing builder images index with the format 'images: [ { target:<target>, name:<image-name>, arch: <arch>, tag: <imagetag>, gcc_versions: [ <gcc-tag> ] },...]', in descending priority order. Used to search for builder images. eg: --builderrepo myorg/driverkit-builder --builderrepo falcosecurity/driverkit-builder --builderrepo '/path/to/my/index.yaml'. (default [docker.io/falcosecurity/driverkit-builder])
--cache-dir string default cache directory (default "$HOME/.kube/cache")
--cache-dir string default HTTP cache directory (default "$HOME/.kube/http-cache")
--certificate-authority string path to a cert file for the certificate authority
--client-certificate string path to a client certificate file for TLS
--client-key string path to a client key file for TLS
--cluster string the name of the kubeconfig cluster to use
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--context string the name of the kubeconfig context to use
--disable-compression if true, opt-out of response compression for all requests to the server
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--gccversion string enforce a specific gcc version for the build
-h, --help help for kubernetes
--image-pull-secret string ImagePullSecret
--insecure-skip-tls-verify if true, the server's certificate will not be checked for validity, this will make your HTTPS connections insecure
--kernelconfigdata string base64 encoded kernel config data: in some systems it can be found under the /boot directory, in other it is gzip compressed under /proc
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelurls strings list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
--kernelurls []string list of kernel header urls (e.g. --kernelurls <URL1> --kernelurls <URL2> --kernelurls "<URL3>,<URL4>")
--kernelversion uint16 kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default 1)
--kubeconfig string path to the kubeconfig file to use for CLI requests
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
-l, --loglevel string log level (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
-n, --namespace string If present, the namespace scope for the pods and its config (default "default")
-n, --namespace string if present, the namespace scope for this CLI request
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--proxy string the proxy to use to download data
--registry-name string registry name to which authenticate
--registry-password string registry password
--registry-plain-http allows interacting with remote registry via plain http requests
--registry-user string registry username
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
--request-timeout string the length of time to wait before giving up on a single server request, non-zero values should contain a corresponding time unit (e.g, 1s, 2m, 3h), a value of zero means don't timeout requests (default "0")
--run-as-user int Pods runner user
-s, --server string the address and port of the Kubernetes API server
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla]
-t, --target string the system to target the build for
--timeout int timeout in seconds (default 120)
--tls-server-name string server name to use for server certificate validation, if it is not provided, the hostname used to contact the server is used
--token string bearer token for authentication to the API server
--user string the name of the kubeconfig user to use
```

View File

@ -1,36 +0,0 @@
## driverkit local
Build Falco kernel modules and eBPF probes in local env with local kernel sources and gcc/clang.
```
driverkit local [flags]
```
### Options
```
-c, --config string config file path (default $HOME/.driverkit.yaml if exists)
--dkms Enforce usage of DKMS to build the kernel module.
--download-headers Try to automatically download kernel headers.
--driverversion string driver version as a git commit hash or as a git tag (default "master")
--dryrun do not actually perform the action
--env stringToString Env variables to be enforced during the driver build. (default [])
-h, --help help for local
--kernelrelease string kernel release to build the module for, it can be found by executing 'uname -v'
--kernelversion string kernel version to build the module for, it's the numeric value after the hash when you execute 'uname -v' (default "1")
-l, --loglevel string set level for logs (info, warn, debug, trace) (default "info")
--moduledevicename string kernel module device name (the default is falco, so the device will be under /dev/falco*) (default "falco")
--moduledrivername string kernel module driver name, i.e. the name you see when you check installed modules via lsmod (default "falco")
--output-module string filepath where to save the resulting kernel module
--output-probe string filepath where to save the resulting eBPF probe
--repo-name string repository github name (default "libs")
--repo-org string repository github organization (default "falcosecurity")
--src-dir string Enforce usage of local source dir to build drivers.
-t, --target string the system to target the build for, one of [alinux,almalinux,amazonlinux,amazonlinux2,amazonlinux2022,amazonlinux2023,arch,bottlerocket,centos,debian,fedora,flatcar,minikube,ol,opensuse,photon,redhat,rocky,sles,talos,ubuntu,vanilla]
--timeout int timeout in seconds (default 120)
```
### SEE ALSO
* [driverkit](driverkit.md) - A command line tool to build Falco kernel modules and eBPF probes.

View File

@ -1,31 +0,0 @@
images:
- name: docker.io/falcosecurity/driverkit-builder:any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest
target: any
arch: x86_64
tag: latest
gcc_versions:
- 8.0.0
- 6.0.0
- 5.0.0
- 4.9.0
- 4.8.0
# Name is just the image name that will be used to download the image.
# Contrarily to normal repo lister there is no constraint on it,
# since all fields are already explicitly available
- name: docker.io/foo/bar:mytag
target: arch
arch: x86_64
tag: mytag
gcc_versions:
- 13.1.1
# Image name tag ("mytag" in this case)
# is not even required to match "tag" property below,
# since the latter is used to match against the desired builder image tag for the build,
# while the former is the real image tag that will be used.
- name: docker.io/foo/baz:mytag
target: arch
arch: x86_64
tag: latest
gcc_versions:
- 13.1.1

180
go.mod
View File

@ -1,162 +1,34 @@
module github.com/falcosecurity/driverkit
go 1.24.1
toolchain go1.24.2
go 1.16
require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/blang/semver/v4 v4.0.0
github.com/creasty/defaults v1.7.0
github.com/docker/docker v28.3.3+incompatible
github.com/falcosecurity/falcoctl v0.11.1
github.com/go-playground/locales v0.14.1
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.24.0
github.com/containerd/containerd v1.6.3 // indirect
github.com/creasty/defaults v1.6.0
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v20.10.14+incompatible
github.com/go-playground/locales v0.14.0
github.com/go-playground/universal-translator v0.18.0
github.com/go-playground/validator/v10 v10.10.1
github.com/mitchellh/go-homedir v1.1.0
github.com/olekukonko/tablewriter v0.0.5
github.com/opencontainers/image-spec v1.1.1
github.com/pterm/pterm v0.12.80
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.6
github.com/spf13/viper v1.20.0
gopkg.in/yaml.v3 v3.0.1
github.com/moby/sys/mount v0.3.3 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.4.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.11.0
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
google.golang.org/grpc v1.46.0 // indirect
gotest.tools v2.2.0+incompatible
k8s.io/api v0.32.3
k8s.io/apimachinery v0.32.3
k8s.io/cli-runtime v0.30.0
k8s.io/client-go v0.32.3
k8s.io/kubectl v0.30.0
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
modernc.org/sqlite v1.29.9
oras.land/oras-go/v2 v2.5.0
)
require (
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/chai2010/gettext-go v1.0.3 // indirect
github.com/containerd/console v1.0.4 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
github.com/creack/pty v1.1.21 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
github.com/evanphx/json-patch v5.9.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fatih/camelcase v1.0.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/fvbommel/sortorder v1.1.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-viper/mapstructure/v2 v2.3.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/go-archive v0.1.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/moby/sys/atomicwriter v0.1.0 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.starlark.net v0.0.0-20240507195648-35fe9f26b4bc // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.36.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/net v0.38.0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/sys v0.31.0 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/time v0.11.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools/v3 v3.5.2 // indirect
k8s.io/component-base v0.30.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.50.5 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/kustomize/api v0.17.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.17.0 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
gotest.tools/v3 v3.2.0 // indirect
k8s.io/api v0.23.6
k8s.io/apimachinery v0.23.6
k8s.io/cli-runtime v0.23.6
k8s.io/client-go v0.23.6
k8s.io/kubectl v0.23.6
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9
modernc.org/sqlite v1.17.3
)

2092
go.sum

File diff suppressed because it is too large Load Diff

14
main.go
View File

@ -1,17 +1,3 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (

View File

@ -0,0 +1,153 @@
# Builders
This folder contains all of the actual builders code, for each supported target.
Their bash-like build templates live in the [templates](templates) subfolder.
## Creating a new Builder
You probably came here because you want to tell the [Falco Drivers Build Grid](https://github.com/falcosecurity/test-infra/tree/master/driverkit) to
build drivers for a specific distro you care about.
If that distribution is not supported by driverkit, the Falco Drivers Build Grid will not be able to just build it as it does for other distros.
To add a new supported distribution, you need to create a specific file implementing the `builder.Builder` interface.
Here's the [archlinux](archlinux.go) one for reference.
Following this simple set of instructions should help you while you implement a new `builder.Builder`.
### 1. Builder file
Create a file, named with the name of the distro you want to add in the `pkg/driverbuilder/builder` folder.
```bash
touch pkg/driverbuilder/builder/archlinux.go
```
### 2. Target name
Your builder will need a constant for the target it implements. Usually that constant
can just be the name of the distribution you are implementing. A builder can implement
more than one target at time. For example, the Ubuntu builder implements both `ubuntu-generic` and `ubuntu-aws`
to reflect the organization that the distro itself has.
Once you have the constant, you will need to add it to the `BuilderByTarget` map.
Open your file and you will need to have something like this:
```go
// TargetTypeArchLinux identifies the Arch Linux target.
const TargetTypeArchLinux Type = "archlinux"
type archLinux struct {
}
func init() {
BuilderByTarget[TargetTypeArchLinux] = &archLinux{}
}
```
Now, you can implement the `builder.Builder` interface for the `archlinux` struct
you just registered.
Here's a very minimalistic example:
```go
func (c archlinux) Name() string {
return TargetTypeArchlinux.String()
}
func (c archlinux) TemplateScript() string {
return archlinuxTemplate
}
func (c archlinux) URLs(cfg Config, kr kernelrelease.KernelRelease) ([]string, error) {
urls := []string{}
if kr.Architecture == "amd64" {
urls = append(urls, fmt.Sprintf("https://archive.archlinux.org/packages/l/linux-headers/linux-headers-%s.%s-%d-%s.pkg.tar.xz",
kr.Fullversion,
kr.Extraversion,
cfg.KernelVersion,
kr.Architecture.ToNonDeb()))
} else {
urls = append(urls, fmt.Sprintf("http://tardis.tiny-vps.com/aarm/packages/l/linux-%s-headers/linux-%s-headers-%s-%d-%s.pkg.tar.xz",
kr.Architecture.ToNonDeb(),
kr.Architecture.ToNonDeb(),
kr.Fullversion,
cfg.KernelVersion,
kr.Architecture.ToNonDeb()))
}
return urls, nil
}
func (c archlinux) TemplateData(cfg Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return archlinuxTemplateData{
commonTemplateData: cfg.toTemplateData(),
KernelDownloadURL: urls[0],
GCCVersion: archlinuxGccVersionFromKernelRelease(kr),
}
}
```
Essentially, the various methods that you are implementing are needed to:
* filling the script template (see below), that is a `bash` script that will be executed by driverkit at build time
* fetching kernel headers urls that will later be downloaded inside the builder container, and used for the driver build
Under `pkg/driverbuilder/builder/templates` folder, you can find all the template scripts for the supported builders.
Adding a new template there and using `go:embed` to include it in your builder, allows leaner code
without mixing up templates and builder logic.
For example:
```go
//go:embed templates/archlinux.sh
var archlinuxTemplate string
```
Depending on how the distro works, the script will need to fetch the kernel headers for it at the specific kernel version specified
in the `Config` struct at `c.Build.KernelVersion`.
Once you have those, based on what that kernel can do and based on what was configured
by the user you will need to build the kernel module driver and/or the eBPF probe driver.
How does this work?
If the user specifies:
- `c.Build.ModuleFilePath` you will need to build the kernel module and save it in /tmp/driver/falco.ko`
- `c.Build.ProbeFilePath` you will need to build the eBPF probe and save it in /tmp/driver/probe.o`
The `/tmp/driver` MUST be interpolated from the `DriverDirectory` constant from [`builders.go`](/pkg/driverbuilder/builder/builders.go).
If you look at the various builder implemented, you will see that the task of creating a new builder
can be easy or difficult depending on how the distribution ships their artifacts.
Indeed, the hardest part is fetching the kernel headers urls for each distro.
### 3. Customize GCC version
Driverkit builder image supports 4 gcc versions:
* GCC-8
* GCC-6.3.0
* GCC-5.5.0
* GCC-4.8.4
You can dynamically choose the one you prefer, likely switching on the kernel version.
For an example, you can check out Ubuntu builder, namely: `ubuntuGCCVersionFromKernelRelease`.
### 4. Customize llvm version
Driverkit builder image supports 2 llvm versions:
* llvm-7
* llvm-12
You can dynamically choose the one you prefer, likely switching on the kernel version.
For an example, you can check out Debian builder, namely: `debianLLVMVersionFromKernelRelease`.
### 5. kernel-crawler
When creating a new builder, it is recommended to check that [kernel-crawler](https://github.com/falcosecurity/kernel-crawler)
can also support collecting the new builders kernel versions and header package URLs. This will make sure that the latest drivers
for the new builder are automatically built by [test-infra](https://github.com/falcosecurity/test-infra). If required, add a feature request
for support for the new builder on the kernel-crawler repository.
Note: be sure that the crawler you wants to add is interesting for the community as a whole.
For example, an archlinux crawler doesn't make much sense, because Arch is a rolling release and we should not support
any past Arch kernel for Falco.

View File

@ -1,84 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/alinux_kernel.sh
var alinuxKernelTemplate string
//go:embed templates/alinux.sh
var alinuxTemplate string
// TargetTypeAlinux identifies the AliyunLinux 2 and 3 target.
const TargetTypeAlinux Type = "alinux"
func init() {
byTarget[TargetTypeAlinux] = &alinux{}
}
type alinuxTemplateData struct {
KernelDownloadURL string
}
type alinux struct {
}
func (c *alinux) Name() string {
return TargetTypeAlinux.String()
}
func (c *alinux) TemplateKernelUrlsScript() string {
return alinuxKernelTemplate
}
func (c *alinux) TemplateScript() string {
return alinuxTemplate
}
func (c *alinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
return fetchAlinuxKernelURLS(kr), nil
}
func (c *alinux) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
return alinuxTemplateData{
KernelDownloadURL: urls[0],
}
}
func fetchAlinuxKernelURLS(kr kernelrelease.KernelRelease) []string {
alinuxReleases := []string{
"2",
"2.1903",
"3",
}
urls := []string{}
for _, r := range alinuxReleases {
urls = append(urls, fmt.Sprintf(
"http://mirrors.aliyun.com/alinux/%s/os/%s/Packages/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
}
return urls
}

View File

@ -1,96 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/almalinux_kernel.sh
var almaKernelTemplate string
//go:embed templates/almalinux.sh
var almaTemplate string
// TargetTypeAlma identifies the AlmaLinux target.
const TargetTypeAlma Type = "almalinux"
func init() {
byTarget[TargetTypeAlma] = &alma{}
}
type almaTemplateData struct {
KernelDownloadURL string
}
// alma is a driverkit target.
type alma struct {
}
func (c *alma) Name() string {
return TargetTypeAlma.String()
}
func (c *alma) TemplateKernelUrlsScript() string {
return almaKernelTemplate
}
func (c *alma) TemplateScript() string {
return almaTemplate
}
func (c *alma) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
return fetchAlmaKernelURLS(kr), nil
}
func (c *alma) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
return almaTemplateData{
KernelDownloadURL: urls[0],
}
}
func fetchAlmaKernelURLS(kr kernelrelease.KernelRelease) []string {
almaReleases := []string{
"8",
"8.6",
"9",
"9.0",
}
urls := []string{}
for _, r := range almaReleases {
if r >= "9" {
urls = append(urls, fmt.Sprintf(
"https://repo.almalinux.org/almalinux/%s/AppStream/%s/os/Packages/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
} else {
urls = append(urls, fmt.Sprintf(
"https://repo.almalinux.org/almalinux/%s/BaseOS/%s/os/Packages/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
}
}
return urls
}

View File

@ -1,17 +1,3 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
@ -22,8 +8,8 @@ import (
"database/sql"
_ "embed"
"fmt"
"github.com/blang/semver/v4"
"io"
"io/ioutil"
"log"
"net/http"
"os"
@ -32,11 +18,9 @@ import (
_ "modernc.org/sqlite"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
logger "github.com/sirupsen/logrus"
)
//go:embed templates/amazonlinux_kernel.sh
var amazonlinuxKernelTemplate string
//go:embed templates/amazonlinux.sh
var amazonlinuxTemplate string
@ -58,13 +42,6 @@ type amazonlinux2022 struct {
amazonlinux
}
type amazonlinux2023 struct {
amazonlinux
}
// TargetTypeAmazonLinux2023 identifies the AmazonLinux2023 target.
const TargetTypeAmazonLinux2023 Type = "amazonlinux2023"
// TargetTypeAmazonLinux2022 identifies the AmazonLinux2022 target.
const TargetTypeAmazonLinux2022 Type = "amazonlinux2022"
@ -75,37 +52,38 @@ const TargetTypeAmazonLinux2 Type = "amazonlinux2"
const TargetTypeAmazonLinux Type = "amazonlinux"
func init() {
byTarget[TargetTypeAmazonLinux2023] = &amazonlinux2023{}
byTarget[TargetTypeAmazonLinux2022] = &amazonlinux2022{}
byTarget[TargetTypeAmazonLinux2] = &amazonlinux2{}
byTarget[TargetTypeAmazonLinux] = &amazonlinux{}
BuilderByTarget[TargetTypeAmazonLinux2022] = &amazonlinux2022{}
BuilderByTarget[TargetTypeAmazonLinux2] = &amazonlinux2{}
BuilderByTarget[TargetTypeAmazonLinux] = &amazonlinux{}
}
type amazonlinuxTemplateData struct {
commonTemplateData
KernelDownloadURLs []string
LLVMVersion string
}
func (a *amazonlinux) Name() string {
func (a amazonlinux) Name() string {
return TargetTypeAmazonLinux.String()
}
func (a *amazonlinux) TemplateKernelUrlsScript() string { return amazonlinuxKernelTemplate }
func (a *amazonlinux) TemplateScript() string {
func (a amazonlinux) TemplateScript() string {
return amazonlinuxTemplate
}
func (a *amazonlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
func (a amazonlinux) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
return fetchAmazonLinuxPackagesURLs(a, kr)
}
func (a *amazonlinux) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
func (a amazonlinux) TemplateData(c Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return amazonlinuxTemplateData{
commonTemplateData: c.toTemplateData(),
KernelDownloadURLs: urls,
LLVMVersion: amazonLLVMVersionFromKernelRelease(kr),
}
}
func (a *amazonlinux) repos() []string {
func (a amazonlinux) repos() []string {
return []string{
"latest/updates",
"latest/main",
@ -118,105 +96,77 @@ func (a *amazonlinux) repos() []string {
}
}
func (a *amazonlinux) baseUrl() string {
func (a amazonlinux) baseUrl() string {
return "http://repo.us-east-1.amazonaws.com"
}
func (a *amazonlinux) ext() string {
func (a amazonlinux) ext() string {
return "bz2"
}
func (a *amazonlinux2022) Name() string {
func (a amazonlinux2022) Name() string {
return TargetTypeAmazonLinux2022.String()
}
func (a *amazonlinux2022) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
func (a amazonlinux2022) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
return fetchAmazonLinuxPackagesURLs(a, kr)
}
func (a *amazonlinux2022) repos() []string {
func (a amazonlinux2022) repos() []string {
return []string{
"2022.0.20220202",
"2022.0.20220315",
}
}
func (a *amazonlinux2022) baseUrl() string {
func (a amazonlinux2022) baseUrl() string {
return "https://al2022-repos-us-east-1-9761ab97.s3.dualstack.us-east-1.amazonaws.com/core/mirrors"
}
func (a *amazonlinux2022) ext() string {
func (a amazonlinux2022) ext() string {
return "gz"
}
func (a *amazonlinux2023) Name() string {
return TargetTypeAmazonLinux2023.String()
}
func (a *amazonlinux2023) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
return fetchAmazonLinuxPackagesURLs(a, kr)
}
func (a *amazonlinux2023) repos() []string {
return []string{
"latest",
}
}
func (a *amazonlinux2023) baseUrl() string {
return "https://cdn.amazonlinux.com/al2023/core/mirrors"
}
func (a *amazonlinux2023) ext() string {
return "gz"
}
func (a *amazonlinux2) Name() string {
func (a amazonlinux2) Name() string {
return TargetTypeAmazonLinux2.String()
}
func (a *amazonlinux2) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
func (a amazonlinux2) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
return fetchAmazonLinuxPackagesURLs(a, kr)
}
func (a *amazonlinux2) GCCVersion(kr kernelrelease.KernelRelease) semver.Version {
// 5.10 amazonlinux2 kernels need gcc 10
if kr.Major == 5 && kr.Minor == 10 {
return semver.Version{Major: 10}
}
return semver.Version{}
}
func (a *amazonlinux2) repos() []string {
func (a amazonlinux2) repos() []string {
return []string{
"core/2.0",
"core/latest",
"extras/kernel-5.4/latest",
"extras/kernel-5.10/latest",
"extras/kernel-5.15/latest",
}
}
func (a *amazonlinux2) baseUrl() string {
func (a amazonlinux2) baseUrl() string {
return "http://amazonlinux.us-east-1.amazonaws.com/2"
}
func (a *amazonlinux2) ext() string {
func (a amazonlinux2) ext() string {
return "gz"
}
func buildMirror(a amazonBuilder, r string, kv kernelrelease.KernelRelease) (string, error) {
var baseURL string
switch a.(type) {
case *amazonlinux:
case amazonlinux:
baseURL = fmt.Sprintf("%s/%s", a.baseUrl(), r)
case *amazonlinux2, *amazonlinux2022, *amazonlinux2023:
case amazonlinux2:
baseURL = fmt.Sprintf("%s/%s/%s", a.baseUrl(), r, kv.Architecture.ToNonDeb())
case amazonlinux2022:
baseURL = fmt.Sprintf("%s/%s/%s", a.baseUrl(), r, kv.Architecture.ToNonDeb())
default:
return "", fmt.Errorf("unsupported target")
}
mirror := fmt.Sprintf("%s/%s", baseURL, "mirror.list")
logger.WithField("url", mirror).WithField("version", r).Debug("looking for repo...")
return mirror, nil
}
@ -237,92 +187,92 @@ func fetchAmazonLinuxPackagesURLs(a amazonBuilder, kv kernelrelease.KernelReleas
visited := make(map[string]struct{})
for _, v := range a.repos() {
err := func() error {
mirror, err := buildMirror(a, v, kv)
if err != nil {
return err
}
// Obtain the repo URL by getting mirror URL content
mirrorRes, err := http.Get(mirror)
if err != nil {
return err
}
defer mirrorRes.Body.Close()
var repo string
scanner := bufio.NewScanner(mirrorRes.Body)
if scanner.Scan() {
repo = scanner.Text()
}
if repo == "" {
return fmt.Errorf("repository not found")
}
repo = strings.ReplaceAll(strings.TrimSuffix(repo, "\n"), "$basearch", kv.Architecture.ToNonDeb())
repo = strings.TrimSuffix(repo, "/")
repoDatabaseURL := fmt.Sprintf("%s/repodata/primary.sqlite.%s", repo, a.ext())
if _, ok := visited[repoDatabaseURL]; ok {
return nil
}
// Download the repo database
repoRes, err := http.Get(repoDatabaseURL)
if err != nil {
return err
}
defer repoRes.Body.Close()
visited[repoDatabaseURL] = struct{}{}
unzip, err := unzipFuncFromBuilder(a)
if err != nil {
return err
}
dbBytes, err := unzip(repoRes.Body)
if err != nil {
return err
}
// Create the temporary database file
dbFile, err := os.CreateTemp(os.TempDir(), fmt.Sprintf("%s-*.sqlite", a.Name()))
if err != nil {
return err
}
defer os.Remove(dbFile.Name())
if _, err := dbFile.Write(dbBytes); err != nil {
return err
}
// Open the database
db, err := sql.Open("sqlite", dbFile.Name())
if err != nil {
return err
}
defer db.Close()
// Query the database
rel := strings.TrimPrefix(strings.TrimSuffix(kv.FullExtraversion, fmt.Sprintf(".%s", kv.Architecture.ToNonDeb())), "-")
q := fmt.Sprintf("SELECT location_href FROM packages WHERE name LIKE 'kernel-devel%%' AND version='%s' AND release='%s'", kv.Fullversion, rel)
stmt, err := db.Prepare(q)
if err != nil {
return err
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var href string
err = rows.Scan(&href)
if err != nil {
log.Fatal(err)
}
urls = append(urls, fmt.Sprintf("%s/%s", repo, href))
}
return dbFile.Close()
}()
mirror, err := buildMirror(a, v, kv)
if err != nil {
return nil, err
}
// Obtain the repo URL by getting mirror URL content
mirrorRes, err := http.Get(mirror)
if err != nil {
return nil, err
}
defer mirrorRes.Body.Close()
var repo string
scanner := bufio.NewScanner(mirrorRes.Body)
if scanner.Scan() {
repo = scanner.Text()
}
if repo == "" {
return nil, fmt.Errorf("repository not found")
}
repo = strings.ReplaceAll(strings.TrimSuffix(repo, "\n"), "$basearch", kv.Architecture.ToNonDeb())
repo = strings.TrimSuffix(repo, "/")
repoDatabaseURL := fmt.Sprintf("%s/repodata/primary.sqlite.%s", repo, a.ext())
if _, ok := visited[repoDatabaseURL]; ok {
continue
}
// Download the repo database
repoRes, err := http.Get(repoDatabaseURL)
logger.WithField("url", repoDatabaseURL).Debug("downloading...")
if err != nil {
return nil, err
}
defer repoRes.Body.Close()
visited[repoDatabaseURL] = struct{}{}
unzip, err := unzipFuncFromBuilder(a)
if err != nil {
return nil, err
}
dbBytes, err := unzip(repoRes.Body)
if err != nil {
return nil, err
}
// Create the temporary database file
dbFile, err := ioutil.TempFile(os.TempDir(), fmt.Sprintf("%s-*.sqlite", a.Name()))
if err != nil {
return nil, err
}
defer os.Remove(dbFile.Name())
if _, err := dbFile.Write(dbBytes); err != nil {
return nil, err
}
// Open the database
db, err := sql.Open("sqlite", dbFile.Name())
if err != nil {
return nil, err
}
defer db.Close()
logger.WithField("db", dbFile.Name()).Debug("connecting to database...")
// Query the database
rel := strings.TrimPrefix(strings.TrimSuffix(kv.FullExtraversion, fmt.Sprintf(".%s", kv.Architecture.ToNonDeb())), "-")
q := fmt.Sprintf("SELECT location_href FROM packages WHERE name LIKE 'kernel-devel%%' AND version='%s' AND release='%s'", kv.Fullversion, rel)
stmt, err := db.Prepare(q)
if err != nil {
return nil, err
}
defer stmt.Close()
rows, err := stmt.Query()
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var href string
err = rows.Scan(&href)
if err != nil {
log.Fatal(err)
}
urls = append(urls, fmt.Sprintf("%s/%s", repo, href))
}
if err := dbFile.Close(); err != nil {
return nil, err
}
// Found, do not continue
if len(urls) > 0 {
break
@ -364,3 +314,14 @@ func bunzip(data io.Reader) (res []byte, err error) {
return
}
func amazonLLVMVersionFromKernelRelease(kr kernelrelease.KernelRelease) string {
switch kr.Version {
case 4:
return "7"
case 5:
return "12"
default:
return "12"
}
}

View File

@ -1,38 +1,19 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"strings"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/archlinux_kernel.sh
var archlinuxKernelTemplate string
//go:embed templates/archlinux.sh
var archlinuxTemplate string
// TargetTypeArchlinux identifies the Archlinux target.
const TargetTypeArchlinux Type = "arch"
const TargetTypeArchlinux Type = "archlinux"
func init() {
byTarget[TargetTypeArchlinux] = &archlinux{}
BuilderByTarget[TargetTypeArchlinux] = &archlinux{}
}
// archlinux is a driverkit target.
@ -40,118 +21,55 @@ type archlinux struct {
}
type archlinuxTemplateData struct {
commonTemplateData
KernelDownloadURL string
GCCVersion string
}
func (c *archlinux) Name() string {
func (c archlinux) Name() string {
return TargetTypeArchlinux.String()
}
func (c *archlinux) TemplateKernelUrlsScript() string { return archlinuxKernelTemplate }
func (c *archlinux) TemplateScript() string {
func (c archlinux) TemplateScript() string {
return archlinuxTemplate
}
func (c *archlinux) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
// uname -r returns "6.8.1-arch1-1" but headers URL is "6.8.1.arch1-1"
// Also, for 0-patch releases, like: "6.8.0-arch1-1", headers url is "6.8.arch1-1"
kr.FullExtraversion = strings.Replace(kr.FullExtraversion, "-arch", ".arch", 1)
if kr.Patch == 0 {
kr.Fullversion = strings.TrimSuffix(kr.Fullversion, ".0")
}
func (c archlinux) URLs(cfg Config, kr kernelrelease.KernelRelease) ([]string, error) {
urls := []string{}
possibleCompressionSuffixes := []string{
"xz",
"zst",
}
// check the architecture, which limits the mirror options
if kr.Architecture.ToNonDeb() == "x86_64" {
if strings.Contains(kr.FullExtraversion, "arch") { // arch stable kernel
baseURL := "https://archive.archlinux.org/packages/l/linux-headers"
for _, compressionAlgo := range possibleCompressionSuffixes {
urls = append(
urls,
fmt.Sprintf(
"%s/linux-headers-%s-%s-%s.pkg.tar.%s",
baseURL,
kr.String(),
kr.KernelVersion,
kr.Architecture.ToNonDeb(),
compressionAlgo,
),
)
}
} else if strings.Contains(kr.FullExtraversion, "hardened") || strings.Contains(kr.FullExtraversion, ".a-1") { // arch hardened kernel ("a-1" is old naming standard)
baseURL := "https://archive.archlinux.org/packages/l/linux-hardened-headers"
for _, compressionAlgo := range possibleCompressionSuffixes {
urls = append(
urls,
fmt.Sprintf(
"%s/linux-hardened-headers-%s-%s-%s.pkg.tar.%s",
baseURL,
kr.String(),
kr.KernelVersion,
kr.Architecture.ToNonDeb(),
compressionAlgo,
),
)
}
} else if strings.Contains(kr.FullExtraversion, "zen") { // arch zen kernel
baseURL := "https://archive.archlinux.org/packages/l/linux-zen-headers"
for _, compressionAlgo := range possibleCompressionSuffixes {
urls = append(
urls,
fmt.Sprintf(
"%s/linux-zen-headers-%s-%s-%s.pkg.tar.%s",
baseURL,
kr.String(),
kr.KernelVersion,
kr.Architecture.ToNonDeb(),
compressionAlgo,
),
)
}
} else { // arch LTS kernel
baseURL := "https://archive.archlinux.org/packages/l/linux-lts-headers"
for _, compressionAlgo := range possibleCompressionSuffixes {
urls = append(
urls,
fmt.Sprintf(
"%s/linux-lts-headers-%s-%s-%s.pkg.tar.%s",
baseURL,
kr.String(),
kr.KernelVersion,
kr.Architecture.ToNonDeb(),
compressionAlgo,
),
)
}
}
} else if kr.Architecture.ToNonDeb() == "aarch64" {
baseURL := "https://alaa.ad24.cz/packages/l/linux-aarch64-headers/"
for _, compressionAlgo := range possibleCompressionSuffixes {
urls = append(
urls,
fmt.Sprintf(
"%s/linux-aarch64-headers-%s-%s-%s.pkg.tar.%s",
baseURL,
kr.String(),
kr.KernelVersion,
kr.Architecture.ToNonDeb(),
compressionAlgo,
),
)
}
if kr.Architecture == "amd64" {
urls = append(urls, fmt.Sprintf(
"https://archive.archlinux.org/packages/l/linux-headers/linux-headers-%s.%s-%s-%s.pkg.tar.xz",
kr.Fullversion,
kr.Extraversion,
cfg.KernelVersion,
kr.Architecture.ToNonDeb()))
} else {
urls = append(urls, fmt.Sprintf(
"http://tardis.tiny-vps.com/aarm/packages/l/linux-%s-headers/linux-%s-headers-%s-%s-%s.pkg.tar.xz",
kr.Architecture.ToNonDeb(),
kr.Architecture.ToNonDeb(),
kr.Fullversion,
cfg.KernelVersion,
kr.Architecture.ToNonDeb()))
}
return urls, nil
}
func (c *archlinux) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
func (c archlinux) TemplateData(cfg Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return archlinuxTemplateData{
KernelDownloadURL: urls[0],
commonTemplateData: cfg.toTemplateData(),
KernelDownloadURL: urls[0],
GCCVersion: archlinuxGccVersionFromKernelRelease(kr),
}
}
func archlinuxGccVersionFromKernelRelease(kr kernelrelease.KernelRelease) string {
switch kr.Version {
case 3:
return "5"
case 2:
return "4.8"
}
return "8"
}

View File

@ -1,43 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
// TargetTypeBottlerocket identifies the Bottlerocket target.
const TargetTypeBottlerocket Type = "bottlerocket"
func init() {
byTarget[TargetTypeBottlerocket] = &bottlerocket{
vanilla{},
}
}
type bottlerocket struct {
vanilla
}
func (b *bottlerocket) Name() string {
return TargetTypeBottlerocket.String()
}
func (b *bottlerocket) KernelTemplateData(kr kernelrelease.KernelRelease, urls []string) interface{} {
return vanillaTemplateData{
KernelDownloadURL: urls[0],
KernelLocalVersion: kr.FullExtraversion,
}
}

View File

@ -1,113 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"context"
"fmt"
"github.com/falcosecurity/falcoctl/pkg/output"
"strings"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"oras.land/oras-go/v2/registry/remote/auth"
)
var defaultImageTag = "latest" // This is overwritten when using the Makefile to build
import "github.com/falcosecurity/driverkit/pkg/kernelrelease"
// Build contains the info about the on-going build.
type Build struct {
TargetType Type
KernelConfigData string
KernelRelease string
KernelVersion string
DriverVersion string
Architecture string
ModuleFilePath string
ProbeFilePath string
ModuleDriverName string
ModuleDeviceName string
BuilderImage string
BuilderRepos []string
ImagesListers []ImagesLister
KernelUrls []string
GCCVersion string
RepoOrg string
RepoName string
Images ImagesMap
RegistryName string
RegistryUser string
RegistryPassword string
RegistryPlainHTTP bool
*output.Printer
TargetType Type
KernelConfigData string
KernelRelease string
KernelVersion string
DriverVersion string
Architecture string
ModuleFilePath string
ProbeFilePath string
ModuleDriverName string
ModuleDeviceName string
CustomBuilderImage string
KernelUrls []string
}
func (b *Build) KernelReleaseFromBuildConfig() kernelrelease.KernelRelease {
kv := kernelrelease.FromString(b.KernelRelease)
kv.Architecture = kernelrelease.Architecture(b.Architecture)
kv.KernelVersion = b.KernelVersion
return kv
}
func (b *Build) toGithubRepoArchive() string {
return fmt.Sprintf("https://github.com/%s/%s/archive", b.RepoOrg, b.RepoName)
}
func (b *Build) ToConfig() Config {
return Config{
DriverName: b.ModuleDriverName,
DeviceName: b.ModuleDeviceName,
DownloadBaseURL: b.toGithubRepoArchive(),
Build: b,
}
}
// hasCustomBuilderImage return true if a custom builder image has been set by the user.
func (b *Build) hasCustomBuilderImage() bool {
if len(b.BuilderImage) > 0 {
customNames := strings.Split(b.BuilderImage, ":")
return customNames[0] != "auto"
}
return false
}
// builderImageTag returns the tag(latest, master or hash) to be used for the builder image.
func (b *Build) builderImageTag() string {
if len(b.BuilderImage) > 0 {
customNames := strings.Split(b.BuilderImage, ":")
// Updated image tag if "auto:tag" is passed
if len(customNames) > 1 {
return customNames[1]
}
}
return defaultImageTag
}
func (b *Build) ClientForRegistry(registry string) *auth.Client {
client := auth.DefaultClient
client.SetUserAgent("driverkit")
client.Credential = func(ctx context.Context, reg string) (auth.Credential, error) {
if b.RegistryName == registry {
return auth.Credential{
Username: b.RegistryUser,
Password: b.RegistryPassword,
}, nil
}
return auth.EmptyCredential, nil
}
return client
}

View File

@ -1,58 +1,33 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"bytes"
_ "embed"
"errors"
"fmt"
"github.com/falcosecurity/falcoctl/pkg/output"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"log"
"net/http"
"net/url"
"path"
"strings"
"text/template"
"github.com/blang/semver/v4"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
logger "github.com/sirupsen/logrus"
)
// DriverDirectory is the directory the processor uses to store the driver.
const (
DriverDirectory = "/tmp/driver"
cmakeCmdFmt = `cmake -Wno-dev \
-DUSE_BUNDLED_DEPS=On \
-DCREATE_TEST_TARGETS=Off \
-DBUILD_LIBSCAP_GVISOR=Off \
-DBUILD_LIBSCAP_MODERN_BPF=Off \
-DENABLE_DRIVERS_TESTS=Off \
-DDRIVER_NAME=%s \
-DPROBE_NAME=%s \
-DBUILD_BPF=On \
-DDRIVER_VERSION=%s \
-DPROBE_VERSION=%s \
-DGIT_COMMIT=%s \
-DDRIVER_DEVICE_NAME=%s \
-DPROBE_DEVICE_NAME=%s \
.. && \
sed -i s/'DRIVER_COMMIT ""'/'DRIVER_COMMIT "%s"'/g driver/src/driver_config.h`
)
const DriverDirectory = "/tmp/driver"
//go:embed templates/libs_download.sh
var libsDownloadTemplate string
// ModuleFileName is the standard file name for the kernel module.
const ModuleFileName = "module.ko"
// ProbeFileName is the standard file name for the eBPF probe.
const ProbeFileName = "probe.o"
// ModuleFullPath is the standard path for the kernel module. Builders must place the compiled module at this location.
var ModuleFullPath = path.Join(DriverDirectory, ModuleFileName)
// ProbeFullPath is the standard path for the eBPF probe. Builders must place the compiled probe at this location.
var ProbeFullPath = path.Join(DriverDirectory, "bpf", ProbeFileName)
var HeadersNotFoundErr = errors.New("kernel headers not found")
@ -64,92 +39,44 @@ type Config struct {
*Build
}
func (c Config) ToDriverFullPath() string {
return path.Join(DriverDirectory, "build", "driver", fmt.Sprintf("%s.ko", c.DriverName))
}
func (c Config) ToProbeFullPath() string {
return path.Join(DriverDirectory, "build", "driver", "bpf", "probe.o")
}
type commonTemplateData struct {
DriverBuildDir string
ModuleDriverName string
ModuleFullPath string
BuildModule bool
BuildProbe bool
GCCVersion string
CmakeCmd string
DriverBuildDir string
ModuleDownloadURL string
ModuleDriverName string
ModuleFullPath string
BuildModule bool
BuildProbe bool
}
// Builder represents a builder capable of generating a script for a driverkit target.
type Builder interface {
Name() string
TemplateKernelUrlsScript() string
TemplateScript() string
URLs(kr kernelrelease.KernelRelease) ([]string, error)
KernelTemplateData(kr kernelrelease.KernelRelease, urls []string) interface{} // error return type is managed
URLs(c Config, kr kernelrelease.KernelRelease) ([]string, error)
TemplateData(c Config, kr kernelrelease.KernelRelease, urls []string) interface{}
}
// MinimumURLsBuilder is an optional interface implemented by builders
// MinimumURLsBuilder is an optional interface
// to specify minimum number of requested headers urls
type MinimumURLsBuilder interface {
MinimumURLs() int
}
// TemplateDataSpecifier is an optional interface implemented by builders
// to specify a custom template data instead of the default one.
type TemplateDataSpecifier interface {
TemplateData(c Config, kr kernelrelease.KernelRelease) interface{}
}
type libsDownloadTemplateData struct {
DriverBuildDir string
ModuleDownloadURL string
}
// LibsDownloadScript returns the script that downloads and configures libs repo at requested commit/tag
func LibsDownloadScript(c Config) (string, error) {
t := template.New("download-libs")
parsed, err := t.Parse(libsDownloadTemplate)
func Script(b Builder, c Config, kr kernelrelease.KernelRelease) (string, error) {
t := template.New(b.Name())
parsed, err := t.Parse(b.TemplateScript())
if err != nil {
return "", err
}
td := libsDownloadTemplateData{
DriverBuildDir: DriverDirectory,
ModuleDownloadURL: fmt.Sprintf("%s/%s.tar.gz", c.DownloadBaseURL, c.DriverVersion),
}
buf := bytes.NewBuffer(nil)
err = parsed.Execute(buf, td)
if err != nil {
return "", err
}
return buf.String(), nil
}
// KernelDownloadScript returns the script that will download and extract kernel headers
func KernelDownloadScript(b Builder,
kernelurls []string,
kr kernelrelease.KernelRelease,
printer *output.Printer,
) (string, error) {
t := template.New("download-kernel")
parsed, err := t.Parse(b.TemplateKernelUrlsScript())
if err != nil {
return "", err
}
var urls []string
minimumURLs := 1
if bb, ok := b.(MinimumURLsBuilder); ok {
minimumURLs = bb.MinimumURLs()
}
if kernelurls == nil {
urls, err = b.URLs(kr)
var urls []string
if c.KernelUrls == nil {
urls, err = b.URLs(c, kr)
if err != nil {
return "", err
}
@ -157,10 +84,10 @@ func KernelDownloadScript(b Builder,
// Otherwise, it is up to the builder to return an error
if len(urls) > 0 {
// Check (and filter) existing kernels before continuing
urls, err = GetResolvingURLs(urls)
urls, err = getResolvingURLs(urls)
}
} else {
urls, err = GetResolvingURLs(kernelurls)
urls, err = getResolvingURLs(c.KernelUrls)
}
if err != nil {
return "", err
@ -170,246 +97,48 @@ func KernelDownloadScript(b Builder,
return "", fmt.Errorf("not enough headers packages found; expected %d, found %d", minimumURLs, len(urls))
}
printer.Logger.Debug("kernel headers found",
printer.Logger.Args("urls", urls))
td := b.KernelTemplateData(kr, urls)
if tdErr, ok := td.(error); ok {
return "", tdErr
}
td := b.TemplateData(c, kr, urls)
buf := bytes.NewBuffer(nil)
err = parsed.Execute(buf, td)
if err != nil {
return "", err
}
return buf.String(), nil
}
// Script retrieves the actually drivers building script
func Script(b Builder, c Config, kr kernelrelease.KernelRelease) (string, error) {
t := template.New(b.Name())
parsed, err := t.Parse(b.TemplateScript())
if err != nil {
return "", err
}
var td interface{}
if bb, ok := b.(TemplateDataSpecifier); ok {
td = bb.TemplateData(c, kr)
} else {
td = c.toTemplateData(b, kr)
}
buf := bytes.NewBuffer(nil)
err = parsed.Execute(buf, td)
if err != nil {
return "", err
}
return buf.String(), nil
}
type GCCVersionRequestor interface {
// GCCVersion returns the GCC version to be used.
// If the returned value is empty, the default algorithm will be enforced.
GCCVersion(kr kernelrelease.KernelRelease) semver.Version
}
func defaultGCC(kr kernelrelease.KernelRelease) semver.Version {
switch kr.Major {
case 6:
if kr.Minor >= 9 {
return semver.Version{Major: 14}
}
if kr.Minor >= 5 {
return semver.Version{Major: 13}
}
return semver.Version{Major: 12}
case 5:
if kr.Minor >= 15 {
return semver.Version{Major: 12}
}
return semver.Version{Major: 11}
case 4:
return semver.Version{Major: 8}
case 3:
if kr.Minor >= 18 {
return semver.Version{Major: 5}
}
return semver.Version{Major: 4, Minor: 9}
case 2:
return semver.Version{Major: 4, Minor: 8}
default:
return semver.Version{Major: 14}
}
}
func mustParseTolerant(gccStr string) semver.Version {
g, err := semver.ParseTolerant(gccStr)
if err != nil {
panic(err)
}
return g
}
// Algorithm.
// * always load images (note that it loads only images that provide gccversion, if set by user)
// * if user set a fixed gccversion, we are good to go
// * otherwise, try to fix the best-match gcc version provided by any of the loaded images;
// see below for algorithm explanation
func (b *Build) setGCCVersion(builder Builder, kr kernelrelease.KernelRelease) {
if !b.hasCustomBuilderImage() {
b.LoadImages()
}
if len(b.GCCVersion) > 0 {
// If set from user, go on
return
}
b.GCCVersion = "8" // default value
// if builder implements "GCCVersionRequestor" interface -> use it
// Else, fetch the best builder available from the kernelrelease version
// using the deadly simple defaultGCC() algorithm
// Always returns the nearest one
var targetGCC semver.Version
if bb, ok := builder.(GCCVersionRequestor); ok {
targetGCC = bb.GCCVersion(kr)
}
// If builder implements GCCVersionRequestor but returns an empty semver.Version
// it means that it does not want to manage this kernelrelease,
// and instead wants to fallback to default algorithm
if targetGCC.EQ(semver.Version{}) {
targetGCC = defaultGCC(kr)
}
if b.hasCustomBuilderImage() {
b.GCCVersion = targetGCC.String()
return
}
// Step 1:
// If we are able to either find a specific-target image,
// or "any" target image that provide desired gcc,
// we are over.
image, ok := b.Images.findImage(b.TargetType, targetGCC)
if ok {
b.GCCVersion = image.GCCVersion.String()
} else {
// Step 2:
// Build the list of "proposed" GCC versions,
// that is, the list of available gccs from images
// for each builder image
proposedGCCs := make([]semver.Version, 0)
for _, img := range b.Images {
proposedGCCs = append(proposedGCCs, img.GCCVersion)
b.Logger.Debug("proposed GCC",
b.Logger.Args("image", img.Name,
"targetGCC", targetGCC.String(),
"proposedGCC", img.GCCVersion.String()))
}
// Now, sort versions and fetch
// the nearest gcc, that is also < targetGCC
semver.Sort(proposedGCCs)
lastGCC := proposedGCCs[0]
for _, gcc := range proposedGCCs {
if gcc.GT(targetGCC) {
break
}
lastGCC = gcc
}
b.GCCVersion = lastGCC.String()
}
b.Logger.Debug("found GCC",
b.Logger.Args("targetGCC", targetGCC.String(), "version", b.GCCVersion))
}
type BuilderImageNetworkMode interface {
// sets the network mode of the builder image, allows individual builders to override
BuilderImageNetMode() string
}
func (b *Build) GetBuilderImage() string {
if b.hasCustomBuilderImage() {
// BuilderImage MUST have requested GCC installed inside
return b.BuilderImage
}
// NOTE: here below we are already sure that we are going
// to find an image, because setGCCVersion()
// has already set an existent gcc version
// (ie: one provided by an image) for us
image, _ := b.Images.findImage(b.TargetType, mustParseTolerant(b.GCCVersion))
return image.Name
}
// Factory returns a builder for the given target.
func Factory(target Type) (Builder, error) {
// Workaround for "local" target (that is not exposed to users,
// nor registered in byTarget map)".
if target.String() == "local" {
return &LocalBuilder{}, nil
}
// Driverkit builder is named "ubuntu"; there is no ubuntu-foo
if strings.HasPrefix(target.String(), "ubuntu") {
target = Type("ubuntu")
}
b, ok := byTarget[target]
b, ok := BuilderByTarget[target]
if !ok {
return nil, fmt.Errorf("no builder found for target: %s", target)
}
return b, nil
}
// Targets returns the list of all the supported targets.
func Targets() []string {
res := []string{}
for k := range byTarget {
res = append(res, k.String())
}
return res
}
func (c Config) toTemplateData(b Builder, kr kernelrelease.KernelRelease) commonTemplateData {
c.setGCCVersion(b, kr)
func (c Config) toTemplateData() commonTemplateData {
return commonTemplateData{
DriverBuildDir: DriverDirectory,
ModuleDriverName: c.DriverName,
ModuleFullPath: c.ToDriverFullPath(),
BuildModule: len(c.ModuleFilePath) > 0,
BuildProbe: len(c.ProbeFilePath) > 0,
GCCVersion: c.GCCVersion,
CmakeCmd: fmt.Sprintf(cmakeCmdFmt,
c.DriverName,
c.DriverName,
c.DriverVersion,
c.DriverVersion,
c.DriverVersion,
c.DeviceName,
c.DeviceName,
c.DriverVersion),
DriverBuildDir: DriverDirectory,
ModuleDownloadURL: fmt.Sprintf("%s/%s.tar.gz", c.DownloadBaseURL, c.DriverVersion),
ModuleDriverName: c.DriverName,
ModuleFullPath: ModuleFullPath,
BuildModule: len(c.ModuleFilePath) > 0,
BuildProbe: len(c.ProbeFilePath) > 0,
}
}
func resolveURLReference(u string) string {
uu, err := url.Parse(u)
if err != nil {
panic(err)
log.Fatal(err)
}
base, err := url.Parse(uu.Host)
if err != nil {
panic(err)
log.Fatal(err)
}
return base.ResolveReference(uu).String()
}
func GetResolvingURLs(urls []string) ([]string, error) {
func getResolvingURLs(urls []string) ([]string, error) {
var results []string
for _, u := range urls {
// in case url has some relative paths
@ -424,6 +153,7 @@ func GetResolvingURLs(urls []string) ([]string, error) {
}
if res.StatusCode == http.StatusOK {
results = append(results, u)
logger.WithField("url", u).Debug("kernel header url found")
}
}
if len(results) == 0 {

View File

@ -1,107 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"testing"
"github.com/blang/semver/v4"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
var gccTests = []struct {
config kernelrelease.KernelRelease
expectedGCC semver.Version
}{
{
config: kernelrelease.KernelRelease{
Fullversion: "4.15.0",
Version: semver.Version{
Major: 4,
Minor: 15,
Patch: 0,
},
Extraversion: "188",
FullExtraversion: "-188",
Architecture: kernelrelease.ArchitectureAmd64,
},
expectedGCC: semver.Version{
Major: 8,
},
},
{
config: kernelrelease.KernelRelease{
Fullversion: "5.15.0",
Version: semver.Version{
Major: 5,
Minor: 15,
Patch: 0,
},
Extraversion: "1004-intel-iotg",
FullExtraversion: "-1004-intel-iotg",
Architecture: kernelrelease.ArchitectureAmd64,
},
expectedGCC: semver.Version{
Major: 12,
},
},
{
config: kernelrelease.KernelRelease{
Fullversion: "3.13.0",
Version: semver.Version{
Major: 3,
Minor: 13,
Patch: 0,
},
Extraversion: "100",
FullExtraversion: "-100",
Architecture: kernelrelease.ArchitectureAmd64,
},
expectedGCC: semver.Version{
Major: 4,
Minor: 9,
},
},
{
config: kernelrelease.KernelRelease{
Fullversion: "5.18.0",
Version: semver.Version{
Major: 5,
Minor: 18,
Patch: 0,
},
Extraversion: "1001-kvm",
FullExtraversion: "-1001-kvm",
Architecture: kernelrelease.ArchitectureAmd64,
},
expectedGCC: semver.Version{
Major: 12,
},
},
}
func TestDefaultGCC(t *testing.T) {
for _, test := range gccTests {
// call function
selectedGCC := defaultGCC(test.config)
// compare errors
// there are no official errors, so comparing fmt.Errorf() doesn't really work
// compare error message text instead
if test.expectedGCC.NE(selectedGCC) {
t.Fatalf("SelectedGCC (%s) != expectedGCC (%s) with kernelrelease: '%v'", selectedGCC, test.expectedGCC, test.config)
}
}
}

View File

@ -1,30 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"github.com/blang/semver/v4"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/centos_kernel.sh
var centosKernelTemplate string
//go:embed templates/centos.sh
var centosTemplate string
@ -32,7 +13,7 @@ var centosTemplate string
const TargetTypeCentos Type = "centos"
func init() {
byTarget[TargetTypeCentos] = &centos{}
BuilderByTarget[TargetTypeCentos] = &centos{}
}
// centos is a driverkit target.
@ -40,20 +21,20 @@ type centos struct {
}
type centosTemplateData struct {
commonTemplateData
KernelDownloadURL string
GCCVersion string
}
func (c *centos) Name() string {
func (c centos) Name() string {
return TargetTypeCentos.String()
}
func (c *centos) TemplateKernelUrlsScript() string { return centosKernelTemplate }
func (c *centos) TemplateScript() string {
func (c centos) TemplateScript() string {
return centosTemplate
}
func (c *centos) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
func (c centos) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
vaultReleases := []string{
"6.0/os",
"6.0/updates",
@ -180,21 +161,20 @@ func (c *centos) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
return urls, nil
}
func (c *centos) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
func (c centos) TemplateData(cfg Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return centosTemplateData{
KernelDownloadURL: urls[0],
commonTemplateData: cfg.toTemplateData(),
KernelDownloadURL: urls[0],
GCCVersion: centosGccVersionFromKernelRelease(kr),
}
}
func (c *centos) GCCVersion(kr kernelrelease.KernelRelease) semver.Version {
// 4.18+ centos 8 kernels need gcc 9
if kr.Major == 4 && kr.Minor >= 18 {
return semver.Version{Major: 9}
func centosGccVersionFromKernelRelease(kr kernelrelease.KernelRelease) string {
switch kr.Version {
case 3:
return "5"
case 2:
return "4.8"
}
// 3.10.X kernels need 4.8.5 gcc version; see:
// https://github.com/falcosecurity/driverkit/issues/236
if kr.Major == 3 && kr.Minor == 10 {
return semver.Version{Major: 4, Minor: 8, Patch: 5}
}
return semver.Version{}
return "8"
}

View File

@ -1,34 +1,15 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"io"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"io/ioutil"
"net/http"
"regexp"
"strings"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/debian_kernel.sh
var debianKernelTemplate string
//go:embed templates/debian.sh
var debianTemplate string
@ -42,51 +23,44 @@ const TargetTypeDebian Type = "debian"
const debianRequiredURLs = 3
func init() {
byTarget[TargetTypeDebian] = &debian{}
BuilderByTarget[TargetTypeDebian] = &debian{}
}
type debianTemplateData struct {
KernelDownloadURLS []string
KernelLocalVersion string
KernelHeadersPattern string
commonTemplateData
KernelDownloadURLS []string
KernelLocalVersion string
LLVMVersion string
KernelArch string
}
// debian is a driverkit target.
type debian struct {
}
func (v *debian) Name() string {
func (v debian) Name() string {
return TargetTypeDebian.String()
}
func (v *debian) TemplateKernelUrlsScript() string { return debianKernelTemplate }
func (v *debian) TemplateScript() string {
func (v debian) TemplateScript() string {
return debianTemplate
}
func (v *debian) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
func (v debian) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
return fetchDebianKernelURLs(kr)
}
func (v *debian) KernelTemplateData(kr kernelrelease.KernelRelease, urls []string) interface{} {
var KernelHeadersPattern string
if strings.HasSuffix(kr.Extraversion, "pve") {
KernelHeadersPattern = "linux-headers-*pve"
} else if strings.Contains(kr.FullExtraversion, "rpi") {
KernelHeadersPattern = "linux-headers-*-rpi-v*"
} else {
KernelHeadersPattern = "linux-headers-*" + kr.Architecture.String()
}
func (v debian) TemplateData(c Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return debianTemplateData{
KernelDownloadURLS: urls,
KernelLocalVersion: kr.FullExtraversion,
KernelHeadersPattern: KernelHeadersPattern,
commonTemplateData: c.toTemplateData(),
KernelDownloadURLS: urls,
KernelLocalVersion: kr.FullExtraversion,
LLVMVersion: debianLLVMVersionFromKernelRelease(kr),
KernelArch: kr.Architecture.String(),
}
}
func (v *debian) MinimumURLs() int {
func (v debian) MinimumURLs() int {
return debianRequiredURLs
}
@ -135,18 +109,9 @@ func fetchDebianHeadersURLFromRelease(baseURL string, kr kernelrelease.KernelRel
matchExtraGroupCommon := "common"
// match for kernel versions like 4.19.0-6-cloud-amd64
supportedExtraFlavors := []string{"cloud", "rt", "rpi"}
for _, supportedExtraFlavor := range supportedExtraFlavors {
if strings.Contains(kr.FullExtraversion, "-"+supportedExtraFlavor) {
extraVersionPartial = strings.TrimSuffix(extraVersionPartial, "-"+supportedExtraFlavor)
matchExtraGroup = supportedExtraFlavor + "-" + matchExtraGroup
// rpi and rt have a different common package, named `common-{rt,rpi}`
if supportedExtraFlavor == "rt" || supportedExtraFlavor == "rpi" {
matchExtraGroupCommon += "-" + supportedExtraFlavor
}
break
}
if strings.Contains(kr.FullExtraversion, "-cloud") {
extraVersionPartial = strings.TrimSuffix(extraVersionPartial, "-cloud")
matchExtraGroup = "cloud-" + matchExtraGroup
}
// download index
@ -155,19 +120,19 @@ func fetchDebianHeadersURLFromRelease(baseURL string, kr kernelrelease.KernelRel
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
bodyStr := string(body)
// look for kernel headers
fullregex := fmt.Sprintf(rmatch, kr.Major, kr.Minor, kr.Patch,
fullregex := fmt.Sprintf(rmatch, kr.Version, kr.PatchLevel, kr.Sublevel,
extraVersionPartial, matchExtraGroup, kr.Architecture.String())
pattern := regexp.MustCompile(fullregex)
matches := pattern.FindStringSubmatch(bodyStr)
if len(matches) < 1 {
fullregex = fmt.Sprintf(rmatchNew, matchExtraGroup, kr.Major, kr.Minor, kr.Patch,
fullregex = fmt.Sprintf(rmatchNew, matchExtraGroup, kr.Version, kr.PatchLevel, kr.Sublevel,
extraVersionPartial, kr.Architecture.String())
pattern = regexp.MustCompile(fullregex)
matches = pattern.FindStringSubmatch(bodyStr)
@ -177,12 +142,12 @@ func fetchDebianHeadersURLFromRelease(baseURL string, kr kernelrelease.KernelRel
}
// look for kernel headers common
fullregexCommon := fmt.Sprintf(rmatch, kr.Major, kr.Minor, kr.Patch,
fullregexCommon := fmt.Sprintf(rmatch, kr.Version, kr.PatchLevel, kr.Sublevel,
extraVersionPartial, matchExtraGroupCommon, kr.Architecture.String())
patternCommon := regexp.MustCompile(fullregexCommon)
matchesCommon := patternCommon.FindStringSubmatch(bodyStr)
if len(matchesCommon) < 1 {
fullregexCommon = fmt.Sprintf(rmatchNew, matchExtraGroupCommon, kr.Major, kr.Minor, kr.Patch,
fullregexCommon = fmt.Sprintf(rmatchNew, matchExtraGroupCommon, kr.Version, kr.PatchLevel, kr.Sublevel,
extraVersionPartial, kr.Architecture.String())
patternCommon = regexp.MustCompile(fullregexCommon)
matchesCommon = patternCommon.FindStringSubmatch(bodyStr)
@ -200,9 +165,9 @@ func fetchDebianHeadersURLFromRelease(baseURL string, kr kernelrelease.KernelRel
func debianKbuildURLFromRelease(kr kernelrelease.KernelRelease) (string, error) {
rmatch := `href="(linux-kbuild-%d\.%d.*%s\.deb)"`
kbuildPattern := regexp.MustCompile(fmt.Sprintf(rmatch, kr.Major, kr.Minor, kr.Architecture.String()))
kbuildPattern := regexp.MustCompile(fmt.Sprintf(rmatch, kr.Version, kr.PatchLevel, kr.Architecture.String()))
baseURL := "http://mirrors.kernel.org/debian/pool/main/l/linux/"
if kr.Major == 3 {
if kr.Version == 3 {
baseURL = "http://mirrors.kernel.org/debian/pool/main/l/linux-tools/"
}
@ -223,3 +188,11 @@ func debianKbuildURLFromRelease(kr kernelrelease.KernelRelease) (string, error)
return fmt.Sprintf("%s%s", baseURL, match[1]), nil
}
func debianLLVMVersionFromKernelRelease(kr kernelrelease.KernelRelease) string {
switch kr.Version {
case 5:
return "12"
}
return "7"
}

View File

@ -1,105 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"strings"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/fedora_kernel.sh
var fedoraKernelTemplate string
//go:embed templates/fedora.sh
var fedoraTemplate string
// TargetTypeFedora identifies the Fedora target.
const TargetTypeFedora Type = "fedora"
func init() {
byTarget[TargetTypeFedora] = &fedora{}
}
// fedora is a driverkit target.
type fedora struct {
}
type fedoraTemplateData struct {
KernelDownloadURL string
}
func (c *fedora) Name() string {
return TargetTypeFedora.String()
}
func (c *fedora) TemplateKernelUrlsScript() string { return fedoraKernelTemplate }
func (c *fedora) TemplateScript() string {
return fedoraTemplate
}
func (c *fedora) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
// fedora FullExtraversion looks like "-200.fc36.x86_64"
// need to get the "fc36" out of the middle
fedoraVersion := strings.Split(kr.FullExtraversion, ".")[1]
// trim off the "fc" from fedoraVersion
version := strings.Trim(fedoraVersion, "fc")
// template the kernel info into all possible URL strings
urls := []string{
fmt.Sprintf( // updates
"https://mirrors.kernel.org/fedora/updates/%s/Everything/%s/Packages/k/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
fmt.Sprintf( // releases
"https://mirrors.kernel.org/fedora/releases/%s/Everything/%s/os/Packages/k/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
fmt.Sprintf( // development
"https://mirrors.kernel.org/fedora/development/%s/Everything/%s/os/Packages/k/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
fmt.Sprintf( // updates-archive
"https://fedoraproject-updates-archive.fedoraproject.org/fedora/%s/%s/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
}
// return out all possible urls
return urls, nil
}
func (c *fedora) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
return fedoraTemplateData{
KernelDownloadURL: urls[0],
}
}

View File

@ -1,33 +1,14 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"io/ioutil"
"net/http"
"strings"
"github.com/blang/semver/v4"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/flatcar_kernel.sh
var flatcarKernelTemplate string
//go:embed templates/flatcar.sh
var flatcarTemplate string
@ -35,79 +16,72 @@ var flatcarTemplate string
const TargetTypeFlatcar Type = "flatcar"
func init() {
byTarget[TargetTypeFlatcar] = &flatcar{}
BuilderByTarget[TargetTypeFlatcar] = &flatcar{}
}
type flatcarTemplateData struct {
commonTemplateData
KernelDownloadURL string
GCCVersion string
FlatcarVersion string
FlatcarChannel string
KernelConfigURL string
}
// flatcar is a driverkit target.
type flatcar struct {
info *flatcarReleaseInfo
version string
info *flatcarReleaseInfo
kconfUrls []string
}
func (f *flatcar) Name() string {
func (f flatcar) Name() string {
return TargetTypeFlatcar.String()
}
func (f *flatcar) TemplateKernelUrlsScript() string {
return flatcarKernelTemplate
}
func (f *flatcar) TemplateScript() string {
func (f flatcar) TemplateScript() string {
return flatcarTemplate
}
func (f *flatcar) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
if err := f.fillFlatcarInfos(kr); err != nil {
func (f flatcar) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
if kr.Extraversion != "" {
return nil, fmt.Errorf("unexpected extraversion: %s", kr.Extraversion)
}
// convert string to int
if kr.Version < 1500 {
return nil, fmt.Errorf("not a valid flatcar release version: %d", kr.Version)
}
f.version = kr.Fullversion
var err error
f.info, err = fetchFlatcarMetadata(kr)
if err != nil {
return nil, err
}
f.kconfUrls, err = getResolvingURLs(fetchFlatcarKernelConfigURL(kr.Architecture, f.info.Channel, kr.Fullversion))
if err != nil {
return nil, err
}
return fetchFlatcarKernelURLS(f.info.KernelVersion), nil
}
func (f *flatcar) KernelTemplateData(kr kernelrelease.KernelRelease, urls []string) interface{} {
// This happens when `kernelurls` option is passed,
// therefore URLs() method is not called.
if f.info == nil {
if err := f.fillFlatcarInfos(kr); err != nil {
return err
}
}
func (f flatcar) TemplateData(c Config, _ kernelrelease.KernelRelease, urls []string) interface{} {
return flatcarTemplateData{
KernelDownloadURL: urls[0],
commonTemplateData: c.toTemplateData(),
KernelDownloadURL: urls[0],
GCCVersion: flatcarGccVersion(f.info.GCCVersion),
FlatcarVersion: f.version,
FlatcarChannel: f.info.Channel,
KernelConfigURL: f.kconfUrls[0],
}
}
func (f *flatcar) GCCVersion(_ kernelrelease.KernelRelease) semver.Version {
return f.info.GCCVersion
}
func (f *flatcar) fillFlatcarInfos(kr kernelrelease.KernelRelease) error {
if kr.Extraversion != "" {
return fmt.Errorf("unexpected extraversion: %s", kr.Extraversion)
}
// convert string to int
if kr.Major < 1500 {
return fmt.Errorf("not a valid flatcar release version: %d", kr.Major)
}
var err error
f.info, err = fetchFlatcarMetadata(kr)
return err
}
func fetchFlatcarKernelURLS(kernelVersion string) []string {
kv := kernelrelease.FromString(kernelVersion)
return []string{fetchVanillaKernelURLFromKernelVersion(kv)}
}
func fetchFlatcarMetadata(kr kernelrelease.KernelRelease) (*flatcarReleaseInfo, error) {
flatcarInfo := flatcarReleaseInfo{}
flatcarVersion := kr.Fullversion
packageIndexUrl, err := GetResolvingURLs(fetchFlatcarPackageListURL(kr.Architecture, flatcarVersion))
packageIndexUrl, err := getResolvingURLs(fetchFlatcarPackageListURL(kr.Architecture, flatcarVersion))
if err != nil {
return nil, err
}
@ -142,10 +116,7 @@ func fetchFlatcarMetadata(kr kernelrelease.KernelRelease) (*flatcarReleaseInfo,
kernelVersion = strings.Split(kernelVersion, "-")[0]
}
}
flatcarInfo.GCCVersion, err = semver.ParseTolerant(gccVersion)
if err != nil {
return nil, err
}
flatcarInfo.GCCVersion = gccVersion
flatcarInfo.KernelVersion = kernelVersion
return &flatcarInfo, nil
@ -165,8 +136,29 @@ func fetchFlatcarPackageListURL(architecture kernelrelease.Architecture, flatcar
return urls
}
func fetchFlatcarKernelConfigURL(architecture kernelrelease.Architecture, flatcarChannel, flatcarVersion string) []string {
return []string{fmt.Sprintf("https://%s.release.flatcar-linux.net/%s-usr/%s/flatcar_production_image_kernel_config.txt", flatcarChannel, architecture.String(), flatcarVersion)}
}
func fetchFlatcarKernelURLS(kernelVersion string) []string {
kv := kernelrelease.FromString(kernelVersion)
return []string{fmt.Sprintf("https://cdn.kernel.org/pub/linux/kernel/v%d.x/linux-%s.tar.xz", kv.Version, kv.Fullversion)}
}
type flatcarReleaseInfo struct {
Channel string
GCCVersion semver.Version
GCCVersion string
KernelVersion string
}
func flatcarGccVersion(gccVersion string) string {
// reuse kernelrelease version parsing for gcc
gv := kernelrelease.FromString(gccVersion)
switch gv.Version {
case 7:
return "6"
default:
// builder doesn't support anything newer than 8 right now
return "8"
}
}

View File

@ -1,263 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"context"
"fmt"
"github.com/falcosecurity/falcoctl/pkg/output"
"os"
"regexp"
"strings"
"github.com/blang/semver/v4"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"github.com/falcosecurity/falcoctl/pkg/oci/repository"
"gopkg.in/yaml.v3"
)
type YAMLImage struct {
Target string `yaml:"target"`
GCCVersions []string `yaml:"gcc_versions"` // we expect images to internally link eg: gcc5 to gcc5.0.0
Name string `yaml:"name"`
Arch string `yaml:"arch"`
Tag string `yaml:"tag"`
}
type YAMLImagesList struct {
Images []YAMLImage `yaml:"images"`
}
type Image struct {
Target Type
GCCVersion semver.Version // we expect images to internally link eg: gcc5 to gcc5.0.0
Name string
}
type ImagesLister interface {
LoadImages(printer *output.Printer) []Image
}
type FileImagesLister struct {
FilePath string
Arch string
Tag string
Target string
}
type RepoImagesLister struct {
*repository.Repository
}
type ImageKey string
func (i *Image) toKey() ImageKey {
return ImageKey(i.Target.String() + "_" + i.GCCVersion.String())
}
type ImagesMap map[ImageKey]Image
var tagReg *regexp.Regexp
func (im ImagesMap) findImage(target Type, gccVers semver.Version) (Image, bool) {
targetImage := Image{
Target: target,
GCCVersion: gccVers,
}
// Try to find specific image for specific target first
if img, ok := im[targetImage.toKey()]; ok {
return img, true
}
// Fallback at "any" target that offers specific gcc
targetImage.Target = "any"
if img, ok := im[targetImage.toKey()]; ok {
return img, true
}
return Image{}, false
}
func NewFileImagesLister(filePath string, build *Build) (*FileImagesLister, error) {
return &FileImagesLister{
FilePath: filePath,
Arch: kernelrelease.Architecture(build.Architecture).ToNonDeb(),
Tag: build.builderImageTag(),
Target: build.TargetType.String(),
}, nil
}
func (f *FileImagesLister) LoadImages(printer *output.Printer) []Image {
var (
res []Image
imageList YAMLImagesList
)
// loop over lines in file to print them
fileData, err := os.ReadFile(f.FilePath)
if err != nil {
printer.Logger.Warn("error opening builder repo file",
printer.Logger.Args("err", err.Error(), "filepath", f.FilePath))
return res
}
err = yaml.Unmarshal(fileData, &imageList)
if err != nil {
printer.Logger.Warn("error unmarshalling builder repo file",
printer.Logger.Args("err", err.Error(), "filepath", f.FilePath))
return res
}
for _, image := range imageList.Images {
// Values checks
if image.Arch != f.Arch {
printer.Logger.Debug("skipping wrong-arch image",
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue
}
if image.Tag != f.Tag {
printer.Logger.Debug("skipping wrong-tag image",
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue
}
if image.Target != "any" && image.Target != f.Target {
printer.Logger.Debug("skipping wrong-target image",
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue
}
if image.Name == "" {
printer.Logger.Debug("skipping empty name image",
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue
}
if len(image.GCCVersions) == 0 {
printer.Logger.Debug("expected at least 1 gcc version",
printer.Logger.Args("filepath", f.FilePath, "image", image))
continue
}
for _, gcc := range image.GCCVersions {
buildImage := Image{
Name: image.Name,
Target: Type(image.Target),
GCCVersion: mustParseTolerant(gcc),
}
res = append(res, buildImage)
}
}
return res
}
func NewRepoImagesLister(repo string, build *Build) (*RepoImagesLister, error) {
// Lazy inizialization
if tagReg == nil {
imageTag := build.builderImageTag()
// Create the proper regexes to load "any" and target-specific images for requested arch
arch := kernelrelease.Architecture(build.Architecture).ToNonDeb()
targetFmt := fmt.Sprintf("^(?P<target>%s|any)-%s(?P<gccVers>(_gcc[0-9]+.[0-9]+.[0-9]+)+)-%s$", build.TargetType.String(), arch, imageTag)
tagReg = regexp.MustCompile(targetFmt)
}
// Get the registry URL from repository.
registry, err := getRegistryFromRef(repo)
if err != nil {
return nil, err
}
repoOCI, err := repository.NewRepository(repo,
repository.WithPlainHTTP(build.RegistryPlainHTTP),
repository.WithClient(build.ClientForRegistry(registry)))
if err != nil {
return nil, err
}
return &RepoImagesLister{repoOCI}, nil
}
func (repo *RepoImagesLister) LoadImages(printer *output.Printer) []Image {
tags, err := repo.Tags(context.Background())
if err != nil {
printer.Logger.Warn("skipping repo",
printer.Logger.Args("repo", repo.Reference, "err", err.Error()))
return nil
}
var res []Image
for _, t := range tags {
img := fmt.Sprintf("%s:%s", repo.Reference, t)
match := tagReg.FindStringSubmatch(t)
if len(match) == 0 {
continue
}
var (
target string
gccVers []string
)
for i, name := range tagReg.SubexpNames() {
if i > 0 && i <= len(match) {
switch name {
case "gccVers":
gccVers = strings.Split(match[i], "_gcc")
gccVers = gccVers[1:] // remove initial whitespace
case "target":
target = match[i]
}
}
}
// Note: we store "any" target images as "any",
// instead of adding them to the target,
// because we always prefer specific target images,
// and we cannot guarantee here that any subsequent docker repos
// does not provide a target-specific image that offers same gcc version
for _, gccVer := range gccVers {
// If user set a fixed gcc version, only load images that provide it.
buildImage := Image{
GCCVersion: mustParseTolerant(gccVer),
Name: img,
Target: Type(target),
}
res = append(res, buildImage)
}
}
return res
}
func (b *Build) LoadImages() {
for _, imagesLister := range b.ImagesListers {
for _, image := range imagesLister.LoadImages(b.Printer) {
// User forced a gcc version? Only load images matching the requested gcc version.
if b.GCCVersion != "" && b.GCCVersion != image.GCCVersion.String() {
continue
}
// Skip if key already exists: we have a descending prio list of docker repos!
if _, ok := b.Images[image.toKey()]; !ok {
b.Images[image.toKey()] = image
}
}
}
if len(b.Images) == 0 {
b.Printer.Logger.Fatal("Could not load any builder image. Leaving.")
}
}
// getRegistryFromRef extracts the registry from a ref string.
func getRegistryFromRef(ref string) (string, error) {
index := strings.Index(ref, "/")
if index <= 0 {
return "", fmt.Errorf("cannot extract registry name from ref %q", ref)
}
return ref[0:index], nil
}

View File

@ -1,311 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"github.com/falcosecurity/falcoctl/pkg/output"
"github.com/pterm/pterm"
"io"
"net/http"
"os"
"testing"
"github.com/blang/semver/v4"
"github.com/docker/docker/testutil/registry"
"gotest.tools/assert"
)
var imagesTests = []struct {
yamlData string
jsonData string
expected []Image
}{
// Test that multiple gcc versions are correctly mapped to multiple images
{
yamlData: `
images:
- name: foo/test:any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest
target: any
arch: x86_64
tag: latest
gcc_versions:
- 8.0.0
- 6.0.0
- 5.0.0
- 4.9.0
- 4.8.0
`,
jsonData: `
{
"name": "foo/test",
"tags": [
"any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest"
]
}
`,
expected: []Image{
{
Target: "any",
GCCVersion: semver.MustParse("8.0.0"),
Name: "foo/test:any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest",
},
{
Target: "any",
GCCVersion: semver.MustParse("6.0.0"),
Name: "foo/test:any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest",
},
{
Target: "any",
GCCVersion: semver.MustParse("5.0.0"),
Name: "foo/test:any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest",
},
{
Target: "any",
GCCVersion: semver.MustParse("4.9.0"),
Name: "foo/test:any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest",
},
{
Target: "any",
GCCVersion: semver.MustParse("4.8.0"),
Name: "foo/test:any-x86_64_gcc8.0.0_gcc6.0.0_gcc5.0.0_gcc4.9.0_gcc4.8.0-latest",
},
},
},
// Test that arm64 is correctly skipped on amd64 images listing
{
yamlData: `
images:
- name: foo/test:any-x86_64_gcc8.0.0-latest
target: any
arch: x86_64
tag: latest
gcc_versions:
- 8.0.0
- name: foo/test:any-aarch64_gcc8.0.0-latest
target: any
arch: aarch64
tag: latest
gcc_versions:
- 8.0.0
`,
jsonData: `
{
"name": "foo/test",
"tags": [
"any-x86_64_gcc8.0.0-latest",
"any-aarch64_gcc8.0.0-latest"
]
}
`,
expected: []Image{
{
Target: "any",
GCCVersion: semver.MustParse("8.0.0"),
Name: "foo/test:any-x86_64_gcc8.0.0-latest",
},
},
},
// Test empty gcc versions image is skipped
{
yamlData: `
images:
- name: foo/test:any-x86_64_gcc8.0.0-latest
target: any
arch: x86_64
tag: latest
gcc_versions:
- 8.0.0
- name: bar/test:any-x86_64-latest
target: any
arch: x86_64
tag: latest
`,
jsonData: `
{
"name": "foo/test",
"tags": [
"any-x86_64_gcc8.0.0-latest",
"any-x86_64-latest"
]
}
`,
expected: []Image{
{
Target: "any",
GCCVersion: semver.MustParse("8.0.0"),
Name: "foo/test:any-x86_64_gcc8.0.0-latest",
},
},
},
// Test wrong target image is skipped
{
yamlData: `
images:
- name: foo/test:centos-x86_64_gcc8.0.0-latest
target: centos
arch: x86_64
tag: latest
gcc_versions:
- 8.0.0
- name: foo/test:wrongtarget-x86_64_gcc6.0.0-latest
target: wrongtarget
arch: x86_64
tag: latest
gcc_versions:
- 6.0.0
`,
jsonData: `
{
"name": "foo/test",
"tags": [
"centos-x86_64_gcc8.0.0-latest",
"wrongtarget-x86_64_gcc8.0.0-latest"
]
}
`,
expected: []Image{
{
Target: "centos",
GCCVersion: semver.MustParse("8.0.0"),
Name: "foo/test:centos-x86_64_gcc8.0.0-latest",
},
},
},
// Test empty name image is skipped
{
yamlData: `
images:
- name: foo/test:any-x86_64_gcc8.0.0-latest
target: any
arch: x86_64
tag: latest
gcc_versions:
- 8.0.0
- target: any
arch: x86_64
tag: latest
gcc_versions:
- 6.0.0
`,
jsonData: "",
expected: []Image{
{
Target: "any",
GCCVersion: semver.MustParse("8.0.0"),
Name: "foo/test:any-x86_64_gcc8.0.0-latest",
},
},
},
// Test empty list returned for yaml/json with no images
{
yamlData: `
images:
`,
jsonData: `
{
"name": "foo/test",
"tags": [
]
}
`,
expected: nil,
},
// Test empty list returned for malformed yaml/json answer
{
yamlData: `
images:
* name: foo/test
target: any
arch: x86_64
gcc_versions:
* 8.0.0
`,
jsonData: "malformedresponse",
expected: nil,
},
}
func TestFileImagesLister(t *testing.T) {
printer := output.NewPrinter(pterm.LogLevelInfo, pterm.LogFormatterColorful, os.Stdout)
// setup images file
f, err := os.CreateTemp(t.TempDir(), "imagetest")
if err != nil {
t.Fatal(err)
}
defer os.Remove(f.Name())
lister, err := NewFileImagesLister(f.Name(), &Build{
TargetType: Type("centos"),
Architecture: "amd64",
BuilderImage: "auto:latest",
})
assert.NilError(t, err)
for _, test := range imagesTests {
if test.yamlData == "" {
t.Log("Skipping unsuitable test for FileImagesLister")
continue
}
err = f.Truncate(0)
if err != nil {
t.Fatal(err)
}
_, err = f.Seek(0, io.SeekStart)
if err != nil {
t.Fatal(err)
}
_, err = f.WriteString(test.yamlData)
if err != nil {
t.Fatal(err)
}
assert.DeepEqual(t, test.expected, lister.LoadImages(printer))
}
}
func TestRepoImagesLister(t *testing.T) {
printer := output.NewPrinter(pterm.LogLevelInfo, pterm.LogFormatterColorful, os.Stdout)
mock, err := registry.NewMock(t)
assert.NilError(t, err)
defer mock.Close()
lister, err := NewRepoImagesLister(mock.URL()+"/foo/test", &Build{
TargetType: Type("centos"),
Architecture: "amd64",
BuilderImage: "auto:latest",
RegistryPlainHTTP: true,
})
assert.NilError(t, err)
for _, test := range imagesTests {
if test.jsonData == "" {
t.Log("Skipping unsuitable test for RepoImagesLister")
continue
}
// Update expected names adding the mocked server URL as prefix
for idx, _ := range test.expected {
test.expected[idx].Name = mock.URL() + "/" + test.expected[idx].Name
}
mock.RegisterHandler("/v2/foo/test/tags/list", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(test.jsonData))
})
assert.DeepEqual(t, test.expected, lister.LoadImages(printer))
}
}

View File

@ -1,106 +0,0 @@
package builder
import (
_ "embed"
"fmt"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
"path/filepath"
)
// NOTE: since this is only used by local build,
// it is not exposed in `target` array,
// so no init() function to register it is present.
//go:embed templates/local.sh
var localTemplate string
type LocalBuilder struct {
GccPath string
UseDKMS bool
SrcDir string
}
func (l *LocalBuilder) Name() string {
return "local"
}
func (l *LocalBuilder) TemplateKernelUrlsScript() string {
panic("cannot be called on local builder")
}
func (l *LocalBuilder) TemplateScript() string {
return localTemplate
}
func (l *LocalBuilder) URLs(_ kernelrelease.KernelRelease) ([]string, error) {
return nil, nil
}
func (l *LocalBuilder) MinimumURLs() int {
// We don't need any url
return 0
}
type localTemplateData struct {
commonTemplateData
UseDKMS bool
DownloadSrc bool
DriverVersion string
KernelRelease string
}
func (l *LocalBuilder) KernelTemplateData(_ kernelrelease.KernelRelease, _ []string) interface{} {
panic("cannot be called on local builder")
}
func (l *LocalBuilder) TemplateData(c Config, kr kernelrelease.KernelRelease) interface{} {
return localTemplateData{
commonTemplateData: commonTemplateData{
DriverBuildDir: l.GetDriverBuildDir(),
ModuleDriverName: c.DriverName,
ModuleFullPath: l.GetModuleFullPath(c, kr),
BuildModule: len(c.ModuleFilePath) > 0,
BuildProbe: len(c.ProbeFilePath) > 0,
GCCVersion: l.GccPath,
CmakeCmd: fmt.Sprintf(cmakeCmdFmt,
c.DriverName,
c.DriverName,
c.DriverVersion,
c.DriverVersion,
c.DriverVersion,
c.DeviceName,
c.DeviceName,
c.DriverVersion),
},
UseDKMS: l.UseDKMS,
DownloadSrc: len(l.SrcDir) == 0, // if no srcdir is provided, download src!
DriverVersion: c.DriverVersion,
KernelRelease: c.KernelRelease,
}
}
func (l *LocalBuilder) GetModuleFullPath(c Config, kr kernelrelease.KernelRelease) string {
if l.UseDKMS {
// When using dkms, we will use a GLOB to match the pattern; ModuleFullPath won't be used in the templated script anyway.
return fmt.Sprintf("/var/lib/dkms/%s/%s/%s/%s/module/%s.*", c.DriverName, c.DriverVersion, kr.String(), kr.Architecture.ToNonDeb(), c.DriverName)
}
if l.SrcDir != "" {
return filepath.Join(l.SrcDir, fmt.Sprintf("%s.ko", c.DriverName))
}
return c.ToDriverFullPath()
}
func (l *LocalBuilder) GetProbeFullPath(c Config) string {
if l.SrcDir != "" {
return filepath.Join(l.SrcDir, "bpf", "probe.o")
}
return c.ToProbeFullPath()
}
func (l *LocalBuilder) GetDriverBuildDir() string {
driverBuildDir := DriverDirectory
if l.SrcDir != "" {
driverBuildDir = l.SrcDir
}
return driverBuildDir
}

View File

@ -1,56 +1,8 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"github.com/blang/semver/v4"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
// TargetTypeMinikube identifies the Minikube target.
const TargetTypeMinikube Type = "minikube"
func init() {
byTarget[TargetTypeMinikube] = &minikube{
vanilla{},
}
}
type minikube struct {
vanilla
}
func (m *minikube) Name() string {
return TargetTypeMinikube.String()
}
func (m *minikube) KernelTemplateData(kr kernelrelease.KernelRelease, urls []string) interface{} {
return vanillaTemplateData{
KernelDownloadURL: urls[0],
KernelLocalVersion: kr.FullExtraversion,
}
}
func (m *minikube) GCCVersion(kr kernelrelease.KernelRelease) semver.Version {
// The supported versions of minikube use kernels > 4.19.
switch kr.Major {
case 5:
return semver.Version{Major: 10}
case 4:
return semver.Version{Major: 8}
default:
return semver.Version{Major: 12}
}
BuilderByTarget[TargetTypeMinikube] = &vanilla{}
}

View File

@ -1,272 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"strings"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/opensuse_kernel.sh
var opensuseKernelTemplate string
//go:embed templates/opensuse.sh
var opensuseTemplate string
// TargetTypeOpenSUSE identifies the OpenSUSE target.
const TargetTypeOpenSUSE Type = "opensuse"
// We need:
// kernel-default-devel-*-{arch}
// kernel-devel-*-noarch
const opensuseMinimumURLs = 2
// base URLs to begin searches
var baseURLs []string = []string{
// general releases, leap releases
"https://mirrors.edge.kernel.org/opensuse/distribution",
"http://download.opensuse.org/distribution",
"https://download.opensuse.org/repositories/Kernel:",
// some releases are stored at the top level specifically
"http://download.opensuse.org",
}
// all known releases - will need to expand as more are added
var releases = []string{
// openSUSE leap
"43.2",
"15.0",
"15.1",
"15.2",
"15.3",
"15.4",
"15.5",
"15.6",
// other releases
"HEAD",
"stable",
"tumbleweed",
}
func init() {
byTarget[TargetTypeOpenSUSE] = &opensuse{}
}
// opensuse is a driverkit target.
type opensuse struct {
}
type opensuseTemplateData struct {
KernelDownloadURLs []string
}
func (o *opensuse) MinimumURLs() int {
return opensuseMinimumURLs
}
func (o *opensuse) Name() string {
return TargetTypeOpenSUSE.String()
}
func (o *opensuse) TemplateKernelUrlsScript() string {
return opensuseKernelTemplate
}
func (o *opensuse) TemplateScript() string {
return opensuseTemplate
}
func (o *opensuse) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
// SUSE requires 2 urls: a kernel-default-devel*{arch}.rpm and a kernel-devel*noarch.rpm
kernelDefaultDevelPattern := fmt.Sprintf("kernel-default-devel-%s%s.rpm", kr.Fullversion, kr.FullExtraversion)
kernelDevelNoArchPattern := strings.ReplaceAll( // need to replace architecture string with "noarch"
fmt.Sprintf("kernel-devel-%s%s.rpm", kr.Fullversion, kr.FullExtraversion),
kr.Architecture.ToNonDeb(),
"noarch",
)
// get all possible URLs
possibleURLs := buildURLs(kr, kernelDefaultDevelPattern, kernelDevelNoArchPattern)
// trim the list to only resolving URLs
urls, err := GetResolvingURLs(possibleURLs)
if err != nil {
return nil, err
}
// ensure there is at least one URL of each required package type
if validateURLs(urls, kernelDefaultDevelPattern, kernelDevelNoArchPattern) {
return urls, nil
} else {
return nil, fmt.Errorf(
"missing one of the required package types: [ kernel-default-devel, kernel-devel*noarch ]: %v",
urls,
)
}
}
// build all possible url combinations from base URLs and releases
func buildURLs(kr kernelrelease.KernelRelease, kernelDefaultDevelPattern string, kernelDevelNoArchPattern string) []string {
possibleURLs := []string{}
for _, release := range releases {
for _, baseURL := range baseURLs {
possibleURLs = append(
possibleURLs,
// leap urls
fmt.Sprintf(
"%s/leap/%s/repo/oss/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
fmt.Sprintf( // noarch
"%s/leap/%s/repo/oss/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
// other urls
fmt.Sprintf(
"%s/%s/repo/oss/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
fmt.Sprintf( // noarch
"%s/%s/repo/oss/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
// weird opensuse site urls
fmt.Sprintf(
"%s/openSUSE-%s/Submit/standard/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
fmt.Sprintf(
"%s/openSUSE-%s/standard/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
fmt.Sprintf(
"%s/openSUSE-%s:/Submit/standard/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
fmt.Sprintf(
"%s/openSUSE-%s:/standard/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
fmt.Sprintf(
"%s/%s/Submit/standard/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
fmt.Sprintf(
"%s/%s/standard/%s/%s",
baseURL,
release,
kr.Architecture.ToNonDeb(),
kernelDefaultDevelPattern,
),
// weird opensuse site urls - kernel-devel*noarch edition
fmt.Sprintf(
"%s/openSUSE-%s/Submit/standard/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
fmt.Sprintf(
"%s/openSUSE-%s/standard/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
fmt.Sprintf(
"%s/openSUSE-%s:/Submit/standard/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
fmt.Sprintf(
"%s/openSUSE-%s:/standard/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
fmt.Sprintf(
"%s/%s/Submit/standard/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
fmt.Sprintf(
"%s/%s/standard/noarch/%s",
baseURL,
release,
kernelDevelNoArchPattern,
),
)
}
}
return possibleURLs
}
// check to ensure there is at least one URL of each package type
func validateURLs(urls []string, kernelDefaultDevelPattern string, kernelDevelNoArchPattern string) bool {
// setup some flags
kernelDefaultDevelFlag := false
kernelDevelNoArchFlag := false
for _, url := range urls {
if strings.Contains(url, kernelDefaultDevelPattern) {
kernelDefaultDevelFlag = true
}
if strings.Contains(url, kernelDevelNoArchPattern) {
kernelDevelNoArchFlag = true
}
}
return kernelDefaultDevelFlag && kernelDevelNoArchFlag
}
func (o *opensuse) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
return opensuseTemplateData{
KernelDownloadURLs: urls,
}
}

View File

@ -1,132 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"strings"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/oracle_kernel.sh
var oracleKernelTemplate string
//go:embed templates/oracle.sh
var oracleTemplate string
// TargetTypeoracle identifies the oracle target ("ol" is the ID from /etc/os-release that Oracle uses)
const TargetTypeoracle Type = "ol"
func init() {
byTarget[TargetTypeoracle] = &oracle{}
}
// oracle is a driverkit target.
type oracle struct {
}
type oracleTemplateData struct {
KernelDownloadURL string
}
func (c *oracle) Name() string {
return TargetTypeoracle.String()
}
func (c *oracle) TemplateKernelUrlsScript() string {
return oracleKernelTemplate
}
func (c *oracle) TemplateScript() string {
return oracleTemplate
}
func (c *oracle) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
// oracle FullExtraversion looks like "-2047.510.5.5.el7uek.x86_64"
// need to get the "el7uek" out of the middle
splitVersion := strings.Split(kr.FullExtraversion, ".")
oracleVersion := splitVersion[len(splitVersion)-2] // [ "-2047", "510", "5", "5", "el7uek","x86_64" ] want -2
// trim off the "el" and "uek" from oracleVersion
version := strings.Trim(strings.Trim(oracleVersion, "el"), "uek")
// sometimes Oracle 8 does "8_x" for version, only want the "8"
if strings.Contains(version, "_") {
version = strings.Split(version, "_")[0]
}
// list of possible UEK versions, which are used in the URL - ex: "UEKR3"
// may need to evolve over time if Oracle adds more
ueks := []string{"R3", "R4", "R5", "R6", "R7"}
// template the kernel info into all possible URL strings
urls := []string{
fmt.Sprintf( // latest (Oracle 7)
"http://yum.oracle.com/repo/OracleLinux/OL%s/latest/%s/getPackage/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
fmt.Sprintf( // latest + baseos (Oracle 8 + 9)
"http://yum.oracle.com/repo/OracleLinux/OL%s/baseos/latest/%s/getPackage/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
fmt.Sprintf( // appstream (Oracle 8 + 9)
"http://yum.oracle.com/repo/OracleLinux/OL%s/appstream/%s/getPackage/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
fmt.Sprintf( // MODRHCK (Oracle 7)
"http://yum.oracle.com/repo/OracleLinux/OL%s/MODRHCK/%s/getPackage/kernel-devel-%s%s.rpm",
version,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
}
// add in all the UEK versions
for _, uekVers := range ueks {
urls = append(
urls,
fmt.Sprintf( // UEK versions URL
"http://yum.oracle.com/repo/OracleLinux/OL%s/UEK%s/%s/getPackage/kernel-uek-devel-%s%s.rpm",
version,
uekVers,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
),
)
}
// return out all possible urls
return urls, nil
}
func (c *oracle) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
return oracleTemplateData{
KernelDownloadURL: urls[0],
}
}

View File

@ -1,37 +1,19 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
// TargetTypePhoton identifies the Photon target.
const TargetTypePhoton Type = "photon"
//go:embed templates/photonos_kernel.sh
var photonKernelTemplate string
//go:embed templates/photonos.sh
var photonTemplate string
func init() {
byTarget[TargetTypePhoton] = &photon{}
BuilderByTarget[TargetTypePhoton] = &photon{}
}
// photon is a driverkit target.
@ -39,28 +21,28 @@ type photon struct {
}
type photonTemplateData struct {
commonTemplateData
KernelDownloadURL string
GCCVersion string
}
func (p *photon) Name() string {
func (p photon) Name() string {
return TargetTypePhoton.String()
}
func (p *photon) TemplateKernelUrlsScript() string {
return photonKernelTemplate
}
func (p *photon) TemplateScript() string {
func (p photon) TemplateScript() string {
return photonTemplate
}
func (p *photon) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
func (p photon) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
return fetchPhotonKernelURLS(kr), nil
}
func (p *photon) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
func (p photon) TemplateData(cfg Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return photonTemplateData{
KernelDownloadURL: urls[0],
commonTemplateData: cfg.toTemplateData(),
KernelDownloadURL: urls[0],
GCCVersion: photonGccVersionFromKernelRelease(kr),
}
}
@ -68,38 +50,50 @@ func fetchPhotonKernelURLS(kr kernelrelease.KernelRelease) []string {
photonReleases := []string{
"3.0",
"4.0",
"5.0",
}
var urls []string
urls := []string{}
for _, r := range photonReleases {
urls = append(urls, fmt.Sprintf(
"https://packages.vmware.com/photon/%s/photon_%s_%s/%s/linux-devel-%s%s.x86_64.rpm",
r,
r,
kr.Architecture.ToNonDeb(),
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
urls = append(urls, fmt.Sprintf(
"https://packages.vmware.com/photon/%s/photon_release_%s_%s/%s/linux-devel-%s%s.x86_64.rpm",
r,
r,
kr.Architecture.ToNonDeb(),
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
urls = append(urls, fmt.Sprintf(
"https://packages.vmware.com/photon/%s/photon_updates_%s_%s/%s/linux-devel-%s%s.x86_64.rpm",
r,
r,
kr.Architecture.ToNonDeb(),
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
switch r {
case "3.0":
urls = append(urls, fmt.Sprintf(
"https://packages.vmware.com/photon/%s/photon_updates_%s_x86_64/x86_64/linux-devel-%s%s.x86_64.rpm",
r,
r,
kr.Fullversion,
kr.FullExtraversion,
))
urls = append(urls, fmt.Sprintf(
"https://packages.vmware.com/photon/%s/photon_release_%s_x86_64/x86_64/linux-devel-%s%s.x86_64.rpm",
r,
r,
kr.Fullversion,
kr.FullExtraversion,
))
case "4.0":
urls = append(urls, fmt.Sprintf(
"https://packages.vmware.com/photon/%s/photon_%s_x86_64/x86_64/linux-devel-%s%s.x86_64.rpm",
r,
r,
kr.Fullversion,
kr.FullExtraversion,
))
urls = append(urls, fmt.Sprintf(
"https://packages.vmware.com/photon/%s/photon_release_%s_x86_64/x86_64/linux-devel-%s%s.x86_64.rpm",
r,
r,
kr.Fullversion,
kr.FullExtraversion,
))
}
}
return urls
}
func photonGccVersionFromKernelRelease(kr kernelrelease.KernelRelease) string {
switch kr.Version {
default:
return "8"
}
}

View File

@ -1,28 +1,10 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/redhat_kernel.sh
var redhatKernelTemplate string
//go:embed templates/redhat.sh
var redhatTemplate string
@ -34,36 +16,34 @@ type redhat struct {
}
func init() {
byTarget[TargetTypeRedhat] = &redhat{}
BuilderByTarget[TargetTypeRedhat] = &redhat{}
}
type redhatTemplateData struct {
commonTemplateData
KernelPackage string
}
func (v *redhat) Name() string {
func (v redhat) Name() string {
return TargetTypeRedhat.String()
}
func (v *redhat) TemplateKernelUrlsScript() string {
return redhatKernelTemplate
}
func (v *redhat) TemplateScript() string {
func (v redhat) TemplateScript() string {
return redhatTemplate
}
func (v *redhat) URLs(_ kernelrelease.KernelRelease) ([]string, error) {
func (v redhat) URLs(_ Config, _ kernelrelease.KernelRelease) ([]string, error) {
return nil, nil
}
func (v *redhat) MinimumURLs() int {
func (v redhat) MinimumURLs() int {
// We don't need any url
return 0
}
func (v *redhat) KernelTemplateData(kr kernelrelease.KernelRelease, _ []string) interface{} {
func (v redhat) TemplateData(c Config, kr kernelrelease.KernelRelease, _ []string) interface{} {
return redhatTemplateData{
KernelPackage: kr.Fullversion + kr.FullExtraversion,
commonTemplateData: c.toTemplateData(),
KernelPackage: kr.Fullversion + kr.FullExtraversion,
}
}

View File

@ -1,29 +1,11 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"fmt"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/rocky_kernel.sh
var rockyKernelTemplate string
//go:embed templates/rocky.sh
var rockyTemplate string
@ -31,93 +13,64 @@ var rockyTemplate string
const TargetTypeRocky Type = "rocky"
func init() {
byTarget[TargetTypeRocky] = &rocky{}
BuilderByTarget[TargetTypeRocky] = &rocky{}
}
type rockyTemplateData struct {
commonTemplateData
KernelDownloadURL string
GCCVersion string
}
// rocky is a driverkit target.
type rocky struct {
}
func (c *rocky) Name() string {
func (c rocky) Name() string {
return TargetTypeRocky.String()
}
func (c *rocky) TemplateKernelUrlsScript() string {
return rockyKernelTemplate
}
func (c *rocky) TemplateScript() string {
func (c rocky) TemplateScript() string {
return rockyTemplate
}
func (c *rocky) URLs(kr kernelrelease.KernelRelease) ([]string, error) {
func (c rocky) URLs(_ Config, kr kernelrelease.KernelRelease) ([]string, error) {
return fetchRockyKernelURLS(kr), nil
}
func (c *rocky) KernelTemplateData(_ kernelrelease.KernelRelease, urls []string) interface{} {
func (c rocky) TemplateData(cfg Config, kr kernelrelease.KernelRelease, urls []string) interface{} {
return rockyTemplateData{
KernelDownloadURL: urls[0],
commonTemplateData: cfg.toTemplateData(),
KernelDownloadURL: urls[0],
GCCVersion: rockyGccVersionFromKernelRelease(kr),
}
}
func fetchRockyKernelURLS(kr kernelrelease.KernelRelease) []string {
rockyReleases := []string{
"8",
"8.7",
"9",
"9.1",
}
rockyVaultReleases := []string{
"8.3",
"8.4",
"8.5",
"8.6",
"9.1",
}
urls := []string{}
for _, r := range rockyReleases {
if r >= "9" {
urls = append(urls, fmt.Sprintf(
"https://download.rockylinux.org/pub/rocky/%s/AppStream/%s/os/Packages/k/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
} else {
urls = append(urls, fmt.Sprintf(
"https://download.rockylinux.org/pub/rocky/%s/BaseOS/%s/os/Packages/k/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
}
}
for _, r := range rockyVaultReleases {
if r >= "9" {
urls = append(urls, fmt.Sprintf(
"https://download.rockylinux.org/vault/rocky/%s/AppStream/%s/os/Packages/k/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
} else {
urls = append(urls, fmt.Sprintf(
"https://download.rockylinux.org/vault/rocky/%s/BaseOS/%s/os/Packages/k/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
}
urls = append(urls, fmt.Sprintf(
"https://download.rockylinux.org/pub/rocky/%s/BaseOS/%s/os/Packages/k/kernel-devel-%s%s.rpm",
r,
kr.Architecture.ToNonDeb(),
kr.Fullversion,
kr.FullExtraversion,
))
}
return urls
}
func rockyGccVersionFromKernelRelease(kr kernelrelease.KernelRelease) string {
switch kr.Version {
case 3:
return "5"
case 2:
return "4.8"
}
return "8"
}

View File

@ -1,75 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
_ "embed"
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
//go:embed templates/sles_kernel.sh
var slesKernelTemplate string
//go:embed templates/sles.sh
var slesTemplate string
// TargetTypeSLES identifies the sles target.
const TargetTypeSLES Type = "sles"
// sles is a driverkit target.
type sles struct {
}
func init() {
byTarget[TargetTypeSLES] = &sles{}
}
type slesTemplateData struct {
KernelPackage string
}
func (v *sles) Name() string {
return TargetTypeSLES.String()
}
func (v *sles) TemplateKernelUrlsScript() string {
return slesKernelTemplate
}
func (v *sles) TemplateScript() string {
return slesTemplate
}
func (v *sles) URLs(_ kernelrelease.KernelRelease) ([]string, error) {
return nil, nil
}
func (v *sles) MinimumURLs() int {
// We don't need any url
return 0
}
func (v *sles) KernelTemplateData(kr kernelrelease.KernelRelease, _ []string) interface{} {
return slesTemplateData{
KernelPackage: kr.Fullversion + kr.FullExtraversion,
}
}
// sles requires docker to run with `--net=host` for builder images to work
// for more info, see the suse container connect README: https://github.com/SUSE/container-suseconnect
func (v *sles) BuilderImageNetMode() string {
return "host"
}

View File

@ -1,43 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
import (
"github.com/falcosecurity/driverkit/pkg/kernelrelease"
)
// TargetTypeTalos identifies the Talos target.
const TargetTypeTalos Type = "talos"
func init() {
byTarget[TargetTypeTalos] = &talos{
vanilla{},
}
}
type talos struct {
vanilla
}
func (b *talos) Name() string {
return TargetTypeTalos.String()
}
func (b *talos) KernelTemplateData(kr kernelrelease.KernelRelease, urls []string) interface{} {
return vanillaTemplateData{
KernelDownloadURL: urls[0],
KernelLocalVersion: kr.FullExtraversion,
}
}

View File

@ -1,21 +1,7 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package builder
// byTarget maps targets to their builder.
var byTarget = map[Type]Builder{}
// BuilderByTarget maps targets to their builder.
var BuilderByTarget = Targets{}
// Type is a type representing targets.
type Type string
@ -23,3 +9,15 @@ type Type string
func (t Type) String() string {
return string(t)
}
// Targets is a type representing the list of the supported targets.
type Targets map[Type]Builder
// Targets returns the list of all the supported targets.
func (t Targets) Targets() []string {
res := []string{}
for k := range t {
res = append(res, k.String())
}
return res
}

View File

@ -1,41 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2023 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Simple script that desperately tries to load the kernel instrumentation by
# looking for it in a bunch of ways. Convenient when running Falco inside
# a container or in other weird environments.
#
set -xeuo pipefail
cd {{ .DriverBuildDir }}
mkdir -p build && cd build
{{ .CmakeCmd }}
{{ if .BuildModule }}
# Build the module
make CC=/usr/bin/gcc-{{ .GCCVersion }} driver
strip -g {{ .ModuleFullPath }}
# Print results
modinfo {{ .ModuleFullPath }}
{{ end }}
{{ if .BuildProbe }}
# Build the eBPF probe
make bpf
ls -l driver/bpf/probe.o
{{ end }}

View File

@ -1,35 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2023 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Simple script that desperately tries to load the kernel instrumentation by
# looking for it in a bunch of ways. Convenient when running Falco inside
# a container or in other weird environments.
#
set -xeuo pipefail
# Fetch the kernel
mkdir /tmp/kernel-download
cd /tmp/kernel-download
curl --silent -o kernel-devel.rpm -SL {{ .KernelDownloadURL }}
rpm2cpio kernel-devel.rpm | cpio --extract --make-directories
rm -Rf /tmp/kernel
mkdir -p /tmp/kernel
mv usr/src/kernels/*/* /tmp/kernel
# exit value
export KERNELDIR=/tmp/kernel

View File

@ -1,41 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2023 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Simple script that desperately tries to load the kernel instrumentation by
# looking for it in a bunch of ways. Convenient when running Falco inside
# a container or in other weird environments.
#
set -xeuo pipefail
cd {{ .DriverBuildDir }}
mkdir -p build && cd build
{{ .CmakeCmd }}
{{ if .BuildModule }}
# Build the module
make CC=/usr/bin/gcc-{{ .GCCVersion }} driver
strip -g {{ .ModuleFullPath }}
# Print results
modinfo {{ .ModuleFullPath }}
{{ end }}
{{ if .BuildProbe }}
# Build the eBPF probe
make bpf
ls -l driver/bpf/probe.o
{{ end }}

View File

@ -1,35 +0,0 @@
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2023 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Simple script that desperately tries to load the kernel instrumentation by
# looking for it in a bunch of ways. Convenient when running Falco inside
# a container or in other weird environments.
#
set -xeuo pipefail
# Fetch the kernel
mkdir /tmp/kernel-download
cd /tmp/kernel-download
curl --silent -o kernel-devel.rpm -SL {{ .KernelDownloadURL }}
rpm2cpio kernel-devel.rpm | cpio --extract --make-directories
rm -Rf /tmp/kernel
mkdir -p /tmp/kernel
mv usr/src/kernels/*/* /tmp/kernel
# exit value
export KERNELDIR=/tmp/kernel

View File

@ -1,41 +1,42 @@
#!/bin/bash
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2023 The Falco Authors.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Simple script that desperately tries to load the kernel instrumentation by
# looking for it in a bunch of ways. Convenient when running Falco inside
# a container or in other weird environments.
#
set -xeuo pipefail
cd {{ .DriverBuildDir }}
mkdir -p build && cd build
{{ .CmakeCmd }}
rm -Rf {{ .DriverBuildDir }}
mkdir {{ .DriverBuildDir }}
rm -Rf /tmp/module-download
mkdir -p /tmp/module-download
curl --silent -SL {{ .ModuleDownloadURL }} | tar -xzf - -C /tmp/module-download
mv /tmp/module-download/*/driver/* {{ .DriverBuildDir }}
cp /driverkit/module-Makefile {{ .DriverBuildDir }}/Makefile
bash /driverkit/fill-driver-config.sh {{ .DriverBuildDir }}
# Fetch the kernel
mkdir /tmp/kernel-download
cd /tmp/kernel-download
{{ range $url := .KernelDownloadURLs }}
curl --silent -o kernel.rpm -SL {{ $url }}
rpm2cpio kernel.rpm | cpio --extract --make-directories
rm -rf kernel.rpm
{{ end }}
rm -Rf /tmp/kernel
mkdir -p /tmp/kernel
mv usr/src/kernels/*/* /tmp/kernel
{{ if .BuildModule }}
# Build the module
make CC=/usr/bin/gcc-{{ .GCCVersion }} LD=/usr/bin/ld.bfd CROSS_COMPILE="" driver
strip -g {{ .ModuleFullPath }}
# Build the kernel module
cd {{ .DriverBuildDir }}
make KERNELDIR=/tmp/kernel CC=/usr/bin/gcc LD=/usr/bin/ld.bfd CROSS_COMPILE=""
mv {{ .ModuleDriverName }}.ko {{ .ModuleFullPath }}
# Print results
modinfo {{ .ModuleFullPath }}
{{ end }}
{{ if .BuildProbe }}
# Build the eBPF probe
make bpf
ls -l driver/bpf/probe.o
cd {{ .DriverBuildDir }}/bpf
make LLC=/usr/bin/llc-{{ .LLVMVersion }} CLANG=/usr/bin/clang-{{ .LLVMVersion }} CC=/usr/bin/gcc KERNELDIR=/tmp/kernel
ls -l probe.o
{{ end }}

Some files were not shown because too many files have changed in this diff Show More