diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 8f05efd0..ee3fba8a 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -48,10 +48,10 @@ jobs: run: | if [[ "${{ github.ref }}" == refs/tags/* ]]; then VERSION=$(cat sourcecode-parser/VERSION) - echo "tag=${VERSION}" >> $GITHUB_OUTPUT + echo "tag=v${VERSION}, stable-latest" >> $GITHUB_OUTPUT elif [ "${{ github.event_name }}" == "push" ] && [ "${{ github.ref }}" == "refs/heads/main" ]; then VERSION=$(cat sourcecode-parser/VERSION) - echo "tag=dev-${VERSION}" >> $GITHUB_OUTPUT + echo "tag=dev-${VERSION}, nightly-latest" >> $GITHUB_OUTPUT else echo "tag=dev" >> $GITHUB_OUTPUT fi diff --git a/Dockerfile b/Dockerfile index b21ae02f..1e57a7f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,10 +22,14 @@ FROM cgr.dev/chainguard/wolfi-base:latest WORKDIR /app -COPY --from=builder /app/pathfinder /usr/local/bin/pathfinder +COPY --from=builder /app/pathfinder /usr/bin/pathfinder -RUN chmod +x /usr/local/bin/pathfinder +COPY entrypoint.sh /usr/bin/entrypoint.sh -CMD ["pathfinder", "version"] +RUN chmod +x /usr/bin/pathfinder -LABEL maintainer="shiva@shivasurya.me" \ No newline at end of file +RUN chmod +x /usr/bin/entrypoint.sh + +LABEL maintainer="shiva@shivasurya.me" + +ENTRYPOINT ["/usr/bin/entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 00c615be..2fd167bd 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,25 @@ Code Pathfinder, the open-source alternative to GitHub CodeQL. Built for advance [![codecov](https://codecov.io/gh/shivasurya/code-pathfinder/graph/badge.svg?token=VYQLI49TF4)](https://codecov.io/gh/shivasurya/code-pathfinder) -## Documentation +## :tv: Demo + +```bash +docker run --rm -v "./src:/src" shivasurya/code-pathfinder:stable-latest pathfinder ci --project /src/code-pathfinder/test-src --ruleset cpf/java +``` + +## :book: Documentation - [Documentation](https://codepathfinder.dev/) - [Pathfinder Queries](https://github.com/shivasurya/code-pathfinder/tree/main/pathfinder-rules) -## Installation +## :floppy_disk: Installation + +### :whale: Using Docker + +```bash +$ docker pull shivasurya/code-pathfinder:dev +``` ### From npm diff --git a/action.yml b/action.yml new file mode 100644 index 00000000..810018a4 --- /dev/null +++ b/action.yml @@ -0,0 +1,41 @@ +# action.yml +name: 'Code-Pathfinder OSS' +description: 'Code-Pathfinder open-source alternative to CodeQL' +author: 'Shivasurya shiva@shivasurya.me' +branding: + icon: "shield" + color: "blue" +inputs: + command: + description: 'Command to run example: ci, query' + required: true + default: 'ci' + project: + description: 'Source code to scan. eg: /path/to/project' + required: true + default: ${{ github.workspace }} + ruleset: + description: 'Predefined rules eg: cpf/java or rules directory' + required: false + output: + description: 'Output format eg: json' + required: false + default: 'json' + output-file: + description: 'Output file name eg: output.json' + required: false + default: 'output.json' +runs: + using: 'docker' + image: 'docker://shivasurya/code-pathfinder:stable-latest' + args: + - pathfinder + - ${{ inputs.command }} + - --project + - ${{ inputs.project }} + - --ruleset + - ${{ inputs.ruleset }} + - --output + - ${{ inputs.output }} + - --output-file + - ${{ inputs.output-file }} diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 00000000..faa35ce0 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env sh + +if [ $# -eq 0 ]; then + /usr/bin/pathfinder version +else + /usr/bin/pathfinder "$@" +fi \ No newline at end of file diff --git a/sourcecode-parser/cmd/ci.go b/sourcecode-parser/cmd/ci.go index aee9389b..5143f36a 100644 --- a/sourcecode-parser/cmd/ci.go +++ b/sourcecode-parser/cmd/ci.go @@ -9,6 +9,8 @@ import ( "path/filepath" "strings" + "github.com/shivasurya/code-pathfinder/sourcecode-parser/graph" + "github.com/spf13/cobra" ) @@ -17,7 +19,6 @@ var ciCmd = &cobra.Command{ Short: "Scan a project for vulnerabilities with ruleset in ci mode", Run: func(cmd *cobra.Command, _ []string) { rulesetConfig := cmd.Flag("ruleset").Value.String() - rulesetDirectory := cmd.Flag("rules-directory").Value.String() projectInput := cmd.Flag("project").Value.String() output := cmd.Flag("output").Value.String() outputFile := cmd.Flag("output-file").Value.String() @@ -31,8 +32,8 @@ var ciCmd = &cobra.Command{ fmt.Println("Executing in CI mode") } - if rulesetConfig == "" && rulesetDirectory == "" { - fmt.Println("Ruleset or rules directory not specified") + if rulesetConfig == "" { + fmt.Println("ruleset are not specified. Please specify a ruleset eg: cpf/java or directory path") os.Exit(1) } @@ -41,26 +42,12 @@ var ciCmd = &cobra.Command{ os.Exit(1) } - if rulesetConfig != "" { - if !strings.HasPrefix(rulesetConfig, "cpf/") { - fmt.Println("Ruleset not specified") - os.Exit(1) - } - ruleset, err = loadRules(rulesetConfig, true) - if err != nil { - if verboseFlag { - fmt.Printf("%s - error loading rules or ruleset not found: \nStacktrace: \n%s \n", rulesetConfig, err) - } - os.Exit(1) - } - } else if rulesetDirectory != "" { - ruleset, err = loadRules(rulesetDirectory, false) - if err != nil { - if verboseFlag { - fmt.Printf("%s - error loading rules or ruleset not found: \nStacktrace: \n%s \n", rulesetDirectory, err) - } - os.Exit(1) + ruleset, err = loadRules(rulesetConfig, strings.HasPrefix(rulesetConfig, "cpf/")) + if err != nil { + if verboseFlag { + fmt.Printf("%s - error loading rules or ruleset not found: \nStacktrace: \n%s \n", rulesetConfig, err) } + os.Exit(1) } codeGraph := initializeProject(projectInput) for _, rule := range ruleset { @@ -85,6 +72,10 @@ var ciCmd = &cobra.Command{ // TODO: Add sarif file support if output == "json" { if outputFile != "" { + if graph.IsGitHubActions() { + // append GITHUB_WORKSPACE to output file path + outputFile = os.Getenv("GITHUB_WORKSPACE") + "/" + outputFile + } file, err := os.Create(outputFile) if err != nil { fmt.Println("Error creating output file: ", err) @@ -115,8 +106,7 @@ func init() { ciCmd.Flags().StringP("output", "o", "", "Supported output format: json") ciCmd.Flags().StringP("output-file", "f", "", "Output file path") ciCmd.Flags().StringP("project", "p", "", "Project to analyze") - ciCmd.Flags().StringP("ruleset", "q", "", "Ruleset to use example: cfp/java") - ciCmd.Flags().StringP("rules-directory", "r", "", "Rules directory to use") + ciCmd.Flags().StringP("ruleset", "r", "", "Ruleset to use example: cfp/java or directory path") } func loadRules(rulesDirectory string, isHosted bool) ([]string, error) { diff --git a/sourcecode-parser/cmd/ci_test.go b/sourcecode-parser/cmd/ci_test.go index 785039e9..1ade3f46 100644 --- a/sourcecode-parser/cmd/ci_test.go +++ b/sourcecode-parser/cmd/ci_test.go @@ -20,7 +20,7 @@ func TestCiCmd(t *testing.T) { { name: "Basic CI command", args: []string{"ci", "--help"}, - expectedOutput: "Scan a project for vulnerabilities with ruleset in ci mode\n\nUsage:\n pathfinder ci [flags]\n\nFlags:\n -h, --help help for ci\n -o, --output string Supported output format: json\n -f, --output-file string Output file path\n -p, --project string Project to analyze\n -r, --rules-directory string Rules directory to use\n -q, --ruleset string Ruleset to use example: cfp/java\n", + expectedOutput: "Scan a project for vulnerabilities with ruleset in ci mode\n\nUsage:\n pathfinder ci [flags]\n\nFlags:\n -h, --help help for ci\n -o, --output string Supported output format: json\n -f, --output-file string Output file path\n -p, --project string Project to analyze\n -r, --ruleset string Ruleset to use example: cfp/java or directory path\n", }, } diff --git a/sourcecode-parser/graph/util.go b/sourcecode-parser/graph/util.go index 129c7c59..1cb41aaf 100644 --- a/sourcecode-parser/graph/util.go +++ b/sourcecode-parser/graph/util.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "log" + "os" ) var verboseFlag bool @@ -63,3 +64,7 @@ func Fmt(format string, args ...interface{}) { fmt.Printf(format, args...) } } + +func IsGitHubActions() bool { + return os.Getenv("GITHUB_ACTIONS") == "true" +}