-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
implement feature 356, minimal checkov producer
- Loading branch information
1 parent
da58d76
commit e4ad707
Showing
7 changed files
with
3,599 additions
and
0 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
components/producers/checkov/exampleData/checkov_cyclonedx_out.pb
Large diffs are not rendered by default.
Oops, something went wrong.
10 changes: 10 additions & 0 deletions
10
components/producers/checkov/exampleData/checkov_sarif_out.pb
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
2,716 changes: 2,716 additions & 0 deletions
2,716
components/producers/checkov/exampleData/results_cyclonedx.json
Large diffs are not rendered by default.
Oops, something went wrong.
639 changes: 639 additions & 0 deletions
639
components/producers/checkov/exampleData/results_sarif.sarif
Large diffs are not rendered by default.
Oops, something went wrong.
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,71 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"log" | ||
|
||
"github.com/go-errors/errors" | ||
v1 "github.com/ocurity/dracon/api/proto/v1" | ||
"github.com/ocurity/dracon/pkg/cyclonedx" | ||
"github.com/ocurity/dracon/pkg/sarif" | ||
|
||
"github.com/ocurity/dracon/components/producers" | ||
) | ||
|
||
// the CycloneDX target override | ||
var Target string | ||
|
||
func main() { | ||
flag.StringVar(&Target, "target", "", "The target being scanned, this will override the CycloneDX target and is useful for cases where you scan iac or a dockerfile for an application that you know it's purl") | ||
|
||
if err := producers.ParseFlags(); err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
inFile, err := producers.ReadInFile() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
if err := run(inFile); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
func run(inFile []byte) error { | ||
sarifResults, sarifErr := handleSarif(inFile) | ||
cyclondxResults, cyclonedxErr := handleCycloneDX(inFile) | ||
if sarifErr != nil && cyclonedxErr != nil { | ||
return errors.Errorf("Could not parse input file as neither Sarif nor CycloneDX sarif error: %v, cyclonedx error: %v", sarifErr, cyclonedxErr) | ||
} | ||
|
||
var issues []*v1.Issue | ||
if sarifResults != nil { | ||
issues = sarifResults | ||
} else { | ||
issues = cyclondxResults | ||
} | ||
if err := producers.WriteDraconOut( | ||
"checkov", | ||
issues, | ||
); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func handleSarif(inFile []byte) ([]*v1.Issue, error) { | ||
var sarifResults []*sarif.DraconIssueCollection | ||
var draconResults []*v1.Issue | ||
sarifResults, err := sarif.ToDracon(string(inFile)) | ||
if err != nil { | ||
return draconResults, err | ||
} | ||
for _, result := range sarifResults { | ||
draconResults = append(draconResults, result.Issues...) | ||
} | ||
return draconResults, nil | ||
} | ||
|
||
func handleCycloneDX(inFile []byte) ([]*v1.Issue, error) { | ||
return cyclonedx.ToDracon(inFile, "json", Target) | ||
} |
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,103 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
"testing" | ||
|
||
"google.golang.org/protobuf/proto" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
v1 "github.com/ocurity/dracon/api/proto/v1" | ||
"github.com/ocurity/dracon/components/producers" | ||
) | ||
|
||
const ( | ||
sarifInputPath = "exampleData/results_sarif.sarif" | ||
cyclonedxInputPath = "exampleData/results_cyclonedx.json" | ||
) | ||
|
||
func TestRunSarif(t *testing.T) { | ||
workspace, err := os.MkdirTemp("", "dracon") | ||
require.NoError(t, err) | ||
defer os.RemoveAll(workspace) | ||
producers.OutFile = filepath.Join(workspace, "out.pb") | ||
input, err := os.ReadFile(sarifInputPath) | ||
require.NoError(t, err) | ||
require.NoError(t, run(input)) | ||
|
||
_, err = os.Stat(producers.OutFile) | ||
require.NoError(t, err) | ||
|
||
in, err := os.ReadFile(producers.OutFile) | ||
require.NoError(t, err) | ||
var wrote v1.LaunchToolResponse | ||
err = proto.Unmarshal(in, &wrote) | ||
require.NoError(t, err) | ||
expectedIssues := []*v1.Issue{ | ||
{ | ||
Target: "code/cfngoat/cfngoat.yaml:891-892", | ||
Type: "CKV_SECRET_6", | ||
Title: "Base64 High Entropy String", | ||
Severity: v1.Severity_SEVERITY_HIGH, | ||
Description: "MatchedRule: {\"id\":\"CKV_SECRET_6\",\"name\":\"Base64 High Entropy String\",\"shortDescription\":{\"text\":\"Base64 High Entropy String\"},\"fullDescription\":{\"text\":\"Base64 High Entropy String\"},\"defaultConfiguration\":{\"level\":\"error\"},\"help\":{\"text\":\"Base64 High Entropy String\\nResource: c00f1a6e4b20aa64691d50781b810756d6254b8e\"}} \n Message: Base64 High Entropy String", | ||
}, { | ||
Target: "code/cfngoat/.github/workflows/checkov.yaml:1-1", | ||
Type: "CKV2_GHA_1", | ||
Title: "Ensure top-level permissions are not set to write-all", | ||
Severity: v1.Severity_SEVERITY_HIGH, | ||
Description: "MatchedRule: {\"id\":\"CKV2_GHA_1\",\"name\":\"Ensure top-level permissions are not set to write-all\",\"shortDescription\":{\"text\":\"Ensure top-level permissions are not set to write-all\"},\"fullDescription\":{\"text\":\"Ensure top-level permissions are not set to write-all\"},\"defaultConfiguration\":{\"level\":\"error\"},\"help\":{\"text\":\"Ensure top-level permissions are not set to write-all\\nResource: on(build)\"}} \n Message: Ensure top-level permissions are not set to write-all", | ||
}, { | ||
Target: "code/cfngoat/.github/workflows/main.yaml:1-1", | ||
Type: "CKV2_GHA_1", | ||
Title: "Ensure top-level permissions are not set to write-all", | ||
Severity: v1.Severity_SEVERITY_HIGH, | ||
Description: "MatchedRule: {\"id\":\"CKV2_GHA_1\",\"name\":\"Ensure top-level permissions are not set to write-all\",\"shortDescription\":{\"text\":\"Ensure top-level permissions are not set to write-all\"},\"fullDescription\":{\"text\":\"Ensure top-level permissions are not set to write-all\"},\"defaultConfiguration\":{\"level\":\"error\"},\"help\":{\"text\":\"Ensure top-level permissions are not set to write-all\\nResource: on(build)\"}} \n Message: Ensure top-level permissions are not set to write-all", | ||
}, | ||
} | ||
|
||
foundIssues := 0 | ||
for _, wroteIssue := range wrote.Issues { | ||
for _, expectedIssue := range expectedIssues { | ||
if wroteIssue.Target == expectedIssue.Target { | ||
foundIssues += 1 | ||
require.Equal(t, expectedIssue.Title, wroteIssue.Title) | ||
require.Equal(t, expectedIssue.Description, wroteIssue.Description) | ||
require.Equal(t, expectedIssue.Target, wroteIssue.Target) | ||
require.Equal(t, expectedIssue.Severity, wroteIssue.Severity) | ||
} | ||
} | ||
} | ||
require.Equal(t, len(expectedIssues), foundIssues) | ||
} | ||
|
||
func TestRunCyclonedx(t *testing.T) { | ||
workspace, err := os.MkdirTemp("", "dracon") | ||
require.NoError(t, err) | ||
defer os.RemoveAll(workspace) | ||
producers.OutFile = filepath.Join(workspace, "out.pb") | ||
input, err := os.ReadFile(cyclonedxInputPath) | ||
require.NoError(t, err) | ||
|
||
Target = "pkg:my/awesome/package" | ||
require.NoError(t, run(input)) | ||
|
||
_, err = os.Stat(producers.OutFile) | ||
require.NoError(t, err) | ||
|
||
in, err := os.ReadFile(producers.OutFile) | ||
require.NoError(t, err) | ||
var wrote v1.LaunchToolResponse | ||
err = proto.Unmarshal(in, &wrote) | ||
require.NoError(t, err) | ||
sbom := string(input) | ||
expectedIssue := v1.Issue{ | ||
|
||
Target: "pkg:my/awesome/package", | ||
CycloneDXSBOM: &sbom, | ||
} | ||
require.Equal(t, 1, len(wrote.Issues)) | ||
require.Equal(t, *expectedIssue.CycloneDXSBOM, *wrote.Issues[0].CycloneDXSBOM) | ||
require.Equal(t, expectedIssue.Target, wrote.Issues[0].Target) | ||
} |
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,58 @@ | ||
--- | ||
apiVersion: tekton.dev/v1beta1 | ||
kind: Task | ||
metadata: | ||
name: producer-checkov | ||
labels: | ||
v1.dracon.ocurity.com/component: producer | ||
v1.dracon.ocurity.com/test-type: sast | ||
v1.dracon.ocurity.com/language: iac | ||
spec: | ||
description: Analyse IAC source code to look for security issues. | ||
params: | ||
- name: producer-checkov-cyclonedx-target-override | ||
type: string | ||
default: "" | ||
volumes: | ||
- name: scratch | ||
emptyDir: {} | ||
workspaces: | ||
- name: output | ||
description: The workspace containing the source-code to scan. | ||
steps: | ||
- name: run-checkov | ||
image: bridgecrew/checkov:3.2.255 | ||
command: [/usr/local/bin/checkov] | ||
args: | ||
- --skip-download | ||
- --directory | ||
- "$(workspaces.output.path)/source-code" | ||
- --output=cyclonedx_json | ||
- --output=sarif | ||
- --output-file-path | ||
- /scratch | ||
- --soft-fail | ||
volumeMounts: | ||
- mountPath: /scratch | ||
name: scratch | ||
- name: produce-issues-sarif | ||
imagePullPolicy: IfNotPresent | ||
image: '{{ default "ghcr.io/ocurity/dracon" .Values.image.registry }}/components/producers/checkov:{{ .Chart.AppVersion }}' | ||
command: ["/app/components/producers/checkov/checkov-parser"] | ||
args: | ||
- "-in=/scratch/results_sarif.sarif" | ||
- "-out=$(workspaces.output.path)/.dracon/producers/checkov-sarif.pb" | ||
volumeMounts: | ||
- mountPath: /scratch | ||
name: scratch | ||
- name: produce-issues-cyclonedx | ||
imagePullPolicy: IfNotPresent | ||
image: '{{ default "ghcr.io/ocurity/dracon" .Values.image.registry }}/components/producers/checkov:{{ .Chart.AppVersion }}' | ||
command: ["/app/components/producers/checkov/checkov-parser"] | ||
args: | ||
- "-in=/scratch/results_cyclonedx.json" | ||
- "-out=$(workspaces.output.path)/.dracon/producers/checkov-cyclonedx.pb" | ||
- "-target=$(producer-checkov-cyclonedx-target-override)" | ||
volumeMounts: | ||
- mountPath: /scratch | ||
name: scratch |