2023-04-10 15:36:59 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2020-05-15 15:09:01 +00:00
|
|
|
package fingerprint
|
|
|
|
|
|
|
|
import (
|
2020-11-09 19:56:14 +00:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"strings"
|
2020-05-15 15:09:01 +00:00
|
|
|
"testing"
|
|
|
|
|
2022-03-15 12:42:43 +00:00
|
|
|
"github.com/hashicorp/nomad/ci"
|
2020-11-09 19:56:14 +00:00
|
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
2020-05-15 15:09:01 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
2020-11-09 19:56:14 +00:00
|
|
|
func TestBridgeFingerprint_detect(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
|
|
|
|
2020-11-09 19:56:14 +00:00
|
|
|
f := &BridgeFingerprint{logger: testlog.HCLogger(t)}
|
|
|
|
require.NoError(t, f.detect("ip_tables"))
|
|
|
|
|
|
|
|
err := f.detect("nonexistentmodule")
|
|
|
|
require.Error(t, err)
|
|
|
|
require.Contains(t, err.Error(), "3 errors occurred")
|
|
|
|
}
|
|
|
|
|
|
|
|
func writeFile(t *testing.T, prefix, content string) string {
|
2023-03-08 19:25:10 +00:00
|
|
|
f, err := os.CreateTemp("", "bridge-fp-")
|
2020-11-09 19:56:14 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = io.Copy(f, strings.NewReader(content))
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = f.Close()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
return f.Name()
|
|
|
|
}
|
|
|
|
|
|
|
|
func cleanupFile(t *testing.T, name string) {
|
|
|
|
err := os.Remove(name)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
dynamicModuleContent = `
|
|
|
|
ip_tables 32768 0 - Live 0xffffffffc03ee000
|
|
|
|
x_tables 40960 1 ip_tables, Live 0xffffffffc03e3000
|
|
|
|
autofs4 45056 2 - Live 0xffffffffc03d7000
|
|
|
|
bpfilter 32768 0 - Live 0x0000000000000000
|
|
|
|
br_netfilter 28672 0 - Live 0x0000000000000000
|
|
|
|
bridge 176128 1 br_netfilter, Live 0x0000000000000000
|
|
|
|
btrfs 1253376 0 - Live 0xffffffffc02a4000
|
|
|
|
`
|
|
|
|
|
|
|
|
builtinModuleContent = `
|
|
|
|
kernel/drivers/mfd/max14577.ko
|
|
|
|
kernel/drivers/mfd/max77693.ko
|
|
|
|
kernel/drivers/mfd/sec-core.ko
|
|
|
|
kernel/drivers/mfd/sec-irq.ko
|
|
|
|
kernel/drivers/net/bridge.ko
|
|
|
|
kernel/drivers/net/tun.ko
|
|
|
|
kernel/drivers/net/xen-netfront.k
|
|
|
|
`
|
|
|
|
|
|
|
|
dependsModuleContent = `
|
|
|
|
kernel/net/bridge/netfilter/ebt_log.ko: kernel/net/netfilter/x_tables.ko
|
|
|
|
kernel/net/bridge/netfilter/ebt_nflog.ko: kernel/net/netfilter/x_tables.ko
|
|
|
|
kernel/net/bridge/bridge.ko: kernel/net/802/stp.ko kernel/net/llc/llc.ko
|
|
|
|
kernel/net/bridge/br_netfilter.ko: kernel/net/bridge/bridge.ko kernel/net/802/stp.ko kernel/net/llc/llc.ko
|
|
|
|
kernel/net/appletalk/appletalk.ko: kernel/net/802/psnap.ko kernel/net/llc/llc.ko
|
|
|
|
kernel/net/x25/x25.ko:
|
2021-01-12 17:25:53 +00:00
|
|
|
# Dummy module to test RHEL modules.dep format
|
|
|
|
kernel/net/bridge/bridgeRHEL.ko.xz: kernel/net/802/stp.ko.xz kernel/net/llc/llc.ko.xz
|
2020-11-09 19:56:14 +00:00
|
|
|
`
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestBridgeFingerprint_search(t *testing.T) {
|
2022-03-15 12:42:43 +00:00
|
|
|
ci.Parallel(t)
|
|
|
|
|
2020-11-09 19:56:14 +00:00
|
|
|
f := &BridgeFingerprint{logger: testlog.HCLogger(t)}
|
|
|
|
|
|
|
|
t.Run("dynamic loaded module", func(t *testing.T) {
|
|
|
|
t.Run("present", func(t *testing.T) {
|
|
|
|
file := writeFile(t, "bridge-fp-", dynamicModuleContent)
|
|
|
|
defer cleanupFile(t, file)
|
|
|
|
|
|
|
|
err := f.searchFile("bridge", file, f.regexp(dynamicModuleRe, "bridge"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("absent", func(t *testing.T) {
|
|
|
|
file := writeFile(t, "bridge-fp-", dynamicModuleContent)
|
|
|
|
defer cleanupFile(t, file)
|
|
|
|
|
|
|
|
err := f.searchFile("nonexistent", file, f.regexp(dynamicModuleRe, "nonexistent"))
|
|
|
|
require.EqualError(t, err, fmt.Sprintf("module nonexistent not in %s", file))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("builtin module", func(t *testing.T) {
|
|
|
|
t.Run("present", func(t *testing.T) {
|
|
|
|
file := writeFile(t, "bridge-fp-", builtinModuleContent)
|
|
|
|
defer cleanupFile(t, file)
|
|
|
|
|
|
|
|
err := f.searchFile("bridge", file, f.regexp(builtinModuleRe, "bridge"))
|
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("absent", func(t *testing.T) {
|
|
|
|
file := writeFile(t, "bridge-fp-", builtinModuleContent)
|
|
|
|
defer cleanupFile(t, file)
|
|
|
|
|
|
|
|
err := f.searchFile("nonexistent", file, f.regexp(builtinModuleRe, "nonexistent"))
|
|
|
|
require.EqualError(t, err, fmt.Sprintf("module nonexistent not in %s", file))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("dynamic unloaded module", func(t *testing.T) {
|
|
|
|
t.Run("present", func(t *testing.T) {
|
|
|
|
file := writeFile(t, "bridge-fp-", dependsModuleContent)
|
|
|
|
defer cleanupFile(t, file)
|
|
|
|
|
|
|
|
err := f.searchFile("bridge", file, f.regexp(dependsModuleRe, "bridge"))
|
|
|
|
require.NoError(t, err)
|
2021-01-12 17:25:53 +00:00
|
|
|
|
|
|
|
err = f.searchFile("bridgeRHEL", file, f.regexp(dependsModuleRe, "bridgeRHEL"))
|
|
|
|
require.NoError(t, err)
|
2020-11-09 19:56:14 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("absent", func(t *testing.T) {
|
|
|
|
file := writeFile(t, "bridge-fp-", dependsModuleContent)
|
|
|
|
defer cleanupFile(t, file)
|
|
|
|
|
|
|
|
err := f.searchFile("nonexistent", file, f.regexp(dependsModuleRe, "nonexistent"))
|
|
|
|
require.EqualError(t, err, fmt.Sprintf("module nonexistent not in %s", file))
|
|
|
|
})
|
|
|
|
})
|
2020-05-15 15:09:01 +00:00
|
|
|
}
|