Skip to content

Commit 57eb8b0

Browse files
test: add new e2e test cases for kubectl plugin
Signed-off-by: Venkatesh Jayagopal <venkatesh.jayagopal@suse.com>
1 parent ee1c132 commit 57eb8b0

3 files changed

Lines changed: 905 additions & 0 deletions

File tree

test/e2e/e2e_suite_test.go

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@ package e2e_test
22

33
import (
44
"context"
5+
"crypto/sha256"
6+
"encoding/hex"
57
"fmt"
8+
"io"
69
"log/slog"
10+
"net/http"
711
"os"
12+
"os/exec"
13+
"path/filepath"
14+
"runtime"
815
"slices"
916
"strings"
1017
"testing"
@@ -116,10 +123,12 @@ func getCharts() []helmChart {
116123

117124
func TestMain(m *testing.M) {
118125
charts := getCharts()
126+
119127
commonSetupFuncs := []env.Func{
120128
// we uninstall here as a defensive check but nothing should be left behind
121129
uninstallHelmRepos(charts),
122130
installHelmRepos(charts),
131+
installKubectlRuntimeEnforcer(),
123132
}
124133

125134
commonFinishFuncs := []env.Func{
@@ -257,3 +266,157 @@ func installHelmRepos(charts []helmChart) env.Func {
257266
return ctx, nil
258267
}
259268
}
269+
270+
// installKubectlRuntimeEnforcer downloads and installs the kubectl runtime-enforcer plugin
271+
func installKubectlRuntimeEnforcer() env.Func {
272+
return func(ctx context.Context, config *envconf.Config) (context.Context, error) {
273+
// runtime-enforcer version
274+
version := "v0.6.0"
275+
installDir := "/usr/local/bin"
276+
277+
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
278+
goos := runtime.GOOS
279+
goarch := runtime.GOARCH
280+
281+
if !isSupportedPlatform(goos, goarch) {
282+
return ctx, fmt.Errorf("unsupported platform: %s/%s (supported: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64)", goos, goarch)
283+
}
284+
285+
logger.InfoContext(ctx, "Downloading and installing kubectl runtime-enforcer plugin.")
286+
287+
pluginName := "kubectl-runtime_enforcer"
288+
binaryName := fmt.Sprintf("%s-%s-%s", pluginName, goos, goarch)
289+
downloadURL := fmt.Sprintf("https://github.com/rancher-sandbox/runtime-enforcer/releases/download/%s/%s", version, binaryName)
290+
checksumURL := fmt.Sprintf("%s.sha256", downloadURL)
291+
292+
tempDir, err := os.MkdirTemp("", "runtime-enforcer-install-")
293+
if err != nil {
294+
return ctx, fmt.Errorf("failed to create temp directory: %w", err)
295+
}
296+
defer os.RemoveAll(tempDir)
297+
298+
binaryPath := filepath.Join(tempDir, binaryName)
299+
checksumPath := filepath.Join(tempDir, binaryName+".sha256")
300+
301+
if err := downloadFile(downloadURL, binaryPath); err != nil {
302+
return ctx, fmt.Errorf("failed to download binary: %w", err)
303+
}
304+
305+
if err := downloadFile(checksumURL, checksumPath); err != nil {
306+
return ctx, fmt.Errorf("failed to download checksum: %w", err)
307+
}
308+
309+
if err := verifyChecksum(binaryPath, checksumPath); err != nil {
310+
return ctx, fmt.Errorf("checksum verification failed: %w", err)
311+
}
312+
313+
if err := os.Chmod(binaryPath, 0755); err != nil {
314+
return ctx, fmt.Errorf("failed to make binary executable: %w", err)
315+
}
316+
317+
installPath := filepath.Join(installDir, pluginName)
318+
if err := moveFile(binaryPath, installPath); err != nil {
319+
return ctx, fmt.Errorf("failed to install binary: %w", err)
320+
}
321+
322+
cmd := exec.Command(pluginName, "-v")
323+
if output, err := cmd.CombinedOutput(); err != nil {
324+
return ctx, fmt.Errorf("installation verification failed: %w\nOutput: %s", err, string(output))
325+
}
326+
327+
return ctx, nil
328+
}
329+
}
330+
331+
func isSupportedPlatform(goos, goarch string) bool {
332+
supported := map[string][]string{
333+
"linux": {"amd64", "arm64"},
334+
"darwin": {"amd64", "arm64"},
335+
}
336+
337+
if archs, ok := supported[goos]; ok {
338+
for _, arch := range archs {
339+
if arch == goarch {
340+
return true
341+
}
342+
}
343+
}
344+
return false
345+
}
346+
347+
func downloadFile(url, filepath string) error {
348+
resp, err := http.Get(url)
349+
if err != nil {
350+
return err
351+
}
352+
defer resp.Body.Close()
353+
354+
if resp.StatusCode != http.StatusOK {
355+
return fmt.Errorf("bad status: %s", resp.Status)
356+
}
357+
358+
out, err := os.Create(filepath)
359+
if err != nil {
360+
return err
361+
}
362+
defer out.Close()
363+
364+
_, err = io.Copy(out, resp.Body)
365+
return err
366+
}
367+
368+
func verifyChecksum(binaryPath, checksumPath string) error {
369+
checksumData, err := os.ReadFile(checksumPath)
370+
if err != nil {
371+
return err
372+
}
373+
374+
var expected string
375+
fmt.Sscanf(string(checksumData), "%s", &expected)
376+
377+
file, err := os.Open(binaryPath)
378+
if err != nil {
379+
return err
380+
}
381+
defer file.Close()
382+
383+
hash := sha256.New()
384+
if _, err := io.Copy(hash, file); err != nil {
385+
return err
386+
}
387+
actual := hex.EncodeToString(hash.Sum(nil))
388+
389+
if actual != expected {
390+
return fmt.Errorf("checksum mismatch: expected %s, got %s", expected, actual)
391+
}
392+
393+
return nil
394+
}
395+
396+
func moveFile(src, dst string) error {
397+
if err := os.Rename(src, dst); err == nil {
398+
return nil
399+
}
400+
401+
srcFile, err := os.Open(src)
402+
if err != nil {
403+
return err
404+
}
405+
defer srcFile.Close()
406+
407+
dstFile, err := os.Create(dst)
408+
if err != nil {
409+
return err
410+
}
411+
defer dstFile.Close()
412+
413+
if _, err := io.Copy(dstFile, srcFile); err != nil {
414+
return err
415+
}
416+
417+
if err := dstFile.Sync(); err != nil {
418+
return err
419+
}
420+
421+
return os.Remove(src)
422+
}

test/e2e/e2e_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,34 @@ func TestOtelCollector(t *testing.T) {
6464

6565
testEnv.Test(t, getOtelCollectorTest())
6666
}
67+
68+
func TestKubectlPluginProposalPromoteTest(t *testing.T) {
69+
t.Log("test kubectl runtime-enforcer proposal promote PROPOSAL_NAME [flags]")
70+
71+
testEnv.Test(t, getKubectlPluginProposalPromoteTest())
72+
}
73+
74+
func TestKubectlPluginPolicyModeTest(t *testing.T) {
75+
t.Log("test kubectl runtime-enforcer policy monitor POLICY_NAME [flags]")
76+
77+
testEnv.Test(t, getKubectlPluginPolicyModeTest())
78+
}
79+
80+
func TestKubectlPluginPolicyExecAllowTest(t *testing.T) {
81+
t.Log("test kubectl runtime-enforcer policy allow POLICY_NAME <container-name> <executable-name> [<executable-name>...] [flags]")
82+
83+
testEnv.Test(t, getKubectlPluginPolicyExecAllowTest())
84+
}
85+
86+
func TestKubectlPluginPolicyExecDenyTest(t *testing.T) {
87+
t.Log("test kubectl runtime-enforcer policy deny POLICY_NAME <container-name> <executable-name> [<executable-name>...] [flags]")
88+
89+
testEnv.Test(t, getKubectlPluginPolicyExecDenyTest())
90+
}
91+
92+
func TestKubectlPluginErrorHandlingTest(t *testing.T) {
93+
t.Log("test kubectl runtime-enforcer ERROR handling")
94+
95+
testEnv.Test(t, getKubectlPluginErrorHandlingTest())
96+
}
97+

0 commit comments

Comments
 (0)