Enable BPF tests in CI (#10933)

This commit is contained in:
Jakub Nyckowski 2022-07-14 20:16:56 -04:00 committed by GitHub
parent dd12a7f60e
commit c380f86bd9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 37 deletions

View file

@ -1,3 +1,5 @@
//go:build linux
/*
Copyright 2021 Gravitational, Inc.
@ -23,10 +25,12 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/gravitational/trace"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
"github.com/gravitational/teleport/.cloudbuild/scripts/internal/artifacts"
"github.com/gravitational/teleport/.cloudbuild/scripts/internal/changes"
@ -36,8 +40,11 @@ import (
"github.com/gravitational/teleport/.cloudbuild/scripts/internal/secrets"
)
// debugFsPath is the path where debugfs should be mounted.
const debugFsPath = "/sys/kernel/debug"
// main is just a stub that prints out an error message and sets a nonzero exit
// code on failure. All of the work happens in `innerMain()`.
// code on failure. All the work happens in `innerMain()`.
func main() {
if err := run(); err != nil {
log.Fatalf("FAILED: %s", err.Error())
@ -165,6 +172,11 @@ func run() error {
artifacts.FindAndUpload(timeoutCtx, args.bucket, prefix, args.artifactSearchPatterns)
}()
log.Printf("Mounting debugfs")
if err := mountDebugFS(); err != nil {
return trace.Wrap(err)
}
log.Printf("Running unit tests...")
err = runUnitTests(args.workspace)
if err != nil {
@ -177,13 +189,49 @@ func run() error {
}
func runUnitTests(workspace string) error {
enableTests := []string{
"TELEPORT_ETCD_TEST=yes",
"TELEPORT_XAUTH_TEST=yes",
"TELEPORT_BPF_TEST=yes",
}
cmd := exec.Command("make", "test")
cmd.Dir = workspace
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "TELEPORT_ETCD_TEST=yes")
cmd.Env = append(cmd.Env, "TELEPORT_XAUTH_TEST=yes")
cmd.Env = append(cmd.Env, enableTests...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
// mountDebugFS mounts debugfs at /sys/kernel/debug, so BPF test can run in GCB.
func mountDebugFS() error {
if isDebugFsMounted() {
return nil
}
// equivalent to: mount -t debugfs none /sys/kernel/debug/
if err := unix.Mount("debugfs", debugFsPath, "debugfs", 0, ""); err != nil {
return trace.Wrap(err, "failed to mount debugfs")
}
return nil
}
// isDebugFsMounted returns true if debugfs is mounted, false otherwise.
func isDebugFsMounted() bool {
mounts, err := os.ReadFile("/proc/mounts")
if err != nil {
log.Warningf("Failed to read /proc/mounts: %v", err)
return false
}
for _, line := range strings.Split(string(mounts), "\n") {
tokens := strings.Fields(line)
if len(tokens) == 6 && tokens[0] == "debugfs" && tokens[1] == debugFsPath {
return true
}
}
return false
}

View file

@ -11,6 +11,7 @@ require (
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c
)
@ -42,7 +43,6 @@ require (
go.opencensus.io v0.23.0 // indirect
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect

View file

@ -57,15 +57,14 @@ func TestRootBPF(t *testing.T) {
}
func (s *Suite) TestWatch(c *check.C) {
// TODO(jakule): Find a way to run this test in CI. Disable for now to not block all BPF tests.
c.Skip("this test always fails when running inside a CGroup/Docker")
// This test must be run as root and the host has to be capable of running
// BPF programs.
if !isRoot() {
c.Skip("Tests for package bpf can only be run as root.")
}
err := IsHostCompatible()
if err != nil {
c.Skip(fmt.Sprintf("Tests for package bpf can not be run: %v.", err))
}
// Create temporary directory where cgroup2 hierarchy will be mounted.
dir, err := os.MkdirTemp("", "cgroup-test")
@ -145,11 +144,6 @@ func (s *Suite) TestObfuscate(c *check.C) {
c.Skip("Tests for package bpf can only be run as root.")
return
}
err := IsHostCompatible()
if err != nil {
c.Skip(fmt.Sprintf("Tests for package bpf can not be run: %v.", err))
return
}
// Find the programs needed to run these tests on the host.
decoderPath, err := os_exec.LookPath("base64")
@ -229,10 +223,6 @@ func (s *Suite) TestScript(c *check.C) {
if !isRoot() {
c.Skip("Tests for package bpf can only be run as root.")
}
err := IsHostCompatible()
if err != nil {
c.Skip(fmt.Sprintf("Tests for package bpf can not be run: %v.", err))
}
// Start execsnoop.
execsnoop, err := startExec(8192)
@ -303,12 +293,6 @@ func (s *Suite) TestPrograms(c *check.C) {
c.Skip("Tests for package bpf can only be run as root.")
}
// Check that the host is capable of running BPF programs.
err := IsHostCompatible()
if err != nil {
c.Skip(fmt.Sprintf("Tests for package bpf can not be run: %v.", err))
}
// Start a debug server that tcpconnect will connect to.
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello, world")
@ -395,12 +379,6 @@ func (s *Suite) TestBPFCounter(c *check.C) {
c.Skip("Tests for package bpf can only be run as root.")
}
// Check that the host is capable of running BPF programs.
err := IsHostCompatible()
if err != nil {
c.Skip(fmt.Sprintf("Tests for package bpf can not be run: %v.", err))
}
counterTestBPF, err := embedFS.ReadFile("bytecode/counter_test.bpf.o")
if err != nil {
c.Skip(fmt.Sprintf("Tests for package bpf can not be run: %v.", err))

View file

@ -182,16 +182,13 @@ func (s *Suite) SetUpSuite(c *check.C) {
if !isRoot() {
c.Skip("Tests for package restrictedsession can only be run as root.")
}
err := bpf.IsHostCompatible()
if err != nil {
c.Skip(fmt.Sprintf("Tests for package restrictedsession can not be run: %v.", err))
}
s.srcAddrs = map[int]string{
4: "0.0.0.0",
6: "::",
}
var err error
// Create temporary directory where cgroup2 hierarchy will be mounted.
s.cgroupDir, err = os.MkdirTemp("", "cgroup-test")
c.Assert(err, check.IsNil)
@ -287,7 +284,7 @@ func (s *Suite) closeSession(c *check.C) {
var ip4Regex = regexp.MustCompile(`^\d+\.\d+\.\d+\.\d+$`)
// mustParseIP parses the IP and also converts IPv4 addresses
// to 4 byte represenetation. IPv4 mapped (into IPv6) addresses
// to 4 byte representation. IPv4 mapped (into IPv6) addresses
// are kept in 16 byte encoding
func mustParseIP(addr string) net.IP {
is4 := ip4Regex.MatchString(addr)
@ -508,8 +505,8 @@ func isRoot() bool {
return os.Geteuid() == 0
}
// bpfTestEnabled returns true if BPF tests should run. Tests can be enabled by
// setting TELEPORT_BPF_TEST environment variable to any value.
// bpfTestEnabled returns true if BPF/LSM tests should run. Tests can be enabled by
// setting TELEPORT_BPF_LSM_TEST environment variable to any value.
func bpfTestEnabled() bool {
return os.Getenv("TELEPORT_BPF_TEST") != ""
return os.Getenv("TELEPORT_BPF_LSM_TEST") != ""
}