Skip to content

Commit

Permalink
implement feature 356, minimal checkov producer
Browse files Browse the repository at this point in the history
  • Loading branch information
northdpole committed Sep 19, 2024
1 parent da58d76 commit e4ad707
Show file tree
Hide file tree
Showing 7 changed files with 3,599 additions and 0 deletions.

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions components/producers/checkov/exampleData/checkov_sarif_out.pb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

 ����[checkov�
!code/cfngoat/cfngoat.yaml:891-892 CKV_SECRET_6Base64 High Entropy String :�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"}}
Message: Base64 High Entropy StringBunknown�
/code/cfngoat/.github/workflows/checkov.yaml:1-1
CKV2_GHA_15Ensure top-level permissions are not set to write-all :�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)"}}
Message: Ensure top-level permissions are not set to write-allBunknown�
,code/cfngoat/.github/workflows/main.yaml:1-1
CKV2_GHA_15Ensure top-level permissions are not set to write-all :�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)"}}
Message: Ensure top-level permissions are not set to write-allBunknown
Expand Down
2,716 changes: 2,716 additions & 0 deletions components/producers/checkov/exampleData/results_cyclonedx.json

Large diffs are not rendered by default.

639 changes: 639 additions & 0 deletions components/producers/checkov/exampleData/results_sarif.sarif

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions components/producers/checkov/main.go
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)
}
103 changes: 103 additions & 0 deletions components/producers/checkov/main_test.go
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)
}
58 changes: 58 additions & 0 deletions components/producers/checkov/task.yaml
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

0 comments on commit e4ad707

Please sign in to comment.