-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Vulnerable functionality for java (maven focused) (#81)
* Add vf-cli for java (mvn) to cli * Refactor find-files and finder logic * Add callgraph cmd test * Refactor MapFilesToDir * Improve test coverage * Rewrite tests to be OS-agnostic * Add build flag to call graph command, without build functionality. * Add viper binding for build flag and fix test not asserting flags as intended. * Change build arg to no-build arg to indicate that auto build is default. * Add build arg to callgraph config and strategy. * Add build maven package cmd and call it if auto build is enabled (default true). * Add functionality to run maven package compilation (build) step by default with a flag to disable it. * Add mini java project for testing and test build on it. * add functional test to make sure build works correctly. this test is slow and should possibly be separated in the future. * Fix linting issues, including a cyclic complexity reduction (at a cost). * Ignore the build target location in case it was not properly deleted in a failed test run. * Add spinner UI in CLI for the build step of Maven projects in call graph. Add rich error logging. * Improve testing of error logging. * Add a Command struct that wraps os/exec.Cmd to allow mocking for test purposes. * Implement command mock. Refactor command methods to allow better testing. * Add upload + postprocess logic to java callgraph and improve tests * Improve testing in io, command and callgraph * Cleanup * Move mvn test to correct folder * Remove gradle callgraph logic from groovy file * Fix windows problem * Fix an issue where the zipping tool was looking in root instead of the real location of the call graph. * Fix mapping pom files to class directories * Increase time before timeout to 60min * Change build to only fail if all build pom.xml fails * Increase upload time for callgraphs to 10min * Add fix for zipped filename being a long location * Rewrite java-callgraph-files logic to handle each .class-dir + .jar-files * Update sootWrapper to support .jar-files * Change to refresh files of interest after build * Add functionality to stop run preemptively if error occours * Add --generate-timeout flag to callgraph command * Add callgraph generation timeout and upload timeout flags to scan command * Add e2e test of callgraph generation * Move exclude logic to its own module * Move callgraph finder from io to callgraph package * Utilise Excluded in callgraph finder * Add test coverage for callgraph finder file exclusion * Update callgraph documentation * Fix failing tests * Change deps of pom.xml file * Update SootWrapper * Change name of .debricked-call-graph to debricked-call-graph (#138) * Change to scan for groups after callgraph generated * Update documentation link * Add windows-latest to e2e tests again * Fix general cleanup --------- Co-authored-by: AntonDebricked <[email protected]> Co-authored-by: filip-debricked <[email protected]> Co-authored-by: jonnadebricked <[email protected]> Co-authored-by: klaradebricked <[email protected]>
- Loading branch information
1 parent
35392ff
commit 8729272
Showing
108 changed files
with
5,742 additions
and
194 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package cgexec | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
) | ||
|
||
type ICommand interface { | ||
CombinedOutput() ([]byte, error) | ||
Start() error | ||
Wait() error | ||
GetProcess() *os.Process | ||
SetStderr(*bytes.Buffer) | ||
SetStdout(*bytes.Buffer) | ||
GetArgs() []string | ||
GetDir() string | ||
Signal(process *os.Process, signal os.Signal) error | ||
} | ||
|
||
type Command struct { | ||
osCmd *exec.Cmd | ||
} | ||
|
||
func NewCommand(osCmd *exec.Cmd) *Command { | ||
return &Command{osCmd} | ||
} | ||
|
||
func (cmd Command) SetStderr(stderr *bytes.Buffer) { | ||
cmd.osCmd.Stderr = stderr | ||
} | ||
|
||
func (cmd Command) SetStdout(stdout *bytes.Buffer) { | ||
cmd.osCmd.Stdout = stdout | ||
} | ||
|
||
func (cmd Command) GetArgs() []string { | ||
return cmd.osCmd.Args | ||
} | ||
|
||
func (cmd Command) CombinedOutput() ([]byte, error) { | ||
return cmd.osCmd.CombinedOutput() | ||
} | ||
|
||
func (cmd Command) Start() error { | ||
return cmd.osCmd.Start() | ||
} | ||
|
||
func (cmd Command) Wait() error { | ||
return cmd.osCmd.Wait() | ||
} | ||
|
||
func (cmd Command) GetProcess() *os.Process { | ||
return cmd.osCmd.Process | ||
} | ||
|
||
func (cmd Command) GetDir() string { | ||
return cmd.osCmd.Dir | ||
} | ||
|
||
func (cmd Command) Signal(process *os.Process, signal os.Signal) error { | ||
return process.Signal(signal) | ||
} | ||
|
||
func RunCommand(cmd ICommand, ctx IContext) error { | ||
args := strings.Join(cmd.GetArgs(), " ") | ||
var stdoutBuf, stderrBuf bytes.Buffer | ||
var err error | ||
var outputCmd []byte | ||
if ctx == nil { | ||
outputCmd, err = cmd.CombinedOutput() | ||
if _, ok := err.(*exec.ExitError); ok { | ||
err = fmt.Errorf("Command '%s' executed in folder '%s' gave the following error:\n%s", args, cmd.GetDir(), outputCmd) | ||
} | ||
|
||
return err | ||
} | ||
|
||
cmd.SetStderr(&stderrBuf) | ||
cmd.SetStdout(&stdoutBuf) | ||
|
||
// Start the external process | ||
if err := cmd.Start(); err != nil { | ||
|
||
return err | ||
} | ||
|
||
// Channel to signal when the external process completes | ||
done := make(chan error, 1) | ||
|
||
// Goroutine to wait for the process to complete | ||
go func() { | ||
err := cmd.Wait() | ||
if err != nil { | ||
err = fmt.Errorf("Command '%s' executed in folder '%s' gave the following error: \n%s\n%s", args, cmd.GetDir(), stdoutBuf.String(), stderrBuf.String()) | ||
} | ||
|
||
done <- err | ||
}() | ||
|
||
select { | ||
case <-ctx.Context().Done(): | ||
|
||
if ctx.Context().Err() == context.DeadlineExceeded { | ||
// Context timeout occurred before the process started | ||
return fmt.Errorf("Timeout error: Set timeout duration for Callgraph jobs reached") | ||
} | ||
|
||
// The context was canceled, handle cancellation if needed | ||
// Send a signal to the process to terminate | ||
process := cmd.GetProcess() | ||
if process != nil { | ||
err := cmd.Signal(process, os.Interrupt) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
|
||
// Wait for the process to exit | ||
<-done | ||
|
||
return fmt.Errorf("Timeout error: Set timeout duration for Callgraph jobs reached") | ||
case err := <-done: | ||
// The external process completed before the context was canceled | ||
return err | ||
} | ||
} | ||
|
||
func MakeCommand(workingDir string, path string, args []string, ctx IContext) *exec.Cmd { | ||
var cmd *exec.Cmd | ||
|
||
if ctx == nil { | ||
cmd = &exec.Cmd{ | ||
Path: path, | ||
Args: args, | ||
Dir: workingDir, | ||
} | ||
} else { | ||
command := args[0] | ||
arguments := args[1:] | ||
cmd = exec.CommandContext(ctx.Context(), command, arguments...) | ||
cmd.Path = path | ||
cmd.Dir = workingDir | ||
} | ||
|
||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package cgexec | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
|
||
execTestdata "github.com/debricked/cli/internal/callgraph/cgexec/testdata" | ||
) | ||
|
||
func TestMakeCommandWithContext(t *testing.T) { | ||
cmdName := "echo" | ||
path, _ := exec.LookPath(cmdName) | ||
ctx, cancel := NewContext(100) | ||
defer cancel() | ||
osCmd := MakeCommand(".", path, []string{ | ||
"echo", | ||
"package", | ||
}, ctx) | ||
cmd := NewCommand(osCmd) | ||
err := RunCommand(*cmd, ctx) | ||
assert.Nil(t, err) | ||
} | ||
|
||
func TestMakeCommandWithNoContext(t *testing.T) { | ||
cmdName := "echo" | ||
path, _ := exec.LookPath(cmdName) | ||
osCmd := MakeCommand(".", path, []string{ | ||
"echo", | ||
"package", | ||
"-q", | ||
"-DskipTests", | ||
"-e", | ||
}, nil) | ||
cmd := NewCommand(osCmd) | ||
err := RunCommand(*cmd, nil) | ||
assert.Nil(t, err) | ||
} | ||
|
||
func TestMakeCommandDeadlineExceeded(t *testing.T) { | ||
ctx, _ := execTestdata.NewContextMockDeadlineReached() | ||
cmd := execTestdata.NewCommandMock() | ||
err := RunCommand(cmd, ctx) | ||
t.Log(err) | ||
if err == nil { | ||
assert.FailNow(t, "Error was unexpectedly nil.") | ||
} | ||
assert.Contains(t, err.Error(), "Timeout error: Set timeout duration for Callgraph jobs reached") | ||
} | ||
|
||
func TestMakeCommandCancelled(t *testing.T) { | ||
ctx, _ := execTestdata.NewContextMockCancelled() | ||
cmd := execTestdata.NewCommandMock() | ||
err := RunCommand(cmd, ctx) | ||
t.Log(err) | ||
assert.Contains(t, err.Error(), "Timeout error: Set timeout duration for Callgraph jobs reached") | ||
} | ||
|
||
func TestMakeCommandCancelledInteruptedError(t *testing.T) { | ||
ctx, _ := execTestdata.NewContextMockCancelled() | ||
cmd := execTestdata.NewCommandMock() | ||
cmd.Process = &os.Process{} | ||
cmd.SignalError = fmt.Errorf("error") | ||
err := RunCommand(cmd, ctx) | ||
t.Log(err) | ||
assert.Contains(t, err.Error(), "error") | ||
} | ||
|
||
func TestMakeCommandStartFailure(t *testing.T) { | ||
ctx, _ := execTestdata.NewContextMock() | ||
cmdConfig := execTestdata.NewCmdConfig() | ||
cmd := execTestdata.NewCommandMockWithConfig(*cmdConfig) | ||
err := RunCommand(cmd, ctx) | ||
t.Log(err) | ||
assert.Contains(t, err.Error(), "test error") | ||
} | ||
|
||
func TestWaitExecutionFail(t *testing.T) { | ||
ctx, _ := execTestdata.NewContextMock() | ||
cmd := execTestdata.NewCommandMock() | ||
cmd.WaitError = fmt.Errorf("error") | ||
err := RunCommand(cmd, ctx) | ||
t.Log(err) | ||
assert.Contains(t, err.Error(), "error") | ||
} | ||
|
||
func TestNoContextCommandFail(t *testing.T) { | ||
cmd := execTestdata.NewCommandMock() | ||
cmd.CombinedOutputError = &exec.ExitError{} | ||
err := RunCommand(cmd, nil) | ||
t.Log(err) | ||
assert.Contains(t, err.Error(), "executed in folder") | ||
} | ||
|
||
func TestMakeCommandSuccess(t *testing.T) { | ||
ctx, _ := execTestdata.NewContextMock() | ||
cmd := execTestdata.NewCommandMock() | ||
err := RunCommand(cmd, ctx) | ||
t.Log(err) | ||
assert.Nil(t, err) | ||
} | ||
|
||
func TestCmdGetProcess(t *testing.T) { | ||
cmd := NewCommand(exec.Command("echo", "GetProcess")) | ||
process := cmd.GetProcess() | ||
|
||
assert.Nil(t, process) | ||
} | ||
|
||
func TestCmdGetDir(t *testing.T) { | ||
cmd := NewCommand(exec.Command("echo", "GetProcess")) | ||
dir := cmd.GetDir() | ||
|
||
assert.NotNil(t, dir) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package cgexec | ||
|
||
import ( | ||
"context" | ||
"time" | ||
) | ||
|
||
type IContext interface { | ||
Context() context.Context | ||
Done() <-chan struct{} | ||
} | ||
|
||
type Context struct { | ||
ctx context.Context | ||
} | ||
|
||
func NewContext(timer int) (Context, context.CancelFunc) { | ||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timer)*time.Second) | ||
|
||
return Context{ctx}, cancel | ||
} | ||
|
||
func (c Context) Context() context.Context { | ||
return c.ctx | ||
} | ||
|
||
func (c Context) Done() <-chan struct{} { | ||
return c.ctx.Done() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package cgexec | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestDone(t *testing.T) { | ||
|
||
ctx, cancel := NewContext(0) | ||
defer cancel() | ||
val := <-ctx.Done() | ||
assert.NotNil(t, val) | ||
} |
Oops, something went wrong.